Version 1.18.0-dev.1.0

Merge '42f5c25fa5686e1613cf8ae5ee875b41680ec09' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 637e978..8f44d60 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,22 @@
-## 1.17.0 - 2016-06-06
+## 1.18.0
+
+### Core library changes
+
+* `dart:io`
+  * Adds file locking modes `FileLock.BLOCKING_SHARED` and
+    `FileLock.BLOCKING_EXCLUSIVE`.
+
+## 1.17.1 - 2016-06-10
+
+Patch release, resolves two issues:
+
+* VM: Fixes a bug that caused crashes in async functions.
+(SDK issue [26668](https://github.com/dart-lang/sdk/issues/26668))
+
+* VM: Fixes a bug that caused garbage collection of reachable weak properties.
+(https://codereview.chromium.org/2041413005)
+
+## 1.17.0 - 2016-06-08
 
 ### Core library changes
 * `dart:convert`
diff --git a/DEPS b/DEPS
index 7264d41..d46d997 100644
--- a/DEPS
+++ b/DEPS
@@ -50,7 +50,7 @@
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
   "dartdoc_tag" : "@v0.9.0",
-  "dev_compiler_rev": "@7f68e5ef424dd26344572daf02595ab23fb16941",
+  "dev_compiler_rev": "@7e9708eb5e9f3fcdc68b9af039d78cf39ce502b7",
   "fixnum_tag": "@0.10.5",
   "func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
@@ -64,7 +64,7 @@
   "intl_tag": "@0.13.0",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@2.0.0",
-  "linter_rev": "@ccd8dbf7562b7645dc8c54a578b78b38970c71d6",
+  "linter_rev": "@1a08f395b1f4e24b3901018938320f053bad6aa8",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
   "matcher_tag": "@0.12.0",
@@ -74,7 +74,7 @@
   "oauth2_tag": "@1.0.0",
   "observatory_pub_packages_rev": "@cf90eb9077177d3d6b3fd5e8289477c2385c026a",
   "observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
-  "package_config_rev": "@0.1.3",
+  "package_config_rev": "@0.1.5",
   "path_tag": "@1.3.6",
   "plugin_tag": "@0.2.0",
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 886d65b..140a8df 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -7,8 +7,8 @@
 \usepackage{lmodern}
 \newcommand{\code}[1]{{\sf #1}}
 \title{Dart Programming Language  Specification  \\
-(4th edition draft)\\
-{\large Version 1.11}}
+{4th edition draft}\\
+{\large Version 1.14}}
 
 % For information about Location Markers (and in particular the
 % commands \LMHash and \LMLabel), see the long comment at the
@@ -35,7 +35,7 @@
 \LMLabel{ecmaConformance}
 
 \LMHash{}
-A conforming  implementation of the Dart programming language must provide and support all the  APIs (libraries, types, functions, getters, setters, whether top-level, static, instance or local) mandated in this specification. 
+A conforming  implementation of the Dart programming language must provide and support all the  APIs (libraries, types, functions, getters, setters, whether top-level, static, instance or local) mandated in this specification.
 
 \LMHash{}
 A conforming implementation is permitted to provide additional APIs, but not additional syntax, except for experimental features in support of null-aware cascades and tear-offs that are likely to be introduced in the next revision of this specification.
@@ -61,7 +61,7 @@
 Terms and definitions used in this specification are given in the body of the specification proper. Such terms are highlighted in italics when they are introduced, e.g., `we use the term {\em verbosity} to refer to the property of excess verbiage'.
 % End Ecma Boilerplate
 
-  
+
 \section{Notation}
 \LMLabel{notation}
 
@@ -104,16 +104,16 @@
 % need a match anything or a production that does that, so we can correct bugs wrt use
 % ~. ~ does not actually parse stuff - it just looks ahead and checks. To get the effect of
 % parsing anything but X, one needs ~X ANYTHING, not just ~X. There are bugs in the
-% grammar related to this. 
-% The alternative is to define ~X as anything but X, or to introduce an anthingBut(X) 
+% grammar related to this.
+% The alternative is to define ~X as anything but X, or to introduce an anthingBut(X)
 % combinator, such as !X
 
 \LMHash{}
-Both syntactic and lexical productions are represented this way. Lexical productions are distinguished by their names. The names of lexical productions consist exclusively of upper case characters and underscores.  As always, within grammatical productions, whitespace and comments between elements of the production are implicitly ignored unless stated otherwise. 
-Punctuation tokens appear in quotes. 
+Both syntactic and lexical productions are represented this way. Lexical productions are distinguished by their names. The names of lexical productions consist exclusively of upper case characters and underscores.  As always, within grammatical productions, whitespace and comments between elements of the production are implicitly ignored unless stated otherwise.
+Punctuation tokens appear in quotes.
 
 \LMHash{}
-Productions are embedded, as much as possible, in the discussion of the constructs they represent. 
+Productions are embedded, as much as possible, in the discussion of the constructs they represent.
 
 \LMHash{}
 A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification.
@@ -128,9 +128,9 @@
 The specifications of operators often involve statements such as $x$ $op$ $y$ is equivalent to the method invocation $x.op(y)$. Such specifications should be understood as a shorthand for:
 \begin{itemize}
 \item
- $x$ $op$ $y$ is equivalent to the method invocation $x.op^\prime(y)$, assuming the class of $x$ actually declared a non-operator method named $op^\prime$ defining the same function as the operator $op$. 
+ $x$ $op$ $y$ is equivalent to the method invocation $x.op^\prime(y)$, assuming the class of $x$ actually declared a non-operator method named $op^\prime$ defining the same function as the operator $op$.
  \end{itemize}
- 
+
  \rationale{This circumlocution is required because x.op(y), where op is an operator, is not legal syntax. However, it is painfully verbose, and we prefer to state this rule once here, and use a concise and clear notation across the specification.
  }
 
@@ -141,7 +141,7 @@
 References to otherwise unspecified names of program entities (such as classes or functions) are interpreted as the names of members of the Dart core library.
 
 \commentary{
-Examples would be the classes \code{Object} and \code{Type} representing the root of the class hierarchy and the reification of runtime types respectively. 
+Examples would be the classes \code{Object} and \code{Type} representing the root of the class hierarchy and the reification of runtime types respectively.
 }
 
 \section{Overview}
@@ -151,15 +151,15 @@
 Dart is a class-based, single-inheritance, pure object-oriented programming language. Dart is optionally typed (\ref{types}) and supports reified generics. The run-time type of every object is represented as an instance of class \code{Type}  which can be obtained by calling the getter  \code{runtimeType} declared in class \code{Object}, the root of the Dart class hierarchy.
 
 \LMHash{}
-Dart programs may be statically checked. The static checker will report some violations of the type rules, but such violations do not abort compilation or preclude execution. 
+Dart programs may be statically checked. The static checker will report some violations of the type rules, but such violations do not abort compilation or preclude execution.
 
 \LMHash{}
-Dart programs may be executed in one of two modes: production mode or checked mode. In production mode, static type annotations (\ref{staticTypes}) have absolutely no effect on execution with the exception of reflection and structural type tests. 
+Dart programs may be executed in one of two modes: production mode or checked mode. In production mode, static type annotations (\ref{staticTypes}) have absolutely no effect on execution with the exception of reflection and structural type tests.
 
 \commentary{
 Reflection, by definition, examines the program structure. If we provide reflective access to the type of a declaration, or to source code, it will inevitably produce results that depend on the types used in the underlying code.
 
-Type tests also examine the types in a program explicitly. Nevertheless, in most cases, these will not depend on type annotations. The exceptions to this rule are type tests involving function types. Function types are structural, and so depend on the types declared for their parameters and on their return types. 
+Type tests also examine the types in a program explicitly. Nevertheless, in most cases, these will not depend on type annotations. The exceptions to this rule are type tests involving function types. Function types are structural, and so depend on the types declared for their parameters and on their return types.
 }
 
 \LMHash{}
@@ -168,17 +168,17 @@
 \commentary{
 The coexistence between optional typing and reification is based on the following:
 \begin{enumerate}
-\item Reified type information reflects the types of objects at runtime and may always be queried by dynamic typechecking constructs (the analogs of instanceOf, casts, typecase etc. in other languages). Reified type information includes class declarations, the runtime type (aka class) of an object, and type arguments to constructors. 
-\item Static type annotations determine the types of variables and function declarations (including methods and constructors). 
+\item Reified type information reflects the types of objects at runtime and may always be queried by dynamic typechecking constructs (the analogs of instanceOf, casts, typecase etc. in other languages). Reified type information includes class declarations, the runtime type (aka class) of an object, and type arguments to constructors.
+\item Static type annotations determine the types of variables and function declarations (including methods and constructors).
 \item Production mode respects optional typing. Static type annotations do not affect runtime behavior.
 \item Checked mode utilizes static type annotations and dynamic type information aggressively yet selectively to provide early error detection during development.
 \end{enumerate}
 }
 
 \LMHash{}
-Dart programs are organized in a modular fashion into units called {\em libraries} (\ref{librariesAndScripts}). Libraries are units of encapsulation and may be mutually recursive. 
+Dart programs are organized in a modular fashion into units called {\em libraries} (\ref{librariesAndScripts}). Libraries are units of encapsulation and may be mutually recursive.
 
-\commentary{However they are not first class.  To get multiple copies of a library running simultaneously, one needs to spawn an isolate. 
+\commentary{However they are not first class.  To get multiple copies of a library running simultaneously, one needs to spawn an isolate.
 }
 
 \subsection{Scoping}
@@ -192,7 +192,7 @@
 
 \commentary{It is therefore impossible, e.g.,  to define a class that declares a method and a field with the same name in Dart. Similarly one cannot declare a top-level function with the same name as a library variable or class.
   }
-  
+
 \LMHash{}
 It is a compile-time error if there is more than one entity with the same name declared in the same scope.
 
@@ -201,11 +201,11 @@
 }
 
 \LMHash{}
-Dart is lexically scoped.    Scopes may nest.  A name or declaration $d$ is {\em available in scope} $S$ if $d$ is in the namespace induced by $S$ or if $d$ is available in the lexically enclosing scope of $S$. We  say that a name or declaration $d$ is {\em in scope} if $d$ is available in the current scope. 
+Dart is lexically scoped.    Scopes may nest.  A name or declaration $d$ is {\em available in scope} $S$ if $d$ is in the namespace induced by $S$ or if $d$ is available in the lexically enclosing scope of $S$. We  say that a name or declaration $d$ is {\em in scope} if $d$ is available in the current scope.
 
 
 \LMHash{}
-If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$. 
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
 
 \commentary {
 A consequence of these rules is that it is possible to hide a type with a method or variable.
@@ -251,8 +251,8 @@
 
 These considerations become even more important if one introduces constructs such as nested classes, which might be considered in future versions of the language.
 
-Good tooling should of course endeavor to inform programmers of such situations (discreetly). For example, an identifier that is both inherited and lexically visible could be highlighted (via underlining or colorization). Better yet, tight integration of source control with language aware tools would detect such changes when they occur. 
- 
+Good tooling should of course endeavor to inform programmers of such situations (discreetly). For example, an identifier that is both inherited and lexically visible could be highlighted (via underlining or colorization). Better yet, tight integration of source control with language aware tools would detect such changes when they occur.
+
 }
 
 
@@ -263,7 +263,7 @@
 
 \LMHash{}
 Dart supports two levels of privacy: {\em public} and {\em private}.  A declaration is {\em private} iff its name is private, otherwise it is {\em public.}  A  name $q$ is private iff any one of the identifiers that comprise $q$ is private,  otherwise it is {\em public.}  An identifier is private iff it
-begins with an underscore (the \_ character) otherwise it is {\em public.} 
+begins with an underscore (the \_ character) otherwise it is {\em public.}
 
 \LMHash{}
 A declaration $m$ is {\em accessible to library $L$}  if $m$ is declared in $L$ or if $m$ is public.
@@ -273,7 +273,7 @@
 }
 
 \LMHash{}
-Privacy applies only to declarations within a library, not to library declarations themselves. 
+Privacy applies only to declarations within a library, not to library declarations themselves.
 
 \rationale{Libraries do not reference each other by name and so the idea of a private library is meaningless.
 Thus, if the name of a library begins with an underscore, it has no effect on the accessibility of the library or its members.
@@ -290,7 +290,7 @@
 Dart code is always single threaded. There is no shared-state concurrency in Dart. Concurrency is supported via actor-like entities called {\em isolates}.
 
 \LMHash{}
-An isolate is a unit of concurrency. It has its own memory and its own thread of control. Isolates communicate by message passing (\ref{sendingMessages}). No state is ever shared between isolates. Isolates are created by spawning (\ref{spawningAnIsolate}). 
+An isolate is a unit of concurrency. It has its own memory and its own thread of control. Isolates communicate by message passing (\ref{sendingMessages}). No state is ever shared between isolates. Isolates are created by spawning (\ref{spawningAnIsolate}).
 
 
 \section{Errors and Warnings}
@@ -300,7 +300,7 @@
 This specification distinguishes between several kinds of errors.
 
 \LMHash{}
-{\em Compile-time errors} are errors that preclude execution. A compile-time error must be reported by a Dart compiler before the erroneous code is executed. 
+{\em Compile-time errors} are errors that preclude execution. A compile-time error must be reported by a Dart compiler before the erroneous code is executed.
 
 \rationale{A Dart implementation has considerable freedom as to when compilation takes place. Modern programming language implementations often interleave compilation and execution, so that compilation of a method may be delayed, e.g.,  until it is first invoked. Consequently, compile-time errors in a method $m$ may be reported as late as the time of $m$'s first invocation.
 
@@ -312,8 +312,8 @@
 \LMHash{}
 If an uncaught compile-time error occurs within the code of a running isolate $A$, $A$ is immediately suspended.  The only circumstance where a compile-time error could be caught would be via code run reflectively, where the mirror system can catch it.
 
-\rationale{Typically, once a compile-time error is thrown and $A$ is suspended, $A$ will then be terminated. However, this depends on the overall environment. 
-A Dart engine runs in the context of an {\em embedder}, 
+\rationale{Typically, once a compile-time error is thrown and $A$ is suspended, $A$ will then be terminated. However, this depends on the overall environment.
+A Dart engine runs in the context of an {\em embedder},
 a program that interfaces between the engine and the surrounding computing environment. The embedder will often be a web browser, but need not be; it may be a C++ program on the server for example. When an isolate fails with a compile-time error as described above, control returns to the embedder, along with an exception describing the problem.  This is necessary so that the embedder can clean up resources etc. It is then the embedder's decision whether to terminate the isolate or not.
 }
 
@@ -324,23 +324,23 @@
 {\em Dynamic type errors} are type errors reported in checked mode.
 
 \LMHash{}
-{\em Run-time errors} are exceptions raised during execution. Whenever we say that an exception $ex$ is {\em raised} or {\em thrown}, we mean that a throw expression  (\ref{throw}) of the form: \code{\THROW{} $ex$;} was implicitly evaluated or that a rethrow statement (\ref{rethrow}) of the form \code{\RETHROW} was executed. When we say that {\em a} $C$ {\em is thrown}, where $C$ is a class, we mean that an instance of class $C$ is thrown.
+{\em Run-time errors} are exceptions raised during execution. Whenever we say that an exception $ex$ is {\em raised} or {\em thrown}, we mean that a throw expression  (\ref{throw}) of the form: \code{\THROW{} $ex$;} was implicitly evaluated or that a rethrow statement (\ref{rethrow}) of the form \code{\RETHROW} was executed. When we say that {\em a} $C$ {\em is thrown}, where $C$ is a class, we mean that an instance of class $C$ is thrown. When we say that a stream raises an exception, we mean that an exception occurred while computing the value(s) of the stream.
 
 \LMHash{}
-If an uncaught exception is thrown by a running isolate $A$, $A$ is immediately suspended. 
+If an uncaught exception is thrown by a running isolate $A$, $A$ is immediately suspended.
 
 
 \section{Variables}
 \LMLabel{variables}
 
 \LMHash{}
-Variables are storage locations in memory.  
+Variables are storage locations in memory.
 
 \begin{grammar}
 {\bf variableDeclaration:}
       declaredIdentifier (`,' identifier)*
       .
-      
+
 {\bf declaredIdentifier:}
       metadata finalConstVarOrType identifier
     .
@@ -349,7 +349,7 @@
            \CONST{} type?;
 	varOrType
     .
-    
+
  {\bf varOrType:}\VAR{};
 	type
     .
@@ -361,7 +361,7 @@
 {\bf initializedIdentifier:}
       identifier (`=' expression)? % could do top-level here
     .
-    
+
 {\bf initializedIdentifierList:}
       initializedIdentifier (`,' initializedIdentifier)*
     .
@@ -375,22 +375,22 @@
 A variable that has not been initialized has the initial value \NULL{} (\ref{null}).
 
 \LMHash{}
-A variable declared at the top-level of a library is referred to as either a {\em library variable} or simply a top-level variable. 
+A variable declared at the top-level of a library is referred to as either a {\em library variable} or simply a top-level variable.
 
 \LMHash{}
-A {\em static variable} is a variable that is not associated with a particular instance, but rather with an entire library or class.  Static variables include library variables and class variables. Class variables are variables whose declaration is immediately nested inside a class declaration and includes the modifier \STATIC{}. A library variable is implicitly static. It is a compile-time error to preface a top-level variable declaration with the built-in identifier  (\ref{identifierReference}) \STATIC{}.  
+A {\em static variable} is a variable that is not associated with a particular instance, but rather with an entire library or class.  Static variables include library variables and class variables. Class variables are variables whose declaration is immediately nested inside a class declaration and includes the modifier \STATIC{}. A library variable is implicitly static. It is a compile-time error to preface a top-level variable declaration with the built-in identifier  (\ref{identifierReference}) \STATIC{}.
 
 \LMHash{}
-Static variable declarations are initialized lazily. When a static variable $v$ is read, iff it has not yet been assigned,  it is set to the result of evaluating its initializer. The precise rules are given in section \ref{evaluationOfImplicitVariableGetters}. 
+Static variable declarations are initialized lazily. When a static variable $v$ is read, iff it has not yet been assigned,  it is set to the result of evaluating its initializer. The precise rules are given in section \ref{evaluationOfImplicitVariableGetters}.
 
 \rationale{The lazy semantics are given because we do not want a language where one tends to define expensive initialization computations, causing long application startup times. This is especially crucial for Dart, which must support the coding of  client applications.
 }
 
 \LMHash{}
-A {\em final variable} is a variable whose binding is fixed upon initialization; a final variable $v$ will always refer to the same object after $v$ has been initialized. The declaration of a final variable must  include the modifier \FINAL{}. 
+A {\em final variable} is a variable whose binding is fixed upon initialization; a final variable $v$ will always refer to the same object after $v$ has been initialized. The declaration of a final variable must  include the modifier \FINAL{}.
 
 \LMHash{}
-It is a static warning if a final instance variable that has been initialized at its point of declaration  is  also initialized in a constructor. 
+It is a static warning if a final instance variable that has been initialized at its point of declaration  is  also initialized in a constructor.
 % It is a static warning if a final instance variable that has been initialized by means of an initializing formal of a constructor is  also initialized elsewhere in the same constructor.
 It is a compile-time error if a local variable $v$ is final and $v$ is not initialized at its point of declaration.
 
@@ -410,24 +410,24 @@
 We say that a variable $v$ is {\em potentially mutated} in some scope $s$ if $v$ is not final or constant and an assignment to $v$ occurs in $s$.
 
 \LMHash{}
-If a variable declaration does not explicitly specify a type, the type of the declared variable(s) is  \DYNAMIC{}, the unknown type (\ref{typeDynamic}). 
+If a variable declaration does not explicitly specify a type, the type of the declared variable(s) is  \DYNAMIC{}, the unknown type (\ref{typeDynamic}).
 
 \LMHash{}
 A variable is {\em mutable} if it is not final.
 Static and instance variable declarations always induce implicit getters. If the variable is mutable it also introduces an implicit setter.
-The scope into which the implicit getters and setters are introduced depends on the kind of variable declaration involved. 
+The scope into which the implicit getters and setters are introduced depends on the kind of variable declaration involved.
 
 \LMHash{}
-A library variable introduces a getter into the top level scope of the enclosing library. A static class variable introduces a static getter into the immediately enclosing class. An instance variable introduces an instance getter into the immediately enclosing class. 
+A library variable introduces a getter into the top level scope of the enclosing library. A static class variable introduces a static getter into the immediately enclosing class. An instance variable introduces an instance getter into the immediately enclosing class.
 
 \LMHash{}
-A mutable library variable introduces a setter into the top level scope of the enclosing library. A mutable static class variable introduces a static setter into the immediately enclosing class. A mutable instance variable introduces an instance setter into the immediately enclosing class. 
+A mutable library variable introduces a setter into the top level scope of the enclosing library. A mutable static class variable introduces a static setter into the immediately enclosing class. A mutable instance variable introduces an instance setter into the immediately enclosing class.
 
 \LMHash{}
 Local variables are added to the innermost enclosing scope.  They do not induce getters and setters.  A local variable may only be referenced at a source code location that is after its initializer, if any, is complete, or a compile-time error occurs.  The error may be reported either at the point where the premature reference occurs, or at the variable declaration.
 
 \rationale {
-We allow the error to be reported at the declaration to allow implementations to avoid an extra processing phase. 
+We allow the error to be reported at the declaration to allow implementations to avoid an extra processing phase.
 }
 
 \commentary{
@@ -438,7 +438,7 @@
 \VAR{} x = 0;
 
 f(y) \{
-  \VAR{} z = x; // compile-time error 
+  \VAR{} z = x; // compile-time error
   if (y) \{
     x = x + 1; // two compile time errors
     print(x); // compile time error
@@ -455,7 +455,7 @@
 }
 
 \commentary {
-As another example  \code{\VAR{} x = 3, y = x;} is legal, because \code{x} is referenced after its initializer. 
+As another example  \code{\VAR{} x = 3, y = x;} is legal, because \code{x} is referenced after its initializer.
 
 A particularly perverse example involves a local variable name shadowing a type. This is possible because Dart has a single namespace for types, functions and variables.
 }
@@ -473,19 +473,19 @@
 }
 
 \rationale{
-As a rule, type annotations are ignored in production mode. However, we do 
+As a rule, type annotations are ignored in production mode. However, we do
  not want to allow programs to compile legally in one mode and not another, and in this extremely odd situation, that consideration takes precedence.
 }
 
 \end{dartCode}
 
-% the grammar does not support local getters and setters. The local var discussion does not seem to mention getters and setters based semantics. It simply discusses the creation of the variable, not its access. Access is either assignment or identifiers. Identifiers ignore the getter story. 
+% the grammar does not support local getters and setters. The local var discussion does not seem to mention getters and setters based semantics. It simply discusses the creation of the variable, not its access. Access is either assignment or identifiers. Identifiers ignore the getter story.
 
 \LMHash{}
 The following rules apply to all static and instance variables.
 
 \LMHash{}
-A  variable declaration  of one of the forms \code{$T$ $v$;},  \code{$T$ $v$ = $e$;} ,  \code{\CONST{} $T$ $v$ = $e$;}, \code{\FINAL{} $T$ $v$;}  or \code{\FINAL{} $T$ $v$ = $e$;} always induces an implicit  getter function (\ref{getters}) with signature 
+A  variable declaration  of one of the forms \code{$T$ $v$;},  \code{$T$ $v$ = $e$;} ,  \code{\CONST{} $T$ $v$ = $e$;}, \code{\FINAL{} $T$ $v$;}  or \code{\FINAL{} $T$ $v$ = $e$;} always induces an implicit  getter function (\ref{getters}) with signature
 
 $T$ \GET{} $v$
 
@@ -493,21 +493,21 @@
 
 
 \LMHash{}
-A  variable declaration  of one of the forms \code{\VAR{} $v$;},  \code{\VAR{} $v$ = $e$;} ,  \code{\CONST{} $v$ = $e$;}, \code{\FINAL{} $v$;} or \code{\FINAL{}  $v$ = $e$;}  always induces an implicit  getter function with signature 
+A  variable declaration  of one of the forms \code{\VAR{} $v$;},  \code{\VAR{} $v$ = $e$;} ,  \code{\CONST{} $v$ = $e$;}, \code{\FINAL{} $v$;} or \code{\FINAL{}  $v$ = $e$;}  always induces an implicit  getter function with signature
 
  \GET{} $v$
 
 whose  invocation evaluates as described below (\ref{evaluationOfImplicitVariableGetters}).
 
 \LMHash{}
-A non-final  variable declaration  of the form \code{{} $T$ $v$;} or the form  \code{$T$ $v$ = $e$;}   always induces an implicit  setter function (\ref{setters}) with signature 
+A non-final  variable declaration  of the form \code{{} $T$ $v$;} or the form  \code{$T$ $v$ = $e$;}   always induces an implicit  setter function (\ref{setters}) with signature
 
  \VOID{} \SET{} $v=(T$ $x)$
 
 whose execution sets the value of $v$ to the incoming argument $x$.
 
 \LMHash{}
-A  non-final variable declaration  of the form \code{\VAR{} $v$;} or the form  \code{\VAR{} $v$ = $e$;}   always induces an implicit  setter function with signature 
+A  non-final variable declaration  of the form \code{\VAR{} $v$;} or the form  \code{\VAR{} $v$ = $e$;}   always induces an implicit  setter function with signature
 
 \SET{} $v=(x)$
 
@@ -519,12 +519,12 @@
 
 \LMHash{}
 Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
-If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows: 
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
 \begin{itemize}
-\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$. 
-\item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.} 
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
+\item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
 Otherwise
-\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.  
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
 \end{itemize}
 
 
@@ -541,7 +541,7 @@
 {\bf functionSignature:}
     metadata returnType? identifier formalParameterList
     .
-    
+
 {\bf returnType:}
       \VOID{};
       type
@@ -558,7 +558,7 @@
 \end{grammar}
 
 \LMHash{}
-Functions include  function declarations (\ref{functionDeclarations}), methods (\ref{instanceMethods},  \ref{staticMethods}), getters  (\ref{getters}), setters  (\ref{setters}), constructors  (\ref{constructors}) and function literals  (\ref{functionExpressions}).  
+Functions include  function declarations (\ref{functionDeclarations}), methods (\ref{instanceMethods},  \ref{staticMethods}), getters  (\ref{getters}), setters  (\ref{setters}), constructors  (\ref{constructors}) and function literals  (\ref{functionExpressions}).
 
 \LMHash{}
 All functions have a signature and a body. The signature describes the formal parameters of the function, and possibly its name and return type.  A function body is either:
@@ -575,31 +575,31 @@
 \end{itemize}
 
 \LMHash{}
-A function is {\em asynchronous} if its body is marked with the \ASYNC{} or \ASYNC* modifier. Otherwise the function is {\em synchronous}. A function is a {\em generator} if its body is marked with the \SYNC* or \ASYNC* modifier.  
+A function is {\em asynchronous} if its body is marked with the \ASYNC{} or \ASYNC* modifier. Otherwise the function is {\em synchronous}. A function is a {\em generator} if its body is marked with the \SYNC* or \ASYNC* modifier.
 
 \commentary{
-Whether a function is synchronous or asynchronous is orthogonal to whether it is a generator or not. Generator functions are a sugar for functions that produce collections in a systematic way, by lazily applying a function that {\em generates} individual elements of a collection. Dart provides such a sugar in both the synchronous case, where one returns an iterable, and in the asynchronous case, where one returns a stream. Dart also allows both synchronous and asynchronous functions that produce a single value. 
+Whether a function is synchronous or asynchronous is orthogonal to whether it is a generator or not. Generator functions are a sugar for functions that produce collections in a systematic way, by lazily applying a function that {\em generates} individual elements of a collection. Dart provides such a sugar in both the synchronous case, where one returns an iterable, and in the asynchronous case, where one returns a stream. Dart also allows both synchronous and asynchronous functions that produce a single value.
 }
 
 \LMHash{}
 It is a compile-time error if an \ASYNC, \ASYNC* or \SYNC* modifier is attached to the body of a setter or constructor.
 
 \rationale{
-An asynchronous setter would be of little use, since setters can only be used in the context of an assignment (\ref{assignment}), and an assignment expression always evaluates to the value of the assignment's right hand side. If the setter actually did its work asynchronously, one might imagine that one would return a future that resolved to the assignment's right hand side after the setter did its work. However, this would require dynamic tests at every assignment, and so would be prohibitively expensive. 
+An asynchronous setter would be of little use, since setters can only be used in the context of an assignment (\ref{assignment}), and an assignment expression always evaluates to the value of the assignment's right hand side. If the setter actually did its work asynchronously, one might imagine that one would return a future that resolved to the assignment's right hand side after the setter did its work. However, this would require dynamic tests at every assignment, and so would be prohibitively expensive.
 
 An asynchronous constructor would, by definition, never return an instance of the class it purports to construct, but instead return a future. Calling such a beast via \NEW{} would be very confusing. If you need to produce an object asynchronously, use a method.
 
 One could allow modifiers for factories. A factory for \code{Future} could be modified by \ASYNC{}, a factory for \code{Stream} could be modified by \ASYNC* and a factory for \code{Iterable} could be modified by \SYNC*. No other scenario makes sense because the object returned by the factory would be of the wrong type. This situation is very unusual so it is not worth making an exception to the general rule for constructors in order to allow it.
 }
 \LMHash{}
-It is a static warning if the declared return type of a function marked \ASYNC{} may not be assigned to \code{Future}. It is a static warning if the declared return type of a function marked \SYNC* may not be assigned to \code{Iterable}. It is a static warning if the declared return type of  a function marked \ASYNC* may not be assigned to \code{Stream}.  
+It is a static warning if the declared return type of a function marked \ASYNC{} may not be assigned to \code{Future}. It is a static warning if the declared return type of a function marked \SYNC* may not be assigned to \code{Iterable}. It is a static warning if the declared return type of  a function marked \ASYNC* may not be assigned to \code{Stream}.
 
 \subsection{Function Declarations}
 \LMLabel{functionDeclarations}
 
 \LMHash{}
-A {\em function declaration} is a function that is neither a member of a class nor a function literal. Function declarations include {\em library functions}, which are function declarations 
-%(including getters and setters) 
+A {\em function declaration} is a function that is neither a member of a class nor a function literal. Function declarations include {\em library functions}, which are function declarations
+%(including getters and setters)
 at the top level of a library, and {\em local functions}, which are function declarations declared inside other functions. Library functions are often referred to simply as top-level functions.
 
 \LMHash{}
@@ -608,7 +608,7 @@
 \LMHash{}
 The scope of a library function is the scope of the enclosing library. The scope of a local function is  described in section \ref{localFunctionDeclaration}. In both cases, the name of the function is in scope in its formal parameter scope (\ref{formalParameters}).
 
-%A function declaration of the form  $T_0$ $id(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k} = d_k])\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k}= d_k])\{s\}$}, where $F$ is the function type alias (\ref{typedef}) \code{\TYPEDEF{} $T_0$ $F(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}])$}.  Likewise,  a function declaration of the form  $id(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k} = d_k])\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k} = d_k])\{s\}$}, where $F$ is the function type alias \code{\TYPEDEF{}  $F(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}])$}. 
+%A function declaration of the form  $T_0$ $id(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k} = d_k])\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k}= d_k])\{s\}$}, where $F$ is the function type alias (\ref{typedef}) \code{\TYPEDEF{} $T_0$ $F(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}])$}.  Likewise,  a function declaration of the form  $id(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k} = d_k])\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{n+k} = d_k])\{s\}$}, where $F$ is the function type alias \code{\TYPEDEF{}  $F(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}])$}.
 
 %\Q{We need to cover library getters as well.}
 
@@ -646,9 +646,9 @@
 The body of a function introduces a new scope known as the function's {\em  body scope}. The body scope of a function $f$  is enclosed  in the scope introduced by the formal parameter scope of $f$.
 
 
-%The formal parameter scope of a function maps the name of each formal parameter $p$ to the value $p$ is bound to. 
+%The formal parameter scope of a function maps the name of each formal parameter $p$ to the value $p$ is bound to.
 
-% The formal parameters of a function are processed in the enclosing scope of the function. 
+% The formal parameters of a function are processed in the enclosing scope of the function.
 % \commentary{this means that the parameters themselves may not be referenced within the formal parameter list.}
 
 \LMHash{}
@@ -663,7 +663,7 @@
 %}
 
 %\begin{grammar}
-%formalParameterList:     
+%formalParameterList:
 %      '(' restFormalParameter? ')';
 %      '(' namedFormalParameters ')';
  %     '(' normalFormalParameters normalFormalParameterTail? ')'
@@ -685,12 +685,12 @@
     .
 \end{grammar}
 
-%Formal parameters are always \FINAL{}.  
+%Formal parameters are always \FINAL{}.
 %\Q{We're awaiting some data on whether enforcing this would cause widespread pain.}
 %A formal parameter is always considered to be initialized.  \rationale{This is because it will always be initialized by the call - even if it is optional.}
 
 
-\subsubsection{Required Formals} 
+\subsubsection{Required Formals}
 \LMLabel{requiredFormals}
 
 \LMHash{}
@@ -719,7 +719,7 @@
 %\subsubsection{Rest Formals}
 %\LMLabel{restFormals}
 
-%A rest formal $R$ must be the last parameter in a formal parameter list.  If a  type $T$ is specified for $R$, it signifies that the type of $R$ is $T[]$. 
+%A rest formal $R$ must be the last parameter in a formal parameter list.  If a  type $T$ is specified for $R$, it signifies that the type of $R$ is $T[]$.
 
 %\begin{grammar}
 %restFormalParameter:
@@ -735,11 +735,11 @@
 \begin{grammar}
 {\bf defaultFormalParameter:}
       normalFormalParameter ('=' expression)?
-    .   
-        
+    .
+
 {\bf defaultNamedParameter:}
       normalFormalParameter ( `{\escapegrammar :}' expression)?
-    .   
+    .
 \end{grammar}
 
 \LMHash{}
@@ -750,7 +750,7 @@
 
 \rationale{
 The need for this  restriction is a direct consequence of the fact that naming and privacy are not orthogonal.
-If we allowed named parameters to begin with an underscore, they would be considered private and inaccessible to callers from outside the library where it was defined. If a method outside the library overrode a method with a private optional name, it would not be a subtype of the original method. The static checker would of course flag such situations, but the consequence would be that adding a private named formal would break clients outside the library in a way they could not easily correct. 
+If we allowed named parameters to begin with an underscore, they would be considered private and inaccessible to callers from outside the library where it was defined. If a method outside the library overrode a method with a private optional name, it would not be a subtype of the original method. The static checker would of course flag such situations, but the consequence would be that adding a private named formal would break clients outside the library in a way they could not easily correct.
 }
 
 \subsection{Type of a Function}
@@ -769,7 +769,7 @@
 Let $F$ be a function with required formal parameters $T_1$ $p_1 \ldots, T_n$ $p_n$, return type $T_0$ and named optional parameters $T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $ p_{n+k}$. Then the type of $F$ is $(T_1 ,\ldots, T_n, \{T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$  $p_{n+k}\}) \rightarrow T_0$.
 
 \LMHash{}
-The run time type of a function object always implements the class \cd{Function}. 
+The run time type of a function object always implements the class \cd{Function}.
 
 \commentary{
 One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type.
@@ -785,10 +785,10 @@
 \LMLabel{externalFunctions}
 
 \LMHash{}
-An {\em external function} is a function whose body is provided separately from its declaration. An external function may be a top-level function (\ref{librariesAndScripts}), a method (\ref{instanceMethods}, \ref{staticMethods}), a getter (\ref{getters}), a setter (\ref{setters}) or a non-redirecting constructor (\ref{generativeConstructors}, \ref{factories}). External functions are introduced via the built-in identifier \EXTERNAL{}  (\ref{identifierReference}) followed by the function signature.  
+An {\em external function} is a function whose body is provided separately from its declaration. An external function may be a top-level function (\ref{librariesAndScripts}), a method (\ref{instanceMethods}, \ref{staticMethods}), a getter (\ref{getters}), a setter (\ref{setters}) or a non-redirecting constructor (\ref{generativeConstructors}, \ref{factories}). External functions are introduced via the built-in identifier \EXTERNAL{}  (\ref{identifierReference}) followed by the function signature.
 
 \rationale{
-External functions allow us to introduce  type information for code that is not statically known to the Dart compiler. 
+External functions allow us to introduce  type information for code that is not statically known to the Dart compiler.
 }
 
 \commentary{
@@ -811,10 +811,10 @@
 {\bf classDefinition:}
 metadata \ABSTRACT{}?  \CLASS{} identifier typeParameters? (superclass mixins?)? interfaces? \\
        `\{' (metadata classMemberDefinition)* `\}';
-       
+
 metadata \ABSTRACT{}?  \CLASS{} mixinApplicationClass
     .
-    
+
 {\bf mixins:}
   \WITH{} typeList
   .
@@ -860,7 +860,7 @@
 
 A class has several scopes:
 \begin{itemize}
-\item A {\em type-parameter scope}, which is empty if the class is not generic (\ref{generics}).  The enclosing scope of the type-parameter scope of a class is the enclosing scope of the class declaration. 
+\item A {\em type-parameter scope}, which is empty if the class is not generic (\ref{generics}).  The enclosing scope of the type-parameter scope of a class is the enclosing scope of the class declaration.
 \item A {\em static scope}. The enclosing scope of the static scope of a  class is the type parameter scope (\ref{generics}) of the class.
 \item  An {\em instance scope}.
 The enclosing scope of a class' instance scope is the class' static scope.
@@ -873,14 +873,14 @@
 
 \LMHash{}
 Every class has a single superclass  except class \code{Object} which has no superclass. A class may implement a number of interfaces
-%, either 
+%, either
 by declaring them in its implements clause  (\ref{superinterfaces}).
 % or via interface injection declarations (\ref{interfaceInjection}) outside the class declaration
 
 
 \LMHash{}
-An {\em abstract class} is 
-%either 
+An {\em abstract class} is
+%either
 a class that is explicitly declared with the  \ABSTRACT{}  modifier, either by means of a class declaration or via a type alias (\ref{typedef}) for a mixin application (\ref{mixinApplication}). A {\em concrete class} is a class that is not abstract.
 %, or a class that declares at least one abstract method  (\ref{abstractInstanceMembers}).
 
@@ -900,7 +900,7 @@
 \LMHash{}
  It is a compile-time error if a class declares two members of the same name.
  %, except that a getter and a setter may be declared with the same name provided both are instance members or both are static members.
-It is a compile-time error if a class has an instance member and a static member  with the same name. 
+It is a compile-time error if a class has an instance member and a static member  with the same name.
 % It is a compile-time error if a generic (\ref{generics}) class declares a member with the same name as one of its type parameters.
 
 \commentary{Here are simple examples, that illustrate the difference between ``has a member'' and ``declares a member''. For example, \code{B} {\em declares} one member named \code{f}, but {\em has} two such members. The rules of inheritance determine what members a class has.
@@ -915,11 +915,11 @@
 
 \CLASS{} B \EXTENDS{} A \{
   int i = 1; //  getter i and setter i= override versions from A
-  \STATIC{} j; // compile-time error: static getter \& setter conflict with 
+  \STATIC{} j; // compile-time error: static getter \& setter conflict with
   //instance getter \& setter
-  
+
   /* compile-time error: static method conflicts with instance method */
-  \STATIC{} f(x) =$>$ 3; 
+  \STATIC{} f(x) =$>$ 3;
 \}
 \end{dartCode}
 
@@ -935,7 +935,7 @@
 %make these warnings if possible
 
 \LMHash{}
-It is a static warning if an instance method $m_1$ overrides  (\ref{inheritanceAndOverriding}) an instance member $m_2$ and  $m_1$ has a greater number of required parameters than $m_2$. It is a static warning if an instance method $m_1$ overrides  an instance member $m_2$ and  $m_1$ has fewer positional parameters than $m_2$.  It is a static warning if an instance method $m_1$ overrides  an instance member $m_2$ and  $m_1$ does not declare all the named parameters declared by $m_2$. 
+It is a static warning if an instance method $m_1$ overrides  (\ref{inheritanceAndOverriding}) an instance member $m_2$ and  $m_1$ has a greater number of required parameters than $m_2$. It is a static warning if an instance method $m_1$ overrides  an instance member $m_2$ and  $m_1$ has fewer positional parameters than $m_2$.  It is a static warning if an instance method $m_1$ overrides  an instance member $m_2$ and  $m_1$ does not declare all the named parameters declared by $m_2$.
 
 % not quite right. It should be ok to override a method that requires N parameters with one that requires M < N but accepts the others as optional.
 
@@ -949,13 +949,13 @@
 \LMLabel{operators}
 
 \LMHash{}
-{\em Operators} are instance methods with special names. 
+{\em Operators} are instance methods with special names.
 
 \begin{grammar}
 {\bf operatorSignature:}
        returnType? \OPERATOR{} operator formalParameterList
        .
-       
+
  {\bf operator:}`\~{}';
       binaryOperator;
       `[' `]' ;
@@ -979,10 +979,10 @@
 
 
 \LMHash{}
-It is a compile-time error if the arity of the user-declared operator \code{[]=} is not 2. It is a compile-time error if the arity of a user-declared operator with one of the names:  \code{ $<$, $>$, $<$=, $>$=, ==, -, +,  \~{}/, /, *, \%, $|$, \^{}, \&, $<<$, $>>$, []} is not 1. It is a compile-time error if the arity of the user-declared operator  \code{-} is not 0 or 1. 
+It is a compile-time error if the arity of the user-declared operator \code{[]=} is not 2. It is a compile-time error if the arity of a user-declared operator with one of the names:  \code{ $<$, $>$, $<$=, $>$=, ==, -, +,  \~{}/, /, *, \%, $|$, \^{}, \&, $<<$, $>>$, []} is not 1. It is a compile-time error if the arity of the user-declared operator  \code{-} is not 0 or 1.
 
 \commentary{
-The \code{-} operator is unique in that two overloaded versions are permitted. If the operator has no arguments, it denotes unary minus. If it has an argument, it denotes binary subtraction. 
+The \code{-} operator is unique in that two overloaded versions are permitted. If the operator has no arguments, it denotes unary minus. If it has an argument, it denotes binary subtraction.
 }
 
 \LMHash{}
@@ -993,7 +993,7 @@
 }
 
 \LMHash{}
-It is a compile-time error if the arity of the user-declared operator  \code{ \~{}} is not 0. 
+It is a compile-time error if the arity of the user-declared operator  \code{ \~{}} is not 0.
 
 \LMHash{}
 It is a compile-time error to declare an optional parameter in an operator.
@@ -1004,7 +1004,7 @@
 % add rationale: return in []= methods will have no effect, a the expression always returns its second argument (the RHS of the assignment, for consistency with assignment in general). So it's best to enforce this by declaring the method to be void, even though the expression that uses it returns an object with the type of the RHS, as described in \ref{assignment}.
 
 
-\subsection{Getters} 
+\subsection{Getters}
 \LMLabel{getters}
 
 \LMHash{}
@@ -1012,7 +1012,7 @@
 
 \begin{grammar}
 {\bf getterSignature:}
-       returnType? \GET{} identifier 
+       returnType? \GET{} identifier
 .
 \end{grammar}
 
@@ -1033,13 +1033,13 @@
 It is a compile-time error if a class has both a getter and a method with the same name. This restriction holds regardless of whether the getter is defined explicitly or implicitly, or whether the getter or the method are inherited or not.
 
 \commentary{
-This implies that a getter can never override a method, and a method can never override a getter or field. 
+This implies that a getter can never override a method, and a method can never override a getter or field.
 }
 
 \LMHash{}
 It is a static warning if the return type of a getter is \VOID.
-It is a static warning if a getter $m_1$ overrides  (\ref{inheritanceAndOverriding}) a getter 
-$m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.   
+It is a static warning if a getter $m_1$ overrides  (\ref{inheritanceAndOverriding}) a getter
+$m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$.
 
 \LMHash{}
 It is a static warning if a class  declares a static getter named $v$ and also has a non-static setter named $v=$. It is a static warning if a class $C$ declares an instance getter named $v$ and an accessible static member named $v$ or $v=$ is declared in a superclass of $C$. These warnings must be issued regardless of whether the getters or setters are declared explicitly or implicitly.
@@ -1076,7 +1076,7 @@
 
 \LMHash{}
 It is a static warning if a setter declares a return type other than \VOID{}.
-It is a static warning if a setter $m_1$ overrides  (\ref{inheritanceAndOverriding}) a setter $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$. It is a static warning if a class has a setter named $v=$ with argument type $T$ and a getter named $v$ with return type $S$, and $T$ may not be assigned to $S$. 
+It is a static warning if a setter $m_1$ overrides  (\ref{inheritanceAndOverriding}) a setter $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$. It is a static warning if a class has a setter named $v=$ with argument type $T$ and a getter named $v$ with return type $S$, and $T$ may not be assigned to $S$.
 
 \LMHash{}
 It is a static warning if a class  declares a static setter named $v=$ and also has a non-static member named $v$. It is a static warning if a class $C$ declares an instance setter named $v=$ and an accessible static member named $v=$ or $v$ is declared in a superclass of $C$.
@@ -1114,7 +1114,7 @@
 \LMHash{}
 It is a static warning if an abstract member $m$ is declared or inherited in a concrete class $C$ unless:
 \begin{itemize}
-\item  $m$ overrides a concrete member, or 
+\item  $m$ overrides a concrete member, or
 \item $C$ has a \cd{noSuchMethod()} method distinct from the one declared in class \cd{Object}.
 \end{itemize}
 
@@ -1150,20 +1150,20 @@
 The notion of a constant instance variable is subtle and confusing to programmers.
 An instance variable is intended to vary per instance. A constant instance variable would have the same value for all instances, and as such is already a dubious idea.
 
-The language could interpret const instance variable declarations as instance getters that return a constant.  However, a constant instance variable could not be treated as a true compile time constant, as its getter would be subject to overriding.   
+The language could interpret const instance variable declarations as instance getters that return a constant.  However, a constant instance variable could not be treated as a true compile time constant, as its getter would be subject to overriding.
 
 Given that the value does not depend on  the instance, it is better to use a static class variable.
 An instance getter for it can always be defined manually if desired.
 }
 
 
-%An instance variable declaration of one of the forms \code{$T$ $v$;}, \code{\FINAL{} $T$ $v$;} ,  \code{$T$ $v$ = $e$;} ,  \code{\CONST{} $T$ $v$ = $e$;} or \code{\FINAL{} $T$ $v$ = $e$;}  always induces an implicit getter function (\ref{getters}) with signature 
+%An instance variable declaration of one of the forms \code{$T$ $v$;}, \code{\FINAL{} $T$ $v$;} ,  \code{$T$ $v$ = $e$;} ,  \code{\CONST{} $T$ $v$ = $e$;} or \code{\FINAL{} $T$ $v$ = $e$;}  always induces an implicit getter function (\ref{getters}) with signature
 
 %$T$ \GET{} $v$
 
 %whose invocation evaluates to the value stored in $v$.
 
-%An instance variable declaration  of one of the forms \code{\VAR{} $v$;}, \code{\FINAL{} $v$;}, \code{\VAR{} $v$ = $e$;} ,  \code{\CONST{} $v$ = $e$;} or \code{\FINAL{} $v$ = $e$;}   always induces an implicit getter function with signature 
+%An instance variable declaration  of one of the forms \code{\VAR{} $v$;}, \code{\FINAL{} $v$;}, \code{\VAR{} $v$ = $e$;} ,  \code{\CONST{} $v$ = $e$;} or \code{\FINAL{} $v$ = $e$;}   always induces an implicit getter function with signature
 
 %\GET{} $v$
 
@@ -1171,13 +1171,13 @@
 
 %\commentary{Getters are introduced for all instance and static variables (\ref{staticVariables}), regardless of whether they are const/final or not.}
 
-%A non-final instance variable declaration  of the form \code{$T$ $v$;} or the form  \code{$T$ $v$ = $e$;}   always induces an implicit setter function (\ref{setters}) with signature 
+%A non-final instance variable declaration  of the form \code{$T$ $v$;} or the form  \code{$T$ $v$ = $e$;}   always induces an implicit setter function (\ref{setters}) with signature
 
 %\VOID{} \SET{} $v=(T$ $x)$
 
 %whose execution sets the value of $v$ to the incoming argument $x$.
 
-%A non-final instance variable declaration  of the form \code{\VAR{} $v$;} or the form  \code{\VAR{} $v$ = $e$;}   always induces an implicit setter function with signature 
+%A non-final instance variable declaration  of the form \code{\VAR{} $v$;} or the form  \code{\VAR{} $v$ = $e$;}   always induces an implicit setter function with signature
 
 %\SET{} $v=(x)$
 
@@ -1190,15 +1190,15 @@
 \LMLabel{constructors}
 
 \LMHash{}
-A {\em constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to produce objects. Constructors may be generative (\ref{generativeConstructors}) or they may be factories (\ref{factories}). 
+A {\em constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to produce objects. Constructors may be generative (\ref{generativeConstructors}) or they may be factories (\ref{factories}).
 
 \LMHash{}
-A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier $id$. It is a compile-time error if $id$ is the name of a member  declared in the immediately enclosing class. It is a compile-time error if the name of a  constructor is not a constructor name. 
+A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier $id$. It is a compile-time error if $id$ is the name of a member  declared in the immediately enclosing class. It is a compile-time error if the name of a  constructor is not a constructor name.
 
 
 % In what scope do constructors go? The simple names of named constructors go  in the static scope of the class. Unnamed ones go nowhere, but we use the class name to refer to them; the class name could also in the static scope of the class as well to prevent weird errors, or we could ban it explicitly and avoiding duplication. Similarly, the instance scope could contain the constructor names and class name, or we could have special rules to prevent collisions between instance members and constructors or the class.
 
-% The enclosing scope of a generative constructor is the instance scope of the class in which it is declared (but what about redirecting?) 
+% The enclosing scope of a generative constructor is the instance scope of the class in which it is declared (but what about redirecting?)
 
 \LMHash{}
 Iff no constructor is specified for a class $C$, it implicitly has a default constructor \code{C() : \SUPER{}() \{\}}, unless $C$ is class \code{Object}.
@@ -1216,7 +1216,7 @@
  \end{grammar}
 
 \LMHash{}
-A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters. A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal. An {\em initializing formal} has the form \code{\THIS{}.id}, where \code{id} is the name of an instance variable of the immediately enclosing class.  It is a compile-time error if \code{id} is not an instance variable of the immediately enclosing class. It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor. 
+A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters. A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal. An {\em initializing formal} has the form \code{\THIS{}.id}, where \code{id} is the name of an instance variable of the immediately enclosing class.  It is a compile-time error if \code{id} is not an instance variable of the immediately enclosing class. It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor.
 
 \LMHash{}
 If an explicit type is attached to the initializing formal, that is its static type. Otherwise, the type of an initializing formal named \code{id} is $T_{id}$, where $T_{id}$ is the type of the field named \code{id} in the immediately enclosing class. It is a static warning if the static type of \code{id} is not assignable to $T_{id}$.
@@ -1242,14 +1242,14 @@
 \commentary{is legal, and has the same effect as}
 
 \begin{dartCode}
-class A \{ 
+class A \{
   int x;
   A([int x]): this.x = x;
 \}
 \end{dartCode}
 
 \LMHash{}
-A {\em fresh instance} is an instance whose identity  is distinct from any previously allocated instance of its class. A generative constructor always operates on a fresh instance of its immediately enclosing class. 
+A {\em fresh instance} is an instance whose identity  is distinct from any previously allocated instance of its class. A generative constructor always operates on a fresh instance of its immediately enclosing class.
 
 \commentary{
 The above holds if the constructor is actually run, as it is by \NEW{}. If a constructor $c$ is referenced by \CONST{}, $c$ may not be run; instead, a canonical object may be looked up. See the section on instance creation (\ref{instanceCreation}).
@@ -1284,7 +1284,7 @@
 \begin{itemize}
 \item A {\em superinitializer} identifies a {\em superconstructor} - that is, a specific  constructor of the superclass.  Execution of the superinitializer causes the initializer list of the superconstructor to be executed.
 
-\item An {\em instance variable initializer} assigns a value to an individual instance variable. 
+\item An {\em instance variable initializer} assigns a value to an individual instance variable.
 \end{itemize}
 
 \begin{grammar}
@@ -1297,7 +1297,7 @@
       \SUPER{} `{\escapegrammar .}' identifier arguments;
      fieldInitializer
     .
-    
+
    {\bf  fieldInitializer:}
       (\THIS{} `{\escapegrammar .}')? identifier `=' conditionalExpression cascadeSection*
     .
@@ -1306,35 +1306,35 @@
 
 \LMHash{}
 Let $k$ be a generative constructor.  Then $k$ may include at most one  superinitializer in its initializer list or a compile-time error occurs. If no superinitializer is provided, an implicit superinitializer of the form \SUPER{}() is added at the end of $k$'s initializer list, unless the enclosing class is class \code{Object}. It is a compile-time error if more than one initializer corresponding to a given instance variable appears in $k$'s initializer list. It is a compile-time error if $k$'s initializer list contains an initializer for a variable that is initialized by means of an initializing formal of $k$. % It is a compile-time error if  $k$'s initializer list contains an initializer for a final variable $f$ whose declaration includes an initialization expression.
- 
+
 \LMHash{}
 Each final instance variable $f$ declared in the immediately enclosing class must have an initializer in $k$'s initializer list unless it has already been initialized by one of the following means:
  \begin{itemize}
  \item Initialization at the declaration of $f$.
  \item Initialization by  means of an initializing formal of $k$.
  \end{itemize}
- 
+
 or a static warning occurs. It is a compile-time error if $k$'s initializer list contains an initializer for a variable that is not an instance variable declared in the immediately surrounding class.
 
- 
-\commentary{The  initializer list may of course contain an initializer for any  instance variable declared by the immediately surrounding class, even if it is not final. 
+
+\commentary{The  initializer list may of course contain an initializer for any  instance variable declared by the immediately surrounding class, even if it is not final.
 }
 
 \LMHash{}
- It is a compile-time error if a  generative constructor of class \code{Object} includes a superinitializer. 
+ It is a compile-time error if a  generative constructor of class \code{Object} includes a superinitializer.
 
 \LMHash{}
-Execution of a generative constructor $k$ is always done with respect to a set of bindings for its formal parameters and with  \THIS{} bound to a fresh instance $i$ and the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$. 
+Execution of a generative constructor $k$ is always done with respect to a set of bindings for its formal parameters and with  \THIS{} bound to a fresh instance $i$ and the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$.
 
 \commentary{These bindings are usually determined by the instance creation expression that invoked the constructor (directly or indirectly). However, they may also be determined by a reflective call,.
 }
 
 \LMHash{}
-If $k$ is redirecting then its redirect clause has the form 
+If $k$ is redirecting then its redirect clause has the form
 
-\THIS{}$.g(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\THIS{}$.g(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
-where $g$ identifies another  generative constructor of the immediately surrounding class. Then execution of $k$ proceeds by evaluating the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, and then executing $g$ with respect to the bindings resulting from the evaluation of $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ and with  \THIS{} bound to $i$ and the type parameters of the immediately enclosing class bound to $V_1, \ldots , V_m$. 
+where $g$ identifies another  generative constructor of the immediately surrounding class. Then execution of $k$ proceeds by evaluating the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, and then executing $g$ with respect to the bindings resulting from the evaluation of $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ and with  \THIS{} bound to $i$ and the type parameters of the immediately enclosing class bound to $V_1, \ldots , V_m$.
 
 \LMHash{}
 Otherwise, execution  proceeds as follows:
@@ -1342,7 +1342,7 @@
 \LMHash{}
 %First, a fresh instance (\ref{generativeConstructors}) $i$ of the immediately enclosing class is allocated.  Next, the instance variable declarations of the immediately enclosing class are visited in the order they appear in the program text. For each such declaration $d$, if $d$ has the form  \code{$finalConstVarOrType$ $v$ = $e$; } then the instance variable $v$ of $i$ is bound to the value of $e$ (which is necessarily a compile-time constant).
 %Next, a
-Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text.  
+Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text.
 % In fact, this order is unobservable; this could be done any time prior to running the body, since
 % these only effect \THIS{}.
 Then, $k$'s  initializers are executed in the order they appear in the program.
@@ -1353,7 +1353,7 @@
 After all the initializers  have completed, the body of $k$ is executed  in a scope where \THIS{} is bound to $i$. Execution of the body begins with execution of the body of the superconstructor  with \THIS{} bound to $i$, the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$ and the formal parameters bindings determined by the argument list of the superinitializer of $k$.
 
 \rationale{
-This process ensures that no uninitialized final field is ever seen by code. Note that \THIS{} is not in scope on the right hand side of an initializer (see \ref{this}) so no instance method can execute during initialization: an instance method cannot be directly invoked, nor can  \THIS{} be passed into any other code being invoked in the initializer. 
+This process ensures that no uninitialized final field is ever seen by code. Note that \THIS{} is not in scope on the right hand side of an initializer (see \ref{this}) so no instance method can execute during initialization: an instance method cannot be directly invoked, nor can  \THIS{} be passed into any other code being invoked in the initializer.
 }
 
 \LMHash{}
@@ -1363,14 +1363,14 @@
 First, the expression $e$ is evaluated to an object $o$. Then, the instance variable $v$ of the object denoted by \THIS{} is bound to $o$, unless $v$ is a final variable that has already been initialized, in which case a runtime error occurs. In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type of the field $v$.
 
 \LMHash{}
-An initializer of the form \code{$v$ = $e$} is equivalent to an initializer of the form  \code{\THIS{}.$v$ = $e$}. 
+An initializer of the form \code{$v$ = $e$} is equivalent to an initializer of the form  \code{\THIS{}.$v$ = $e$}.
 
 \LMHash{}
-Execution of a superinitializer of the form 
+Execution of a superinitializer of the form
 
-\SUPER{}$(a_1, \ldots, a_n,  x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$ 
+\SUPER{}$(a_1, \ldots, a_n,  x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$
 
-(respectively  \SUPER{}$.id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$ 
+(respectively  \SUPER{}$.id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$
 
 proceeds as follows:
 
@@ -1390,7 +1390,7 @@
 \LMLabel{factories}
 
 \LMHash{}
-A {\em factory} is a constructor prefaced by the built-in identifier  (\ref{identifierReference})   \FACTORY{}. 
+A {\em factory} is a constructor prefaced by the built-in identifier  (\ref{identifierReference})   \FACTORY{}.
 
 \begin{grammar}
 {\bf factoryConstructorSignature:}
@@ -1405,7 +1405,7 @@
 The {\em return type} of a factory whose signature is of the form \FACTORY{} $M$ or the form \FACTORY{} $M.id$ is $M$ if $M$ is not a generic type; otherwise the return type is  $M <T_1, \ldots, T_n>$ where $T_1, \ldots, T_n$ are the type parameters of the enclosing class
 
 \LMHash{}
-It is a compile-time error if $M$ is not the name of the immediately enclosing class. 
+It is a compile-time error if $M$ is not the name of the immediately enclosing class.
 
 \LMHash{}
 In checked mode, it is a dynamic type error if a factory returns a non-null object whose type is not a subtype of its actual (\ref{actualTypeOfADeclaration}) return type.
@@ -1413,7 +1413,7 @@
 \rationale{It seems useless to allow a factory to return null. But it is more uniform to allow it, as the rules currently do.}
 
 \rationale{Factories address classic weaknesses associated with constructors in other languages.
-Factories can produce instances that are not freshly allocated: they can come from a cache. Likewise, factories can return instances of different classes. 
+Factories can produce instances that are not freshly allocated: they can come from a cache. Likewise, factories can return instances of different classes.
 
 }
 
@@ -1430,7 +1430,7 @@
 \end{grammar}
 
 \LMHash{}
-Calling a redirecting factory constructor $k$ causes the constructor $k^\prime$ denoted by $type$ (respectively, $type.identifier$) to be called with the actual arguments passed to $k$, and returns the result of $k^\prime$ as the result of $k$.  The resulting constructor call is governed by the same rules as an instance creation expression using \NEW{} (\ref{instanceCreation}). 
+Calling a redirecting factory constructor $k$ causes the constructor $k^\prime$ denoted by $type$ (respectively, $type.identifier$) to be called with the actual arguments passed to $k$, and returns the result of $k^\prime$ as the result of $k$.  The resulting constructor call is governed by the same rules as an instance creation expression using \NEW{} (\ref{instanceCreation}).
 
 \commentary{
 It follows that if $type$ or $type.id$ are not defined, or do not refer to a class or constructor, a dynamic error occurs, as with any other undefined constructor call. The same holds if $k$ is called with fewer required parameters or more positional parameters than $k^\prime$ expects, or if $k$  is called with a named parameter that is not declared by $k^\prime$.
@@ -1448,14 +1448,14 @@
 
 \rationale{
 If a redirecting factory $F_1$ redirects to another redirecting factory $F_2$ and $F_2$ then redirects to $F_1$, then both $F_1$ and $F_2$ are ill-defined. Such cycles are therefore illegal.
-} 
+}
 
 
 \LMHash{}
 It is a static warning if $type$ does not denote a class accessible in the current scope; if $type$ does denote such a class $C$ it is a static warning if the referenced constructor (be it $type$ or $type.id$) is not a constructor of $C$.
 
 \commentary{
-Note that it is not possible to modify the arguments being passed to  $k'$.  
+Note that it is not possible to modify the arguments being passed to  $k'$.
 }
 % but we have the same issue with other redirecting constructors, no?)
 \rationale{
@@ -1485,7 +1485,7 @@
 %}
 
 %\CLASS{} A$<$T$>${
-%  \FACTORY{} A.idw(w) $=>$ F$<$T$>$.idw(w); 
+%  \FACTORY{} A.idw(w) $=>$ F$<$T$>$.idw(w);
 %// illegal - cannot pass type parameter to static method
 %  \FACTORY{} A.idx(x) $=> \NEW{} $F$<$T$>$.idx(x); // works, but allocates a gratuitous instance of F
 %  \FACTORY{} A.idy(y) = Y$<$T$>$; // works
@@ -1511,7 +1511,7 @@
 \LMLabel{constantConstructors}
 
 \LMHash{}
-A {\em constant constructor} may be used to create compile-time constant  (\ref{constants}) objects. A constant constructor is prefixed by the reserved word \CONST{}. 
+A {\em constant constructor} may be used to create compile-time constant  (\ref{constants}) objects. A constant constructor is prefixed by the reserved word \CONST{}.
 
 \begin{grammar}
 {\bf constantConstructorSignature:}
@@ -1527,7 +1527,7 @@
 \commentary{All the work of a constant constructor must be handled via its initializers.}
 
 \LMHash{}
-It is a compile-time error if a constant constructor is declared by a class that has a non-final instance variable.  
+It is a compile-time error if a constant constructor is declared by a class that has a non-final instance variable.
 
 \commentary{
 The above refers to both locally declared and inherited instance variables.
@@ -1544,7 +1544,7 @@
 The superinitializer that appears, explicitly or implicitly, in the initializer list of a constant constructor must specify a constant constructor of the superclass of the immediately enclosing class or a compile-time error occurs.
 
 \LMHash{}
-Any expression that appears within the initializer list of a constant constructor must be a potentially constant expression, or a compile-time error occurs. 
+Any expression that appears within the initializer list of a constant constructor must be a potentially constant expression, or a compile-time error occurs.
 
 \LMHash{}
 A {\em potentially constant expression} is an expression $e$ that would be a valid constant expression if all formal parameters of $e$'s immediately enclosing constant constructor were treated as compile-time constants that were guaranteed to evaluate to an integer, boolean or string value as required by their immediately enclosing superexpression, <em>and</em> where $e$ is also a valid expression if all the formal parameters are treated as non-constant variables.
@@ -1564,9 +1564,9 @@
 
 
 \commentary{
-The difference between a potentially constant expression and a compile-time constant expression (\ref{const}) deserves some explanation. 
+The difference between a potentially constant expression and a compile-time constant expression (\ref{const}) deserves some explanation.
 
-The key issue is whether one treats the formal parameters of a constructor as compile-time constants. 
+The key issue is whether one treats the formal parameters of a constructor as compile-time constants.
 
 If a constant constructor is invoked from a constant object expression, the actual arguments will be required to be compile-time constants. Therefore, if we were assured that constant constructors were always invoked from constant object expressions, we could assume that the formal parameters of a constructor were compile-time constants.
 
@@ -1579,7 +1579,7 @@
 \CLASS{} C \{
   \FINAL{} x; \FINAL{} y; \FINAL{} z;
   \CONST{} C(p, q): x = q, y = p + 100, z = p + q;
-  % what about 
+  % what about
  %  \CONST{} C(p, q): x = q, y = p + 100, z = p + 'foo';
  % perhaps moot. Current spec says that would be ok; type checker can worry, as can execution, which is at compile time anyway
 \}
@@ -1627,15 +1627,15 @@
 \rationale{
 Inheritance of static methods has little utility in Dart. Static methods cannot be overridden. Any required static function can be obtained from its declaring library, and there is no need to bring it into scope via inheritance. Experience shows that developers are confused by the idea of inherited methods that are not instance methods.
 
-Of course, the entire notion of static methods is debatable, but it is retained here because so many programmers are familiar with it. Dart static methods may be seen as functions of the enclosing library. 
+Of course, the entire notion of static methods is debatable, but it is retained here because so many programmers are familiar with it. Dart static methods may be seen as functions of the enclosing library.
 }
 
 \LMHash{}
-It is a static warning if a class $C$ declares a static method named $n$ and has a setter named $n=$. 
+It is a static warning if a class $C$ declares a static method named $n$ and has a setter named $n=$.
 %It is a static warning if a class has a static method with the same name as a static member of one of its superclasses.
 
 %\rationale{
-%This last restriction makes classes more brittle with respect to changes in the class hierarchy. It stems from a general observation that shadowing of names in the same scope is questionable and should elicit a warning. 
+%This last restriction makes classes more brittle with respect to changes in the class hierarchy. It stems from a general observation that shadowing of names in the same scope is questionable and should elicit a warning.
 %}
 %\commentary{
 %There is no hiding of static methods, or of static variables.
@@ -1648,26 +1648,26 @@
 \LMHash{}
 {\em Static variables} are variables whose declarations are immediately contained within a class declaration and that are declared \STATIC{}. The static variables of a class $C$ are those static variables declared by $C$.
 
-%A static variable declaration  of one of the forms \code{\STATIC{} $T$ $v$;},  \code{\STATIC{} $T$ $v$ = $e$;} ,  \code{\STATIC{} \CONST{} $T$ $v$ = $e$;}  or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} always induces an implicit static getter function (\ref{getters}) with signature 
+%A static variable declaration  of one of the forms \code{\STATIC{} $T$ $v$;},  \code{\STATIC{} $T$ $v$ = $e$;} ,  \code{\STATIC{} \CONST{} $T$ $v$ = $e$;}  or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} always induces an implicit static getter function (\ref{getters}) with signature
 
 %\STATIC{} $T$ \GET{} $v$
 
 %whose invocation evaluates as described below (\ref{evaluationOfStaticVariableGetters}).%to the value stored in $v$.
 
 
-%A static variable declaration  of one of the forms \code{\STATIC{} \VAR{} $v$;},  \code{\STATIC{} \VAR{} $v$ = $e$;} ,  \code{\STATIC{} \CONST{} $v$ = $e$;} or \code{\STATIC{} \FINAL{}  $v$ = $e$;}  always induces an implicit static getter function with signature 
+%A static variable declaration  of one of the forms \code{\STATIC{} \VAR{} $v$;},  \code{\STATIC{} \VAR{} $v$ = $e$;} ,  \code{\STATIC{} \CONST{} $v$ = $e$;} or \code{\STATIC{} \FINAL{}  $v$ = $e$;}  always induces an implicit static getter function with signature
 
 %\STATIC{} \GET{} $v$
 
 %whose  invocation evaluates as described below (\ref{evaluationOfStaticVariableGetters}).%to the value stored in $v$.
 
-%A non-final static variable declaration  of the form \code{\STATIC{} $T$ $v$;} or the form  \code{\STATIC{} $T$ $v$ = $e$;}   always induces an implicit static setter function (\ref{setters}) with signature 
+%A non-final static variable declaration  of the form \code{\STATIC{} $T$ $v$;} or the form  \code{\STATIC{} $T$ $v$ = $e$;}   always induces an implicit static setter function (\ref{setters}) with signature
 
 %\STATIC{} \VOID{} \SET{} $v=(T$ $x)$
 
 %whose execution sets the value of $v$ to the incoming argument $x$.
 
-%A static variable declaration  of the form \code{\STATIC{} \VAR{} $v$;} or the form  \code{\STATIC{} \VAR{} $v$ = $e$;}   always induces an implicit static setter function with signature 
+%A static variable declaration  of the form \code{\STATIC{} \VAR{} $v$;} or the form  \code{\STATIC{} \VAR{} $v$ = $e$;}   always induces an implicit static setter function with signature
 
 %\STATIC{} \SET{} $v=(x)$
 
@@ -1678,12 +1678,12 @@
 %\subsubsection{Evaluation of Implicit Static Variable Getters}
 %\LMLabel{evaluationOfStaticVariableGetters}
 
-%Let $d$ be the declaration of a static variable $v$. The implicit getter method of $v$ executes as follows: 
+%Let $d$ be the declaration of a static variable $v$. The implicit getter method of $v$ executes as follows:
 %\begin{itemize}
-%\item If $d$ is of one of the forms \code{\STATIC{} \VAR{} $v$ = $e$;} , \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is referenced, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$. 
+%\item If $d$ is of one of the forms \code{\STATIC{} \VAR{} $v$ = $e$;} , \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is referenced, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
 %\item  If $d$ is of one of the forms \code{\STATIC{} \CONST{} $v$ = $e$; } or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$.
 %Otherwise
-%\item The result of executing the getter method is the value stored in $v$.  
+%\item The result of executing the getter method is the value stored in $v$.
 %\end{itemize}
 
 
@@ -1695,7 +1695,7 @@
 The superclass of a class $C$ that has a with clause \code{\WITH{} $M_1, \ldots, M_k$} and an extends clause \code{\EXTENDS{} S} is the application of mixin (\ref{mixins}) $M_k* \cdots * M_1$  to S.  If no \WITH{} clause is specified then  the \EXTENDS{} clause of a class $C$ specifies its superclass. If no \EXTENDS{} clause is specified, then either:
 \begin{itemize}
 \item $C$ is \code{Object}, which has no superclass. OR
-\item Class $C$ is  deemed to have an \EXTENDS{} clause of the form \code{\EXTENDS{} Object}, and the rules above apply. 
+\item Class $C$ is  deemed to have an \EXTENDS{} clause of the form \code{\EXTENDS{} Object}, and the rules above apply.
 \end{itemize}
 
 \LMHash{}
@@ -1710,15 +1710,15 @@
 %The superclass clause of a class C is processed within the enclosing scope of the static scope of C.
 %\commentary{
 %This means that in a generic class, the type parameters of the generic are available in the superclass clause.
-%} 
+%}
 
 \LMHash{}
 The scope of the \EXTENDS{} and \WITH{} clauses of a class $C$ is the type-parameter scope of $C$.
 
 \LMHash{}
-%It is a compile-time error if  the \EXTENDS{} clause of a class $C$ includes a type expression that does not denote a class available in the lexical scope of $C$. 
+%It is a compile-time error if  the \EXTENDS{} clause of a class $C$ includes a type expression that does not denote a class available in the lexical scope of $C$.
 It is a compile-time error if  the \EXTENDS{} clause of a class $C$ specifies an enumerated type (\ref{enums}), a malformed  type or a deferred type (\ref{staticTypes}) as a superclass.
-% too strict? Do we e want extends List<Undeclared> to work as List<dynamic>? 
+% too strict? Do we e want extends List<Undeclared> to work as List<dynamic>?
 
 \commentary{ The type parameters of a generic class are available in the lexical scope of the superclass clause, potentially shadowing classes in the surrounding scope. The following code is therefore illegal and should cause a compile-time error:
 }
@@ -1727,7 +1727,7 @@
 class T \{\}
 
 /* Compilation error: Attempt to subclass a type parameter */
-class G$<$T$>$ extends T \{\} 
+class G$<$T$>$ extends T \{\}
 
 \end{dartCode}
 
@@ -1735,33 +1735,33 @@
 \LMHash{}
 A class $S$ is {\em a superclass} of a class $C$ iff either:
 \begin{itemize}
-\item $S$ is the superclass of $C$, or 
-\item $S$ is a superclass of a class $S^{\prime}$ and $S^{\prime}$ is a superclass of $C$. 
+\item $S$ is the superclass of $C$, or
+\item $S$ is a superclass of a class $S^{\prime}$ and $S^{\prime}$ is a superclass of $C$.
 \end{itemize}
 
 \LMHash{}
 It is a compile-time error if a class $C$ is a superclass of itself.
 
 
-    
- 
+
+
  \subsubsection{Inheritance and Overriding}
  \LMLabel{inheritanceAndOverriding}
 
 
-%A class $C$  {\em inherits} any accessible instance members of its superclass that are not overridden by members declared in $C$. 
+%A class $C$  {\em inherits} any accessible instance members of its superclass that are not overridden by members declared in $C$.
 
 \LMHash{}
 Let $C$ be a class,  let $A$ be a superclass of $C$, and let  $S_1 \ldots S_k$ be superclasses of $C$ that are also subclasses of $A$. $C$ {\em inherits} all accessible instance  members of  $A$ that have not been overridden by a declaration in $C$ or in at least one of $S_1 \ldots S_k$.
 
 \rationale {
 It would be  more attractive to give a purely local definition of inheritance, that depended only on the members of the direct superclass $S$. However, a class $C$ can inherit a member $m$ that  is not a member of its superclass  $S$. This can occur when the member $m$ is private
-to the library $L_1$ of $C$, whereas $S$ comes from a different library $L_2$, but 
+to the library $L_1$ of $C$, whereas $S$ comes from a different library $L_2$, but
 the superclass chain of $S$ includes a class declared in $L_1$.
 }
 
 \LMHash{}
-A class may override instance members that would otherwise have been inherited from its superclass. 
+A class may override instance members that would otherwise have been inherited from its superclass.
 
 \LMHash{}
 Let $C = S_0$ be a class declared in library $L$, and let $\{S_1 \ldots S_k\}$ be the set of all superclasses of $C$, where $S_i$ is the superclass of $S_{i-1}$ for $i \in 1 .. k$. Let $C$ declare a member $m$, and let  $m^\prime$ be a member of $S_j, j  \in 1 .. k$,  that has the same name as $m$, such that $m^\prime$ is accessible to $L$.  Then $m$ overrides $m^\prime$ if $m^\prime$ is not already overridden by a member of at least one of $S_1 \ldots S_{j-1}$ and neither $m$ nor $m^\prime$ are fields.
@@ -1774,10 +1774,10 @@
 }
 
 \LMHash{}
-Whether an override is legal or not is described elsewhere in this specification (see \ref{instanceMethods}, \ref{getters} and \ref{setters}). 
+Whether an override is legal or not is described elsewhere in this specification (see \ref{instanceMethods}, \ref{getters} and \ref{setters}).
 
 \commentary{For example getters may not legally override methods and vice versa. Setters never override methods or getters, and vice versa, because their names always differ.
-}  
+}
 
 \rationale{
 It is nevertheless convenient to define the override relation between members in this way, so that we can concisely describe the illegal cases.
@@ -1805,19 +1805,19 @@
 \item \label{typeSigAssignable}
 If two members override each other, it is a static warning if their type signatures are not assignable to each other (\ref{instanceMethods}, \ref{getters}, \ref{setters}) (and  since these are function types, this means the same as "subtypes of each other").
 \item \label{requiredParams}
-If two members override each other, it is a static warning if the overriding member has more required parameters  than the overridden one (\ref{instanceMethods}). 
+If two members override each other, it is a static warning if the overriding member has more required parameters  than the overridden one (\ref{instanceMethods}).
 \item  \label{optionalPositionals}
 If two members override each other, it is a static warning if the overriding member has fewer  positional parameters than the overridden one (\ref{instanceMethods}).
 \item  \label{namedParams}
 If two members override each other, it is a static warning if the overriding member does not have all the named parameters that the overridden one has (\ref{instanceMethods}).
 \item Setters, getters and operators never have optional parameters of any kind; it's a compile-time error (\ref{operators}, \ref{getters}, \ref{setters}).
 \item It is a compile-time error if a member has the same name as its enclosing class (\ref{classes}).
-\item A class has an implicit interface (\ref{classes}). 
+\item A class has an implicit interface (\ref{classes}).
 \item Superinterface members are not inherited by a class, but are inherited by its implicit interface. Interfaces have their own inheritance rules (\ref{interfaceInheritanceAndOverriding}).
 \item A member is abstract if it has no body and is not labeled \EXTERNAL{} (\ref{abstractInstanceMembers}, \ref{externalFunctions}).
 \item A class is abstract iff it is explicitly labeled \ABSTRACT{}.% or if it declares (not just inherits) an abstract member (\ref{classes}).
 \item It is a static warning if a concrete class has an abstract member (declared or inherited).
-\item It is a static warning and a dynamic error to call a non-factory constructor of an abstract class  (\ref{new}). 
+\item It is a static warning and a dynamic error to call a non-factory constructor of an abstract class  (\ref{new}).
 \item If a class defines an instance member named $m$, and any of its superinterfaces have a  member named $m$, the interface of the class overrides $m$.
 \item  An interface inherits all  members of its superinterfaces that are not overridden and not members of multiple superinterfaces.
 \item  If multiple superinterfaces of an interface define a member with the same name $m$, then at most one member is inherited. That member (if it exists) is the one whose type is a subtype of all the others. If there is no such member, then:
@@ -1826,7 +1826,7 @@
   \item  If possible the interface gets a member named $m$ that has the minimum number of required parameters among all the members in the superinterfaces, the maximal number of    positionals, and the superset of named parameters.  The types of these are all \DYNAMIC{}. If this is impossible then no member $m$ appears in the interface.
   \end{itemize}  (\ref{interfaceInheritanceAndOverriding})
 \item  Rule \ref{typeSigAssignable} applies to interfaces as well as classes  (\ref{interfaceInheritanceAndOverriding}).
-\item  It is a static warning if a concrete class does not have an implementation for a  method in any of its superinterfaces  unless it has a \cd{noSuchMethod} method (\ref{superinterfaces}). 
+\item  It is a static warning if a concrete class does not have an implementation for a  method in any of its superinterfaces  unless it has a \cd{noSuchMethod} method (\ref{superinterfaces}).
 \item The identifier of a named constructor cannot be the same as the name of a member declared (as opposed to inherited) in the same class (\ref{constructors}).
 \end{enumerate}
 }
@@ -1856,7 +1856,7 @@
 It is a compile-time error if the superclass of a class $C$ is specified as a superinterface of $C$.
 
 \rationale{
-One might argue that it is harmless to repeat a type in the superinterface list, so why make it an error? The issue is not so much that the situation described in program source is erroneous, but that it is pointless. As such, it is an indication that the programmer may very well have meant to say something else - and that is a mistake that should be called to her or his attention.  Nevertheless, we could simply issue a warning; and perhaps we should and will. That said, problems like these are local and easily corrected on the spot, so we feel justified in taking a harder line. 
+One might argue that it is harmless to repeat a type in the superinterface list, so why make it an error? The issue is not so much that the situation described in program source is erroneous, but that it is pointless. As such, it is an indication that the programmer may very well have meant to say something else - and that is a mistake that should be called to her or his attention.  Nevertheless, we could simply issue a warning; and perhaps we should and will. That said, problems like these are local and easily corrected on the spot, so we feel justified in taking a harder line.
 }
 
 \LMHash{}
@@ -1864,7 +1864,7 @@
 
 \LMHash{}
 Let $C$ be a concrete class that does not have a \code{noSuchMethod()} method distinct from the one declared in class \cd{Object}.
-It is a static warning if the implicit interface of  $C$ includes an instance member $m$ of type $F$ and $C$ does not declare or inherit a corresponding non-abstract instance member $m$ of type $F'$ such that $F' <: F$. 
+It is a static warning if the implicit interface of  $C$ includes an instance member $m$ of type $F$ and $C$ does not declare or inherit a corresponding non-abstract instance member $m$ of type $F'$ such that $F' <: F$.
 
 \commentary{A class does not inherit members from its superinterfaces. However, its implicit interface does.
 }
@@ -1877,7 +1877,7 @@
 
 
 \LMHash{}
-It is a static warning if the implicit interface of  a class $C$ includes an instance member $m$ of type $F$ and $C$ declares or inherits a corresponding instance member $m$ of type $F'$ if  $F'$ is not a subtype of $F$. 
+It is a static warning if the implicit interface of  a class $C$ includes an instance member $m$ of type $F$ and $C$ declares or inherits a corresponding instance member $m$ of type $F'$ if  $F'$ is not a subtype of $F$.
 
 \rationale{
 However, if a class does explicitly declare a member that conflicts with its superinterface, this always yields a static warning.
@@ -1885,12 +1885,12 @@
 }
 %It is a static warning if an imported superinterface of a class $C$ declares private members.
 
-% Should we ignore unimplemented private members? 
+% Should we ignore unimplemented private members?
 
 %\rationale{This last rule is problematic. As code evolves in one library ($L_1$) it may add private members to a class $I_1$ implemented or inherited in another  library $L_2$ breaking $L_1$.  This is a direct result of coupling an interface based type system with library based privacy.  We are considering alternative semantics that might help resolve this issue.
 %}
 
-%\commentary{However, it is perfectly acceptable if a type mentioned in the implements clause is mentioned as a superinterface in an interface injection clause. 
+%\commentary{However, it is perfectly acceptable if a type mentioned in the implements clause is mentioned as a superinterface in an interface injection clause.
 %}
 
 %\rationale{We disallow repetition of a type in a given implements clause, as that is a localized mistake. However, separate clauses (that is the original class and various injections) may evolve separately over time, and we don't want to cause breakage. For example
@@ -1920,7 +1920,7 @@
 \LMLabel{interfaceSuperinterfaces}
 
 \LMHash{}
-An interface has a set of direct superinterfaces. 
+An interface has a set of direct superinterfaces.
 
 \LMHash{}
 An interface $J$ is a superinterface of an interface $I$ iff either $J$ is a direct superinterface of $I$ or $J$ is a superinterface of a direct superinterface of $I$.
@@ -1934,8 +1934,8 @@
 \LMHash{}
 Let $J$ be an interface and $K$ be a library. We define $inherited(J, K)$  to be the set of members $m$ such that   all of the following hold:
 \begin{itemize}
-\item $m$ is accessible to $K$ and 
-\item $A$ is a direct superinterface of $J$ and either 
+\item $m$ is accessible to $K$ and
+\item $A$ is a direct superinterface of $J$ and either
   \begin{itemize}
   \item $A$ declares a member $m$  or
   \item $m$ is a member of $inherited(A, K)$.
@@ -1949,17 +1949,17 @@
 \item $J$ is the implicit interface of a class $C$.
 \item  $C$ declares a member $m$.
 \item $m^\prime$ has the same name as $m$.
-\item $m^\prime$ is accessible to $K$.  
+\item $m^\prime$ is accessible to $K$.
 \item $A$ is a direct superinterface of $J$ and either
   \begin{itemize}
-  \item $A$ declares a member $m^\prime$ or 
+  \item $A$ declares a member $m^\prime$ or
   \item $m^\prime$ is a member of $inherited(A, K)$.
   \end{itemize}
 \end{itemize}
 
 
 \LMHash{}
-Let $I$ be the implicit interface of a class $C$ declared in library $L$.  $I$ {\em inherits} all members of $inherited(I, L)$ and $I$ {\em overrides} $m^\prime$ if  $m^\prime \in overrides(I, L)$. 
+Let $I$ be the implicit interface of a class $C$ declared in library $L$.  $I$ {\em inherits} all members of $inherited(I, L)$ and $I$ {\em overrides} $m^\prime$ if  $m^\prime \in overrides(I, L)$.
 
 \LMHash{}
 All the static warnings pertaining to the overriding of instance members given in section \ref{classes} above hold for overriding between interfaces as well.
@@ -1969,36 +1969,36 @@
 
 
 
-%Let $I = S_0$ be the implicit interface of a class $C$ declared in library $L$, and let $\{S_1 \ldots S_k\}$ be the set of all superinterfaces of $I$. 
+%Let $I = S_0$ be the implicit interface of a class $C$ declared in library $L$, and let $\{S_1 \ldots S_k\}$ be the set of all superinterfaces of $I$.
 
-%Let $I$ be the implicit interface of a class $C$.  $I$ inherits any instance members of its superinterfaces that are not overridden by members declared in $C$. 
+%Let $I$ be the implicit interface of a class $C$.  $I$ inherits any instance members of its superinterfaces that are not overridden by members declared in $C$.
 
 % tighten definition? do we need chain as for classes?  Definition for interface override?
 
 \LMHash{}
-However, if the above rules would cause multiple members $m_1, \ldots,  m_k$ with the same name $n$ to be inherited (because identically named members existed in several superinterfaces) then at most one member is inherited. 
+However, if the above rules would cause multiple members $m_1, \ldots,  m_k$ with the same name $n$ to be inherited (because identically named members existed in several superinterfaces) then at most one member is inherited.
 
 \LMHash{}
 If some but not all of the $m_i, 1 \le i \le k$ are getters none of the $m_i$ are inherited, and a static warning is issued.
 
 \LMHash{}
 Otherwise, if the static types $T_1, \ldots,  T_k$ of the members $m_1, \ldots,  m_k$  are not identical, then there must be a member $m_x$ such that $T_x <: T_i, 1 \le x \le k$ for all  $i  \in 1..k$, or a static type warning occurs. The member that is inherited  is $m_x$, if it exists; otherwise:
- let $numberOfPositionals(f)$ denote the number of positional parameters of a function $f$, and let $numberOfRequiredParams(f)$ denote the number of required parameters of a function $f$. Furthermore, let $s$ denote the set of all named parameters of the $m_1, \ldots,  m_k$.  Then let 
+ let $numberOfPositionals(f)$ denote the number of positional parameters of a function $f$, and let $numberOfRequiredParams(f)$ denote the number of required parameters of a function $f$. Furthermore, let $s$ denote the set of all named parameters of the $m_1, \ldots,  m_k$.  Then let
 
 $h = max(numberOfPositionals(m_i)), $
 
-$r = min(numberOfRequiredParams(m_i)), i \in 1..k$. 
+$r = min(numberOfRequiredParams(m_i)), i \in 1..k$.
 
 \LMHash{}
-Then $I$ has a method named $n$, with $r$ required parameters of type \DYNAMIC{}, $h$  positional parameters of type \DYNAMIC{}, named parameters $s$ of type  \DYNAMIC{} and  return type  \DYNAMIC{}.  
+Then $I$ has a method named $n$, with $r$ required parameters of type \DYNAMIC{}, $h$  positional parameters of type \DYNAMIC{}, named parameters $s$ of type  \DYNAMIC{} and  return type  \DYNAMIC{}.
 
 
 
-\commentary{The only situation where the runtime would be concerned with this would be during reflection, if a mirror attempted to obtain the signature of an interface member. 
+\commentary{The only situation where the runtime would be concerned with this would be during reflection, if a mirror attempted to obtain the signature of an interface member.
 }
 
 \rationale{
-The current solution is a tad complex, but is robust in the face of type annotation changes.  Alternatives: (a) No member is inherited in case of conflict. (b) The first m is selected (based on order of superinterface list) (c) Inherited member chosen at random. 
+The current solution is a tad complex, but is robust in the face of type annotation changes.  Alternatives: (a) No member is inherited in case of conflict. (b) The first m is selected (based on order of superinterface list) (c) Inherited member chosen at random.
 
 (a) means that the presence of an inherited member of an interface varies depending on type signatures.  (b) is sensitive to irrelevant details of the declaration and (c) is liable to give unpredictable results between implementations or even between different compilation sessions.
 }
@@ -2006,14 +2006,14 @@
 % Need warnings if overrider conflicts with overriddee either because signatures are incompatible or because done is a method and one is a getter or setter.
 
 \section{Mixins}
-\LMLabel{mixins} 
+\LMLabel{mixins}
 
 
 \LMHash{}
-A mixin describes the difference between a class and its superclass. A mixin is always derived from an existing class declaration. 
+A mixin describes the difference between a class and its superclass. A mixin is always derived from an existing class declaration.
 
 \LMHash{}
-It is a compile-time error if a declared or derived mixin explicitly declares a constructor. 
+It is a compile-time error if a declared or derived mixin explicitly declares a constructor which is not a factory constructor.
 
 \rationale{
 This restriction is temporary.  We expect to remove it in later versions of Dart.
@@ -2031,25 +2031,25 @@
 \begin{grammar}
 {\bf  mixinApplicationClass:}
 	identifier typeParameters? `='  mixinApplication `{\escapegrammar ;}' .
-	
+
 {\bf mixinApplication:}
-     type mixins interfaces? 
+     type mixins interfaces?
     .
 \end{grammar}
 
 \LMHash{}
-A  mixin application of the form  \code{$S$ \WITH{} $M$;} defines a class  $C$ with superclass  $S$. 
+A  mixin application of the form  \code{$S$ \WITH{} $M$;} defines a class  $C$ with superclass  $S$.
 
 \LMHash{}
-A  mixin application of the form  \code{$S$ \WITH{} $M_1, \ldots, M_k$;} defines a class  $C$ whose superclass is the application of the mixin composition (\ref{mixinComposition}) $M_{k-1} * \ldots * M_1$ to $S$. 
+A  mixin application of the form  \code{$S$ \WITH{} $M_1, \ldots, M_k$;} defines a class  $C$ whose superclass is the application of the mixin composition (\ref{mixinComposition}) $M_{k-1} * \ldots * M_1$ to $S$.
 
 \LMHash{}
-In both cases above, $C$ declares the same instance members as $M$ (respectively, $M_k$). If any of the instance fields of $M$ (respectively, $M_k$) have initializers, they are executed in the scope of $M$ (respectively, $M_k$) to initialize the corresponding fields of $C$. 
+In both cases above, $C$ declares the same instance members as $M$ (respectively, $M_k$). If any of the instance fields of $M$ (respectively, $M_k$) have initializers, they are executed in the scope of $M$ (respectively, $M_k$) to initialize the corresponding fields of $C$.
 
 \LMHash{}
 Let $L_M$ be the library in which $M$ is declared.
 For each generative constructor named $q_i(T_{i1}$ $ a_{i1}, \ldots , T_{ik_i}$ $ a_{ik_i}), i \in 1..n$ of $S$ that is accessible to $L_M$, $C$ has an implicitly declared constructor named
-$q'_i = [C/S]q_i$ of the form 
+$q'_i = [C/S]q_i$ of the form
 
 $q'_i(a_{i1}, \ldots , a_{ik_i}):\SUPER(a_{i1}, \ldots , a_{ik_i});$.
 
@@ -2059,7 +2059,7 @@
 If the mixin application declares support for interfaces, the resulting class implements those interfaces.
 
 \LMHash{}
-It is a compile-time error if $S$ is an enumerated type (\ref{enums}) or a malformed type. It is a compile-time error if $M$ (respectively, any of $M_1, \ldots, M_k$) is an enumerated type (\ref{enums}) or a malformed type. It is a compile time error if a well formed mixin cannot be derived from $M$ (respectively, from each of $M_1, \ldots, M_k$). 
+It is a compile-time error if $S$ is an enumerated type (\ref{enums}) or a malformed type. It is a compile-time error if $M$ (respectively, any of $M_1, \ldots, M_k$) is an enumerated type (\ref{enums}) or a malformed type. It is a compile time error if a well formed mixin cannot be derived from $M$ (respectively, from each of $M_1, \ldots, M_k$).
 
 \LMHash{}
 Let $K$ be a class declaration  with the same constructors, superclass and interfaces as $C$,  and the instance members declared by $M$ (respectively $M_1, \ldots, M_k$). It is a static warning if the declaration of $K$ would cause a static warning.  It is a compile-time error if the declaration of $K$ would cause a compile-time error.
@@ -2070,15 +2070,15 @@
 }
 
 \LMHash{}
-The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form 
+The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form
  \code{\CLASS{} $C<T_1, \ldots, T_n>$ = $M$; } in library $L$  is to introduce the name $C$ into the scope of $L$, bound to the class (\ref{classes}) defined by the mixin application $M$. The name of the class is also set to $C$. Iff the  class is prefixed by the built-in identifier \ABSTRACT{}, the class being defined is an abstract class.
- 
+
  Let $M_A$ be a mixin derived from a class $M$ with direct superclass $S_{static}$.
 
 Let $A$ be an application of $M_A$. It is a static warning if the superclass of $A$ is not a subtype of $S_{static}$.
 
 Let $C$ be a class declaration that includes $M_A$ in a with clause. It is a static warning if $C$ does not implement, directly or indirectly, all the direct superinterfaces of $M$.
- 
+
 
 \subsection{Mixin Composition}
 \LMLabel{mixinComposition}
@@ -2088,25 +2088,25 @@
 }
 
 \LMHash{}
-The {\em composition of two mixins}, $M_1<T_1 \ldots T_{k_{M_1}}>$ and $M_2<U_1  \ldots U_{k_{M_2}}>$, written $M_1<T_1 \ldots T_{k_{M_1}}> * M_2<U_1  \ldots U_{k_{M_2}}>$ defines an anonymous mixin such that for any class $S<V_1 \ldots V_{k_S}>$, the application of 
+The {\em composition of two mixins}, $M_1<T_1 \ldots T_{k_{M_1}}>$ and $M_2<U_1  \ldots U_{k_{M_2}}>$, written $M_1<T_1 \ldots T_{k_{M_1}}> * M_2<U_1  \ldots U_{k_{M_2}}>$ defines an anonymous mixin such that for any class $S<V_1 \ldots V_{k_S}>$, the application of
 
-$M_1<T_1 \ldots T_{k_{M_1}}> * M_2<U_1  \ldots U_{k_{M_2}}>$  
+$M_1<T_1 \ldots T_{k_{M_1}}> * M_2<U_1  \ldots U_{k_{M_2}}>$
 
-to $S<V_1 \ldots V_{k_S}>$ is equivalent to 
+to $S<V_1 \ldots V_{k_S}>$ is equivalent to
 
 \begin{dartCode}
 \ABSTRACT{} \CLASS{} $Id_1<T_1  \ldots T_{k_{M_1}}, U_1  \ldots U_{k_{M_2}}, V_1  \ldots V_{k_S}> = $
       $Id_2<U_1  \ldots U_{k_{M_2}}, V_1  \ldots V_{k_S}>$ \WITH{} $M_1 <T_1  \ldots T_{k_{M_1}}>$;
 \end{dartCode}
 
-where $Id_2$ denotes 
+where $Id_2$ denotes
 
 \begin{dartCode}
 \ABSTRACT{}  \CLASS{} $Id_2<U_1 \ldots U_{k_{M_2}}, V_1 \ldots V_{k_S}> =$
-                         $S<V_1 \ldots V_{k_S}>$ \WITH{} $M_2<U_1  \ldots U_{k_{M_2}}>$; 
+                         $S<V_1 \ldots V_{k_S}>$ \WITH{} $M_2<U_1  \ldots U_{k_{M_2}}>$;
 \end{dartCode}
 
-and $Id_1$ and $Id_2$ are unique identifiers that do not exist anywhere in the program. 
+and $Id_1$ and $Id_2$ are unique identifiers that do not exist anywhere in the program.
 
 \rationale{
 The classes produced by mixin composition are regarded as abstract because they cannot be instantiated independently. They are only introduced as anonymous superclasses of ordinary class declarations and mixin applications. Consequently, no warning is given if a mixin composition includes abstract members, or incompletely implements an interface.
@@ -2157,8 +2157,8 @@
 \LMLabel{generics}
 
 \LMHash{}
-A class declaration (\ref{classes}) or type alias (\ref{typedef}) 
-$G$ may be {\em generic}, that is, $G$ may have formal type parameters declared. A generic declaration induces a family of declarations, one for each set of actual type parameters provided in the program. 
+A class declaration (\ref{classes}) or type alias (\ref{typedef})
+$G$ may be {\em generic}, that is, $G$ may have formal type parameters declared. A generic declaration induces a family of declarations, one for each set of actual type parameters provided in the program.
 
 \begin{grammar}
 {\bf typeParameter:}
@@ -2177,7 +2177,7 @@
 The type parameters of a generic $G$ are in scope in the bounds of all of the type parameters of $G$. The type parameters of a generic class declaration $G$ are also in scope in the \EXTENDS{} and \IMPLEMENTS{} clauses of $G$ (if these exist) and in the body of $G$.   However, a type parameter is considered to be a malformed type when referenced by a static member.
 
 \rationale{
-The restriction is necessary since a type variable has no meaning in the context of a static member, because statics are shared among all instantiations of a generic. However, a type variable may be referenced from an instance initializer, even though \THIS{} is not available. 
+The restriction is necessary since a type variable has no meaning in the context of a static member, because statics are shared among all instantiations of a generic. However, a type variable may be referenced from an instance initializer, even though \THIS{} is not available.
 }
 
 \commentary{
@@ -2206,7 +2206,7 @@
 The normative versions of these  are given in the appropriate sections of this specification. Some of these restrictions may be lifted in the future.
 }
 
-%The {\em induced type set}, $S$, of a parameterized type $T$ is the set consisting of 
+%The {\em induced type set}, $S$, of a parameterized type $T$ is the set consisting of
 %\begin{itemize}
 %\item The supertypes of any type in $S$.
 %\item The type arguments of any parameterized type in $S$.
@@ -2264,13 +2264,13 @@
     %.
 %\end{grammar}
 
-%\rationale{Since subinterface relations can be tested dynamically via \IS{}, interface injection is not just a directive to the static checker. The dynamic relations implied must  hold regardless of whether a static typecheck has succeeded, or has been performed at all. This makes sense from the perspective of preserving programmer intent. The injection describes a nominal type relation that the programmer wishes to hold. Just as a supertype mentioned within a class declaration is considered a supertype even though type errors might arise among (say) overridden and overriding methods, so it must be that the relation implied by an injection holds regardless of type errors. 
+%\rationale{Since subinterface relations can be tested dynamically via \IS{}, interface injection is not just a directive to the static checker. The dynamic relations implied must  hold regardless of whether a static typecheck has succeeded, or has been performed at all. This makes sense from the perspective of preserving programmer intent. The injection describes a nominal type relation that the programmer wishes to hold. Just as a supertype mentioned within a class declaration is considered a supertype even though type errors might arise among (say) overridden and overriding methods, so it must be that the relation implied by an injection holds regardless of type errors.
 %In addition, this decision helps to produce meaningful and localized error messages. Any errors are reported at the point of injection rather than at program points that rely on the relation (a well known problem with structural subtyping in OO systems).
 %}
 
 %\Q{When does an interface injection take effect? When the containing library is loaded?
-%What is the scope of such a declaration? Is it global, or only in the scope of the containing library? The scope of such a declaration is global. 
-%An injection must be at top level. Who has the right to inject an interface $I$ into another class $C$? Anybody? But since this affects dynamic behavior, is this a weird security issue? 
+%What is the scope of such a declaration? Is it global, or only in the scope of the containing library? The scope of such a declaration is global.
+%An injection must be at top level. Who has the right to inject an interface $I$ into another class $C$? Anybody? But since this affects dynamic behavior, is this a weird security issue?
 %The current theory is that there is no security within an isolate, and one can never refer to a type from another isolate, so supposedly not an issue. This assumption (no mutually suspicious code in the same isolate) is suspect but it seems there is nothing to be done at this point.
 %If libs are first class, they get created dynamically in order, and new libs might modify the type relations among other libs types - but then it is clear when that happened and order is ok.
 %}
@@ -2282,7 +2282,7 @@
 \LMLabel{metadata}
 
 \LMHash{}
-Dart supports metadata which is used to attach user defined annotations to program structures.  
+Dart supports metadata which is used to attach user defined annotations to program structures.
 
 \begin{grammar}
 {\bf metadata:}
@@ -2316,7 +2316,7 @@
 Metadata can appear before a library, part header, class, typedef, type parameter, constructor, factory, function, field, parameter, or variable declaration and before an import, export or part directive.
 
 \LMHash{}
-The constant expression given in an annotation  is type checked and evaluated in the scope surrounding the declaration being annotated.  
+The constant expression given in an annotation  is type checked and evaluated in the scope surrounding the declaration being annotated.
 
 
 \section{Expressions}
@@ -2330,19 +2330,19 @@
 
 {\bf expression:}assignableExpression assignmentOperator expression;
        conditionalExpression cascadeSection*;
-       throwExpression     
+       throwExpression
     .
-     
-    
+
+
 {\bf expressionWithoutCascade:}assignableExpression assignmentOperator expressionWithoutCascade;
       conditionalExpression;
-      throwExpressionWithoutCascade    
+      throwExpressionWithoutCascade
     .
 
 {\bf expressionList:}
       expression (`,' expression)* %should these be top level expressions?
     .
-\end{grammar}    
+\end{grammar}
 
 \begin{grammar}
 {\bf primary:}thisExpression;
@@ -2355,8 +2355,8 @@
       constObjectExpression;
       `(' expression `)'
     .
-    
-\end{grammar}   
+
+\end{grammar}
 
 \LMHash{}
 An expression $e$ may always be enclosed in parentheses, but this never has any semantic effect on $e$.
@@ -2367,7 +2367,7 @@
 
  \subsubsection{Object Identity}
  \LMLabel{objectIdentity}
- 
+
 \LMHash{}
 The predefined Dart function \cd{identical()} is defined such that \code{identical($c_1$, $c_2$)} iff:
  \begin{itemize}
@@ -2387,9 +2387,9 @@
  \item $c_1$ and $c_2$ are constant objects of the same class $C$ and each member field of $c_1$ is identical to the corresponding field of $c_2$. OR
 \item $c_1$ and $c_2$ are the same object.
 \end{itemize}
-    
+
 \commentary{
-The definition of \cd{identity} for doubles differs from that of equality in that a NaN is identical to itself, and that negative and positive zero are distinct.  
+The definition of \cd{identity} for doubles differs from that of equality in that a NaN is identical to itself, and that negative and positive zero are distinct.
 }
 
 \rationale{
@@ -2399,13 +2399,13 @@
 
 The rules for identity make it impossible for a Dart programmer to observe whether a boolean or numerical value is boxed or unboxed.
 }
-    
-    
+
+
 \subsection{Constants}
 \LMLabel{constants}
 
 \LMHash{}
-A {\em constant expression} is an expression whose value can never change, and that can be evaluated entirely at compile time. 
+A {\em constant expression} is an expression whose value can never change, and that can be evaluated entirely at compile time.
 
 \LMHash{}
 A constant expression is one of the following:
@@ -2416,14 +2416,14 @@
 \rationale{It would be tempting to allow string interpolation where the interpolated value is any compile-time constant.  However, this would require running the \code{toString()} method for constant objects, which could contain arbitrary code.}
 \item A literal symbol (\ref{symbols}).
 \item \NULL{} (\ref{null}).
-\item A qualified reference to a static constant variable (\ref{variables}) that is not qualified by a deferred prefix. 
+\item A qualified reference to a static constant variable (\ref{variables}) that is not qualified by a deferred prefix.
 \commentary {For example, If class C declares a constant static variable v, C.v is a constant. The same is true if C is accessed via a prefix p; p.C.v is a constant  unless p is a deferred prefix.
 }
-\item An identifier expression that denotes a constant variable. 
-\item A simple or qualified identifier denoting a class or type alias that is not qualified by a deferred prefix. 
+\item An identifier expression that denotes a constant variable.
+\item A simple or qualified identifier denoting a class or type alias that is not qualified by a deferred prefix.
 \commentary {For example, If C is a class or typedef, C is a constant, and if C is imported with a prefix p, p.C is a constant unless p is a deferred prefix.
 }
-\item A constant constructor invocation (\ref{const}) that is not qualified by a deferred prefix.  
+\item A constant constructor invocation (\ref{const}) that is not qualified by a deferred prefix.
 \item A constant list literal (\ref{lists}).
 \item A constant map literal (\ref{maps}).
 \item A simple or qualified identifier denoting a top-level function (\ref{functions}) or a static method (\ref{staticMethods}) that is not qualified by a deferred prefix.
@@ -2444,7 +2444,7 @@
 % designed so constants do not depend on check diode being on or not.
 
 \LMHash{}
-It is a compile-time error if an expression is required to be a constant expression but its evaluation  would raise an exception. 
+It is a compile-time error if an expression is required to be a constant expression but its evaluation  would raise an exception.
 
 % so, checked mode? analyzers? editor/development compilers?
 \commentary{
@@ -2465,15 +2465,15 @@
     \IF{} (z) \{\RETURN{} x; \}
     \ELSE{} \{ \RETURN{} 2;\}
   \}
-  
+
   m2() \{
     \IF{} (\TRUE{}) \{\RETURN{} y; \}
     \ELSE{} \{ \RETURN{} 3;\}
-  \}  
+  \}
 \}
 \end{dartCode}
 
-\commentary{An implementation is free to immediately issue a compilation error for  \code{x}, but it is not required to do so.  It could defer errors if it does not immediately compile the declarations that reference \code{x}. For example, it could delay giving a compilation error about the method \code{m1} until the first invocation of \code{m1}. However, it could not choose to execute \code{m1},  see that the branch that refers to \code{x} is not taken and return 2 successfully. 
+\commentary{An implementation is free to immediately issue a compilation error for  \code{x}, but it is not required to do so.  It could defer errors if it does not immediately compile the declarations that reference \code{x}. For example, it could delay giving a compilation error about the method \code{m1} until the first invocation of \code{m1}. However, it could not choose to execute \code{m1},  see that the branch that refers to \code{x} is not taken and return 2 successfully.
 
 The situation with respect to an invocation \code{m2} is different. Because \code{y} is not a compile-time constant (even though its value is), one need not give a compile-time error upon compiling \code{m2}. An implementation may run the code, which will cause  the getter for \code{y} to be invoked. At that point, the initialization of \code{y} must take place, which requires the initializer to be compiled, which will cause a compilation error.
 }
@@ -2481,11 +2481,19 @@
 \rationale{
 The treatment of \NULL{} merits some discussion. Consider \code{\NULL{} + 2}.  This expression always causes an error. We could have chosen not to treat it as a constant expression (and in general, not to allow \NULL{} as a subexpression of numeric or boolean constant expressions).  There are two arguments for including it:
 \begin{enumerate}
-\item It is constant. We can evaluate it at compile-time. 
+\item It is constant. We can evaluate it at compile-time.
 \item It seems more useful to give the error stemming from the evaluation explicitly.
 \end{enumerate}
 }
 
+\rationale {
+One might reasonably ask why $e_1? e_1: e_3$ and $e_1?? e_2$ have constant forms. For example, if $e_1$ is known statically, why do we need to test it?.
+The answer is that there are contexts where $e_1$ is a variable. In particular, constant constructor initializers such as
+
+\code{\CONST{} C(foo) : \THIS.foo = foo ?? someDefaultValue;}
+}
+
+
 \LMHash{}
 It is a compile-time error if the value of a compile-time constant expression depends on itself.
 
@@ -2494,7 +2502,7 @@
 }
 
 \begin{dartCode}
-\CLASS{} CircularConsts\{ 
+\CLASS{} CircularConsts\{
 // Illegal program - mutually recursive compile-time constants
   \STATIC{} \CONST{} i = j; // a compile-time constant
   \STATIC{} \CONST{} j = i; // a compile-time constant
@@ -2529,13 +2537,13 @@
 \end{grammar}
 
 \LMHash{}
-The null object is the sole instance of the built-in class \code{Null}. Attempting to instantiate \code{Null} causes a run-time error. It is a compile-time error for a class to attempt to extend, mix in or implement \code{Null}. 
+The null object is the sole instance of the built-in class \code{Null}. Attempting to instantiate \code{Null} causes a run-time error. It is a compile-time error for a class to attempt to extend, mix in or implement \code{Null}.
 Invoking a method on \NULL{}  yields a \code{NoSuchMethodError} unless the method is explicitly implemented by class \code{Null}.
 
 \LMHash{}
 The static type of \NULL{} is $\bot$.
 
-\rationale{The decision to use $\bot$ instead of \code{Null} allows \NULL{} to be be assigned everywhere without complaint by the static checker. 
+\rationale{The decision to use $\bot$ instead of \code{Null} allows \NULL{} to be be assigned everywhere without complaint by the static checker.
 }
 
 
@@ -2549,7 +2557,7 @@
 {\bf numericLiteral:}NUMBER;
       HEX\_NUMBER
     .
-    
+
   {\bf NUMBER:} DIGIT+ (`{\escapegrammar.}' DIGIT+)? EXPONENT?;
       {`\escapegrammar .}' DIGIT+ EXPONENT?
     .
@@ -2567,9 +2575,9 @@
       DIGIT
     .
  \end{grammar}
- 
+
 \LMHash{}
-If a numeric literal begins with the prefix `0x' or `0X', it denotes the hexadecimal integer represented by the part of the literal following `0x' (respectively `0X'). Otherwise, if the numeric literal does not include a decimal point  it denotes a decimal integer.  Otherwise, the numeric literal  denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard. 
+If a numeric literal begins with the prefix `0x' or `0X', it denotes the hexadecimal integer represented by the part of the literal following `0x' (respectively `0X'). Otherwise, if the numeric literal does not include a decimal point  it denotes a decimal integer.  Otherwise, the numeric literal  denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard.
 
 \LMHash{}
 In principle, the range of integers supported by a Dart implementations is unlimited. In practice, it is limited by available memory. Implementations may also be limited by other considerations.
@@ -2582,12 +2590,12 @@
 It is a compile-time error for a class to attempt to extend, mix in or implement \code{int}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{double}. It is a compile-time error for any type other than the types \code{int} and \code{double} to attempt to extend, mix in or implement \code{num}.
 
 \LMHash{}
-An {\em integer literal} is either a hexadecimal integer literal or a  decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}. 
+An {\em integer literal} is either a hexadecimal integer literal or a  decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}.
 
 \LMHash{}
 A {\em literal double} is a numeric literal that is not an integer literal. Invoking the getter \code{runtimeType} on a literal double returns the \code{Type} object that is the value of the expression \code{double}.
 The static type of a literal double is \code{double}.
-    
+
 \subsection{Booleans}
 \LMLabel{booleans}
 
@@ -2601,10 +2609,10 @@
 \end{grammar}
 
 \LMHash{}
-Both  \TRUE{} and \FALSE{} implement the built-in class \code{bool}.  It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}. 
+Both  \TRUE{} and \FALSE{} implement the built-in class \code{bool}.  It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}.
 
 \commentary{
-It follows that the two boolean literals are the only two instances of \code{bool}. 
+It follows that the two boolean literals are the only two instances of \code{bool}.
 }
 
 \LMHash{}
@@ -2625,21 +2633,21 @@
 \end{dartCode}
 
 \rationale{
-Boolean conversion is used as part of control-flow constructs and boolean expressions.  Ideally, one would simply insist that control-flow decisions be based exclusively on booleans.  This is straightforward in a statically typed setting. In a dynamically typed language, it requires a dynamic check. Sophisticated virtual machines can minimize the penalty involved. Alas, Dart must be compiled into Javascript. Boolean conversion allows this to be done efficiently. 
+Boolean conversion is used as part of control-flow constructs and boolean expressions.  Ideally, one would simply insist that control-flow decisions be based exclusively on booleans.  This is straightforward in a statically typed setting. In a dynamically typed language, it requires a dynamic check. Sophisticated virtual machines can minimize the penalty involved. Alas, Dart must be compiled into Javascript. Boolean conversion allows this to be done efficiently.
 
 At the same time, this formulation differs radically from Javascript, where most numbers and objects are interpreted as \TRUE{}.  Dart's approach prevents usages such \code{\IF{} (a-b) ... ; }because it does not agree with the low level conventions whereby non-null objects or non-zero numbers are treated as \TRUE{}. Indeed, there is no way to derive \TRUE{} from a non-boolean object via boolean conversion, so this kind of low level hackery is nipped in the bud.
 
-Dart also avoids the strange behaviors that can arise due to the interaction of boolean conversion with autoboxing in Javascript. A notorious example is the situation where \FALSE{} can be interpreted as \TRUE{}. In Javascript, booleans are not objects, and instead are autoboxed into objects where ``needed''.  If \FALSE{} gets autoboxed into an object, that object can be coerced into \TRUE{} (as it is a non-null object). 
+Dart also avoids the strange behaviors that can arise due to the interaction of boolean conversion with autoboxing in Javascript. A notorious example is the situation where \FALSE{} can be interpreted as \TRUE{}. In Javascript, booleans are not objects, and instead are autoboxed into objects where ``needed''.  If \FALSE{} gets autoboxed into an object, that object can be coerced into \TRUE{} (as it is a non-null object).
 }
 
 \commentary{Because boolean conversion requires its parameter to be a boolean, any construct that makes use of boolean conversion will cause a dynamic type error in checked mode if the value to be converted is not a boolean.
  }
-    
+
 \subsection{Strings}
 \LMLabel{strings}
 
 \LMHash{}
-A {\em string} is a sequence of UTF-16 code units. 
+A {\em string} is a sequence of UTF-16 code units.
 
 \rationale{
 This decision was made for compatibility with web browsers and Javascript. Earlier versions of the specification required a string to be a sequence of valid Unicode code points.  Programmers should not depend on this distinction.
@@ -2651,7 +2659,7 @@
 \end{grammar}
 
 \LMHash{}
-A string can be either a sequence of single line strings or a multiline string. 
+A string can be either a sequence of single line strings or a multiline string.
 
 \begin{grammar}
  {\bf singleLineString:}`{\escapegrammar \code{"}}' stringContentDQ* `{\escapegrammar \code{"}}';
@@ -2662,7 +2670,7 @@
 \end{grammar}
 
 \LMHash{}
-A single line string is delimited by either matching single quotes or matching double quotes.  
+A single line string is delimited by either matching single quotes or matching double quotes.
 
 \commentary{
 Hence, `abc' and ``abc'' are both legal strings, as are `He said ``To be or not to be'' did he not?'  and ``He said `To be or not to be' didn't he''. However  ``This ` is not a valid string, nor is `this''.
@@ -2672,8 +2680,8 @@
 }
 
 \LMHash{}
-Adjacent 
-%single line 
+Adjacent
+%single line
 strings are implicitly concatenated to form a single string literal.
 %, and so are adjacent multiline strings, but the two forms may not be mixed.
 
@@ -2684,7 +2692,7 @@
 print("A string" "and then another"); // prints: A stringand then another
 \end{dartCode}
 
-\rationale{Dart also supports the operator + for string concatenation. 
+\rationale{Dart also supports the operator + for string concatenation.
 
 The + operator on Strings requires a String argument. It does not coerce its argument into a string. This helps avoid puzzlers such as
 }
@@ -2725,8 +2733,8 @@
       `r' `{\escapegrammar \texttt{"""}}'  (\~{} `{\escapegrammar \texttt{"""}}')*   `{\escapegrammar \texttt{"""}}';
       `r' `{\escapegrammar \code{'}\code{'}\code{'}}' (\~{} `{\escapegrammar \code{'}\code{'}\code{'}}')* `{\escapegrammar \code{'}\code{'}\code{'}}'
     .
-    
-    
+
+
     {\bf ESCAPE\_SEQUENCE:} `$\backslash$ n';
     `$\backslash$ r';
    `$\backslash$ f';
@@ -2737,21 +2745,21 @@
    `$\backslash$ u' HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT;
    `$\backslash$ u\{' HEX\_DIGIT\_SEQUENCE `\}'
   .
-  
+
 {\bf HEX\_DIGIT\_SEQUENCE:}
-     HEX\_DIGIT HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? 
+     HEX\_DIGIT HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT?
     .
-   
+
 \end{grammar}
 
 \LMHash{}
 Multiline strings are delimited by either matching triples of single quotes or matching triples of double quotes. If the first line of a multiline string consists solely of the whitespace characters defined by the production {\em WHITESPACE}  \ref{lexicalRules}), possibly prefixed by $\backslash$, then that line is ignored, including the new line at its end.
 
- 
+
  \rationale{
  The idea is to ignore whitespace, where whitespace is defined as tabs, spaces and newlines. These can be represented directly, but since for most characters prefixing by backslash is an identity, we allow those forms as well.
  }
- 
+
  % could be clearer. Is the first line in  """\t
  %    """ ignored not. It depends if we mean whitespace before escapes are interpreted,
  % or after, or both.  See https://code.google.com/p/dart/issues/detail?id=23020
@@ -2765,7 +2773,7 @@
 \item $\backslash$b for backspace, equivalent to $\backslash$x08.
 \item $\backslash$t for tab, equivalent to $\backslash$x09.
 \item $\backslash$v for vertical tab, equivalent to $\backslash$x0B
-\item $\backslash$x $HEX\_DIGIT_1$ $HEX\_DIGIT_2$, equivalent to 
+\item $\backslash$x $HEX\_DIGIT_1$ $HEX\_DIGIT_2$, equivalent to
 
 $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$\}.
 \item $\backslash$u $HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\_DIGIT_4$, equivalent to $\backslash$u\{$HEX\_DIGIT_1$ $HEX\_DIGIT_2$ $HEX\_DIGIT_3$ $HEX\_DIGIT_4$\}.
@@ -2793,21 +2801,21 @@
      stringInterpolation
     .
 
-    
+
  {\bf stringContentTDQ:}\~{}( `$\backslash$' $|$  `{\escapegrammar \texttt{"""}}' $|$ `\$');
      stringInterpolation
-    .    
+    .
 
  {\bf stringContentTSQ:}\~{}( `$\backslash$' $|$ `{\escapegrammar \code{'}\code{'}\code{'}}' $|$ `\$');
      stringInterpolation
     .
-    
+
 {\bf NEWLINE:}$\backslash$ n;
       $\backslash$ r
     .
 
  \end{grammar}
- 
+
 \LMHash{}
 All string literals implement the built-in class \code{String}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{String}. Invoking the getter \code{runtimeType} on a string literal returns the \code{Type} object that is the value of the expression \code{String}. The static type of a string literal is \code{String}.
 
@@ -2822,14 +2830,14 @@
       `\$' `\{' expression `\}' % could be top level expression, no?
     .
  \end{grammar}
- 
-\commentary{The reader will note that the expression inside the interpolation could itself include strings, which could again be interpolated recursively. 
+
+\commentary{The reader will note that the expression inside the interpolation could itself include strings, which could again be interpolated recursively.
 }
 
 \LMHash{}
 An unescaped \$ character in a string signifies the beginning of an interpolated expression.  The \$ sign may be followed by either:
 \begin{itemize}
-\item A single identifier $id$ that must not contain the \$ character. 
+\item A single identifier $id$ that must not contain the \$ character.
 \item An expression $e$ delimited by curly braces.
 \end{itemize}
 
@@ -2840,7 +2848,7 @@
 \LMLabel{symbols}
 
 \LMHash{}
-A {\em symbol literal} denotes the name of a declaration in a Dart program. 
+A {\em symbol literal} denotes the name of a declaration in a Dart program.
 
 \begin{grammar}
 {\bf symbolLiteral:}
@@ -2848,13 +2856,13 @@
 \end{grammar}
 
 \LMHash{}
-A symbol literal \code{\#id} where \code{id} does not begin with an underscore ('\code{\_}')  is equivalent to the expression \code{\CONST{} Symbol('id')}.  
+A symbol literal \code{\#id} where \code{id} does not begin with an underscore ('\code{\_}')  is equivalent to the expression \code{\CONST{} Symbol('id')}.
 
 \LMHash{}
 A symbol literal \code{\#\_id} evaluates to the object that would be returned by the call \code{mirror.getPrivateSymbol('id')} where mirror is an instance of the class \code{LibraryMirror} defined in the library \code{dart:mirrors}, reflecting the current library.
 
 \rationale{
-One may well ask what is the motivation for introducing literal symbols? In some languages, symbols are canonicalized whereas strings are not. However literal strings are already canonicalized in Dart.  Symbols are slightly easier to type compared to strings and their use can become strangely addictive, but this is not nearly sufficient justification for adding a literal form to the language. The primary motivation is related to the use of reflection and a web specific practice known as minification. 
+One may well ask what is the motivation for introducing literal symbols? In some languages, symbols are canonicalized whereas strings are not. However literal strings are already canonicalized in Dart.  Symbols are slightly easier to type compared to strings and their use can become strangely addictive, but this is not nearly sufficient justification for adding a literal form to the language. The primary motivation is related to the use of reflection and a web specific practice known as minification.
 
 Minification compresses identifiers consistently throughout a program in order to reduce download size.  This practice poses difficulties for reflective programs that refer to program declarations via strings. A string will refer to an identifier in the source, but the identifier will no longer be used in the minified code, and reflective code using these would fail.  Therefore, Dart reflection uses  objects of type \code{Symbol} rather than strings. Instances of \code{Symbol} are guaranteed to be stable with repeat to minification. Providing a literal form for symbols makes reflective code easier to read and write. The fact that symbols are easy to type and can often act as convenient substitutes for enums are secondary benefits.
 }
@@ -2866,7 +2874,7 @@
 \LMLabel{lists}
 
 \LMHash{}
-A {\em list literal} denotes a list, which is an integer indexed collection of objects. 
+A {\em list literal} denotes a list, which is an integer indexed collection of objects.
 
 \begin{grammar}
 {\bf listLiteral:}
@@ -2890,7 +2898,7 @@
 The value of a constant list literal  \CONST{} $<E>[e_1\ldots e_n]$ is an object $a$ whose class implements the built-in class $List<E>$. The $i$th element of $a$ is $v_{i+1}$, where $v_i$ is the value of the compile-time expression $e_i$.  The value of a constant list literal  \CONST{} $[e_1 \ldots e_n]$ is defined as the value of the constant list literal \CONST{}$ < \DYNAMIC{}>[e_1\ldots e_n]$.
 
 \LMHash{}
-Let $list_1 =$ \CONST{} $<V>[e_{11} \ldots e_{1n}]$ and $list_2 =$  \CONST{} $<U>[e_{21} \ldots e_{2n}]$ be two constant list literals and let the  elements of $list_1$ and $list_2$  evaluate to  $o_{11} \ldots o_{1n}$ and $o_{21} \ldots o_{2n}$ respectively. Iff \code{identical($o_{1i}$, $o_{2i}$)} for $i \in 1.. n$ and $V = U$ then \code{identical($list_1$, $list_2$)}. 
+Let $list_1 =$ \CONST{} $<V>[e_{11} \ldots e_{1n}]$ and $list_2 =$  \CONST{} $<U>[e_{21} \ldots e_{2n}]$ be two constant list literals and let the  elements of $list_1$ and $list_2$  evaluate to  $o_{11} \ldots o_{1n}$ and $o_{21} \ldots o_{2n}$ respectively. Iff \code{identical($o_{1i}$, $o_{2i}$)} for $i \in 1.. n$ and $V = U$ then \code{identical($list_1$, $list_2$)}.
 
 \commentary{In other words, constant list literals are canonicalized.}
 
@@ -2899,10 +2907,10 @@
 \begin{itemize}
 \item
 First, the expressions $e_1 \ldots e_n$ are evaluated in order they appear in the program, yielding objects $o_1 \ldots o_n$.
-\item A fresh instance  (\ref{generativeConstructors}) $a$, of size $n$,  whose class implements the built-in class $List<E>$ is allocated. 
+\item A fresh instance  (\ref{generativeConstructors}) $a$, of size $n$,  whose class implements the built-in class $List<E>$ is allocated.
 \item
 The operator \code{[]=} is invoked on $a$ with  first  argument $i$ and second argument
-%The $i$th element of $a$ is set to 
+%The $i$th element of $a$ is set to
 $o_{i+1}, 0 \le i < n$.
 \item
 The result of the evaluation is $a$.
@@ -2910,7 +2918,7 @@
 
 
 \commentary{
-Note that this document does not specify an order in which the elements are set. This allows for parallel assignments into the list if an implementation so desires.  The order can only be observed in checked mode (and may not be relied upon): if element $i$ is not a subtype of the element type of the list, a dynamic type error will occur when $a[i]$ is assigned $o_{i-1}$. 
+Note that this document does not specify an order in which the elements are set. This allows for parallel assignments into the list if an implementation so desires.  The order can only be observed in checked mode (and may not be relied upon): if element $i$ is not a subtype of the element type of the list, a dynamic type error will occur when $a[i]$ is assigned $o_{i-1}$.
 }
 
 \LMHash{}
@@ -2919,7 +2927,7 @@
 
 \commentary{
 There is no restriction precluding nesting of list literals. It follows from the rules above that
-$<List<int>>[[1, 2, 3], [4, 5, 6]]$ is a list with type parameter $List<int>$, containing two lists with type parameter  \DYNAMIC{}. 
+$<List<int>>[[1, 2, 3], [4, 5, 6]]$ is a list with type parameter $List<int>$, containing two lists with type parameter  \DYNAMIC{}.
 }
 
 \LMHash{}
@@ -2931,12 +2939,12 @@
 
 %Invoking the getter \code{runtimeType} on a list literal returns the \code{Type} object that is the value of the expression \code{List}. The static type of a list literal is \code{List}.
 % what about generics?
-    
+
 \subsection{Maps}
 \LMLabel{maps}
 
 \LMHash{}
-A {\em map literal} denotes a map object. 
+A {\em map literal} denotes a map object.
 
 \begin{grammar}
 {\bf mapLiteral:}
@@ -2945,28 +2953,28 @@
 
 {\bf mapLiteralEntry:}
         % identifier `{\escapegrammar :}' expression;
-	expression `{\escapegrammar :}' expression 
+	expression `{\escapegrammar :}' expression
     .
 \end{grammar}
 
 \LMHash{}
-A {\em map literal} consists of zero or more entries. Each entry has a {\em key} and a {\em value}.  Each key and each value is denoted by an expression. 
- 
+A {\em map literal} consists of zero or more entries. Each entry has a {\em key} and a {\em value}.  Each key and each value is denoted by an expression.
+
 \LMHash{}
 If a map literal begins with the reserved word \CONST{}, it is a {\em constant map literal} which is a compile-time constant (\ref{constants}) and therefore evaluated at compile-time. Otherwise, it is a {\em run-time map literal} and it is evaluated at run-time. Only run-time map literals can be mutated
 after they are created. Attempting to mutate a constant map literal will result in a dynamic error.
 
 \LMHash{}
-It is a compile-time error if either a key or a value of an entry in a constant map literal is not a compile-time constant. It is a compile-time error if the key of an entry in a constant map literal is an instance of a class that implements the operator $==$ unless the key is a 
-%symbol, 
-string, an integer, a literal symbol or the result of invoking a constant constructor of class \cd{Symbol}. 
-It is a compile-time error if the type arguments of a constant map literal include a type parameter. 
+It is a compile-time error if either a key or a value of an entry in a constant map literal is not a compile-time constant. It is a compile-time error if the key of an entry in a constant map literal is an instance of a class that implements the operator $==$ unless the key is a
+%symbol,
+string, an integer, a literal symbol or the result of invoking a constant constructor of class \cd{Symbol}.
+It is a compile-time error if the type arguments of a constant map literal include a type parameter.
 
 \LMHash{}
 The value of a constant map literal  \CONST{}$ <K, V>\{k_1:e_1\ldots k_n :e_n\}$ is an object $m$ whose class implements the built-in class $Map<K, V>$. The entries of $m$ are $u_i:v_i, i \in 1 .. n$, where $u_i$ is the value of the compile-time expression $k_i$ and $v_i$ is the value of the compile-time expression $e_i$.  The value of a constant map literal  \CONST{} $\{k_1:e_1\ldots k_n :e_n\}$ is defined as the value of a constant map literal \CONST{} $<\DYNAMIC{}, \DYNAMIC{}>\{k_1:e_1\ldots k_n :e_n\}$.
 
 \LMHash{}
-Let $map_1 =$ \CONST{}$ <K, V>\{k_{11}:e_{11} \ldots k_{1n} :e_{1n}\}$ and  $map_2 =$  \CONST{}$ <J, U>\{k_{21}:e_{21} \ldots k_{2n} :e_{2n}\}$ be two constant map literals. Let the keys of $map_1$ and $map_2$ evaluate to  $s_{11} \ldots  s_{1n}$  and   $s_{21} \ldots  s_{2n}$ respectively, and let the elements of $map_1$ and $map_2$ evaluate to $o_{11} \ldots  o_{1n}$ and $o_{21} \ldots  o_{2n}$ respectively. Iff \code{identical($o_{1i}$, $o_{2i}$)}  and \code{identical($s_{1i}$, $s_{2i}$)} for $i \in 1.. n$, and $K = J, V = U$ then \code{identical($map_1$, $map_2$)}. 
+Let $map_1 =$ \CONST{}$ <K, V>\{k_{11}:e_{11} \ldots k_{1n} :e_{1n}\}$ and  $map_2 =$  \CONST{}$ <J, U>\{k_{21}:e_{21} \ldots k_{2n} :e_{2n}\}$ be two constant map literals. Let the keys of $map_1$ and $map_2$ evaluate to  $s_{11} \ldots  s_{1n}$  and   $s_{21} \ldots  s_{2n}$ respectively, and let the elements of $map_1$ and $map_2$ evaluate to $o_{11} \ldots  o_{1n}$ and $o_{21} \ldots  o_{2n}$ respectively. Iff \code{identical($o_{1i}$, $o_{2i}$)}  and \code{identical($s_{1i}$, $s_{2i}$)} for $i \in 1.. n$, and $K = J, V = U$ then \code{identical($map_1$, $map_2$)}.
 
 \commentary{In other words, constant map literals are canonicalized.}
 
@@ -2976,8 +2984,8 @@
 \item
 First, the expression $k_i$ is evaluated yielding object $u_i$, the $e_i$ is vaulted yielding object $o_i$, for $i \in 1..n$ in left to right order, yielding objects $u_1, o_1\ldots u_n, o_n$.
 \item  A fresh instance (\ref{generativeConstructors}) $m$ whose class implements the built-in class
- 
- $Map<K, V>$ is allocated. 
+
+ $Map<K, V>$ is allocated.
 \item
 The operator \code{[]=} is invoked on $m$ with  first  argument $u_i$ and second argument $o_i,  i \in 1.. n$.
 \item
@@ -2986,7 +2994,7 @@
 
 
 \LMHash{}
-A runtime map literal  $\{k_1:e_1\ldots k_n :e_n\}$ is evaluated as  
+A runtime map literal  $\{k_1:e_1\ldots k_n :e_n\}$ is evaluated as
 
 $<\DYNAMIC{},  \DYNAMIC{}>\{k_1:e_1\ldots k_n :e_n\}$.
 
@@ -2994,15 +3002,15 @@
 Iff all the keys in a map literal are compile-time constants, it is a static warning if the values of any two keys in a map literal are equal.
 
 \LMHash{}
-A map literal is ordered: iterating over the keys and/or values of the maps always happens in the 
+A map literal is ordered: iterating over the keys and/or values of the maps always happens in the
  order the keys appeared in the source code.
 
 \commentary{
 Of course, if a key repeats, the order is defined by first occurrence, but the value is defined by the last.
-} 
+}
 
 \LMHash{}
-The static type of a map literal of the form  \CONST{}$ <K, V>\{k_1:e_1\ldots k_n :e_n\}$ or the form $<K, V>\{k_1:e_1\ldots k_n :e_n\}$ is $Map<K, V>$. The static type a map literal of the form  \CONST{}$\{k_1:e_1\ldots k_n :e_n\}$ or the form $\{k_1:e_1\ldots k_n :e_n\}$ is $Map<\DYNAMIC{},  \DYNAMIC{}>$. 
+The static type of a map literal of the form  \CONST{}$ <K, V>\{k_1:e_1\ldots k_n :e_n\}$ or the form $<K, V>\{k_1:e_1\ldots k_n :e_n\}$ is $Map<K, V>$. The static type a map literal of the form  \CONST{}$\{k_1:e_1\ldots k_n :e_n\}$ or the form $\{k_1:e_1\ldots k_n :e_n\}$ is $Map<\DYNAMIC{},  \DYNAMIC{}>$.
 
 
 \subsection{Throw}
@@ -3013,23 +3021,23 @@
 
  \begin{grammar}
 {\bf throwExpression:}
-     \THROW{} expression 
+     \THROW{} expression
     .
-    
+
    {\bf throwExpressionWithoutCascade:}
-     \THROW{} expressionWithoutCascade 
+     \THROW{} expressionWithoutCascade
     .
- 
+
  \end{grammar}
- 
+
 \LMHash{}
- The {\em current exception} is the last exception raised and not subsequently caught at a given moment during runtime. 
+ The {\em current exception} is the last exception raised and not subsequently caught at a given moment during runtime.
 
 \LMHash{}
  Evaluation of a throw expression of the form  \code{\THROW{} $e$;} proceeds as follows:
- 
+
 \LMHash{}
-The expression $e$ is evaluated yielding a value $v$. 
+The expression $e$ is evaluated yielding a value $v$.
 
 \commentary{
 There is no requirement that the expression $e$ evaluate to a special kind of exception or error object.
@@ -3038,11 +3046,11 @@
 \LMHash{}
 If $e$ evaluates to \NULL{} (\ref{null}), then a \code{NullThrownError} is thrown. Otherwise the current exception is set to $v$ and the current return value (\ref{return}) becomes undefined.
 
-\rationale{The current exception and the current return value must never be simultaneously defined, as they represent mutually exclusive options for exiting the current function. 
+\rationale{The current exception and the current return value must never be simultaneously defined, as they represent mutually exclusive options for exiting the current function.
 }
 
 \LMHash{}
-Let $f$ be the immediately enclosing function. 
+Let $f$ be the immediately enclosing function.
 
 \LMHash{}
 If $f$ is synchronous (\ref{functions}), control is transferred to the nearest dynamically enclosing exception handler.
@@ -3069,16 +3077,16 @@
 \LMLabel{functionExpressions}
 
 \LMHash{}
-A {\em function literal} is an object that encapsulates an executable unit of code. 
+A {\em function literal} is an object that encapsulates an executable unit of code.
 
 \begin{grammar}
 {\bf functionExpression:}
     formalParameterList functionBody
     .
- \end{grammar}   
- 
+ \end{grammar}
+
 \LMHash{}
-The class of a function literal implements the built-in class \code{Function}.   
+The class of a function literal implements the built-in class \code{Function}.
 %Invoking the getter \code{runtimeType} on a function literal returns the \code{Type} object that is the value of the expression \code{Function}.
 % not necessarily
 
@@ -3086,35 +3094,35 @@
 %Q{Can anyone implement it? Then we should define things via call}
 
 \LMHash{}
-The static type of a function literal of the form 
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k} = d_k]) => e$ 
-is 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k} = d_k]) => e$
+is
 
-$(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow T_0$, where $T_0$ is the static type of $e$. 
+$(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow T_0$, where $T_0$ is the static type of $e$.
 
 \LMHash{}
-The static type of a function literal of the form 
+The static type of a function literal of the form
 
 $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k} = d_k])$ \ASYNC{} $=> e$
 is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Future<flatten(T_0)>$, where $T_0$ is the static type of $e$ and  $flatten(T)$ is defined as follows:
 
- If $T = Future<S>$ then $flatten(T) = flatten(S)$. 
- 
- Otherwise if $T <: Future$ then let $S$ be a type such that $T << Future<S>$ and for all $R$, if $T << Future<R>$ then $S << R$.  
+ If $T = Future<S>$ then $flatten(T) = flatten(S)$.
+
+ Otherwise if $T <: Future$ then let $S$ be a type such that $T << Future<S>$ and for all $R$, if $T << Future<R>$ then $S << R$.
 
 \rationale{
 This ensures that $Future<S>$ is the most specific instantiation of \cd{Future} that is a super type of $T$.
 }
 
-Then $flatten(T) =  S$.  
+Then $flatten(T) =  S$.
 
 In any other circumstance, $flatten(T) = T$.
 
 
 
 \rationale{
-We collapse multiple layers of futures into one. If $e$ evaluates to a future $f$, the future will not invoke its \code{then()} callback until f completes to a non-future value, and so the result of an await is never a future, and the result of an async function will never have type \code{Future$<X>$} where $X$ itself is an invocation of \code{Future}. 
+We collapse multiple layers of futures into one. If $e$ evaluates to a future $f$, the future will not invoke its \code{then()} callback until f completes to a non-future value, and so the result of an await is never a future, and the result of an async function will never have type \code{Future$<X>$} where $X$ itself is an invocation of \code{Future}.
 
 The  exception to that would be a type $X$ that extended or implemented \code{Future}. In that case, only one unwrapping takes place. As an example of why this is done, consider
 
@@ -3126,73 +3134,73 @@
 
 
 \LMHash{}
-The static type of a function literal of the form 
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1} : d_1, \ldots,  T_{n+k}$ $x_{n+k} : d_k\}) => e$ 
-is 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1} : d_1, \ldots,  T_{n+k}$ $x_{n+k} : d_k\}) => e$
+is
 
-$(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow T_0$, where $T_0$ is the static type of $e$. 
+$(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow T_0$, where $T_0$ is the static type of $e$.
 
 \LMHash{}
-The static type of a function literal of the form 
+The static type of a function literal of the form
 
 $(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1} : d_1, \ldots,  T_{n+k}$ $x_{n+k} : d_k\})$ \ASYNC{}  $=> e$
 
-is $(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow Future<flatten(T_0)>$, where $T_0$ is the static type of $e$. 
+is $(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow Future<flatten(T_0)>$, where $T_0$ is the static type of $e$.
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])\{s\}$ 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])\{s\}$
 
 is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow  \DYNAMIC{}$.
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])$ $ \ASYNC{}$ $\{s\}$ 
-is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Future$. 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])$ $ \ASYNC{}$ $\{s\}$
+is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Future$.
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])$ $ \ASYNC*{}$ $\{s\}$ 
-is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Stream$. 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])$ $ \ASYNC*{}$ $\{s\}$
+is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Stream$.
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])$ $ \SYNC*{}$ $\{s\}$ 
-is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Iterable$. 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])$ $ \SYNC*{}$ $\{s\}$
+is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow Iterable$.
 
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
-$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])\{s\}$ 
+$(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots,  T_{n+k}$ $x_{n+k}= d_k])\{s\}$
 
-is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow  \DYNAMIC{}$. 
+is $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow  \DYNAMIC{}$.
 
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
 $(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1} : d_1, \ldots,  T_{n+k}$ $x_{n+k} : d_k\})$ $\ASYNC{}$ $\{s\}$
- 
+
 is $(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow  Future{}$.
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
 $(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1} : d_1, \ldots,  T_{n+k}$ $x_{n+k} : d_k\})$ $\ASYNC*{}$ $\{s\}$
- 
+
 is $(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow  Stream{}$.
 
 \LMHash{}
-The static type of a function literal of the form  
+The static type of a function literal of the form
 
 $(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1} : d_1, \ldots,  T_{n+k}$ $x_{n+k} : d_k\})$ $\SYNC*{}$ $\{s\}$
- 
+
 is $(T_1 \ldots, T_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \rightarrow  Iterable{}$.
 
 \LMHash{}
@@ -3215,44 +3223,44 @@
 The static type of \THIS{} is the interface of the immediately enclosing class.
 
 \commentary{
-We do not support self-types at this point. 
+We do not support self-types at this point.
 }
 
 \LMHash{}
-It is a compile-time error if \THIS{} appears, implicitly or explicitly,  in a top-level function or variable initializer,  in a factory constructor, or in a static method or variable initializer, or in the initializer of an instance variable. 
+It is a compile-time error if \THIS{} appears, implicitly or explicitly,  in a top-level function or variable initializer,  in a factory constructor, or in a static method or variable initializer, or in the initializer of an instance variable.
 
 \subsection{ Instance Creation}
 \LMLabel{instanceCreation}
 
 \LMHash{}
-Instance creation expressions invoke constructors to produce instances. 
+Instance creation expressions invoke constructors to produce instances.
 
-%It is a compile-time error if any of the type arguments to a constructor of a generic type invoked by a new expression or a constant object expression do not denote types in the enclosing lexical scope. 
+%It is a compile-time error if any of the type arguments to a constructor of a generic type invoked by a new expression or a constant object expression do not denote types in the enclosing lexical scope.
 
 %It is a compile-time error if a constructor of a non-generic type invoked by a new expression or a constant object expression is passed any type arguments. It is a compile-time error if a constructor of a generic type with $n$ type parameters invoked by a new expression or a constant object expression is passed $m$ type arguments where $m \ne n$, or if any of its type arguments is  misconstructed (\ref{parameterizedTypes}).
 
 \LMHash{}
 It is a static type warning if
-the type $T$ in an instance creation expression of one of  the forms 
+the type $T$ in an instance creation expression of one of  the forms
 
-\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,  
+\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
 \NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
-\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,  
+\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
 \CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is malformed (\ref{dynamicTypeSystem}) or malbounded (\ref{parameterizedTypes}).
 
 \LMHash{}
-It is a compile-time error if the type $T$ in an instance creation expression of one of the forms 
+It is a compile-time error if the type $T$ in an instance creation expression of one of the forms
 
-\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,  
+\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
 \NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
-\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,  
+\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
-\CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
 is an enumerated type (\ref{enums}).
 %any of the type arguments to a constructor of a generic type $G$ invoked by a new expression or a constant object expression are not subtypes of the bounds of the corresponding formal type parameters of $G$.
@@ -3271,49 +3279,49 @@
 \end{grammar}
 
 \LMHash{}
-Let $e$ be a new expression of the form  
+Let $e$ be a new expression of the form
 
-\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ or the form  
+\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ or the form
 
-\NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. 
+\NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 %It is a runtime type error if
 %the type $T$  is malformed.
 %It is a static warning if $T$ is a malformed type.
 
-%not a class accessible in the current scope,  optionally followed by type arguments. 
+%not a class accessible in the current scope,  optionally followed by type arguments.
 
 \LMHash{}
 If $T$ is  a class or parameterized type accessible in the current scope then:
 \begin{itemize}
 \item
-If $e$ is of the form \NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a static warning if $T.id$ is not the name of a constructor declared by the type $T$. If $e$ is of the form  \NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a static warning if the type $T$ does not declare a constructor with the same name as the declaration of $T$. 
+If $e$ is of the form \NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a static warning if $T.id$ is not the name of a constructor declared by the type $T$. If $e$ is of the form  \NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a static warning if the type $T$ does not declare a constructor with the same name as the declaration of $T$.
 \end{itemize}
 
 \LMHash{}
-If $T$ is a parameterized type (\ref{parameterizedTypes}) $S<U_1,  \ldots, U_m>$, let $R = S$.  
-%It is a 
+If $T$ is a parameterized type (\ref{parameterizedTypes}) $S<U_1,  \ldots, U_m>$, let $R = S$.
+%It is a
 %compile-time CHANGED
 %runtime type
-%error if $S$ is not a generic (\ref{generics}) type with $m$ type parameters. 
+%error if $S$ is not a generic (\ref{generics}) type with $m$ type parameters.
 If $T$ is not a parameterized type, let $R = T$.
-Furthermore, if $e$ is of the form \NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ then let  $q$ be the constructor  $T.id$, otherwise let $q$ be the constructor $T$. 
+Furthermore, if $e$ is of the form \NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ then let  $q$ be the constructor  $T.id$, otherwise let $q$ be the constructor $T$.
 
 \LMHash{}
 If $R$ is a generic with $l = m$ type parameters then
 \begin{itemize}
 \item  If $T$ is not a parameterized type, then for $ i \in 1 .. l$, let $V_i =  \DYNAMIC{}$.
-\item  If $T$ is  a parameterized type then let $V_i = U_i$ for $ i \in 1 .. m$.  
+\item  If $T$ is  a parameterized type then let $V_i = U_i$ for $ i \in 1 .. m$.
 \end{itemize}
 
 \LMHash{}
-If $R$ is a generic with $l \ne m$ type parameters then for $ i \in 1 .. l$, let $V_i =  \DYNAMIC{}$. In any other case, let $V_i = U_i$ for $ i \in 1 .. m$.  
+If $R$ is a generic with $l \ne m$ type parameters then for $ i \in 1 .. l$, let $V_i =  \DYNAMIC{}$. In any other case, let $V_i = U_i$ for $ i \in 1 .. m$.
 
 \LMHash{}
 Evaluation of $e$ proceeds as follows:
 
 \LMHash{}
-First, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated. 
+First, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated.
 
 \LMHash{}
 If $T$ is a deferred type with prefix $p$, then if $p$ has not been successfully loaded, a dynamic error occurs.
@@ -3344,7 +3352,7 @@
 Otherwise, $q$ is a factory constructor (\ref{factories}). Then:
 
 \LMHash{}
-If $q$ is a redirecting factory constructor of the form $T(p_1, \ldots, p_{n+k}) = c;$ or of the form  $T.id(p_1, \ldots, p_{n+k}) = c;$ then the result of the evaluation of $e$ is equivalent to evaluating the expression 
+If $q$ is a redirecting factory constructor of the form $T(p_1, \ldots, p_{n+k}) = c;$ or of the form  $T.id(p_1, \ldots, p_{n+k}) = c;$ then the result of the evaluation of $e$ is equivalent to evaluating the expression
 
 $[V_1,  \ldots, V_m/T_1,  \ldots, T_m]($\code{\NEW{} $c(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k}))$}.  If evaluation of $q$ causes $q$ to be re-evaluated cyclically, a runtime error occurs.
 
@@ -3355,23 +3363,23 @@
 \LMHash{}
 It is a static warning if $q$ is a constructor of an abstract class and $q$ is not a factory constructor.
 
-\commentary{The above gives precise meaning to the idea that instantiating an abstract class leads to a warning. 
+\commentary{The above gives precise meaning to the idea that instantiating an abstract class leads to a warning.
 A similar clause applies to constant object creation in the next section.
-} 
+}
 
 \rationale{In particular, a factory constructor can be declared in an abstract class and used safely, as it will either produce a valid instance or lead to a warning inside its own declaration.
 }
 
 \LMHash{}
-The static type of an instance creation expression of either the form 
+The static type of an instance creation expression of either the form
 
-\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
-or the form 
+or the form
 
-\NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
-is $T$.  
+is $T$.
 It is a static warning if the static type of $a_i, 1 \le i \le n+ k$ may not be assigned to the type of the corresponding formal parameter of the constructor $T.id$ (respectively $T$).
 
 
@@ -3380,7 +3388,7 @@
 \LMLabel{const}
 
 \LMHash{}
-A {\em constant object expression} invokes a constant constructor (\ref{constantConstructors}). 
+A {\em constant object expression} invokes a constant constructor (\ref{constantConstructors}).
 
 \begin{grammar}
 {\bf constObjectExpression:}
@@ -3389,9 +3397,9 @@
 \end{grammar}
 
 \LMHash{}
-Let $e$ be a constant object expression of the form  
+Let $e$ be a constant object expression of the form
 
-\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
 or the form  \CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. It is a compile-time error if $T$ does not denote a class accessible in the current scope.  It is a compile-time error if $T$ is a deferred type (\ref{staticTypes}).
 
@@ -3401,40 +3409,40 @@
 If $T$ is a parameterized type, it is a compile-time error if $T$ includes a type variable among its type arguments.
 
 \LMHash{}
-If $e$ is of the form \CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a compile-time error if $T.id$ is not the name of a constant constructor declared by the type $T$. If $e$ is of the form  \CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a compile-time error if the type $T$ does not declare a constant constructor with the same name as the declaration of $T$. 
+If $e$ is of the form \CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a compile-time error if $T.id$ is not the name of a constant constructor declared by the type $T$. If $e$ is of the form  \CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ it is a compile-time error if the type $T$ does not declare a constant constructor with the same name as the declaration of $T$.
 
 \LMHash{}
 In all of the above cases, it is a compile-time error if $a_i,  i\in 1 .. n + k$, is not a compile-time constant expression.
 
 %If $T$ is a parameterized type (\ref{parameterizedTypes}) $S<U_1,  \ldots, U_m>$, let $R = S$.  It is a compile-time error if $T$ is is malformed. If $T$ is not a parameterized type, let $R = T$.
- %Finally, 
-% If $T$ is a generic with $l$ retype parameters, then for all $ i \in 1 .. l$, let $V_i =  \DYNAMIC{}$.  
+ %Finally,
+% If $T$ is a generic with $l$ retype parameters, then for all $ i \in 1 .. l$, let $V_i =  \DYNAMIC{}$.
 
 \LMHash{}
 Evaluation of $e$ proceeds as follows:
 
 \LMHash{}
-First, if $e$ is of the form 
+First, if $e$ is of the form
 
-\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
-then let $i$ be the value of the expression 
+then let $i$ be the value of the expression
 
-\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. 
+\NEW{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 \LMHash{}
-Otherwise, $e$ must be of the form  
+Otherwise, $e$ must be of the form
 
-\CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, 
+\CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
-in which case let $i$ be the result of evaluating 
+in which case let $i$ be the result of evaluating
 
-\NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. 
+\NEW{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 \LMHash{}
 Then:
 \begin{itemize}
-\item If during execution of the program, a constant object expression has already evaluated to an instance $j$ of class $R$ with type arguments $V_i, 1 \le i \le m$, then: 
+\item If during execution of the program, a constant object expression has already evaluated to an instance $j$ of class $R$ with type arguments $V_i, 1 \le i \le m$, then:
 \begin{itemize}
 \item For each instance variable $f$ of $i$, let $v_{if}$ be the value of the field $f$ in $i$, and let $v_{jf}$ be the value of the field $f$ in $j$. If  \code{identical($v_{if}$, $v_{jf}$)} for all fields $f$ in $i$, then the value of $e$ is $j$, otherwise the value of $e$ is $i$.
 \end{itemize}
@@ -3446,13 +3454,13 @@
 }
 
 \LMHash{}
-The static type of a constant object expression of either the form 
+The static type of a constant object expression of either the form
 
-\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\CONST{} $T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
-or the form  
+or the form
 
-\CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+\CONST{} $T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
 is $T$. It is a static warning if the static type of $a_i, 1 \le i \le n+ k$ may not be assigned to the type of the corresponding formal parameter of the constructor $T.id$ (respectively $T$).
 
@@ -3484,12 +3492,12 @@
 \end{dartCode}
 
 \commentary{
-Due to the rules governing constant constructors, evaluating the constructor \code{A()} with the argument \code{''x''} or the argument \code{\CONST{} IntPair(1, 2)} would cause it to throw an exception, resulting in a compile-time error.
+Due to the rules governing constant constructors, evaluating the constructor \code{A()} with the argument \code{"x"} or the argument \code{\CONST{} IntPair(1, 2)} would cause it to throw an exception, resulting in a compile-time error.
 }
 
 
 \LMHash{}
-Given an instance creation expression of the form \CONST{} $q(a_1, \ldots , a_n)$ it is a static warning if $q$ is a constructor of an abstract class  (\ref{abstractInstanceMembers}) but $q$ is not a factory constructor.  
+Given an instance creation expression of the form \CONST{} $q(a_1, \ldots , a_n)$ it is a static warning if $q$ is a constructor of an abstract class  (\ref{abstractInstanceMembers}) but $q$ is not a factory constructor.
 
 
 \subsection{ Spawning an Isolate}
@@ -3509,27 +3517,27 @@
 
 \subsection{ Function Invocation}
 \LMLabel{functionInvocation}
- 
-\LMHash{}
-Function invocation occurs in the following cases: when a function expression  (\ref{functionExpressions}) is invoked (\ref{functionExpressionInvocation}), when a method (\ref{methodInvocation}), getter (\ref{topLevelGetterInvocation}, \ref{propertyExtraction}) or setter (\ref{assignment}) is invoked or when a constructor is invoked (either via instance creation (\ref{instanceCreation}), constructor redirection (\ref{redirectingConstructors}) or super initialization). The various kinds of function invocation differ as to how the function to be invoked, $f$,  is determined, as well as whether \THIS{} (\ref{this}) is bound. Once $f$ has been determined, the formal parameters of $f$ are bound to corresponding actual arguments. When the body of $f$ is executed it will be executed with the aforementioned bindings. 
 
 \LMHash{}
-If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation and immediately returned to the caller. The body of $f$ is scheduled for execution at some future time. The future $o$ will complete when $f$ terminates. The value used to complete $o$ is the current return value (\ref{return}), if it is defined, and the current exception (\ref{throw}) otherwise. 
+Function invocation occurs in the following cases: when a function expression  (\ref{functionExpressions}) is invoked (\ref{functionExpressionInvocation}), when a method (\ref{methodInvocation}), getter (\ref{topLevelGetterInvocation}, \ref{propertyExtraction}) or setter (\ref{assignment}) is invoked or when a constructor is invoked (either via instance creation (\ref{instanceCreation}), constructor redirection (\ref{redirectingConstructors}) or super initialization). The various kinds of function invocation differ as to how the function to be invoked, $f$,  is determined, as well as whether \THIS{} (\ref{this}) is bound. Once $f$ has been determined, the formal parameters of $f$ are bound to corresponding actual arguments. When the body of $f$ is executed it will be executed with the aforementioned bindings.
+
+\LMHash{}
+If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation and immediately returned to the caller. The body of $f$ is scheduled for execution at some future time. The future $o$ will complete when $f$ terminates. The value used to complete $o$ is the current return value (\ref{return}), if it is defined, and the current exception (\ref{throw}) otherwise.
 
 \LMHash{}
 If $f$ is marked \ASYNC* (\ref{functions}), then a fresh instance $s$ implementing the built-in class \code{Stream} is associated with the invocation and immediately returned. When $s$ is listened to, execution of the body of $f$ will begin.  When $f$ terminates:
 \begin{itemize}
-\item If the current return value is defined then, if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}). 
+\item If the current return value is defined then, if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}).
 \item If the current exception $x$ is defined:
   \begin{itemize}
-  \item $x$ is added to $s$. 
+  \item $x$ is added to $s$.
   \item If $s$ has been canceled then its cancellation future is completed with $x$ as an error.
   \end{itemize}
 \item $s$ is closed.
 \end{itemize}
 
 \rationale{
-When an asynchronous generator's stream has been canceled, cleanup will occur in the \FINALLY{} clauses (\ref{try}) inside the generator. We choose to direct any exceptions that occur at this time to the cancellation future rather than have them be lost. 
+When an asynchronous generator's stream has been canceled, cleanup will occur in the \FINALLY{} clauses (\ref{try}) inside the generator. We choose to direct any exceptions that occur at this time to the cancellation future rather than have them be lost.
 }
 
 \LMHash{}
@@ -3542,11 +3550,11 @@
 %When a stream is canceled, the implementation must wait for the cancelation future returned by \cd{cancell()} to complete before proceeding.
 
 \LMHash{}
-If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned.  
+If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned.
 
 
 \commentary{
-A Dart implementation will need to provide a specific implementation of \code{Iterable} that will be returned by \SYNC* methods. A typical strategy would be to produce an instance of a subclass of class \code{IterableBase} defined in \code{dart:core}. The only method that needs to be added by the Dart implementation in that case is \code{iterator}.  
+A Dart implementation will need to provide a specific implementation of \code{Iterable} that will be returned by \SYNC* methods. A typical strategy would be to produce an instance of a subclass of class \code{IterableBase} defined in \code{dart:core}. The only method that needs to be added by the Dart implementation in that case is \code{iterator}.
 }
 
 \LMHash{}
@@ -3559,7 +3567,7 @@
 \LMHash{}
 When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()}, execution of the body of $f$ will begin. When $f$ terminates, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls.
 
-Each iterator starts a separate computation. If the \SYNC* function is impure, the sequence of values yielded by each iterator may differ. 
+Each iterator starts a separate computation. If the \SYNC* function is impure, the sequence of values yielded by each iterator may differ.
 
 \commentary{
 One can derive more than one iterator from a given iterable.   Note that operations on the iterable itself can create distinct iterators. An example would be \code{length}.  It is conceivable that different iterators might yield sequences of different length. The same care needs to be taken when writing \SYNC* functions as when
@@ -3570,7 +3578,7 @@
 }
 
 \LMHash{}
-Each iterator runs with its own shallow copies of all local variables; in particular, each iterator has the same initial arguments, even if their bindings are modified by the function. 
+Each iterator runs with its own shallow copies of all local variables; in particular, each iterator has the same initial arguments, even if their bindings are modified by the function.
 \commentary{
 Two executions of an iterator interact only via state outside the function.
 }
@@ -3584,7 +3592,7 @@
 \LMHash{}
 Execution of $f$ terminates when the first of the following occurs:
 \begin{itemize}
-\item An exception is thrown and not caught within the current function activation. 
+\item An exception is thrown and not caught within the current function activation.
 \item A return statement (\ref{return}) immediately nested in the body of $f$ is executed and not intercepted in a \FINALLY{} (\ref{try}) clause.
 \item The last statement of the body completes execution.
 \end{itemize}
@@ -3615,9 +3623,9 @@
  \end{grammar}
 
 \LMHash{}
-Evaluation of an actual argument list of the form 
+Evaluation of an actual argument list of the form
 
-$(a_1, \ldots, a_m, q_1: a_{m+1}, \ldots, q_l: a_{m+l})$ 
+$(a_1, \ldots, a_m, q_1: a_{m+1}, \ldots, q_l: a_{m+l})$
 
 proceeds as follows:
 
@@ -3647,7 +3655,7 @@
 
 
 \LMHash{}
-If  $m < h$, or $m > n$, a \cd{NoSuchMethodError} is thrown. Furthermore, each $q_i, 1 \le i \le l$,  must have a corresponding named parameter in the set $\{p_{n+1}, \ldots, p_{n +k}\}$ or a \cd{NoSuchMethodError} is thrown. Then $p_i$ is bound to $o_i, i \in 1.. m$, and $q_j$  is bound to $o_{m+j}, j \in 1.. l$.  All remaining formal parameters of $f$  are bound to their default values. 
+If  $m < h$, or $m > n$, a \cd{NoSuchMethodError} is thrown. Furthermore, each $q_i, 1 \le i \le l$,  must have a corresponding named parameter in the set $\{p_{n+1}, \ldots, p_{n +k}\}$ or a \cd{NoSuchMethodError} is thrown. Then $p_i$ is bound to $o_i, i \in 1.. m$, and $q_j$  is bound to $o_{m+j}, j \in 1.. l$.  All remaining formal parameters of $f$  are bound to their default values.
 
 \commentary{All of these remaining parameters are necessarily optional and thus have default values.}
 
@@ -3664,16 +3672,16 @@
 \LMLabel{unqualifiedInvocation}
 
 \LMHash{}
-An unqualified function invocation $i$ has the form 
+An unqualified function invocation $i$ has the form
 
-$id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$, 
+$id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$,
 
-where $id$ is an identifier. 
+where $id$ is an identifier.
 
 \LMHash{}
 If there exists a lexically visible declaration named $id$, let $f_{id}$ be the innermost such declaration. Then:
 \begin{itemize}
-\item 
+\item
 If $f_{id}$ is a prefix object, a compile-time error occurs.
 \item
  If $f_{id}$ is a local function, a library function, a library or static getter or a variable then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}).
@@ -3700,11 +3708,11 @@
 \LMLabel{functionExpressionInvocation}
 
 \LMHash{}
-A function expression invocation $i$ has the form 
+A function expression invocation $i$ has the form
 
-$e_f(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, 
+$e_f(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$,
 
-where $e_f$ is an expression. If $e_f$ is an identifier $id$, then $id$ must necessarily denote a local function, a library function, a library or static getter or a variable as described above, or $i$ is not considered a function expression invocation. If $e_f$ is a property extraction expression (\ref{propertyExtraction}), then $i$ is is not a function expression invocation and is instead recognized as an ordinary method invocation (\ref{ordinaryInvocation}). 
+where $e_f$ is an expression. If $e_f$ is an identifier $id$, then $id$ must necessarily denote a local function, a library function, a library or static getter or a variable as described above, or $i$ is not considered a function expression invocation. If $e_f$ is a property extraction expression (\ref{propertyExtraction}), then $i$ is is not a function expression invocation and is instead recognized as an ordinary method invocation (\ref{ordinaryInvocation}).
 
 \commentary{
 \code{$a.b(x)$} is parsed as a method invocation of method \code{$b()$} on object \code{$a$}, not as an invocation of getter \code{$b$} on \code{$a$} followed by a function call \code{$(a.b)(x)$}.  If a method or getter \code{$b$} exists, the two will be equivalent. However, if \code{$b$} is not defined on \code{$a$}, the resulting invocation of \code{noSuchMethod()} would differ.  The \code{Invocation} passed to \code{noSuchMethod()} would describe a call to a method \code{$b$} with argument \code{$x$} in the former case, and a call to a getter \code{$b$} (with no arguments) in the latter.
@@ -3720,8 +3728,8 @@
 }
 
 \LMHash{}
-It is a static warning if the static type $F$ of $e_f$ may not be assigned to a function type.  If $F$ is not a function type, the static type of $i$ is \DYNAMIC{}. Otherwise 
-the static type of $i$ is the declared return type of  $F$.  
+It is a static warning if the static type $F$ of $e_f$ may not be assigned to a function type.  If $F$ is not a function type, the static type of $i$ is \DYNAMIC{}. Otherwise
+the static type of $i$ is the declared return type of  $F$.
 %\item Let $T_i$ be the static type of $a_i, i \in 1 .. n+k$. It is a static warning if $F$ is not a supertype of  $(T_1, \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \to \bot$.
 %\end{itemize}
 
@@ -3739,7 +3747,7 @@
 If $C$ declares a concrete instance method named $m$ that is accessible to $L$,  then that method is the result of the lookup, and we say that the method was {\em looked up in $C$}. Otherwise, if $C$ has a superclass $S$, then the result of the lookup is the result of looking up $m$  in $S$ with respect to $L$. Otherwise, we say that the method lookup has failed.
 
 \rationale {
-The motivation for skipping abstract members during lookup is largely to allow smoother mixin composition. 
+The motivation for skipping abstract members during lookup is largely to allow smoother mixin composition.
 }
 
 
@@ -3754,7 +3762,7 @@
 If $C$ declares a concrete instance getter (respectively setter) named $m$  that is accessible to $L$,  then that getter (respectively setter) is the result of the lookup, and we say that the getter (respectively setter) was {\em looked up in $C$}. Otherwise, if $C$ has a superclass $S$, then the result of the lookup is the result of looking up getter (respectively setter) $m$ in $S$ with respect to $L$. Otherwise, we say that the lookup has failed.
 
 \rationale {
-The motivation for skipping abstract members during lookup is largely to allow smoother mixin composition. 
+The motivation for skipping abstract members during lookup is largely to allow smoother mixin composition.
 }
 
 
@@ -3767,7 +3775,7 @@
 \LMHash{}
 The getter function $m$ is invoked. The value of $i$ is the result returned by the call to the getter function.
 \commentary{
-Note that the invocation is always defined. Per the rules for identifier references, an identifier will not be treated as a top-level getter invocation unless the getter $i$ is defined. 
+Note that the invocation is always defined. Per the rules for identifier references, an identifier will not be treated as a top-level getter invocation unless the getter $i$ is defined.
 }
 
 \LMHash{}
@@ -3777,7 +3785,7 @@
 \LMLabel{methodInvocation}
 
 \LMHash{}
-Method invocation can take several forms as specified below. 
+Method invocation can take several forms as specified below.
 
 \subsubsection{Ordinary Invocation}
 \LMLabel{ordinaryInvocation}
@@ -3786,16 +3794,16 @@
 An ordinary method invocation can be {\em conditional} or {\em unconditional}.
 
 \LMHash{}
-Evaluation of a {\em conditional ordinary method invocation} $e$ of the form 
+Evaluation of a {\em conditional ordinary method invocation} $e$ of the form
 
 \LMHash{}
-$o?.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$  
+$o?.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
 \LMHash{}
-is equivalent to the evaluation of the expression  
+is equivalent to the evaluation of the expression
 
 \LMHash{}
-$((x) => x == \NULL ? \NULL : x.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k}))(o)$. 
+$((x) => x == \NULL ? \NULL : x.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k}))(o)$.
 
 unless $o$ is  a type literal, in which case it is equivalent to $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
@@ -3803,25 +3811,25 @@
 The static type of $e$ is the same as the static type of $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. Exactly the same static warnings that would be caused by $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ are also generated in the case of $o?.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 \LMHash{}
-An {\em unconditional ordinary method invocation} $i$ has the form 
+An {\em unconditional ordinary method invocation} $i$ has the form
 
 $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 \LMHash{}
-Evaluation of an unconditional ordinary method invocation $i$ of the form 
+Evaluation of an unconditional ordinary method invocation $i$ of the form
 
-$o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
+$o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$
 
 proceeds as follows:
 
 \LMHash{}
-First, the expression $o$ is evaluated to a value $v_o$. Next, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated yielding actual argument objects $o_1, \ldots , o_{n+k}$. Let $f$ be the result of looking up (\ref{methodLookup}) method $m$  in $v_o$ with respect to the current library $L$. 
+First, the expression $o$ is evaluated to a value $v_o$. Next, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated yielding actual argument objects $o_1, \ldots , o_{n+k}$. Let $f$ be the result of looking up (\ref{methodLookup}) method $m$  in $v_o$ with respect to the current library $L$.
 
 \LMHash{}
 Let $p_1 \ldots p_h$ be the required parameters of $f$,  let $p_1 \ldots p_m$ be the positional parameters of $f$ and let $p_{h+1}, \ldots, p_{h+l}$ be the optional parameters declared by $f$.
 
 \commentary{
-We have an argument list consisting of $n$ positional arguments and $k$ named arguments. We have a function with $h$ required parameters and $l$ optional parameters. The number of positional arguments must be at least as large as the number of required parameters, and no larger than the number of positional parameters. All named arguments must have a corresponding named parameter. 
+We have an argument list consisting of $n$ positional arguments and $k$ named arguments. We have a function with $h$ required parameters and $l$ optional parameters. The number of positional arguments must be at least as large as the number of required parameters, and no larger than the number of positional parameters. All named arguments must have a corresponding named parameter.
 }
 
 \LMHash{}
@@ -3831,9 +3839,9 @@
 If the method lookup succeeded, the body of $f$ is executed with respect to the bindings that resulted from the evaluation of the argument list, and with \THIS{} bound to $v_o$. The value of $i$ is the value returned after $f$ is executed.
 
 \LMHash{}
-If the method lookup has failed, then let $g$ be the result of looking up getter (\ref{getterAndSetterLookup}) $m$ in $v_o$ with respect to $L$. 
+If the method lookup has failed, then let $g$ be the result of looking up getter (\ref{getterAndSetterLookup}) $m$ in $v_o$ with respect to $L$.
 If $v_o$ is an instance of \code{Type} but $o$ is not a constant type literal, then if $g$ is a getter that forwards to a static getter, getter lookup fails.
-If the getter lookup succeeded, let $v_g$ be the value of the getter invocation $o.m$. Then the value of $i$ is the result of invoking 
+If the getter lookup succeeded, let $v_g$ be the value of the getter invocation $o.m$. Then the value of $i$ is the result of invoking
 the static method \code{Function.apply()} with arguments $v.g, [o_1, \ldots , o_n], \{x_{n+1}: o_{n+1}, \ldots , x_{n+k}: o_{n+k}\}$.
 
 \LMHash{}
@@ -3864,7 +3872,7 @@
     noSuchMethod(x,y) =$>$ x + y;
 \}
 
-\NEW{} Perverse.unknownMethod(); 
+\NEW{} Perverse.unknownMethod();
 \end{code}
 
 \commentary{Notice that the wording carefully avoids re-evaluating the receiver $o$ and the arguments $a_i$. }
@@ -3875,12 +3883,12 @@
 \item
 $T$ or a superinterface of $T$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}.  Or
 \item  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ has a static getter named $m$.
-\item $T$ is \code{Function} and $m$ is \CALL. \rationale {The type \code{Function} is treated as if it has a \code{call} method for any possible signature of \CALL. The expectation is that any concrete subclass of \code{Function} will implement \CALL. Note that a warning will be issue if this is not the case. Furthermore, any use of \CALL{} on a subclass of \code{Function} that fails to implement \CALL{} will also provoke a a warning, as this exemption is limited to type \code{Function}, and does not apply to its subtypes. 
+\item $T$ is \code{Function} and $m$ is \CALL. \rationale {The type \code{Function} is treated as if it has a \code{call} method for any possible signature of \CALL. The expectation is that any concrete subclass of \code{Function} will implement \CALL. Note that a warning will be issue if this is not the case. Furthermore, any use of \CALL{} on a subclass of \code{Function} that fails to implement \CALL{} will also provoke a warning, as this exemption is limited to type \code{Function}, and does not apply to its subtypes.
 }
 \end{itemize}
 
 \LMHash{}
-If $T.m$ exists, it  is a static type warning if the type $F$ of $T.m$ may not be assigned to a function type. If $T.m$ does not exist, or if $F$ is not a function type, the static type of $i$ is \DYNAMIC{}; otherwise the static type of $i$ is the declared return type of  $F$.  
+If $T.m$ exists, it  is a static type warning if the type $F$ of $T.m$ may not be assigned to a function type. If $T.m$ does not exist, or if $F$ is not a function type, the static type of $i$ is \DYNAMIC{}; otherwise the static type of $i$ is the declared return type of  $F$.
 
 \LMHash{}
 It is a compile-time error to invoke any of the methods of class \cd{Object} on a prefix object (\ref{imports}) or on a constant type literal that is  immediately followed by the token `.'.
@@ -3897,7 +3905,7 @@
 {\bf cascadeSection:}
       `{\escapegrammar ..}' (cascadeSelector arguments*) (assignableSelector arguments*)* (assignmentOperator expressionWithoutCascade)?
       .
-     
+
 {\bf cascadeSelector:}`['  expression `]';
       identifier
       .
@@ -3916,7 +3924,7 @@
 \LMLabel{superInvocation}
 
 \LMHash{}
-A super method invocation $i$ has the form 
+A super method invocation $i$ has the form
 
 $\SUPER{}.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
@@ -3924,7 +3932,7 @@
 Evaluation of $i$ proceeds as follows:
 
 \LMHash{}
-First, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated  yielding actual argument objects $o_1, \ldots , o_{n+k}$. Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up (\ref{methodLookup}). Let $S_{dynamic}$ be the superclass of $C$, and let $f$ be the result of looking up method (\ref{methodLookup})  $m$ in $S_{dynamic}$  with respect to the current library $L$. 
+First, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated  yielding actual argument objects $o_1, \ldots , o_{n+k}$. Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up (\ref{methodLookup}). Let $S_{dynamic}$ be the superclass of $C$, and let $f$ be the result of looking up method (\ref{methodLookup})  $m$ in $S_{dynamic}$  with respect to the current library $L$.
 Let $p_1 \ldots p_h$ be the required parameters of $f$,  let $p_1 \ldots p_m$ be the positional parameters of $f$ and let $p_{h+1}, \ldots, p_{h+l}$ be the optional parameters declared by $f$.
 
 \LMHash{}
@@ -3934,9 +3942,9 @@
 If the method lookup succeeded, the body of $f$ is executed with respect to the bindings that resulted from the evaluation of the argument list, and with \THIS{} bound to the current value of \THIS{}. The value of $i$ is the value returned after $f$ is executed.
 
 \LMHash{}
-If the method lookup has failed, then let $g$ be the result of looking up getter (\ref{getterAndSetterLookup}) $m$ in $S_{dynamic}$ with respect to $L$. If the getter lookup succeeded, let $v_g$ be the value of the getter invocation $\SUPER{}.m$. Then the value of $i$ is the result of invoking 
+If the method lookup has failed, then let $g$ be the result of looking up getter (\ref{getterAndSetterLookup}) $m$ in $S_{dynamic}$ with respect to $L$. If the getter lookup succeeded, let $v_g$ be the value of the getter invocation $\SUPER{}.m$. Then the value of $i$ is the result of invoking
 the static method \code{Function.apply()} with arguments $v_g, [o_1, \ldots , o_n], \{x_{n+1}: o_{n+1}, \ldots , x_{n+k}: o_{n+k}\}$.
- 
+
 \LMHash{}
 If  getter lookup has also failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
 \begin{itemize}
@@ -3960,7 +3968,7 @@
 It is a compile-time error if a super method invocation occurs in a top-level function or variable initializer, in an instance variable initializer or initializer list, in class \code{Object}, in a factory constructor or in a static method or variable initializer.
 
 \LMHash{}
-Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible (\ref{privacy}) instance member named $m$ unless $S_{static}$ or a superinterface of $S_{static}$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. If $S_{static}.m$ exists, it  is a static type warning if the type $F$ of $S_{static}.m$ may not be assigned to a function type. If $S_{static}.m$ does not exist, or if $F$ is not a function type, the static type of $i$ is \DYNAMIC{}; otherwise the static type of $i$ is the declared return type of  $F$.  
+Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible (\ref{privacy}) instance member named $m$ unless $S_{static}$ or a superinterface of $S_{static}$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. If $S_{static}.m$ exists, it  is a static type warning if the type $F$ of $S_{static}.m$ may not be assigned to a function type. If $S_{static}.m$ does not exist, or if $F$ is not a function type, the static type of $i$ is \DYNAMIC{}; otherwise the static type of $i$ is the declared return type of  $F$.
 % The following is not needed because it is specified in 'Binding Actuals to Formals"
 %Let $T_i$ be the static type of $a_i, i \in 1 .. n+k$. It is a static warning if $F$ is not a supertype of  $(T_1, \ldots, t_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \to \bot$.
 
@@ -3971,7 +3979,7 @@
 \LMLabel{sendingMessages}
 
 \LMHash{}
-Messages are the sole means of communication among isolates. Messages are sent by invoking specific  methods in the Dart libraries; there is no specific syntax for sending a message. 
+Messages are the sole means of communication among isolates. Messages are sent by invoking specific  methods in the Dart libraries; there is no specific syntax for sending a message.
 
 \commentary{In other words, the methods supporting sending messages embody primitives of Dart that are not accessible to ordinary code, much like the methods that spawn isolates.
 }
@@ -3998,7 +4006,7 @@
 Tear-offs using the \cd{ x\#id}  syntax cannot be conditional at this time; this is inconsistent, and is likely to be addressed in the near future, perhaps via  notation such as  \cd{ x?\#id} . As indicated in section \ref{ecmaConformance}, experimentation in this area is allowed.
 }
 
-Evaluation of a {\em conditional property extraction expression} $e$ of the form $e_1?.id$  is equivalent to the evaluation of the expression  $((x) => x == \NULL ? \NULL : x.id)(e_1)$. 
+Evaluation of a {\em conditional property extraction expression} $e$ of the form $e_1?.id$  is equivalent to the evaluation of the expression  $((x) => x == \NULL ? \NULL : x.id)(e_1)$.
 unless $e_1$ is  a type literal, in which case it is equivalent to $e_1.m$.
 
 The static type of $e$ is the same as the static type of $e_1.id$. Let $T$ be the static type of $e_1$ and let $y$ be a fresh variable of type $T$. Exactly the same static warnings that would be caused by $y.id$ are also generated in the case of $e_1?.id$.
@@ -4013,7 +4021,7 @@
 Evaluation of a property extraction $i$ of the form $e.m$ proceeds as follows:
 
 \LMHash{}
-First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up (\ref{methodLookup}) method  (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$.  If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards (\ref{functionDeclarations}) to a static method,  method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).  
+First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up (\ref{methodLookup}) method  (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$.  If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards (\ref{functionDeclarations}) to a static method,  method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).
 
 \commentary {
 Note that $f$ is never an abstract method, because method lookup skips abstract methods. Hence, if $m$ refers to an abstract method, we will continue to the next step. However, since methods and getters never override each other, getter lookup will necessarily fail as well, and \cd{noSuchMethod()} will ultimately be invoked. The regrettable implication is that the error will refer to a missing getter rather than an attempt to closurize an abstract method.
@@ -4021,7 +4029,7 @@
 
 \LMHash{}
 Otherwise, $i$ is a getter invocation.  Let $f$ be the result of looking up
-(\ref{getterAndSetterLookup}) getter (\ref{getters}) $m$ in $o$  with respect to $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a getter that forwards  to a static getter,  getter lookup fails. Otherwise, the body of $f$ is executed with \THIS{} bound to $o$.  The value of $i$ is the result returned by the call to the getter function. 
+(\ref{getterAndSetterLookup}) getter (\ref{getters}) $m$ in $o$  with respect to $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a getter that forwards  to a static getter,  getter lookup fails. Otherwise, the body of $f$ is executed with \THIS{} bound to $o$.  The value of $i$ is the result returned by the call to the getter function.
 
 \LMHash{}
 If the getter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4063,7 +4071,7 @@
 \item The declared return type of $m$, if  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static getter named $m$.
 \item The static type of function $T.m$ if $T$ has an accessible instance method named $m$.
 \item The static type of function $m$, if  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static method named $m$.
-\item  The type \DYNAMIC{} otherwise.  
+\item  The type \DYNAMIC{} otherwise.
 \end{itemize}
 
 
@@ -4074,10 +4082,10 @@
 Evaluation of a property extraction $i$ of the form $\SUPER.m$ proceeds as follows:
 
 \LMHash{}
-Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. Let $f$ be the result of looking up method $m$ in $S_{dynamic}$ with respect to the current library $L$.  If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).  
- 
+Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. Let $f$ be the result of looking up method $m$ in $S_{dynamic}$ with respect to the current library $L$.  If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).
+
 \LMHash{}
- Otherwise, $i$ is a getter invocation.  Let $f$ be the result of  looking up getter $m$ in $S_{dynamic}$  with respect to $L$.  The body of $f$  is executed with \THIS{} bound to the current value of  \THIS{}.  The value of $i$ is the result returned by the call to the getter function. 
+ Otherwise, $i$ is a getter invocation.  Let $f$ be the result of  looking up getter $m$ in $S_{dynamic}$  with respect to $L$.  The body of $f$  is executed with \THIS{} bound to the current value of  \THIS{}.  The value of $i$ is the result returned by the call to the getter function.
 
 \LMHash{}
 If the getter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4097,13 +4105,13 @@
 and the result of this latter invocation is the result of evaluating $i$.
 
 \LMHash{}
-Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible instance method or getter named $m$.  
+Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible instance method or getter named $m$.
 
 The static type of $i$ is:
 \begin{itemize}
 \item The declared return type of $S_{static}.m$, if $S_{static}$ has an accessible instance getter named $m$.
 \item The static type of function $S_{static}.m$ if $S_{static}$ has an accessible instance method named $m$.
-\item The type  \DYNAMIC{} otherwise. 
+\item The type  \DYNAMIC{} otherwise.
 \end{itemize}
 
 
@@ -4117,23 +4125,23 @@
 First, the expression $e$ is evaluated to an object $o$.  Then:
 
 \LMHash{}
- if $m$ is a setter name, let $f$ be the result of looking up setter $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static setter, setter lookup fails. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$ on object $o$ (\ref{ordinaryMemberClosurization}). 
+ if $m$ is a setter name, let $f$ be the result of looking up setter $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static setter, setter lookup fails. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$ on object $o$ (\ref{ordinaryMemberClosurization}).
  If setter lookup failed, a \cd{NoSuchMethodError} is thrown.
- 
+
   \rationale {
 It would be more in keeping with the rules of Dart to invoke \cd{noSuchMethod} in this and similar cases below. However,  current implementations of \cd{noSuchMethod} cannot distinguish between an invocation of a closurization and an actual call.  It is likely that future versions of Dart will provide a mechanism to detect whether \cd{noSuchMethod} is invoked in response to a closurization, say by means of a getter like \cd{isTearOff}. By being conservative at this stage and insisting on failure, we can ensure that no functioning code will break when/if this functionality is introduced.
  }
 
- 
+
  \LMHash{}
-If $m$ is not a setter name, let $f$ be the result of looking up method $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static method, method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).  
- 
+If $m$ is not a setter name, let $f$ be the result of looking up method $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static method, method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).
+
 \LMHash{}
-If method lookup failed, let $f$ be the result of looking up getter $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static getter, getter lookup fails. If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ on object $o$ (\ref{ordinaryMemberClosurization}).  
+If method lookup failed, let $f$ be the result of looking up getter $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static getter, getter lookup fails. If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ on object $o$ (\ref{ordinaryMemberClosurization}).
  If getter lookup failed, a \cd{NoSuchMethodError} is thrown.
- 
-  
- 
+
+
+
 
 %\LMHash{}
 %Otherwise,  a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4153,7 +4161,7 @@
 %and the result of this latter invocation is the result of evaluating $i$.
 
 \LMHash{}
-It is a compile-time error if $e$ is a prefix object (\ref{imports}) and $m$ refers to a type or a member of class \cd{Object}.
+It is a compile-time error if $e$ is a prefix object, $p$, (\ref{imports}) and $m$ refers to a type accessible via $p$ or to a member of class \cd{Object}.
 
 \commentary{
 This restriction is in line with other limitations on the use of prefixes as objects. The only permitted uses of $p\#m$ are closurizing top level methods and getters imported via the prefix $p$. Top level methods are directly available by their qualified names: $p.m$. However, getters and setters are not, and allowing their closurization is the whole point of the $e\#m$ syntax.
@@ -4172,7 +4180,7 @@
 \item The static type of function $T.m$, if $T$ has an accessible instance member named $m$.
 \item The static type of function $T.m$, if $T$ is \cd{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static member or constructor named $m$.
 \item \code{Function} if $T$ is \code{Function} and $m$ is \CALL.
-\item The type  \DYNAMIC{} otherwise. 
+\item The type  \DYNAMIC{} otherwise.
 \end{itemize}
 
 \subsubsection{Named Constructor Extraction}
@@ -4189,6 +4197,8 @@
 \LMHash{}
 The static type of $i$ is the type of the constructor function, if $T$ denotes a class in the surrounding scope with an accessible constructor $f$ named $m$. Otherwise the static type of $i$ is \DYNAMIC{}.
 
+It is a compile-time error if $T$ is an enumerated type (\ref{enums}).
+
 \subsubsection{Anonymous Constructor Extraction}
 \LMLabel{anonymousConstructorExtraction}
 
@@ -4203,6 +4213,9 @@
 \LMHash{}
 The static type of $i$ is the type of the constructor function $T()$, if $T$ denotes a class in the surrounding scope with an anonymous constructor $T()$. Otherwise the static type of $i$ is \DYNAMIC{}.
 
+It is a compile-time error if $T$ is an enumerated type (\ref{enums}).
+
+
 \subsubsection{General Super Property Extraction}
 \LMLabel{generalSuperPropertyExtraction}
 
@@ -4211,7 +4224,7 @@
 Evaluation of a property extraction $i$ of the form \SUPER$\#m$ proceeds as follows:
 
  \LMHash{}
-Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. 
+Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$.
 
  \LMHash{}
 If $m$ is a setter name, let $f$ be the result of looking up setter $m$ in $S_{dynamic}$ with respect to the current library $L$. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$  with respect to superclass $S_{dynamic}$  (\ref{superClosurization}).  If setter lookup failed, a \cd{NoSuchMethodError} is thrown.
@@ -4241,14 +4254,14 @@
 \item $() \{\RETURN{}$ \~{} $u;$\} if $f$ is named \~{}.
 \item $(a) \{\RETURN{}$ $u[a];$\} if $f$ is named $[]$.
 \item $(a, b) \{\RETURN{}$ $u[a] = b;$\} if $f$ is named $[]=$.
-\item  
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
   \RETURN{} $ u.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
-\} 
+\}
 \end{dartCode}
 if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
-\item 
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
   \RETURN{} $u.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
@@ -4291,15 +4304,15 @@
 \LMHash{}
 The {\em closurization of constructor $f$ of type $T$} is defined to be equivalent to:
 \begin{itemize}
-\item  
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
   \RETURN{} \NEW{} $T.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
-\} 
+\}
 \end{dartCode}
 
 if $f$ is a named constructor with name $m$ that has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
-\item 
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
   \RETURN{} \NEW{} $T.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
@@ -4312,7 +4325,7 @@
 \LMHash{}
 Except that iff  \code{identical($T_1, T_2$)}  then  \cd{\NEW{} $T_1\#m$ == \NEW{} $T_2\#m$}.
 
-\commentary{ 
+\commentary{
 The above implies that for non-parameterized types, one can rely on the equality of closures resulting from closurization on the ``same'' type. For parameterized types, one cannot, since there is no requirement to canonicalize them.
 }
 
@@ -4322,15 +4335,15 @@
 \LMHash{}
 The {\em closurization of anonymous constructor $f$ of type $T$} is defined to be equivalent to:
 \begin{itemize}
-\item  
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
   \RETURN{} \NEW{} $T(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
-\} 
+\}
 \end{dartCode}
 
 if $f$ is an anonymous constructor that has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
-\item 
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
   \RETURN{} \NEW{} $T(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
@@ -4356,14 +4369,14 @@
 \item $() \{\RETURN{}$ \~{}\SUPER;\} if $f$ is named \~{}.
 \item $(a) \{\RETURN{}$ $\SUPER[a];$\} if $f$ is named $[]$.
 \item $(a, b) \{\RETURN{}$ $\SUPER[a] = b;$\} if $f$ is named $[]=$.
-\item  
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
   \RETURN{} \SUPER$.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
-\} 
+\}
 \end{dartCode}
 if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
-\item 
+\item
 \begin{dartCode}
 $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
   \RETURN{} \SUPER$.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
@@ -4403,11 +4416,11 @@
 
 %If there is neither a local variable declaration with name $v$ nor a setter declaration with name $v=$ in the lexical scope enclosing $a$, then:
 %\begin{itemize}
-% \item If  $a$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $a$ causes $e$ to be evaluated, after which a \code{NoSuchMethodError} is thrown. 
-% \item Otherwise, the assignment is equivalent to the assignment \code{ \THIS{}.$v$ = $e$}. 
+% \item If  $a$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $a$ causes $e$ to be evaluated, after which a \code{NoSuchMethodError} is thrown.
+% \item Otherwise, the assignment is equivalent to the assignment \code{ \THIS{}.$v$ = $e$}.
 % \end{itemize}
- 
-%Otherwise 
+
+%Otherwise
 
 \LMHash{}
 Let $d$ be the innermost declaration whose name is $v$ or $v=$, if it exists.
@@ -4415,21 +4428,21 @@
 
 \LMHash{}
 If $d$ is the declaration of a local variable, the expression $e$ is evaluated to an object $o$. Then, the variable $v$ is bound to $o$ unless $v$ is \FINAL{} or \CONST{}, in which case a dynamic error occurs.
-If no error occurs, the value of the assignment expression is $o$.  
+If no error occurs, the value of the assignment expression is $o$.
 
 % add local functions per bug 23218
 
 \LMHash{}
-If $d$ is the declaration of a library variable, top level getter or top level setter, the expression $e$ is evaluated to an object $o$. Then the setter $v=$ is invoked with its formal parameter bound to $o$. The value of the assignment expression is $o$.  
+If $d$ is the declaration of a library variable, top level getter or top level setter, the expression $e$ is evaluated to an object $o$. Then the setter $v=$ is invoked with its formal parameter bound to $o$. The value of the assignment expression is $o$.
 
 \LMHash{}
 Otherwise, if $d$ is the declaration of a static variable, static getter or static setter in class $C$, then the assignment is equivalent to the assignment \code{$C.v$ = $e$}.
 
 \LMHash{}
-Otherwise, If  $a$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $a$ causes $e$ to be evaluated, after which a \code{NoSuchMethodError} is thrown. 
+Otherwise, If  $a$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $a$ causes $e$ to be evaluated, after which a \code{NoSuchMethodError} is thrown.
 
 \LMHash{}
-Otherwise, the assignment is equivalent to the assignment \code{ \THIS{}.$v$ = $e$}. 
+Otherwise, the assignment is equivalent to the assignment \code{ \THIS{}.$v$ = $e$}.
 
 \LMHash{}
 In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type (\ref{actualTypeOfADeclaration}) of $v$.
@@ -4446,7 +4459,7 @@
 Evaluation of an assignment of the form $e_1.v$ \code{=} $e_2$ proceeds as follows:
 
 \LMHash{}
-The expression $e_1$ is evaluated to an object $o_1$. Then, the expression $e_2$  is evaluated to an object $o_2$. Then, the setter $v=$ is looked up (\ref{getterAndSetterLookup}) in $o_1$ with respect to the current library.  If $o_1$ is an instance of \code{Type} but $e_1$ is not a constant type literal, then if $v=$ is a setter that forwards (\ref{functionDeclarations}) to a static setter, setter lookup fails. Otherwise, the body  of $v=$ is executed with its formal parameter bound to $o_2$ and \THIS{} bound to $o_1$. 
+The expression $e_1$ is evaluated to an object $o_1$. Then, the expression $e_2$  is evaluated to an object $o_2$. Then, the setter $v=$ is looked up (\ref{getterAndSetterLookup}) in $o_1$ with respect to the current library.  If $o_1$ is an instance of \code{Type} but $e_1$ is not a constant type literal, then if $v=$ is a setter that forwards (\ref{functionDeclarations}) to a static setter, setter lookup fails. Otherwise, the body  of $v=$ is executed with its formal parameter bound to $o_2$ and \THIS{} bound to $o_1$.
 
 \LMHash{}
 If the setter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4458,7 +4471,7 @@
 \end{itemize}
 
 \LMHash{}
-Then the method \code{noSuchMethod()} is looked up in $o_1$ and invoked  with argument $im$. 
+Then the method \code{noSuchMethod()} is looked up in $o_1$ and invoked  with argument $im$.
 However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on $o_1$ with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
 \begin{itemize}
 \item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
@@ -4477,7 +4490,7 @@
 Let $T$ be the static type of $e_1$. It is a static type warning if $T$ does not have an accessible instance setter named $v=$ unless either:
 \begin{itemize}
 \item $T$ or a superinterface of $T$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. Or
-\item $T$ is \code{Type}, $e_1$ is a constant type literal and the class corresponding to $e_1$ has a static setter named $v=$. 
+\item $T$ is \code{Type}, $e_1$ is a constant type literal and the class corresponding to $e_1$ has a static setter named $v=$.
 \end{itemize}
 
 
@@ -4489,8 +4502,8 @@
 Evaluation of an assignment of the form $\SUPER.v$ \code{=} $e$ proceeds as follows:
 
 \LMHash{}
-Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. 
-The expression $e$ is evaluated to an object $o$.  Then, the setter $v=$ is looked up (\ref{getterAndSetterLookup}) in $S_{dynamic}$ with respect to the current library.  The body  of $v=$ is executed with its formal parameter bound to $o$ and \THIS{} bound to \THIS{}. 
+Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$.
+The expression $e$ is evaluated to an object $o$.  Then, the setter $v=$ is looked up (\ref{getterAndSetterLookup}) in $S_{dynamic}$ with respect to the current library.  The body  of $v=$ is executed with its formal parameter bound to $o$ and \THIS{} bound to \THIS{}.
 
 \LMHash{}
 If the setter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4502,7 +4515,7 @@
 \end{itemize}
 
 \LMHash{}
-Then the method \code{noSuchMethod()} is looked up in $S_{dynamic}$ and invoked  with argument $im$. 
+Then the method \code{noSuchMethod()} is looked up in $S_{dynamic}$ and invoked  with argument $im$.
 However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
 \begin{itemize}
 \item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
@@ -4518,7 +4531,7 @@
 In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type of $S.v$.
 
 \LMHash{}
-Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible instance setter named $v=$ unless $S_{static}$ or a superinterface of $S_{static}$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. 
+Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible instance setter named $v=$ unless $S_{static}$ or a superinterface of $S_{static}$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}.
 
 \LMHash{}
 It is a static type warning if the static type of $e$ may not be assigned to the static type of the formal parameter of the setter $v=$.   The static type of the expression $\SUPER.v$ \code{=} $e$ is the static type of $e$.
@@ -4549,27 +4562,27 @@
 \LMLabel{compoundAssignment}
 
 \LMHash{}
-Evaluation of a compound assignment of the form $v$ {\em ??=} $e$ is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$ ?  $v=e : x)(v)$ where $x$ is a fresh variable that is not used in $e$. 
+Evaluation of a compound assignment of the form $v$ {\em ??=} $e$ is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$ ?  $v=e : x)(v)$ where $x$ is a fresh variable that is not used in $e$.
 
 \LMHash{}
-Evaluation of a compound assignment of the form $C.v$ {\em ??=} $e$, where $C$ is a type literal, is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$?  $C.v=e: x)(C.v)$ where $x$ is a fresh variable that is not used in $e$. 
+Evaluation of a compound assignment of the form $C.v$ {\em ??=} $e$, where $C$ is a type literal, is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$?  $C.v=e: x)(C.v)$ where $x$ is a fresh variable that is not used in $e$.
 
 \commentary {
 The two rules above also apply when the variable v or the type C is prefixed.
 }
 
 \LMHash{}
-Evaluation of a compound assignment of the form $e_1.v$ {\em ??=} $e_2$ is equivalent to the evaluation of the expression  $((x) =>((y) => y == \NULL{}$ ? $ x.v = e_2: y)(x.v))(e_1)$ where $x$ and $y$ are distinct fresh variables that are not used in $e_2$. 
+Evaluation of a compound assignment of the form $e_1.v$ {\em ??=} $e_2$ is equivalent to the evaluation of the expression  $((x) =>((y) => y == \NULL{}$ ? $ x.v = e_2: y)(x.v))(e_1)$ where $x$ and $y$ are distinct fresh variables that are not used in $e_2$.
 
 \LMHash{}
-Evaluation of a compound assignment of the form  $e_1[e_2]$  {\em ??=} $e_3$ is equivalent to the evaluation of the expression  
-$((a, i) => ((x) => x == \NULL{}$ ?  $a[i] = e_3: x)(a[i]))(e_1, e_2)$ where $x$, $a$ and $i$ are distinct fresh variables that are not used in $e_3$. 
+Evaluation of a compound assignment of the form  $e_1[e_2]$  {\em ??=} $e_3$ is equivalent to the evaluation of the expression
+$((a, i) => ((x) => x == \NULL{}$ ?  $a[i] = e_3: x)(a[i]))(e_1, e_2)$ where $x$, $a$ and $i$ are distinct fresh variables that are not used in $e_3$.
 
 \LMHash{}
 Evaluation of a compound assignment of the form $\SUPER.v$  {\em ??=} $e$ is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$ ? $\SUPER.v = e: x)(\SUPER.v)$ where $x$ is a fresh variable that is not used in $e$.
 
 \LMHash{}
-Evaluation of a compound assignment of the form $e_1?.v$  {\em ??=} $e_2$ is equivalent to the evaluation of the expression \code{((x) $=>$ x == \NULL{} ?  \NULL: $x.v ??=  e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. 
+Evaluation of a compound assignment of the form $e_1?.v$  {\em ??=} $e_2$ is equivalent to the evaluation of the expression \code{((x) $=>$ x == \NULL{} ?  \NULL: $x.v ??=  e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$.
 % But what about C?.v ??= e
 
 \LMHash{}
@@ -4592,15 +4605,15 @@
 The static type of a compound assignment of the form $\SUPER.v$  {\em ??=} $e$  is the least upper bound of the static type of $\SUPER.v$ and the static type of $e$. Exactly the same static warnings that would be caused by $\SUPER.v = e$ are also generated in the case of $\SUPER.v$  {\em ??=} $e$.
 
 \LMHash{}
-For any other valid operator $op$, a compound assignment of the form $v$ $op\code{=} e$ is equivalent to $v \code{=} v$ $op$ $e$. A compound assignment of the form $C.v$ $op \code{=} e$ is equivalent to $C.v \code{=} C.v$ $op$ $e$. A compound assignment of the form $e_1.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. A compound assignment of the form  $e_1[e_2]$ $op\code{=} e_3$ is equivalent to 
-\code{((a, i) $=>$ a[i] = a[i] $op$ $e_3$)($e_1, e_2$)} where $a$ and $i$ are a variables that are not used in $e_3$. 
+For any other valid operator $op$, a compound assignment of the form $v$ $op\code{=} e$ is equivalent to $v \code{=} v$ $op$ $e$. A compound assignment of the form $C.v$ $op \code{=} e$ is equivalent to $C.v \code{=} C.v$ $op$ $e$. A compound assignment of the form $e_1.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. A compound assignment of the form  $e_1[e_2]$ $op\code{=} e_3$ is equivalent to
+\code{((a, i) $=>$ a[i] = a[i] $op$ $e_3$)($e_1, e_2$)} where $a$ and $i$ are a variables that are not used in $e_3$.
 
 \LMHash{}
 Evaluation of a compound assignment of the form $e_1?.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x?.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. The static type of $e_1?.v$ $op = e_2$ is the static type of $e_1.v$ $op$ $e_2$. Exactly the same static warnings that would be caused by $e_1.v$ $op = e_2$ are also generated in the case of $e_1?.v$ $op = e_2$.
 
 \LMHash{}
-A compound assignment of the form $C?.v$ $op = e_2$ is equivalent to the expression 
-$C.v$ $op = e_2$. 
+A compound assignment of the form $C?.v$ $op = e_2$ is equivalent to the expression
+$C.v$ $op = e_2$.
 
 \begin{grammar}
 {\bf compoundAssignmentOperator:}`*=';
@@ -4618,7 +4631,7 @@
     .
 \end{grammar}
 
-    
+
 \subsection{ Conditional}
 \LMLabel{conditional}
 
@@ -4635,7 +4648,7 @@
 Evaluation of a conditional expression $c$ of the form $e_1 ? e_2 : e_3$ proceeds as follows:
 
 \LMHash{}
-First, $e_1$ is evaluated to an object $o_1$.  Then, $o_1$ is  subjected to boolean conversion (\ref{booleanConversion}) producing an object $r$.  If $r$ is \TRUE, then the value of $c$ is the result of evaluating the expression $e_2$. Otherwise the value of $c$ is the result of evaluating the expression $e_3$. 
+First, $e_1$ is evaluated to an object $o_1$.  Then, $o_1$ is  subjected to boolean conversion (\ref{booleanConversion}) producing an object $r$.  If $r$ is \TRUE, then the value of $c$ is the result of evaluating the expression $e_2$. Otherwise the value of $c$ is the result of evaluating the expression $e_3$.
 
 \LMHash{}
 If all of the following hold:
@@ -4650,11 +4663,11 @@
 
 \LMHash{}
  It is a static type warning if the static type of $e_1$ may not be assigned to \code{bool}.  The static type of $c$ is the least upper bound (\ref{leastUpperBounds}) of the static type of $e_2$ and the static type of $e_3$.
- 
-   
+
+
  \subsection{If-null Expressions}
  \label{ifNull}
- 
+
  \LMHash{}
  An {\em if-null expression}evaluates an expression and if the result is \NULL, evaluates another.
 
@@ -4662,10 +4675,10 @@
 {\bf ifNullExpression:}
   logicalOrExpression (`??' logicalOrExpression)*
 \end{grammar}
-  
+
 \LMHash{}
 Evaluation of an if-null expression $e$ of the form $e_1??e_2 $ is equivalent to the evaluation of the expression $((x) => x == \NULL? e_2: x)(e_1)$. The static type of $e$ is least upper bound (\ref{leastUpperBounds}) of the static type of $e_1$ and the static type of $e_2$.
-  
+
 
 \subsection{ Logical Boolean Expressions}
 \LMLabel{logicalBooleanExpressions}
@@ -4684,18 +4697,18 @@
 %      bitwiseOrExpression (`\&\&' bitwiseOrExpression)*
     .
  \end{grammar}
- 
+
 \LMHash{}
 A {\em logical boolean expression} is either an equality expression (\ref{equality}), or an invocation of a logical boolean operator on an expression $e_1$ with argument $e_2$.
- 
-\LMHash{}
-Evaluation of a logical boolean expression $b$ of the form $e_1 || e_2$ causes the evaluation of $e_1$ which is then  subjected to boolean conversion, yielding an object $o_1$; if $o_1$ is \TRUE, the result of evaluating $b$ is \TRUE, otherwise $e_2$ is evaluated to an object $o_2$, which is then subjected to boolean conversion (\ref{booleanConversion}) producing an object $r$, which is the value of $b$. 
 
 \LMHash{}
-Evaluation of a logical boolean expression $b$ of the form $e_1 \&\& e_2$ causes the evaluation of $e_1$ which is then subjected to boolean conversion, yielding an object $o_1$; if $o_1$ is not  \TRUE, the result of evaluating $b$ is \FALSE, otherwise $e_2$ is evaluated to an object $o_2$, which is then subjected to boolean conversion producing an object $r$, which is the value of $b$. 
+Evaluation of a logical boolean expression $b$ of the form $e_1 || e_2$ causes the evaluation of $e_1$ which is then  subjected to boolean conversion, yielding an object $o_1$; if $o_1$ is \TRUE, the result of evaluating $b$ is \TRUE, otherwise $e_2$ is evaluated to an object $o_2$, which is then subjected to boolean conversion (\ref{booleanConversion}) producing an object $r$, which is the value of $b$.
 
 \LMHash{}
-A logical boolean expression $b$ of the form $e_1 \&\& e_2$ shows that a variable $v$ has type 
+Evaluation of a logical boolean expression $b$ of the form $e_1 \&\& e_2$ causes the evaluation of $e_1$ which is then subjected to boolean conversion, yielding an object $o_1$; if $o_1$ is not  \TRUE, the result of evaluating $b$ is \FALSE, otherwise $e_2$ is evaluated to an object $o_2$, which is then subjected to boolean conversion producing an object $r$, which is the value of $b$.
+
+\LMHash{}
+A logical boolean expression $b$ of the form $e_1 \&\& e_2$ shows that a variable $v$ has type
 $T$ if all of the following conditions hold:
 \begin{itemize}
 \item Either $e_1$ shows that $v$ has type $T$ or $e_2$ shows that $v$ has type $T$.
@@ -4708,17 +4721,17 @@
 \begin{itemize}
 \item $e_1$ shows that $v$ has type $T$.
 \item $v$ is not mutated in either $e_1$, $e_2$ or within a closure.
-\item If the variable $v$ is accessed by a closure in $e_2$ then the variable $v$ is not potentially mutated anywhere in the scope of $v$. 
+\item If the variable $v$ is accessed by a closure in $e_2$ then the variable $v$ is not potentially mutated anywhere in the scope of $v$.
 \end{itemize}
 then the type of $v$ is known to be $T$ in $e_2$.
 
 \LMHash{}
 It is a static warning if the static type of $e_1$ may not be assigned to \cd{bool} or if the static type of $e_2$ may not be assigned to \cd{bool}. The static type of a logical boolean expression is \code{bool}.
 
-     
+
  \subsection{ Equality}
  \LMLabel{equality}
- 
+
 \LMHash{}
 Equality expressions test objects for equality.
 
@@ -4731,7 +4744,7 @@
       `!='
     .
  \end{grammar}
- 
+
 \LMHash{}
 An {\em equality expression} is either a relational expression (\ref{relationalExpressions}), or an invocation of an equality operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
@@ -4755,24 +4768,24 @@
 \end{itemize}
 
 \commentary{As a result of the above definition, user defined \code{==} methods can assume that their argument is non-null, and avoid the standard boiler-plate prelude:
- 
+
  \code{if (identical(\NULL{}, arg)) return \FALSE{};}
 
-Another implication is that there is never a need to use \code{identical()} to test against \NULL{}, nor should anyone ever worry about whether to write \NULL{} == $e$ or $e$ == \NULL{}. 
+Another implication is that there is never a need to use \code{identical()} to test against \NULL{}, nor should anyone ever worry about whether to write \NULL{} == $e$ or $e$ == \NULL{}.
 }
 
 \LMHash{}
 An equality expression of the form \code{$e_1$ != $e_2$}  is equivalent to the expression \code{!($e_1$ == $e_2$)}. An equality expression of the form \code{\SUPER{} != $e$} is equivalent to the expression \code{!(\SUPER{} == $e$)}.
 
 
- 
- %The expression $e_1$ is evaluated to an object $o_1$; then the expression $e_2$ is evaluated to an object $o_2$.  Next, if $o_1$ and $o_2$ are the same object, then $ee$ evaluates to \TRUE{}, otherwise $ee$ evaluates to \FALSE{}. 
- 
+
+ %The expression $e_1$ is evaluated to an object $o_1$; then the expression $e_2$ is evaluated to an object $o_2$.  Next, if $o_1$ and $o_2$ are the same object, then $ee$ evaluates to \TRUE{}, otherwise $ee$ evaluates to \FALSE{}.
+
 
 \LMHash{}
  The static type of an equality expression is \code{bool}.
- 
- 
+
+
 \subsection{ Relational Expressions}
 \LMLabel{relationalExpressions}
 
@@ -4791,12 +4804,12 @@
       `{\escapegrammar \lt}'
     .
  \end{grammar}
- 
+
 \LMHash{}
 A {\em relational expression} is either a bitwise expression (\ref{bitwiseExpressions}), or an invocation of a relational operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
- 
+
 \LMHash{}
-A relational expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. A relational expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}. 
+A relational expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. A relational expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
 \subsection{ Bitwise Expressions}
 \LMLabel{bitwiseExpressions}
@@ -4822,10 +4835,10 @@
       `$|$'
     .
  \end{grammar}
- 
+
 \LMHash{}
 A {\em bitwise expression} is either a shift expression (\ref{shift}), or an invocation of a bitwise operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
- 
+
 \LMHash{}
  A bitwise expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation $e_1.op(e_2)$.
 A bitwise expression of the form  \code{\SUPER{} $op$ $e_2$} is equivalent to the method invocation \code{\SUPER{}.op($e_2$)}.
@@ -4834,7 +4847,7 @@
 It should be obvious that the static type rules for these expressions are defined by the equivalence above - ergo, by the type rules for method invocation and the signatures of the operators on the type $e_1$. The same holds in similar situations throughout this specification.
 }
 
- 
+
 \subsection{ Shift}
 \LMLabel{shift}
 
@@ -4847,25 +4860,25 @@
     .
 
 {\bf shiftOperator:}`{\escapegrammar \lt\lt'};
-       `{\escapegrammar \gt \gt}' 
+       `{\escapegrammar \gt \gt}'
     .
  \end{grammar}
- 
+
 \LMHash{}
 A {\em shift expression} is either an additive expression (\ref{additiveExpressions}), or an invocation of a shift operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
- 
+
 \LMHash{}
- A shift expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. A shift expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}. 
+ A shift expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. A shift expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
 \commentary{
-Note that this definition implies left-to-right evaluation order among shift expressions: 
+Note that this definition implies left-to-right evaluation order among shift expressions:
 
 $e_1 << e_2 << e_3$
 
 is evaluated as  $(e_1 << e_2 ).<< (e_3)$  which is equivalent to $(e_1 << e_2) << e_3$.
 The same holds for additive and multiplicative expressions.
 }
-     
+
  \subsection{ Additive Expressions}
 \LMLabel{additiveExpressions}
 
@@ -4881,17 +4894,17 @@
       `-'
     .
  \end{grammar}
- 
+
 \LMHash{}
 An {\em additive expression} is either a multiplicative expression (\ref{multiplicativeExpressions}), or an invocation of an additive operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
 
 \LMHash{}
-An additive expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. An additive expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}. 
+An additive expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. An additive expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
 
 \LMHash{}
 The static type of an additive expression is usually determined by the signature given in the declaration of the operator used. However, invocations of the operators \cd{+}  and \cd{-} of class \cd{int} are treated specially by the typechecker. The static type of an expression $e_1 + e_2$ where $e_1$ has static type \cd{int} is \cd{int} if the static type of $e_2$ is \cd{int}, and \cd{double} if the static type of $e_2$ is \cd{double}. The static type of an expression $e_1 - e_2$ where $e_1$ has static type \cd{int} is \cd{int} if the static type of $e_2$ is \cd{int}, and \cd{double} if the static type of $e_2$ is \cd{double}.
- 
- 
+
+
 \subsection{ Multiplicative Expressions}
 \LMLabel{multiplicativeExpressions}
 
@@ -4908,18 +4921,18 @@
       `\%';
       `\~{}/'
     .
-    
+
  \end{grammar}
-    
+
 \LMHash{}
  A {\em multiplicative expression} is either a unary expression (\ref{unaryExpressions}), or an invocation of a multiplicative operator on either \SUPER{} or an expression $e_1$, with argument $e_2$.
- 
+
 \LMHash{}
- A multiplicative expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. A multiplicative expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.   
- 
+ A multiplicative expression of the form  $e_1$ $op$ $e_2$ is equivalent to the method invocation \code{$e_1$.$op$($e_2$)}. A multiplicative expression of the form  \SUPER{} $op$ $e_2$ is equivalent to the method invocation \code{\SUPER{}.$op$($e_2$)}.
+
 \LMHash{}
 The static type of an multiplicative expression is usually determined by the signature given in the declaration of the operator used. However, invocations of the operators \cd{*}, \cd{\%}  and \cd{\~{}/} of class \cd{int} are treated specially by the typechecker. The static type of an expression $e_1 * e_2$ where $e_1$ has static type \cd{int} is \cd{int} if the static type of $e_2$ is \cd{int}, and \cd{double} if the static type of $e_2$ is \cd{double}. The static type of an expression $e_1 \% e_2$ where $e_1$ has static type \cd{int} is \cd{int} if the static type of $e_2$ is \cd{int}, and \cd{double} if the static type of $e_2$ is \cd{double}.  The static type of an expression \cd{$e_1$ \~{}/ $e_2$} where $e_1$ has static type \cd{int} is \cd{int} if the static type of $e_2$ is \cd{int}.
- 
+
 \subsection{ Unary Expressions}
 \LMLabel{unaryExpressions}
 
@@ -4933,33 +4946,33 @@
       (minusOperator $|$ tildeOperator) \SUPER{};
       incrementOperator assignableExpression
     .
- 
+
  {\bf prefixOperator:}minusOperator;
       negationOperator;
       tildeOperator
     .
-       
-       
+
+
   {\bf minusOperator:}`-';  .
 
 
     {\bf negationOperator:}`!' ;
       .
-      
+
     {\bf tildeOperator:}  `\~{}'
     .
-    
-    
+
+
 \end{grammar}
 
 \LMHash{}
 A {\em unary expression} is either a postfix expression  (\ref{postfixExpressions}), an await expression (\ref{awaitExpressions}) or an invocation of a prefix operator on an expression or an invocation of a unary operator on either \SUPER{} or an expression $e$.
 
 \LMHash{}
-The expression $!e$ is equivalent to the expression $e?$ $ \FALSE{} :\TRUE{}$. 
+The expression $!e$ is equivalent to the expression $e?$ $ \FALSE{} :\TRUE{}$.
 
 \LMHash{}
-Evaluation of an expression of the form \code{++$e$} is equivalent to \code{$e$ += 1}.  Evaluation of an expression of the form \code{-{}-$e$} is equivalent to \code{$e$ -= 1}. 
+Evaluation of an expression of the form \code{++$e$} is equivalent to \code{$e$ += 1}.  Evaluation of an expression of the form \code{-{}-$e$} is equivalent to \code{$e$ -= 1}.
 
 %The expression $-e$ is equivalent to the method invocation \code{$e$.-()}.  The expression \code{-\SUPER{}} is equivalent  to the method invocation \code{\SUPER{}.-()}.
 
@@ -4970,7 +4983,7 @@
 \LMLabel{awaitExpressions}
 
 \LMHash{}
-An {\em await expression} allows code to yield control until an asynchronous operation (\ref{functions}) completes. 
+An {\em await expression} allows code to yield control until an asynchronous operation (\ref{functions}) completes.
 
  \begin{grammar}
 {\bf awaitExpression:}
@@ -4982,7 +4995,7 @@
 First, the expression $e$ is evaluated. Next:
 
 \LMHash{}
-If $e$ raises an exception $x$, then an instance $f$ of class \code{Future} is allocated and later completed with $x$. Otherwise, if $e$ evaluates to an object $o$ that is not an instance of \code{Future}, then let $f$ be the result of calling \code{Future.value()} with $o$ as its argument; otherwise let $f$ be the result of evaluating $e$. 
+If $e$ raises an exception $x$, then an instance $f$ of class \code{Future} is allocated and later completed with $x$. Otherwise, if $e$ evaluates to an object $o$ that is not an instance of \code{Future}, then let $f$ be the result of calling \code{Future.value()} with $o$ as its argument; otherwise let $f$ be the result of evaluating $e$.
 
 \LMHash{}
 Next,  execution of the function $m$ immediately enclosing $a$ is suspended until after $f$ completes. The stream associated with the innermost enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused. At some time after $f$ is completed, control returns to the current invocation. The stream associated with the innermost enclosing asynchronous for loop  (\ref{asynchronousFor-in}), if any, is resumed. If $f$ has completed with an exception $x$, $a$ raises $x$. If $f$ completes with a value $v$, $a$ evaluates to $v$.
@@ -5005,7 +5018,7 @@
 The static type of $a$ is $flatten(T)$ (the $flatten$ function is defined in section \ref{functionExpressions}) where $T$ is the static type of $e$.
 
 
-     
+
 \subsection{ Postfix Expressions}
 \LMLabel{postfixExpressions}
 
@@ -5028,9 +5041,9 @@
 {\bf incrementOperator:}`++';
       `-{}-'
     .
-        
+
  \end{grammar}
- 
+
 \LMHash{}
  A {\em postfix expression} is either a primary expression, a function, method or getter invocation, or an invocation of a postfix operator on an expression $e$.
 
@@ -5041,11 +5054,11 @@
 The static type of such an expression is the static type of $v$.
 
 
-\rationale{The above ensures that if $v$ is a field, the getter gets called exactly once. Likewise in the cases below. 
+\rationale{The above ensures that if $v$ is a field, the getter gets called exactly once. Likewise in the cases below.
 }
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$C.v$ ++} is equivalent to executing 
+Execution of a postfix expression of the form \code{$C.v$ ++} is equivalent to executing
 
 \code{()\{\VAR{} r = $C.v$; $C.v$ = r + 1; \RETURN{} r\}()}.
 
@@ -5054,7 +5067,7 @@
 
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$e_1.v$++} is equivalent to executing 
+Execution of a postfix expression of the form \code{$e_1.v$++} is equivalent to executing
 
 \code{(x)\{\VAR{} r = x.v; x.v = r + 1; \RETURN{} r\}($e_1$)}.
 
@@ -5063,7 +5076,7 @@
 
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$e_1[e_2]$++},  is equivalent to executing 
+Execution of a postfix expression of the form \code{$e_1[e_2]$++},  is equivalent to executing
 
 \code{(a, i)\{\VAR{} r = a[i]; a[i] = r + 1; \RETURN{} r\}($e_1$, $e_2$)}.
 
@@ -5072,7 +5085,7 @@
 
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$v$-{}-}, where $v$ is an identifier, is equivalent to executing 
+Execution of a postfix expression of the form \code{$v$-{}-}, where $v$ is an identifier, is equivalent to executing
 
 \code{()\{\VAR{} r = $v$; $v$ = r - 1; \RETURN{} r\}()}.
 
@@ -5081,7 +5094,7 @@
 
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$C.v$-{}-} is equivalent to executing 
+Execution of a postfix expression of the form \code{$C.v$-{}-} is equivalent to executing
 
 \code{()\{\VAR{} r = $C.v$; $C.v$ = r - 1; \RETURN{} r\}()}.
 
@@ -5090,7 +5103,7 @@
 
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$e_1.v$-{}-} is equivalent to executing 
+Execution of a postfix expression of the form \code{$e_1.v$-{}-} is equivalent to executing
 
 \code{(x)\{\VAR{} r = x.v; x.v = r - 1; \RETURN{} r\}($e_1$)}.
 
@@ -5099,7 +5112,7 @@
 
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$e_1[e_2]$-{}-},  is equivalent to executing 
+Execution of a postfix expression of the form \code{$e_1[e_2]$-{}-},  is equivalent to executing
 
 \code{(a, i)\{\VAR{} r = a[i]; a[i] = r - 1; \RETURN{} r\}($e_1$, $e_2$)}.
 
@@ -5107,7 +5120,7 @@
 The static type of such an expression is the static type of $e_1[e_2]$.
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$e_1?.v$++} is equivalent to executing 
+Execution of a postfix expression of the form \code{$e_1?.v$++} is equivalent to executing
 
 \code{((x) =$>$ x == \NULL? \NULL : x.v++)($e_1$)}
 unless $e_1$ is a type literal, in which case it is equivalent to \code{$e_1.v$++}
@@ -5117,7 +5130,7 @@
 The static type of such an expression is the static type of $e_1.v$.
 
 \LMHash{}
-Execution of a postfix expression of the form \code{$e_1?.v$-{}-} is equivalent to executing 
+Execution of a postfix expression of the form \code{$e_1?.v$-{}-} is equivalent to executing
 
 \code{((x) =$>$ x == \NULL? \NULL : x.v-{}-)($e_1$)}
 unless $e_1$ is a type literal, in which case it is equivalent to \code{$e_1.v$-{}-}
@@ -5146,7 +5159,7 @@
       \SUPER{} unconditionalAssignableSelector;
       identifier
     .
-    
+
 {\bf unconditionalAssignableSelector:}`[' expression `]'; % again, could be top level
          `{\escapegrammar .}' identifier
     .
@@ -5162,7 +5175,7 @@
 \LMHash{}
 An {\em assignable expression} is either:
 \begin{itemize}
- \item An identifier. 
+ \item An identifier.
 \item An invocation (possibly conditional) of a getter (\ref{getters}) or list access operator on an expression $e$.
 \item An invocation of a getter or list access operator on  \SUPER{}.
 \end{itemize}
@@ -5195,8 +5208,8 @@
 {\bf identifier:}
      IDENTIFIER
      .
-     
-         
+
+
  {\bf IDENTIFIER\_NO\_DOLLAR:}
       IDENTIFIER\_START\_NO\_DOLLAR IDENTIFIER\_PART\_NO\_DOLLAR*
     .
@@ -5243,8 +5256,8 @@
 
 
 {\bf qualified:}
-      identifier (`{\escapegrammar .}' identifier)?  
-      . 
+      identifier (`{\escapegrammar .}' identifier)?
+      .
 \end{grammar}
 
 \LMHash{}
@@ -5266,27 +5279,27 @@
 
 
 \LMHash{}
-Let $d$ be the innermost declaration in the enclosing lexical scope whose name is $id$ or $id=$.  If no such declaration exists in the lexical scope, let $d$ be the declaration of the inherited member named $id$ if it exists. 
+Let $d$ be the innermost declaration in the enclosing lexical scope whose name is $id$ or $id=$.  If no such declaration exists in the lexical scope, let $d$ be the declaration of the inherited member named $id$ if it exists.
 %If no such member exists, let $d$ be the declaration of the static member name $id$ declared in a superclass of the current class, if it exists.
 
 \begin{itemize}
-\item if $d$ is a prefix $p$, a compile-time error occurs unless the token immediately following $d$ is \code{'.'}.
+\item if $d$ is a prefix $p$, a compile-time error occurs unless the token immediately following $d$ is \code{'.'} or \code{'\#'}.
 \item If $d$ is a class or type alias $T$, the value of $e$ is an instance of  class \code{Type} (or a subclass thereof) reifying $T$.
 \item If $d$ is a type parameter $T$, then the value of $e$ is the value of the actual type argument corresponding to $T$ that was  passed to the generative constructor that created the current binding of \THIS{}. If, however, $e$ occurs inside a static member, a compile-time error occurs.
 
 %\commentary{ We are assured that \THIS{} is well defined, because if we were in a static member the reference to $T$ is a compile-time error (\ref{generics}.)}
 %\item If $d$ is a library variable then:
 %  \begin{itemize}
-%  \item If $d$ is of one of the forms \code{\VAR{} $v$ = $e_i$;} , \code{$T$ $v$ = $e_i$;} , \code{\FINAL{} $v$ = $e_i$;}  or \code{\FINAL{} $T$ $v$ = $e_i$;} and no value has yet been stored into $v$ then the initializer expression $e_i$ is evaluated. If, during the evaluation of $e_i$, the getter for $v$ is referenced, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The value of $e$ is $r$. 
+%  \item If $d$ is of one of the forms \code{\VAR{} $v$ = $e_i$;} , \code{$T$ $v$ = $e_i$;} , \code{\FINAL{} $v$ = $e_i$;}  or \code{\FINAL{} $T$ $v$ = $e_i$;} and no value has yet been stored into $v$ then the initializer expression $e_i$ is evaluated. If, during the evaluation of $e_i$, the getter for $v$ is referenced, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The value of $e$ is $r$.
  \item  If $d$ is a constant variable of one of the forms  \code{\CONST{} $v$ = $e$;} or \code{\CONST{} $T$ $v$ = $e$;} then the value $id$ is the value of the compile-time constant $e$.
 %  Otherwise
-%  \item $e$ evaluates to the current binding of $id$.  
+%  \item $e$ evaluates to the current binding of $id$.
 %  \end{itemize}
-\item If $d$ is a local variable or formal parameter then $e$ evaluates to the current binding of $id$. 
+\item If $d$ is a local variable or formal parameter then $e$ evaluates to the current binding of $id$.
 %\item If $d$ is a library variable, local variable, or formal parameter, then $e$ evaluates to the current binding of $id$. \commentary{This case also applies if d is a library or local function declaration, as these are equivalent to function-valued variable declarations.}
 \item If $d$ is a static method, top-level function or local function then $e$ evaluates to the function defined by $d$.
-\item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, then $e$ is equivalent to the property extraction (\ref{propertyExtraction}) $C.id$. 
-\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, then $e$ is equivalent to the top level getter invocation (\ref{topLevelGetterInvocation}) $id$. 
+\item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, then $e$ is equivalent to the property extraction (\ref{propertyExtraction}) $C.id$.
+\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, then $e$ is equivalent to the top level getter invocation (\ref{topLevelGetterInvocation}) $id$.
 \item Otherwise, if $e$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $e$ causes a \code{NoSuchMethod} to be thrown.
 \item Otherwise, $e$ is equivalent to the property extraction (\ref{propertyExtraction}) \THIS{}.$id$.
 % This implies that referring to an undefined static getter by simple name is an error, whereas doing so by qualified name is only a warning. Same with assignments.  Revise?
@@ -5297,20 +5310,20 @@
 
 \begin{itemize}
 \item If $d$ is a class, type alias or type parameter the static type of $e$ is \code{Type}.
-\item If $d$ is a local variable or formal parameter the static type of $e$ is the type of the variable $id$, unless $id$ is known to have some type $T$, in which case the static type of $e$ is $T$, provided that $T$ is more specific than any other type $S$ such that $v$ is known to have type $S$. 
+\item If $d$ is a local variable or formal parameter the static type of $e$ is the type of the variable $id$, unless $id$ is known to have some type $T$, in which case the static type of $e$ is $T$, provided that $T$ is more specific than any other type $S$ such that $v$ is known to have type $S$.
 \item If $d$ is a static method, top-level function or local function the static type of $e$ is the function type defined by $d$.
 \item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, the static type of $e$ is the static type of the getter invocation (\ref{propertyExtraction}) $C.id$.
-\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, the static type of $e$  is the static type of the top level getter invocation $id$. 
+\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, the static type of $e$  is the static type of the top level getter invocation $id$.
 \item Otherwise, if $e$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, the static type of $e$ is \DYNAMIC{}.
 \item Otherwise, the static type of $e$ is the type of the property extraction (\ref{propertyExtraction}) \THIS{}.$id$.
 \end{itemize}
 
  \commentary{Note that if one declares a setter, we bind to the corresponding getter even if it does not exist.}
- 
+
  \rationale{
  This prevents situations where one uses uncorrelated setters and getters. The intent is to prevent errors when a  getter in a surrounding scope is used accidentally.
  }
- 
+
 \LMHash{}
 It is a static warning if an identifier expression $id$ occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer and there is no declaration $d$ with name $id$ in the lexical scope enclosing the expression.
 
@@ -5324,20 +5337,20 @@
  {\bf typeTest:}
  isOperator type
  .
- 
- 
+
+
 {\bf isOperator:}
 \IS{} `!'?
     .
  \end{grammar}
- 
+
 \LMHash{}
  Evaluation of the is-expression \code{$e$ \IS{} $T$} proceeds as follows:
 
 \LMHash{}
 The expression $e$ is evaluated to a value $v$. Then, if $T$ is a malformed or deferred type (\ref{staticTypes}), a dynamic error occurs. Otherwise, if the interface of the class of $v$ is a subtype of $T$, the is-expression evaluates to \TRUE. Otherwise it evaluates to \FALSE.
 
-\commentary{It follows that \code{$e$ \IS{} Object} is always true. This makes sense in a language where everything is an object. 
+\commentary{It follows that \code{$e$ \IS{} Object} is always true. This makes sense in a language where everything is an object.
 
 Also note that \code{\NULL{} \IS{} $T$} is false unless $T = \code{Object}$, $T = \code{\DYNAMIC{}}$ or $T = \code{Null}$.  The former two are useless, as is anything of the form \code{$e$ \IS{} Object} or \code{$e$ \IS{} \DYNAMIC{}}.  Users should test for a null value directly rather than via type tests.
 }
@@ -5362,7 +5375,7 @@
 }
 
 \LMHash{}
-The static type of an is-expression is \code{bool}. 
+The static type of an is-expression is \code{bool}.
 
 
 \subsection{ Type Cast}
@@ -5375,22 +5388,22 @@
  {\bf typeCast:}
  asOperator type
  .
- 
- 
+
+
 {\bf asOperator:}
 \AS{}
     .
  \end{grammar}
- 
+
 \LMHash{}
  Evaluation of the cast expression \code{$e$ \AS{} $T$} proceeds as follows:
 
 \LMHash{}
-The expression $e$ is evaluated to a value $v$. Then, if $T$ is a malformed or deferred type (\ref{staticTypes}), a dynamic error occurs. Otherwise, if the interface of the class of $v$ is a subtype of $T$, the cast expression evaluates to $v$. Otherwise, if $v$ is \NULL{}, the cast expression evaluates to $v$. 
+The expression $e$ is evaluated to a value $v$. Then, if $T$ is a malformed or deferred type (\ref{staticTypes}), a dynamic error occurs. Otherwise, if the interface of the class of $v$ is a subtype of $T$, the cast expression evaluates to $v$. Otherwise, if $v$ is \NULL{}, the cast expression evaluates to $v$.
 In all other cases,  a \code{CastError} is thrown.
- 
+
 \LMHash{}
-The static type of a cast expression  \code{$e$ \AS{} $T$}  is $T$. 
+The static type of a cast expression  \code{$e$ \AS{} $T$}  is $T$.
 
 
 \section{Statements}
@@ -5406,7 +5419,7 @@
       label* nonLabelledStatement
     .
 
-{\bf nonLabelledStatement:}block; 
+{\bf nonLabelledStatement:}block;
       localVariableDeclaration;
       forStatement;
       whileStatement;
@@ -5425,10 +5438,10 @@
       localFunctionDeclaration
     .
  \end{grammar}
- 
+
  \subsection{Blocks}
  \LMLabel{blocks}
- 
+
 \LMHash{}
  A {\em block statement} supports sequencing of code.
 
@@ -5445,9 +5458,9 @@
 
  \subsection{Expression Statements}
  \LMLabel{expressionStatements}
- 
+
 \LMHash{}
-An {\em expression statement} consists of an expression other than a non-constant map literal (\ref{maps}) that has no explicit type arguments. 
+An {\em expression statement} consists of an expression other than a non-constant map literal (\ref{maps}) that has no explicit type arguments.
 
 \rationale{
 The restriction on maps  is designed to resolve an ambiguity in the grammar, when a statement begins with \{.
@@ -5458,9 +5471,9 @@
   expression? `{\escapegrammar ;}'
   .
  \end{grammar}
- 
+
 \LMHash{}
-Execution of an expression statement \code{$e$;} proceeds by evaluating $e$. 
+Execution of an expression statement \code{$e$;} proceeds by evaluating $e$.
 
 \LMHash{}
 It is a compile-time error if a non-constant map literal that has no explicit type arguments appears in a place where a statement is expected.
@@ -5477,15 +5490,15 @@
     initializedVariableDeclaration {\escapegrammar';'}
   .
  \end{grammar}
- 
+
 \LMHash{}
  Executing a variable declaration statement of one of the forms  \VAR{} $v = e;$, $T$ $v = e; $, \CONST{}  $v = e;$, \CONST{} $T$ $v = e;$, \FINAL{}  $v = e;$ or \FINAL{} $T$ $v = e;$ proceeds as follows:
- 
+
 \LMHash{}
  The expression $e$ is evaluated to an object $o$. Then, the variable $v$ is set to $o$.
- 
+
 \LMHash{}
- A variable declaration statement of the form \VAR{} $v;$ is equivalent to \VAR{} $v = \NULL{};$. A variable declaration statement of the form $T$ $v;$ is equivalent to $T$ $v = \NULL{};$. 
+ A variable declaration statement of the form \VAR{} $v;$ is equivalent to \VAR{} $v = \NULL{};$. A variable declaration statement of the form $T$ $v;$ is equivalent to $T$ $v = \NULL{};$.
 
 \commentary{
 This holds regardless of the type $T$. For example, \code{int i;} does not cause \code{i} to be initialized to zero. Instead, \code{i} is initialized to \NULL{}, just as if we had written \VAR{} \code{i;} or \code{Object i;} or \code{Collection$<$String$>$ i;}.
@@ -5495,13 +5508,13 @@
 To do otherwise would undermine the optionally typed nature of Dart, causing type annotations to modify program behavior.
 }
 
-%A variable declaration statement of one of the forms $T$ $v;$, $T$ $v = e;$, \CONST{} $T$ $v = e;$,  or \FINAL{} $T$ $v = e;$ causes a new getter named $v$ with static return type $T$ to be added to the innermost enclosing scope at the point following the variable declaration statement. The result of executing this getter is the value stored in $v$. 
+%A variable declaration statement of one of the forms $T$ $v;$, $T$ $v = e;$, \CONST{} $T$ $v = e;$,  or \FINAL{} $T$ $v = e;$ causes a new getter named $v$ with static return type $T$ to be added to the innermost enclosing scope at the point following the variable declaration statement. The result of executing this getter is the value stored in $v$.
 
-%A variable declaration statement \VAR{} $v;$, \VAR{} $v = e;$, \CONST{}  $v = e;$ or  \FINAL{}  $v = e;$ causes a new getter named $v$ with static return type  \DYNAMIC{} to be added to the innermost enclosing scope at the point following the variable declaration statement. The result of executing this getter  is the value stored in $v$. 
+%A variable declaration statement \VAR{} $v;$, \VAR{} $v = e;$, \CONST{}  $v = e;$ or  \FINAL{}  $v = e;$ causes a new getter named $v$ with static return type  \DYNAMIC{} to be added to the innermost enclosing scope at the point following the variable declaration statement. The result of executing this getter  is the value stored in $v$.
 
-%A variable declaration statement of one of the forms $T$ $v;$, or $T$ $v = e;$ causes a new setter named $v=$ with argument type $T$ to be added to the innermost enclosing scope at the point following the variable declaration statement. The effect of executing this setter  is to store its argument in $v$. 
+%A variable declaration statement of one of the forms $T$ $v;$, or $T$ $v = e;$ causes a new setter named $v=$ with argument type $T$ to be added to the innermost enclosing scope at the point following the variable declaration statement. The effect of executing this setter  is to store its argument in $v$.
 
-%A variable declaration statement \VAR{} $v;$, \VAR{} $v = e;$, \CONST{}  $v = e;$ or  \FINAL{}  $v = e;$ causes a new setter named $v=$ with  argument type  \DYNAMIC{} to be added to the innermost enclosing scope at the point following the variable declaration statement. The effect of executing this setter  is to store its argument in $v$. 
+%A variable declaration statement \VAR{} $v;$, \VAR{} $v = e;$, \CONST{}  $v = e;$ or  \FINAL{}  $v = e;$ causes a new setter named $v=$ with  argument type  \DYNAMIC{} to be added to the innermost enclosing scope at the point following the variable declaration statement. The effect of executing this setter  is to store its argument in $v$.
 
 %\rationale{
  %The use of getters and setters here is a device to help make the specification more uniform. Introducing getters and setters for local variables has no performance consequences, since they can never be overridden, and so can always be optimized away.  It is not possible to declare a local getter or setter explicitly, since there is little reason to ever do so.
@@ -5512,16 +5525,16 @@
 \LMLabel{localFunctionDeclaration}
 
 \LMHash{}
-A function declaration statement declares a new local function (\ref{functionDeclarations}). 
+A function declaration statement declares a new local function (\ref{functionDeclarations}).
 
  \begin{grammar}
 {\bf localFunctionDeclaration:}
     functionSignature functionBody
   .
  \end{grammar}
- 
+
 \LMHash{}
-A function declaration statement of one of the forms $id$ $signature$ $\{ statements \}$ or $T$ $id$ $signature$ $\{ statements \}$ causes a new function named $id$ to be added to the innermost enclosing scope. It is a compile-time error to reference a local function before its declaration. 
+A function declaration statement of one of the forms $id$ $signature$ $\{ statements \}$ or $T$ $id$ $signature$ $\{ statements \}$ causes a new function named $id$ to be added to the innermost enclosing scope. It is a compile-time error to reference a local function before its declaration.
 
 
 \commentary{ This implies that local functions can be directly recursive, but not mutually recursive. Consider these examples:
@@ -5535,12 +5548,12 @@
   g1(x) $=>$ h(x, 1); // error: h is not declared yet
   h(x, n) $=>$ x $>$ 1? h(x-1, n*x): n; // again, recursion is fine
   g2(x) $=>$ h(x, 1); // legal
-  
+
   p1(x) $=>$ q(x,x); // illegal
   q1(a, b)$ =>$ a $>$ 0 ? p1(a-1): b; // fine
 
   q2(a, b) $=>$ a $>$ 0 ? p2(a-1): b; // illegal
-  p1(x) $=>$ q2(x,x); // fine  
+  p1(x) $=>$ q2(x,x); // fine
 \}
 \end{dartCode}
 
@@ -5550,9 +5563,9 @@
 
 \begin{dartCode}
 top2() \{ // a top level function
- \VAR{} p, q;  
-  p = (x) $=>$ q(x,x); 
-  q = (a, b) $=>$ a $>$ 0 ? p(a-1): b; 
+ \VAR{} p, q;
+  p = (x) $=>$ q(x,x);
+  q = (a, b) $=>$ a $>$ 0 ? p(a-1): b;
 
 \}
 \end{dartCode}
@@ -5574,24 +5587,24 @@
       \IF{} `(' expression `)' statement ( \ELSE{} statement)? % we could allow top level expression
     .
  \end{grammar}
- 
+
 Execution of an if statement of the form  \code {\IF{} (}$b$\code{)}$s_1$ \code{\ELSE{} } $s_2$ proceeds as follows:
- 
+
 \LMHash{}
  First, the expression $b$ is evaluated to an object $o$. Then, $o$ is  subjected to boolean conversion (\ref{booleanConversion}), producing an object $r$. If $r$ is \TRUE{}, then the statement $\{s_1\}$ is executed, otherwise statement $\{s_2\}$ is executed.
 
- 
+
  \commentary {
  Put another way, \code {\IF{} (}$b$\code{)}$s_1$ \code{\ELSE{} } $s_2$ is equivalent to
  \code {\IF{} (}$b$\code{)}$\{s_1\}$ \code{\ELSE{} } $\{s_2\}$
  }
- 
+
  \rationale {
  The reason for this equivalence is to catch errors such as
  }
  \begin{dartCode}
 \VOID{} main() \{
-  \IF{} (somePredicate) 
+  \IF{} (somePredicate)
     \VAR{} v = 2;
   print(v);
 \}
@@ -5600,26 +5613,26 @@
 \rationale {
 Under reasonable scope rules  such code is problematic. If we assume that \code{v} is declared in the scope of the method \code{main()}, then when \code{somePredicate} is false, \code{v} will be uninitialized when accessed.  The cleanest approach would be to require a block following the test, rather than an arbitrary statement. However, this goes against long standing custom, undermining Dart's goal of familiarity.  Instead, we choose to insert a block, introducing a scope,  around the statement following the predicate (and similarly for \ELSE{} and loops). This will cause both a warning and a runtime error in the case above.  Of course, if there is a declaration of \code{v} in the surrounding scope, programmers might still be surprised. We expect tools to highlight cases of shadowing to help avoid such situations.
  }
- 
+
 \LMHash{}
-  It is a static type warning if the type of the expression $b$ may not be assigned to \code{bool}.  
-  
+  It is a static type warning if the type of the expression $b$ may not be assigned to \code{bool}.
+
 \LMHash{}
 If:
 \begin{itemize}
 \item  $b$ shows that a variable $v$ has type $T$.
 \item  $v$ is not potentially mutated in $s_1$ or within a closure.
-\item If the variable $v$ is accessed by a closure in $s_1$ then the variable $v$ is not potentially mutated anywhere in the scope of $v$. 
+\item If the variable $v$ is accessed by a closure in $s_1$ then the variable $v$ is not potentially mutated anywhere in the scope of $v$.
 \end{itemize}
-then the type of $v$ is known to be $T$ in $s_1$.  
+then the type of $v$ is known to be $T$ in $s_1$.
 
 \LMHash{}
- An if statement of the form  \code {\IF{} (}$b$\code{)}$s_1$ is equivalent to the if statement  
- 
- \code {\IF{} (}$b$\code{)}$s_1$ \code{\ELSE{} \{\}}.
-     
+ An if statement of the form  \code {\IF{} (}$b$\code{)}$s_1$ is equivalent to the if statement
 
-    
+ \code {\IF{} (}$b$\code{)}$s_1$ \code{\ELSE{} \{\}}.
+
+
+
 \subsection{For}
 \LMLabel{for}
 
@@ -5640,7 +5653,7 @@
       expression? `{\escapegrammar ;}'
     .
  \end{grammar}
- 
+
 \LMHash{}
  The for statement has three forms - the traditional for loop and two forms of the for-in statement - synchronous and asynchronous.
 
@@ -5661,7 +5674,7 @@
 \label{beginFor}
 If this is the first iteration of the for loop, let $v^\prime$ be $v$. Otherwise,  let $v^\prime$ be the variable $v^{\prime\prime}$ created in the previous execution of step \ref{allocateFreshVar}.
 \item
-The expression $[v^\prime/v]c$ is evaluated and subjected to boolean conversion (\ref{booleans}). If the result is \FALSE{}, the for loop completes. Otherwise, execution continues at step    
+The expression $[v^\prime/v]c$ is evaluated and subjected to boolean conversion (\ref{booleans}). If the result is \FALSE{}, the for loop completes. Otherwise, execution continues at step
 \ref{beginIteration}.
 \item
 \label{beginIteration}
@@ -5699,19 +5712,19 @@
 \LMLabel{for-in}
 
 \LMHash{}
-A for statement of the form \code{ \FOR{} ($finalConstVarOrType?$ id \IN{} $e$) $s$} is equivalent to the following code: 
+A for statement of the form \code{ \FOR{} ($finalConstVarOrType?$ id \IN{} $e$) $s$} is equivalent to the following code:
 
 \begin{dartCode}
 var n0 = $e$.iterator;
 \WHILE{} (n0.moveNext()) \{
    $finalConstVarOrType?$ id = n0.current;
-   $s$ 
+   $s$
 \}
 \end{dartCode}
 where \code{n0} is an identifier that does not occur anywhere in the program, except that for purposes of static typechecking, it is checked under the assumption that $n0$ is declared to be of type $T$, where $T$ is the static type of $e.iterator$.
 
- 
- 
+
+
 \subsubsection{Asynchronous For-in}
 \LMLabel{asynchronousFor-in}
 
@@ -5739,7 +5752,7 @@
 
 \rationale{An asynchronous loop would make no sense within a synchronous function, for the same reasons that an await expression makes no sense in a synchronous function.}
 
- 
+
 \subsection{While}
 \LMLabel{while}
 
@@ -5751,16 +5764,16 @@
       \WHILE{} `(' expression `)' statement  % could do top level here, and in for
 .
  \end{grammar}
- 
+
 \LMHash{}
- Execution of a while statement of the form \code{\WHILE{} ($e$) $s$;} proceeds as follows: 
+ Execution of a while statement of the form \code{\WHILE{} ($e$) $s$;} proceeds as follows:
 
 \LMHash{}
 The expression $e$ is evaluated to an object $o$. Then, $o$ is  subjected to boolean conversion (\ref{booleanConversion}), producing an object $r$.  If $r$ is \TRUE{}, then the statement $\{s\}$ is executed and then the while statement is re-executed recursively. If $r$ is \FALSE{}, execution of the while statement is complete.
 
 \LMHash{}
 It is a static type warning if the static type of $e$ may not be assigned to \code{bool}.
-    
+
 
 \subsection{Do}
 \LMLabel{do}
@@ -5774,15 +5787,15 @@
       .
  \end{grammar}
 
-    
-\LMHash{}
-Execution of a do statement of the form \code{\DO{} $s$ \WHILE{} ($e$);} proceeds as follows: 
 
 \LMHash{}
-The statement $\{s\}$ is executed. Then, the expression $e$ is evaluated to an object $o$. Then, $o$ is  subjected to boolean conversion (\ref{booleanConversion}), producing an object $r$. If $r$ is \FALSE{}, execution of the do statement is complete. If $r$ is \TRUE{}, then the do statement is re-executed recursively. 
+Execution of a do statement of the form \code{\DO{} $s$ \WHILE{} ($e$);} proceeds as follows:
 
 \LMHash{}
-It is a static type warning if the static type of $e$ may not be assigned to \code{bool}. 
+The statement $\{s\}$ is executed. Then, the expression $e$ is evaluated to an object $o$. Then, $o$ is  subjected to boolean conversion (\ref{booleanConversion}), producing an object $r$. If $r$ is \FALSE{}, execution of the do statement is complete. If $r$ is \TRUE{}, then the do statement is re-executed recursively.
+
+\LMHash{}
+It is a static type warning if the static type of $e$ may not be assigned to \code{bool}.
 
 \subsection{Switch}
 \LMLabel{switch}
@@ -5804,10 +5817,10 @@
       label*  \DEFAULT{} `{\escapegrammar :}' statements
     .
  \end{grammar}
- 
+
 \LMHash{}
- Given a switch statement of the form 
- 
+ Given a switch statement of the form
+
 \begin{dartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
@@ -5816,9 +5829,9 @@
    $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
 \end{dartCode}
- 
- or the form 
- 
+
+ or the form
+
 \begin{dartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
@@ -5826,27 +5839,27 @@
    $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
 \end{dartCode}
- 
+
  it is a compile-time error if the expressions $e_k$ are not compile-time constants for all  $k \in 1..n$.  It is a compile-time error if the values of the expressions $e_k$ are not either:
  \begin{itemize}
- \item instances of the same class $C$, for all $k \in 1..n$,  or 
- \item instances of a class that implements \cd{int}, for all $k \in 1..n$,  or 
- \item instances of a class that implements \cd{String}, for all $k \in 1..n$. 
+ \item instances of the same class $C$, for all $k \in 1..n$,  or
+ \item instances of a class that implements \cd{int}, for all $k \in 1..n$,  or
+ \item instances of a class that implements \cd{String}, for all $k \in 1..n$.
  \end{itemize}
- 
+
 \commentary{In other words,  all the expressions in the cases evaluate to constants of the exact same user defined class or are of certain known types.  Note that the values of the expressions are known at compile-time, and are independent of any static type annotations.
 }
 
 \LMHash{}
 It is a compile-time error if the class $C$ has an implementation of the operator $==$ other than the one inherited from \code{Object} unless the value of the expression is a string, an integer, literal symbol or the result of invoking a constant constructor of class \cd{Symbol}.
- 
+
  \rationale{
  The prohibition on user defined equality allows us to implement the switch efficiently for user defined types. We could formulate matching in terms of identity instead with the same efficiency. However, if a type defines an equality operator, programmers would find it quite surprising that equal objects did not match.
- 
+
  }
 
 \commentary{
-The \SWITCH{}  statement should only be used in very limited situations (e.g., interpreters or scanners).  
+The \SWITCH{}  statement should only be used in very limited situations (e.g., interpreters or scanners).
 }
 
 \LMHash{}
@@ -5860,9 +5873,9 @@
    $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
 \end{dartCode}
- 
-or the form 
- 
+
+or the form
+
 \begin{dartCode}
 \SWITCH{} ($e$) \{
    $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
@@ -5874,7 +5887,7 @@
 proceeds as follows:
 
 \LMHash{}
-The statement \code{\VAR{} id = $e$;} is evaluated, where \code{id} is a variable whose name is distinct from any other variable in the program. In checked mode, it is a run time error if the value of $e$ is not an instance of the same class as the constants $e_1 \ldots e_n$. 
+The statement \code{\VAR{} id = $e$;} is evaluated, where \code{id} is a variable whose name is distinct from any other variable in the program. In checked mode, it is a run time error if the value of $e$ is not an instance of the same class as the constants $e_1 \ldots e_n$.
 
 \commentary{Note that if there are no case clauses ($n = 0$), the type of $e$ does not matter.}
 
@@ -5885,7 +5898,7 @@
 A case clause introduces a new scope, nested in the lexically surrounding scope. The scope of a case clause ends immediately after the case clause's statement list.
 
 \LMHash{}
-Execution of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a  switch statement  
+Execution of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a  switch statement
 
 \begin{dartCode}
 \SWITCH{} ($e$) \{
@@ -5899,13 +5912,13 @@
 proceeds as follows:
 
 \LMHash{}
-The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion yielding a value $v$. 
+The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion yielding a value $v$.
 If $v$ is not  \TRUE{} the following case,  \CASE{} $e_{k+1}: s_{k+1}$ is executed if it exists. If  \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause is executed by executing $s_{n+1}$.
 If $v$ is \TRUE{},   let $h$ be the smallest number such that $h \ge k$ and $s_h$ is non-empty. If no such $h$ exists, let $h = n + 1$. The  sequence of statements $s_h$ is then executed.
 If execution reaches the point after $s_h$  then  a runtime error occurs, unless $h = n+1$.
 
 \LMHash{}
-Execution of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a  switch statement  
+Execution of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a  switch statement
 
 \begin{dartCode}
 \SWITCH{} ($e$) \{
@@ -5918,8 +5931,8 @@
 proceeds as follows:
 
 \LMHash{}
-The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion yielding a value $v$. 
-If $v$ is not  \TRUE{} the following case,  \CASE{} $e_{k+1}: s_{k+1}$ is executed if it exists. 
+The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion yielding a value $v$.
+If $v$ is not  \TRUE{} the following case,  \CASE{} $e_{k+1}: s_{k+1}$ is executed if it exists.
 If $v$ is \TRUE{},   let $h$ be the smallest integer such that $h \ge k$ and $s_h$ is non-empty. The  sequence of statements $s_h$ is  executed if it exists.
 If execution reaches the point after $s_h$  then  a runtime error occurs, unless $h = n$.
 
@@ -5946,7 +5959,7 @@
 \rationale{
   Very elaborate code in a case clause is probably bad style in any case, and such code can always be refactored.
 }
- 
+
 \LMHash{}
  It is a static warning if all of the following conditions hold:
  \begin{itemize}
@@ -5959,7 +5972,7 @@
 In other words, a warning will be issued if a switch statement over an enum is not exhaustive.
 }
 
- 
+
 \subsection{ Rethrow}
 \LMLabel{rethrow}
 
@@ -5972,7 +5985,7 @@
      \RETHROW{}  `{\escapegrammar ;}'
     .
  \end{grammar}
- 
+
 \LMHash{}
 Execution of a \code{\RETHROW{}} statement proceeds as follows:
 
@@ -5999,7 +6012,7 @@
 \commentary{The change in control may result in multiple functions terminating if these functions do not catch the exception via a \CATCH{} or \FINALLY{} clause, both of which introduce a dynamically enclosing exception handler.}
 
 \LMHash{}
-It is a compile-time error if a  \code{\RETHROW{}} statement is not enclosed within an \ON-\CATCH{} clause. 
+It is a compile-time error if a  \code{\RETHROW{}} statement is not enclosed within an \ON-\CATCH{} clause.
 
 
 
@@ -6013,27 +6026,27 @@
 {\bf tryStatement:}
       \TRY{} block (onPart+ finallyPart? $|$ finallyPart)
     .
-    
+
  {\bf onPart:}catchPart block;
     \ON{} type catchPart? block
    .
 
 {\bf catchPart:}
-      \CATCH{} `(' identifier (`,' identifier)? `)' 
+      \CATCH{} `(' identifier (`,' identifier)? `)'
     .
 
 {\bf finallyPart:}
       \FINALLY{} block
     .
  \end{grammar}
- 
+
 \LMHash{}
  A try statement consists of a block statement, followed by at least one of:
  \begin{enumerate}
  \item
 A set of \ON{}-\CATCH{} clauses, each of which specifies  (either explicitly or implicitly) the type of exception object to be handled, one or two exception parameters and a block statement.
 \item
-A \FINALLY{} clause, which consists of a block statement. 
+A \FINALLY{} clause, which consists of a block statement.
 \end{enumerate}
 
 \rationale{
@@ -6052,7 +6065,7 @@
 
 
 \LMHash{}
-An \ON{}-\CATCH{} clause of the form  \code{\ON{} $T$ \CATCH{} ($p_1$) $s$} is equivalent to an \ON{}-\CATCH{} clause  \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program. 
+An \ON{}-\CATCH{} clause of the form  \code{\ON{} $T$ \CATCH{} ($p_1$) $s$} is equivalent to an \ON{}-\CATCH{} clause  \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program.
 
 
 \LMHash{}
@@ -6065,31 +6078,31 @@
 The {\em active stack trace} is an object whose \code{toString()} method produces a string that is a record of exactly those function activations within the current isolate that had not completed execution at the point where the current exception (\ref{throw}) was thrown.
 %\begin{enumerate}
 %\item Started execution after the currently executing function.
-%\item Had not completed execution at the point where the exception caught by the currently executing  \ON{}-\CATCH{} clause was initially thrown. 
+%\item Had not completed execution at the point where the exception caught by the currently executing  \ON{}-\CATCH{} clause was initially thrown.
 %\commentary{The active stack trace contains the frames between the exception handling code and the original point when an exception is thrown, not where it was rethrown.}
 %\end{enumerate}
 
  \commentary{
-This implies that no synthetic function activations may be added to the trace, nor may any source level activations be omitted. 
+This implies that no synthetic function activations may be added to the trace, nor may any source level activations be omitted.
 This means, for example, that any inlining of functions done as an optimization must not be visible in the trace. Similarly, any synthetic routines used by the implementation must not appear in the trace.
 
 Nothing is said about how any native function calls may be represented in the trace.
  }
- 
+
 \commentary{
 Note that we say nothing about the identity of the stack trace, or what notion of equality is defined for stack traces.
 }
- 
+
 % Sadly, the info below cannot be computed efficiently. It would need to be computed at the throw point, since at latte points it might be destroyed. Native code in calling frames executes relative to the stack pointer, which therefore needs to be reset as each frame is unwound.  This means that the
 % OS kernel can dispose of this stack memory - it is not reliably preserved. And such code must execute if only to test if the exception should be caught or sent onward.
 
 % For each such function activation, the active stack trace includes the name of the function, the bindings of all its formal parameters, local variables and \THIS{}, and the position at which the function was executing.
- 
+
  % Is this controversial? We were thinking of viewing the trace as a List<Invocation>,
  % but that won't capture the receiver or the locals. More generally, we need a standard interface that describes these traces, so one can type the stack trace variable in the catch.
- 
+
  \commentary{The term position should not be interpreted as a line number, but rather as a precise position - the exact character index of the  expression that raised  the exception. }
- 
+
  % A position can be represented via a Token. If we make that part of the core reflection facility, we can state this here.
 
 \LMHash{}
@@ -6103,7 +6116,7 @@
 A finally clause \FINALLY{} $s$ defines an exception handler $h$ that executes as follows:
 
 \LMHash{}
-Let $r$ be the current return value (\ref{return}). Then the current return value becomes undefined. Any open streams associated with any asynchronous for loops (\ref{asynchronousFor-in}) and yield-each (\ref{yieldEach}) statements executing within the dynamic scope of $h$ are canceled, in the order of their nesting, innermost first. 
+Let $r$ be the current return value (\ref{return}). Then the current return value becomes undefined. Any open streams associated with any asynchronous for loops (\ref{asynchronousFor-in}) and yield-each (\ref{yieldEach}) statements executing within the dynamic scope of $h$ are canceled, in the order of their nesting, innermost first.
 
 \rationale{
 Streams left open by for loops that were escaped for whatever reason would be canceled at function termination, but it is best to cancel them as soon as possible.
@@ -6115,7 +6128,7 @@
 \item
  if there is a dynamically enclosing error handler $g$ defined by a \FINALLY{} clause in $m$, control is transferred to $g$.
  \item
-Otherwise $m$ terminates. 
+Otherwise $m$ terminates.
 \end{itemize}
 
 Otherwise, execution resumes at the end of the try statement.
@@ -6124,7 +6137,7 @@
 Execution of an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1$, $p_2$)} $s$ of a try statement $t$ proceeds as follows: The statement $s$ is executed in the dynamic scope of the exception handler defined by the finally clause of $t$. Then, the current exception and active stack trace both become undefined.
 
 \LMHash{}
-Execution of a \FINALLY{} clause \FINALLY{} $s$ of a try statement proceeds as follows: 
+Execution of a \FINALLY{} clause \FINALLY{} $s$ of a try statement proceeds as follows:
 
 \LMHash{}
 Let $x$ be the current exception and let $t$ be the active stack trace. Then the current exception and the active stack trace both become undefined. The statement $s$ is executed. Then, if $x$ is defined,  it is rethrown as if by a rethrow statement (\ref{rethrow}) enclosed in a \CATCH{} clause of the form \code{\CATCH{} ($v_x$, $v_t$)} where $v_x$ and $v_t$ are fresh variables bound to $x$ and $t$ respectively.
@@ -6137,20 +6150,20 @@
 The statement $s_1$ is executed in the dynamic scope of the exception handler defined by the try statement. Then, the \FINALLY{} clause is executed.
 
 \commentary{
-Whether any of the \ON{}-\CATCH{} clauses is executed depends on whether a matching exception has been raised by $s_1$ (see the specification of the throw statement). 
+Whether any of the \ON{}-\CATCH{} clauses is executed depends on whether a matching exception has been raised by $s_1$ (see the specification of the throw statement).
 
-If $s_1$ has raised an exception, it will transfer control to the try statement's handler, which will examine the catch clauses in order for a match as specified above. If no matches are found, the handler will execute the \FINALLY{} clause. 
+If $s_1$ has raised an exception, it will transfer control to the try statement's handler, which will examine the catch clauses in order for a match as specified above. If no matches are found, the handler will execute the \FINALLY{} clause.
 
-If a matching \ON{}-\CATCH{} was found, it will execute first, and then the \FINALLY{} clause will be executed. 
+If a matching \ON{}-\CATCH{} was found, it will execute first, and then the \FINALLY{} clause will be executed.
 
-If an exception is thrown during execution of an \ON{}-\CATCH{} clause, this will transfer control to the handler for the \FINALLY{} clause, causing the \FINALLY{} clause to execute in this case as well. 
+If an exception is thrown during execution of an \ON{}-\CATCH{} clause, this will transfer control to the handler for the \FINALLY{} clause, causing the \FINALLY{} clause to execute in this case as well.
 
-If no exception was raised, the \FINALLY{} clause is also executed. Execution of the \FINALLY{} clause could also raise an exception, which will cause transfer of control to the next enclosing handler. 
+If no exception was raised, the \FINALLY{} clause is also executed. Execution of the \FINALLY{} clause could also raise an exception, which will cause transfer of control to the next enclosing handler.
 }
 
 \LMHash{}
 A try statement of the form \code{\TRY{} $s_1$ $on-catch_1 \ldots on-catch_n$;} is equivalent to the statement \code{\TRY{} $s_1$ $on-catch_1 \ldots on-catch_n$ \FINALLY{} $\{\}$}.
- 
+
 
 \subsection{ Return}
 \LMLabel{return}
@@ -6164,24 +6177,24 @@
     \RETURN{} expression? `{\escapegrammar ;}' % could do top level here
     .
  \end{grammar}
- 
+
  \commentary{
- Due to \FINALLY{} clauses, the precise behavior of \RETURN{} is a little more involved. Whether the value a return statement is supposed to return is actually returned depends on the behavior of any \FINALLY{} clauses in effect when executing the return. A \FINALLY{} clause may choose to return another value, or throw an exception, or even redirect control flow leading to other returns or throws. All a return statement really does is set a value that is intended to be returned when the function terminates. 
+ Due to \FINALLY{} clauses, the precise behavior of \RETURN{} is a little more involved. Whether the value a return statement is supposed to return is actually returned depends on the behavior of any \FINALLY{} clauses in effect when executing the return. A \FINALLY{} clause may choose to return another value, or throw an exception, or even redirect control flow leading to other returns or throws. All a return statement really does is set a value that is intended to be returned when the function terminates.
  }
 
 \LMHash{}
 The {\em current return value} is a unique value specific to a given function activation. It is undefined unless explicitly set in this specification.
-    
+
 \LMHash{}
 Executing a return statement \code{\RETURN{} $e$;} proceeds as follows:
 
 \LMHash{}
 First the expression $e$ is evaluated, producing an object $o$. Next:
 \begin{itemize}
-\item  
+\item
 The current return value is set to $o$ and the current exception (\ref{throw}) and active stack trace (\ref{try}) become undefined.
 \item
-Let $c$ be the \FINALLY{} clause of the innermost enclosing try-finally statement (\ref{try}), if any. If $c$ is defined, let $h$ be the handler induced by $c$. If $h$ is defined, control is transferred to $h$. 
+Let $c$ be the \FINALLY{} clause of the innermost enclosing try-finally statement (\ref{try}), if any. If $c$ is defined, let $h$ be the handler induced by $c$. If $h$ is defined, control is transferred to $h$.
 \item
 Otherwise execution of the current method terminates.
 \end{itemize}
@@ -6192,15 +6205,15 @@
 }
 
 \LMHash{}
-Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.  
+Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.
 
 \LMHash{}
-It is a static type warning if the body of $f$ is marked \ASYNC{} and the type \code{Future$<$flatten(T)$>$} (\ref{functionExpressions}) may not be assigned to the declared return type of $f$.    Otherwise, it is a static type warning if $T$ may not be assigned to the declared return type of $f$. 
+It is a static type warning if the body of $f$ is marked \ASYNC{} and the type \code{Future$<$flatten(T)$>$} (\ref{functionExpressions}) may not be assigned to the declared return type of $f$.    Otherwise, it is a static type warning if $T$ may not be assigned to the declared return type of $f$.
 
 \LMHash{}
 Let $S$ be the runtime type of $o$. In checked mode:
 \begin{itemize}
-\item  If the body of $f$ is marked \ASYNC{} (\ref{functions}) it is a dynamic type error if $o$ is not \NULL{} (\ref{null}) and \code{Future$<$S$>$} is not a subtype of the actual return type  (\ref{actualTypeOfADeclaration}) of $f$.
+\item  If the body of $f$ is marked \ASYNC{} (\ref{functions}) it is a dynamic type error if $o$ is not \NULL{} (\ref{null}) and \code{Future$<$flatten(S)$>$} is not a subtype of the actual return type  (\ref{actualTypeOfADeclaration}) of $f$.
 \item Otherwise, it is a dynamic type error if $o$ is not \NULL{} and the runtime type of $o$ is not a subtype of the actual return type of $f$.
 \end{itemize}
 
@@ -6215,14 +6228,14 @@
 It is a compile-time error if a return statement of the form \code{\RETURN{} $e$;} appears in a generator function.
 
 \rationale{
-In the case of a generator function, the value returned by the function is the iterable or stream associated with it, and individual elements are added to that iterable using yield statements, and so returning a value makes no sense. 
+In the case of a generator function, the value returned by the function is the iterable or stream associated with it, and individual elements are added to that iterable using yield statements, and so returning a value makes no sense.
 }
 
 \LMHash{}
 Let $f$ be the function immediately enclosing a return statement of the form \RETURN{}; It is a static warning  $f$ is neither a generator nor a generative constructor and either:
 \begin{itemize}
-\item  $f$ is synchronous and the return type of $f$ may not be assigned to \VOID{} (\ref{typeVoid}) or, 
-\item  $f$ is asynchronous and the return type of $f$ may not be assigned to \code{Future$<$Null$>$}.  
+\item  $f$ is synchronous and the return type of $f$ may not be assigned to \VOID{} (\ref{typeVoid}) or,
+\item  $f$ is asynchronous and the return type of $f$ may not be assigned to \code{Future$<$Null$>$}.
 \end{itemize}
 
  \commentary{
@@ -6240,17 +6253,17 @@
 \begin{itemize}
 \item
 The current return value is set to \NULL{}.
-\item 
+\item
 Let $c$ be the \FINALLY{} clause of the innermost enclosing try-finally statement, if any. If $c$ is defined,  let $h$ be the handler induced by $c$. If $h$ is defined, control is transferred to $h$.
 \item
-Otherwise, execution of the current method terminates. 
+Otherwise, execution of the current method terminates.
 \end{itemize}
 
 \LMHash{}
 Otherwise the return statement is executed by executing the statement  \code{\RETURN{} \NULL{};} if it occurs inside a method, getter, setter or factory; otherwise, the return statement necessarily occurs inside a generative constructor, in which case it is executed by executing  \code{\RETURN{} \THIS{};}.
 
-\commentary{Despite the fact that \code{\RETURN{};} is executed as if by a \code{\RETURN{} $e$;}, it is important to understand that it is not a static warning to include a statement of the form \code{\RETURN{};} 
-%in a \VOID{} function; neither is it illegal 
+\commentary{Despite the fact that \code{\RETURN{};} is executed as if by a \code{\RETURN{} $e$;}, it is important to understand that it is not a static warning to include a statement of the form \code{\RETURN{};}
+%in a \VOID{} function; neither is it illegal
 in a generative constructor. The rules relate only to the specific syntactic form \code{\RETURN{} $e$;}.
 }
 
@@ -6275,14 +6288,14 @@
 
 \rationale{The sole role of labels is to provide targets for the break (\ref{break}) and continue (\ref{continue}) statements.}
 
-%\Q{Are labels in a separate namespace? Bug 49774299} 
+%\Q{Are labels in a separate namespace? Bug 49774299}
 
  \begin{grammar}
 {\bf label:}
       identifier `{\escapegrammar :}'
     .
  \end{grammar}
- 
+
 \LMHash{}
  The semantics of a labeled statement $L: s$ are identical to those of the statement $s$. The namespace of labels is distinct from the one used for types, functions and variables.
 
@@ -6292,24 +6305,24 @@
 \rationale{Labels should be avoided by programmers at all costs. The motivation for including labels in the language is primarily making Dart a better target for code generation.
 }
 
- 
+
 \subsection{ Break}
 \LMLabel{break}
 
 \LMHash{}
-The {\em break statement} consists of the reserved word \BREAK{} and an optional label (\ref{labels}). 
+The {\em break statement} consists of the reserved word \BREAK{} and an optional label (\ref{labels}).
 
 \begin{grammar}
 {\bf breakStatement:}
      \BREAK{} identifier? `{\escapegrammar ;}'
     .
  \end{grammar}
- 
-\LMHash{}
-Let $s_b$ be a \BREAK{} statement. If $s_b$ is of the form  \code{\BREAK{} $L$;}, then let $s_E$ be the innermost labeled statement with label $L$ enclosing $s_b$. If $s_b$ is of the form \code{\BREAK{};},  then let $s_E$ be the innermost  \DO{} (\ref{do}), \FOR{} (\ref{for}), \SWITCH{} (\ref{switch}) or \WHILE{} (\ref{while}) statement enclosing  $s_b$. It is a compile-time error if no such statement $s_E$ exists within the innermost function in which  $s_b$ occurs.  Furthermore, let $s_1, \ldots, s_n$ be those \TRY{} statements that are both enclosed in $s_E$ and that enclose  $s_b$, and that have a \FINALLY{} clause. Lastly, let $f_j$ be the \FINALLY{} clause of $s_j, 1 \le j \le n$.   Executing  $s_b$ first executes $f_1, \ldots,  f_n$ in innermost-clause-first  order and then terminates $s_E$. 
 
 \LMHash{}
-If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), its associated stream subscription is canceled. Furthermore, let $a_k$ be the set of asynchronous for loops  and yield-each statements (\ref{yieldEach}) enclosing $s_b$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$. 
+Let $s_b$ be a \BREAK{} statement. If $s_b$ is of the form  \code{\BREAK{} $L$;}, then let $s_E$ be the innermost labeled statement with label $L$ enclosing $s_b$. If $s_b$ is of the form \code{\BREAK{};},  then let $s_E$ be the innermost  \DO{} (\ref{do}), \FOR{} (\ref{for}), \SWITCH{} (\ref{switch}) or \WHILE{} (\ref{while}) statement enclosing  $s_b$. It is a compile-time error if no such statement $s_E$ exists within the innermost function in which  $s_b$ occurs.  Furthermore, let $s_1, \ldots, s_n$ be those \TRY{} statements that are both enclosed in $s_E$ and that enclose  $s_b$, and that have a \FINALLY{} clause. Lastly, let $f_j$ be the \FINALLY{} clause of $s_j, 1 \le j \le n$.   Executing  $s_b$ first executes $f_1, \ldots,  f_n$ in innermost-clause-first  order and then terminates $s_E$.
+
+\LMHash{}
+If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), its associated stream subscription is canceled. Furthermore, let $a_k$ be the set of asynchronous for loops  and yield-each statements (\ref{yieldEach}) enclosing $s_b$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$.
 
 
 
@@ -6317,30 +6330,30 @@
 \LMLabel{continue}
 
 \LMHash{}
-The {\em continue statement} consists of the reserved word \CONTINUE{} and an optional label (\ref{labels}). 
+The {\em continue statement} consists of the reserved word \CONTINUE{} and an optional label (\ref{labels}).
 
 \begin{grammar}
 {\bf continueStatement:}
     \CONTINUE{} identifier? `{\escapegrammar ;}'
         .
- \end{grammar}      
- 
+ \end{grammar}
+
 \LMHash{}
  Let $s_c$ be a \CONTINUE{} statement. If $s_c$ is of the form  \code{\CONTINUE{} $L$;}, then let $s_E$ be the innermost labeled \DO{} (\ref{do}), \FOR{} (\ref{for}) or \WHILE{} (\ref{while}) statement or case clause with label $L$ enclosing $s_c$. If $s_c$ is of the form \code{\CONTINUE{};}  then let $s_E$ be the innermost  \DO{} (\ref{do}), \FOR{} (\ref{for}) or \WHILE{} (\ref{while}) statement enclosing  $s_c$. It is a compile-time error if no such statement or case clause $s_E$ exists within the innermost function in which  $s_c$ occurs.  Furthermore, let $s_1, \ldots, s_n$ be those \TRY{} statements that are both enclosed in $s_E$ and that enclose  $s_c$, and that have a \FINALLY{} clause. Lastly, let $f_j$ be the \FINALLY{} clause of $s_j, 1 \le j \le n$.   Executing  $s_c$ first executes $f_1, \ldots,  f_n$ in innermost-clause-first  order. Then, if $s_E$ is a case clause, control is transferred to the case clause. Otherwise, $s_E$ is necessarily a loop and execution resumes after the last statement in the loop body.
- 
+
  \commentary{
  In a while loop, that would be the boolean expression before the body. In a do loop, it would be the boolean expression after the body. In a for loop, it would be the increment clause.  In other words, execution continues to the next iteration of the loop.
  }
- 
+
 \LMHash{}
- If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_c$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$. 
- 
+ If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_c$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$.
+
  \subsection{ Yield and Yield-Each}
  \LMLabel{yieldAndYieldEach}
- 
+
  \subsubsection{ Yield}
  \LMLabel{yield}
- 
+
 \LMHash{}
  The {\em yield statement} adds an element to the result of a generator function (\ref{functions}).
 
@@ -6357,7 +6370,7 @@
 First, the expression $e$ is evaluated to an object $o$. If the enclosing function $m$ is marked \ASYNC* (\ref{functions}) and the stream $u$ associated with $m$ has been paused,  then execution of $m$ is suspended until $u$ is resumed or canceled.
 
 \LMHash{}
-Next, $o$ is added to the iterable or stream associated with the immediately enclosing function. 
+Next, $o$ is added to the iterable or stream associated with the immediately enclosing function.
 
 \LMHash{}
 If the enclosing function $m$ is marked \ASYNC* and the stream $u$ associated with $m$ has been canceled, then let $c$ be the \FINALLY{} clause (\ref{try}) of the innermost enclosing try-finally statement, if any. If $c$ is defined, let $h$ be the handler induced by $c$. If $h$ is defined, control is transferred to $h$. If $h$ is undefined, the immediately enclosing function terminates.
@@ -6378,7 +6391,7 @@
 If the enclosing function $m$ is marked \SYNC* (\ref{functions}) then:
 \begin{itemize}
 \item
-Execution of the function $m$ immediately enclosing $s$ is suspended until the nullary method \code{moveNext()} is invoked upon the iterator used to initiate the current invocation of $m$. 
+Execution of the function $m$ immediately enclosing $s$ is suspended until the nullary method \code{moveNext()} is invoked upon the iterator used to initiate the current invocation of $m$.
 \item
 The current call to \code{moveNext()} returns \TRUE.
 \end{itemize}
@@ -6390,18 +6403,18 @@
 Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.  It is a static type warning if either:
 \begin{itemize}
 \item
- the body of $f$ is marked \ASYNC* and the type \code{Stream$<$T$>$} may not be assigned to the declared return type of $f$. 
+ the body of $f$ is marked \ASYNC* and the type \code{Stream$<$T$>$} may not be assigned to the declared return type of $f$.
  \item
  the body of $f$ is marked \SYNC* and the type \code{Iterable$<$T$>$} may not be assigned to the declared return type of $f$.
- \end{itemize} 
+ \end{itemize}
 
- 
+
  \subsubsection{ Yield-Each}
  \LMLabel{yieldEach}
- 
+
 \LMHash{}
  The {\em yield-each statement} adds a series of values to the result of a generator function (\ref{functions}).
- 
+
  \begin{grammar}
 {\bf yieldEachStatement:}
    \YIELD* expression `{\escapegrammar ;}'
@@ -6412,16 +6425,16 @@
 Execution of a statement $s$ of the form \code{\YIELD* $e$;}  proceeds as follows:
 
 \LMHash{}
-First, the expression $e$ is evaluated to an object $o$. 
+First, the expression $e$ is evaluated to an object $o$.
 
 \LMHash{}
 If the immediately enclosing function $m$ is marked \SYNC* (\ref{functions}), then:
 \begin{enumerate}
 \item It is a dynamic error if the class of $o$ does not implement \code{Iterable}.  Otherwise
-\item The method \cd{iterator} is invoked upon $o$ returning an object $i$. 
+\item The method \cd{iterator} is invoked upon $o$ returning an object $i$.
 \item \label{moveNext} The \cd{moveNext} method of $i$ is invoked on it with no arguments. If \cd{moveNext} returns \FALSE{} execution of $s$ is complete. Otherwise
 \item The getter \cd{current} is invoked on $i$. If the invocation raises an exception $ex$, execution of $s$ throws $ex$. Otherwise, the result $x$ of the getter invocation is added to the iterable associated with $m$.
-Execution of the function $m$ immediately enclosing $s$ is suspended until the nullary method \code{moveNext()} is invoked upon the iterator used to initiate the current invocation of $m$, at which point execution of $s$ continues at \ref{moveNext}. 
+Execution of the function $m$ immediately enclosing $s$ is suspended until the nullary method \code{moveNext()} is invoked upon the iterator used to initiate the current invocation of $m$, at which point execution of $s$ continues at \ref{moveNext}.
 \item
 The current call to \code{moveNext()} returns \TRUE.
 \end{enumerate}
@@ -6439,7 +6452,7 @@
 \item
 Otherwise,  $x$ is added to the stream associated with $m$ in the order it appears in $o$.  The function $m$ may suspend.
 \end{itemize}
-\item If the stream $o$ is done, execution of $s$ is complete. 
+\item If the stream $o$ is done, execution of $s$ is complete.
 \end{itemize}
 
 
@@ -6447,7 +6460,7 @@
 It is a compile-time error if a yield-each statement appears in a function that is not a generator function.
 
 \LMHash{}
-Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.  It is a static type warning if $T$ may not be assigned to the declared return type of $f$.  If $f$ is synchronous it is a static  type warning if $T$ may not be assigned to \code{Iterable}.  If $f$ is asynchronous it is a static  type warning if $T$ may not be assigned to \code{Stream}. 
+Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.  It is a static type warning if $T$ may not be assigned to the declared return type of $f$.  If $f$ is synchronous it is a static  type warning if $T$ may not be assigned to \code{Iterable}.  If $f$ is asynchronous it is a static  type warning if $T$ may not be assigned to \code{Stream}.
 
 
 \subsection{ Assert}
@@ -6461,30 +6474,30 @@
    assert `(' conditionalExpression `)' `{\escapegrammar ;}'
       .
 \end{grammar}
-      
+
 \LMHash{}
 The assert statement has no effect in production mode. In checked mode, execution of an assert statement \code{\ASSERT{}($e$);} proceeds as follows:
 
 \LMHash{}
-The conditional expression $e$ is evaluated to an object $o$. If the class of $o$ is a subtype of \code{Function} then let $r$ be the result of invoking $o$ with no arguments. Otherwise, let $r$ be $o$. 
+The conditional expression $e$ is evaluated to an object $o$. If the class of $o$ is a subtype of \code{Function} then let $r$ be the result of invoking $o$ with no arguments. Otherwise, let $r$ be $o$.
 It is a dynamic type error if $o$ is not of type \code{bool} or of type \code{Function}, or if $r$ is not of type \code{bool}.  If $r$ is \FALSE{}, we say that the assertion failed. If $r$ is \TRUE{}, we say that the assertion succeeded. If the assertion succeeded, execution of the assert statement is complete. If the assertion failed, an \code{AssertionError} is thrown.
 
 %\Q{Might be cleaner to define it as \code{if (!$e$) \{\THROW{} \NEW{} AssertionError();\}} (in checked mode only).
 %What about an error message as part of the assert?}
 
 \LMHash{}
- It is a static type warning if the type of $e$ may not be assigned to either  \code{bool} or $() \rightarrow$ \code{bool}.  
+ It is a static type warning if the type of $e$ may not be assigned to either  \code{bool} or $() \rightarrow$ \code{bool}.
 
 \rationale{Why is this a statement, not a built in function call? Because it is handled magically so it has no effect and no overhead in production mode. Also, in the absence of final methods. one could not prevent it being overridden (though there is no real harm in that).  It cannot be viewed as a function call that is being optimized away because the argument might have side effects.
 }
 
-%If a lexically visible declaration named \code{assert} is in scope, an assert statement 
+%If a lexically visible declaration named \code{assert} is in scope, an assert statement
 %\code{\ASSERT{} (e); }
 %is interpreted as an expression statement \code{(assert(e));} .
 
 %\rationale{
 %Since \ASSERT{} is a built-in identifier, one might define a function or method with this name.
-%It is impossible to distinguish as \ASSERT{} statement from a method invocation in such a situation. 
+%It is impossible to distinguish as \ASSERT{} statement from a method invocation in such a situation.
 %One could choose to always interpret such code as an \ASSERT{} statement. Or we could choose to give priority to any lexically visible user defined function.  The former can cause rather puzzling situations, e.g.,}
 
 %\begin{dartCode}
@@ -6505,7 +6518,7 @@
 \LMLabel{librariesAndScripts}
 
 \LMHash{}
-A Dart program consists of one or more libraries, and may be built out of one or more {\em compilation units}. A compilation unit may be a library or a part (\ref{parts}). 
+A Dart program consists of one or more libraries, and may be built out of one or more {\em compilation units}. A compilation unit may be a library or a part (\ref{parts}).
 
 \LMHash{}
 A library consists of (a possibly empty) set of imports, a set of exports,  and a set of top-level declarations. A top-level declaration is either a class (\ref{classes}), a type alias declaration (\ref{typedef}), a function (\ref{functions}) or a variable declaration (\ref{variables}). The members of a library $L$ are those top level declarations given within $L$.
@@ -6519,14 +6532,14 @@
       typeAlias;
       \EXTERNAL{}? functionSignature `{\escapegrammar ;}';
       \EXTERNAL{}? getterSignature `{\escapegrammar ;}';
-      \EXTERNAL{}? setterSignature `{\escapegrammar ;}';      
+      \EXTERNAL{}? setterSignature `{\escapegrammar ;}';
       functionSignature functionBody;
       returnType? \GET{} identifier functionBody;
       returnType? \SET{} identifier formalParameterList functionBody;
       (\FINAL{} $|$ \CONST{}) type? staticFinalDeclarationList `{\escapegrammar ;}';
       variableDeclaration `{\escapegrammar ;}'
     .
-    
+
     {\bf getOrSet:} \GET{};
       \SET{}
     .
@@ -6545,47 +6558,47 @@
 %      library '\{' libraryBody '\}'
       scriptTag? libraryName? importOrExport* partDirective* topLevelDefinition*
     .
-    
+
     {\bf     scriptTag:}
    `\#!' {\escapegrammar (\~{}NEWLINE)*} NEWLINE
- .    
+ .
 
 {\bf libraryName:}
    metadata \LIBRARY{} identifier (`{\escapegrammar .}' identifier)* `{\escapegrammar ;}'
    .
 
 {\bf importOrExport:}libraryImport ;
-  libraryExport   
+  libraryExport
  \end{grammar}
- 
+
 \LMHash{}
  Libraries may be {\em explicitly named} or {\em implicitly named}. An explicitly named library begins with  the  word \LIBRARY{} (possibly prefaced with any applicable metadata annotations), followed by a qualified identifier that gives the name of the library.
- 
+
  \commentary{
  Technically, each dot and identifier is a separate token and so spaces between them are acceptable. However, the actual library name is the concatenation of the simple identifiers and dots and contains no spaces.
  }
- 
+
 \LMHash{}
-An implicitly named library has the empty string as its name. 
+An implicitly named library has the empty string as its name.
 
  \rationale{
 The name of a library is used to tie it to separately compiled parts of the library (called parts) and  can be used for printing and, more generally, reflection. The name may be relevant for further language evolution.
  }
- 
+
  \commentary{
 Libraries intended for widespread use should avoid name collisions.  Dart's \code{pub} package management system provides a mechanism for doing so.  Each pub package is guaranteed a unique name, effectively enforcing a global namespace.
  }
- 
+
 \LMHash{}
  A library may optionally begin with a {\em script tag}. Script tags are intended for use with scripts (\ref{scripts}).  A script tag can be used to identify the interpreter of the script to whatever computing environment the script is embedded in. The script tag must appear before any whitespace or comments.  A script  tag begins with the characters \#! and ends at the end of the line. Any characters that follow \#!  in the script tag are ignored by the Dart implementation.
- 
+
 \LMHash{}
 Libraries are units of privacy. A private declaration declared within a library $L$ can only be accessed by code within $L$. Any attempt to access a private member declaration from outside $L$ will cause a method, getter or setter lookup failure.
 
 \commentary{Since top level privates are not imported, using the top level privates of another library is never possible. }
 
 \LMHash{}
-The {\em public namespace} of library $L$ is the mapping that maps the simple name of each public top-level member $m$ of $L$ to $m$. 
+The {\em public namespace} of library $L$ is the mapping that maps the simple name of each public top-level member $m$ of $L$ to $m$.
 The scope of a library $L$ consists of the names introduced by all top-level declarations declared in $L$, and the names added by $L$'s imports (\ref{imports}).
 
 
@@ -6593,28 +6606,28 @@
 \LMLabel{imports}
 
 \LMHash{}
-An {\em import} specifies a library to be used in the scope of another library. 
+An {\em import} specifies a library to be used in the scope of another library.
 \begin{grammar}
 {\bf libraryImport:}
    metadata importSpecification
     .
- 
+
  {\bf importSpecification:}
     \IMPORT{}  uri (\AS{} identifier)?  combinator* `{\escapegrammar ;}';
      \IMPORT{}  uri \DEFERRED{} \AS{} identifier  combinator* `{\escapegrammar ;}'
     .
-       
+
 {\bf combinator:}\SHOW{} identifierList;
 \HIDE{} identifierList
     .
-    
+
     {\bf identifierList:}
       identifier (, identifier)*
  \end{grammar}
- 
+
 
 \LMHash{}
-An import specifies a URI $x$ where the declaration of an imported library is to be found. 
+An import specifies a URI $x$ where the declaration of an imported library is to be found.
 
 \LMHash{}
 Imports may be {\em deferred} or {\em immediate}. A deferred import is distinguished by the appearance of the built-in identifier \DEFERRED{} after the URI. Any import that is not deferred is immediate.
@@ -6629,10 +6642,10 @@
  One cannot detect the problem at compile time because compilation often occurs during execution and  one does not know what the URI refers to.  However the development environment should detect the problem.
  }
 
- 
+
 \LMHash{}
 The {\em current library} is the library currently being compiled. The import modifies the  namespace of the current library in a manner that is determined by the imported library and by the optional elements of  the import.
-     
+
 \LMHash{}
 An immediate import directive $I$ may optionally include a prefix clause of the form \AS{} \code{Id} used to prefix names imported by $I$. A deferred import must include a prefix clause or a compile time error occurs. It is a compile-time error if a prefix used in a deferred import is used in another import clause.
 
@@ -6668,7 +6681,7 @@
 The effect of a repeated call to \code{$p$.loadLibrary} is as follows:
 \begin{itemize}
 \item
-If another call to \code{$p$.loadLibrary} has already succeeded, the repeated call also succeeds. 
+If another call to \code{$p$.loadLibrary} has already succeeded, the repeated call also succeeds.
 Otherwise,
 \item
 If another call to  to \code{$p$.loadLibrary} has failed:
@@ -6700,23 +6713,23 @@
 \LMHash{}
 Let $NS_0$ be the exported namespace (\ref{exports}) of $B$. Then, for each combinator clause $C_i, i \in 1..n$ in $I$:
 \begin{itemize}
-\item If $C_i$ is of the form 
+\item If $C_i$ is of the form
 
-\code{\SHOW{} $id_1, \ldots, id_k$} 
+\code{\SHOW{} $id_1, \ldots, id_k$}
 
 then let $NS_i = \SHOW{}([id_1, \ldots, id_k], NS_{i-1}$)
 
 where $show(l,n)$ takes a list of identifiers $l$ and a namespace $n$, and produces a namespace that maps each name in $l$ to the same element that $n$ does. Furthermore, for each name $x$ in $l$, if $n$ defines the name  $x=$ then the new namespace maps $x=$ to the same element that $n$ does. Otherwise the resulting mapping is undefined.
-  
-\item If $C_i$ is of the form 
 
-\code{\HIDE{} $id_1, \ldots, id_k$} 
+\item If $C_i$ is of the form
 
-then let $NS_i = \HIDE{}([id_1, \ldots, id_k], NS_{i-1}$) 
+\code{\HIDE{} $id_1, \ldots, id_k$}
 
-where $hide(l, n)$ takes a list of identifiers $l$ and a namespace $n$, and produces a namespace that is identical to $n$ except that for each name $k$ in $l$, $k$ and $k=$ are undefined. 
+then let $NS_i = \HIDE{}([id_1, \ldots, id_k], NS_{i-1}$)
+
+where $hide(l, n)$ takes a list of identifiers $l$ and a namespace $n$, and produces a namespace that is identical to $n$ except that for each name $k$ in $l$, $k$ and $k=$ are undefined.
 \end{itemize}
- 
+
 \LMHash{}
 Next, if $I$ includes a prefix clause of the form \AS{} $p$, let $NS =  NS_n \cup \{p: prefixObject(NS_n)\}$ where $prefixObject(NS_n)$ is a {\em prefix object} for the namespace $NS_n$, which is an object that has the following members:
 
@@ -6748,7 +6761,7 @@
 \rationale{The greatly increases the chance that a member can be added to a library without breaking its importers.}
 
 \LMHash{}
-A {\em system library} is a library that is part of the Dart implementation. Any other library is a {\em non-system library}. If a name $N$ is referenced by a library $L$ and $N$ would be introduced into the top level scope of $L$ by 
+A {\em system library} is a library that is part of the Dart implementation. Any other library is a {\em non-system library}. If a name $N$ is referenced by a library $L$ and $N$ would be introduced into the top level scope of $L$ by
 imports of two libraries, $L_1$ and $L_2$, and the exported namespace of $L_1$ binds $N$ to a declaration originating in a system library:
 
 %an import of a  system library and an import of a non-system library:
@@ -6767,7 +6780,7 @@
 If a name $N$ is referenced by a library $L$ and $N$ is  introduced into  the top level scope of $L$ by more than one import, and not all the imports denote the same declaration, then:
 \begin{itemize}
 \item A static warning occurs.
-\item If $N$ is referenced as a function, getter or setter, a \code{NoSuchMethodError} is thrown. 
+\item If $N$ is referenced as a function, getter or setter, a \code{NoSuchMethodError} is thrown.
 \item  If $N$ is referenced as a type, it is treated as a malformed type.
 
 \end{itemize}
@@ -6780,7 +6793,7 @@
 }
 
 \rationale{
-The policy above makes libraries more robust in the face of additions made to their imports.  
+The policy above makes libraries more robust in the face of additions made to their imports.
 
 A clear distinction needs to be made between this approach, and seemingly similar policies with respect to classes or interfaces.  The use of a class or interface, and of its members, is separate from its declaration. The usage and declaration may occur in widely separated places in the code, and may in fact be authored by different people or organizations.  It is important that errors are given at the offending declaration so that the party that receives the error can respond to it a meaningful way.
 
@@ -6797,14 +6810,14 @@
 }
 
 \commentary{Note that no errors or warnings are given if one hides or shows a name that is not in a namespace.}
-\rationale{  
+\rationale{
 This prevents situations where removing a name from a library would cause breakage of a client library.
 }
 
 \LMHash{}
 The dart core library \code{dart:core} is implicitly imported into every dart library other than itself via an  import clause of the form
 
-\code{\IMPORT{}  `dart:core';} 
+\code{\IMPORT{}  `dart:core';}
 
 unless the importing library explicitly imports \code{dart:core}.
 
@@ -6813,7 +6826,7 @@
 }
 
 \rationale{
-It would be nice if there was nothing special about \code{dart:core}. However, its use is pervasive, which leads to the decision to import it automatically.  However, some library $L$  may wish to define entities with names used by \code{dart:core} (which it can easily do, as the names declared by a library take precedence). Other libraries may wish to use $L$ and may want to use members of $L$ that conflict with the core library without having to use a prefix and without encountering warnings. The above rule makes this possible, essentially canceling \code{dart:core}'s special treatment by means of yet another special rule. 
+It would be nice if there was nothing special about \code{dart:core}. However, its use is pervasive, which leads to the decision to import it automatically.  However, some library $L$  may wish to define entities with names used by \code{dart:core} (which it can easily do, as the names declared by a library take precedence). Other libraries may wish to use $L$ and may want to use members of $L$ that conflict with the core library without having to use a prefix and without encountering warnings. The above rule makes this possible, essentially canceling \code{dart:core}'s special treatment by means of yet another special rule.
 }
 
 \subsection{Exports}
@@ -6827,9 +6840,9 @@
    metadata \EXPORT{}  uri  combinator* `{\escapegrammar ;}'
     .
  \end{grammar}
- 
+
 \LMHash{}
- An export specifies a URI $x$ where the declaration of an exported library is to be found.  It is a compile-time error if  the specified URI does not refer to a library declaration.  
+ An export specifies a URI $x$ where the declaration of an exported library is to be found.  It is a compile-time error if  the specified URI does not refer to a library declaration.
 
 \LMHash{}
 We say that a name {\em is exported by a library} (or equivalently, that a library {\em exports a name}) if the name is in the library's exported namespace. We say that a declaration {\em is exported by a library} (or equivalently, that a library {\em exports a declaration}) if the declaration is in the library's exported namespace.
@@ -6853,17 +6866,17 @@
 \LMHash{}
 Let $NS_0$ be the exported namespace of $B$. Then, for each combinator clause $C_i, i \in 1..n$ in $E$:
 \begin{itemize}
-\item If $C_i$ is of the form \code{\SHOW{} $id_1, \ldots, id_k$} then let 
+\item If $C_i$ is of the form \code{\SHOW{} $id_1, \ldots, id_k$} then let
 
-$NS_i = \SHOW{}([id_1, \ldots, id_k], NS_{i-1}$).  
-\item If $C_i$ is of the form \code{\HIDE{} $id_1, \ldots, id_k$} 
+$NS_i = \SHOW{}([id_1, \ldots, id_k], NS_{i-1}$).
+\item If $C_i$ is of the form \code{\HIDE{} $id_1, \ldots, id_k$}
 
-then let $NS_i = \HIDE{}([id_1, \ldots, id_k], NS_{i-1}$). 
+then let $NS_i = \HIDE{}([id_1, \ldots, id_k], NS_{i-1}$).
 \end{itemize}
 
 \LMHash{}
 For each
-entry mapping key $k$ to declaration $d$ in $NS_n$ an entry mapping $k$ to $d$ is added to the exported namespace of $L$ unless a  top-level declaration with the name $k$ exists in $L$.  
+entry mapping key $k$ to declaration $d$ in $NS_n$ an entry mapping $k$ to $d$ is added to the exported namespace of $L$ unless a  top-level declaration with the name $k$ exists in $L$.
 
 \LMHash{}
 If a name $N$ is referenced by a library $L$ and $N$ would be introduced into the exported namespace of $L$ by exports of two libraries, $L_1$ and $L_2$, and the exported namespace of $L_1$ binds $N$ to a declaration originating in a system library:
@@ -6889,14 +6902,14 @@
 \LMLabel{parts}
 
 \LMHash{}
-A library may be divided into {\em parts}, each of which can be stored in a separate location. A library identifies its parts by listing them via \PART{} directives. 
+A library may be divided into {\em parts}, each of which can be stored in a separate location. A library identifies its parts by listing them via \PART{} directives.
 
 \LMHash{}
 A {\em part directive} specifies a URI where a Dart compilation unit that should be incorporated into the current library may be found.
 
 \begin{grammar}
 {\bf partDirective:}
-   metadata \PART{}   uri `{\escapegrammar ;}' 
+   metadata \PART{}   uri `{\escapegrammar ;}'
     .
 
 {\bf partHeader:}
@@ -6925,22 +6938,22 @@
 First, $S$ is compiled as a library as specified above. Then, the top-level function \code{main} that is in the exported namespace of $S$ is invoked. If \code{main} has no positional parameters, it is invoked with no arguments. Otherwise if \code{main} has exactly one positional parameter, it is invoked with a single actual argument whose runtime type implements \code{List$<$String$>$}.  Otherwise \code{main} is invoked with the following two actual arguments:
 \begin{enumerate}
 \item An object whose runtime type implements \code{List$<$String$>$}.
-\item The initial message of the current isolate $i$ as determined by the invocation of \code{Isolate.spawnUri} that spawned $i$. 
+\item The initial message of the current isolate $i$ as determined by the invocation of \code{Isolate.spawnUri} that spawned $i$.
 \end{enumerate}
 
 \LMHash{}
 It is a run time error if $S$ does not declare or export either:
 \begin{itemize}
-\item  A top-level function named  \code{main}, or 
+\item  A top-level function named  \code{main}, or
 \item A top-level getter named  \code{main} that returns a function.
 \end{itemize}
 
 \commentary {
-Note that if \code{main} requires more than two arguments, a run time error will occur. 
+Note that if \code{main} requires more than two arguments, a run time error will occur.
 }
 
 \rationale{
-The names of scripts are optional, in the interests of interactive, informal use. However, any script of long term value should be given a name as a matter of good practice. 
+The names of scripts are optional, in the interests of interactive, informal use. However, any script of long term value should be given a name as a matter of good practice.
 }
 
 \commentary {
@@ -6961,26 +6974,26 @@
 
 \LMHash{}
 It is a compile-time error if  the string literal $x$ that describes a URI is not a compile-time constant, or if $x$ involves string interpolation.
- 
+
 \LMHash{}
-This specification does not discuss the interpretation of URIs, with the following exceptions. 
- 
+This specification does not discuss the interpretation of URIs, with the following exceptions.
+
  \rationale{
  The interpretation of URIs is mostly left to the surrounding computing environment. For example, if Dart is running in a web browser, that browser will likely interpret some URIs. While it might seem attractive to specify, say, that URIs are interpreted with respect to a standard such as IETF RFC 3986, in practice this will usually depend on the browser and cannot be relied upon.
  }
- 
+
 \LMHash{}
-A URI of the form \code{dart:$s$} is interpreted as a reference to a system library (\ref{imports}) $s$. 
- 
+A URI of the form \code{dart:$s$} is interpreted as a reference to a system library (\ref{imports}) $s$.
+
 \LMHash{}
 A URI of the form \code{package:$s$} is interpreted in an implementation specific manner.
 
 \rationale{
-The intent is that, during development, Dart programmers can rely on a package manager to find elements of their program. 
+The intent is that, during development, Dart programmers can rely on a package manager to find elements of their program.
 }
 
 \LMHash{}
-Otherwise, any relative URI is interpreted as relative to the location of the current library. All further interpretation of URIs is implementation dependent. 
+Otherwise, any relative URI is interpreted as relative to the location of the current library. All further interpretation of URIs is implementation dependent.
 
 \commentary{This means it is dependent on the embedder.}
 
@@ -7006,7 +7019,7 @@
     .
 
 {\bf typeName:}
-      qualified 
+      qualified
     .
 
 {\bf typeArguments:}
@@ -7021,7 +7034,7 @@
 \LMHash{}
 A Dart implementation must provide a static checker that detects and reports exactly those situations this specification identifies as static warnings and only those situations. However:
 \begin{itemize}
-\item Running  the static checker on a program $P$ is not required for compiling and running $P$.  
+\item Running  the static checker on a program $P$ is not required for compiling and running $P$.
 \item Running the static checker on a program $P$ must not prevent successful compilation of $P$ nor may it prevent the execution of $P$, regardless of whether any static warnings occur.
 \end{itemize}
 
@@ -7035,17 +7048,17 @@
 \begin{itemize}
 \item $T$ has the form $id$ or the form $prefix.id$, and in the enclosing lexical scope, the name $id$ (respectively $prefix.id$) does not denote a type.
 \item $T$ denotes a type variable in the enclosing lexical scope, but occurs in the signature or body of a static member.
-\item $T$ is a parameterized type of the form $G<S_1, \ldots , S_n>$, and  $G$ is malformed. 
+\item $T$ is a parameterized type of the form $G<S_1, \ldots , S_n>$, and  $G$ is malformed.
 \item $T$ denotes declarations that were imported from multiple imports clauses.
-%Either $G$ or $S_i,  i \in 1.. n$ are malformed. 
+%Either $G$ or $S_i,  i \in 1.. n$ are malformed.
  % \item  $G$ is not a generic type with $n$ type parameters.
-%  \item Let $T_i$ be the type parameters of $G$ (if any) and let $B_i$ be the bound of $T_i,  i \in 1.. n$, and $S_i$ is not a subtype of $[S_1,  \ldots, S_n/T_1, \ldots, T_n]B_i,   i \in 1.. n$. 
+%  \item Let $T_i$ be the type parameters of $G$ (if any) and let $B_i$ be the bound of $T_i,  i \in 1.. n$, and $S_i$ is not a subtype of $[S_1,  \ldots, S_n/T_1, \ldots, T_n]B_i,   i \in 1.. n$.
 %  \end{itemize}
 \end{itemize}
 
 \LMHash{}
  Any use of a malformed  type gives rise to a static warning. A malformed type is then interpreted as \DYNAMIC{} by the static type checker and the runtime unless explicitly specified otherwise.
-  
+
  \rationale{
 This ensures that the developer is spared a series of cascading warnings as the malformed type interacts with other types.
 }
@@ -7057,11 +7070,11 @@
 % Now, when passed to a generic, p.T also has to be treated as dynamic - otherwise we have to fail immediately. Where do we say that? And how does this fit with idea that as a type object it fails? Should we say that the accessor on p returns dynamic instead of failing? Do we distinguish its use in a constructor vs its use in an annotation? It's not that we evaluate type objects in constructor args - these cannot represent parameterized types.
 
 
-\subsubsection{Type Promotion}   
+\subsubsection{Type Promotion}
 \LMLabel{typePromotion}
 
 \LMHash{}
-The static type system ascribes a static type to every expression.  In some cases, the types of local variables and formal parameters may be promoted from their declared types based on control flow. 
+The static type system ascribes a static type to every expression.  In some cases, the types of local variables and formal parameters may be promoted from their declared types based on control flow.
 
 \LMHash{}
 We say that a variable $v$ is known to have type $T$ whenever we allow the type of $v$ to be promoted. The exact circumstances when type promotion is allowed are given in the relevant sections of the specification (\ref{logicalBooleanExpressions}, \ref{conditional} and \ref{if}).
@@ -7088,11 +7101,11 @@
 %It is a run-time type error to access an undeclared type outside .
 
 \LMHash{}
-%It is a dynamic type error if a malformed type is used in a subtype test.  
-In checked mode, it is a dynamic type error if a deferred, malformed or malbounded (\ref{parameterizedTypes}) 
-type is used in a subtype test.  
+%It is a dynamic type error if a malformed type is used in a subtype test.
+In checked mode, it is a dynamic type error if a deferred, malformed or malbounded (\ref{parameterizedTypes})
+type is used in a subtype test.
 
-%In production mode, an undeclared type is treated as an instance of type \DYNAMIC{}. 
+%In production mode, an undeclared type is treated as an instance of type \DYNAMIC{}.
 
 \commentary{Consider the following program}
 
@@ -7108,7 +7121,7 @@
 
 \commentary{
 The type of the formal parameter of $f$ is $foo$, which is undeclared in the lexical scope. This will lead to a static type warning. At runtime the program will print \cd{yoyoma}, because $foo$ is treated as \DYNAMIC{}.
-%fail when executing the type test on the first line of $main()$ because it leads to a subtype comparison involving a malformed type ($foo$). 
+%fail when executing the type test on the first line of $main()$ because it leads to a subtype comparison involving a malformed type ($foo$).
 
 As another example take}
 
@@ -7116,7 +7129,7 @@
 \VAR{} i;
 i  j; //  a variable j of type i (supposedly)
 main() \{
-     j =  'I am not an i'; 
+     j =  'I am not an i';
 \}
 \end{dartCode}
 
@@ -7135,13 +7148,13 @@
 
 \CLASS{} A$<$T$>$ \IMPLEMENTS{} J,  I$<$T$>$ // type warning: T is not a subtype of num
 \{ ...
-\} 
+\}
 \end{dartCode}
 
 \commentary{Given the declarations above, the following}
 
 \begin{dartCode}
-I x = \NEW{} A$<$String$>$(); 
+I x = \NEW{} A$<$String$>$();
 \end{dartCode}
 
 \commentary{
@@ -7149,11 +7162,11 @@
 }
 
 \begin{dartCode}
-J x = \NEW{} A$<$String$>$(); 
+J x = \NEW{} A$<$String$>$();
 \end{dartCode}
 
 \commentary{
-does not cause a dynamic error, as there is no need to test against \code{I$<$String$>$} in this case. 
+does not cause a dynamic error, as there is no need to test against \code{I$<$String$>$} in this case.
 Similarly, in production mode
 }
 
@@ -7183,7 +7196,7 @@
 {\bf typeAlias:}
  	metadata  \TYPEDEF{} typeAliasBody
 	.
-	
+
 {\bf typeAliasBody:}
 	functionTypeAlias
 	.
@@ -7191,22 +7204,22 @@
 {\bf functionTypeAlias:}
        functionPrefix  typeParameters? formalParameterList '{\escapegrammar ;}'
     .
-    
+
     {\bf functionPrefix:}
     returnType? identifier
     .
-    
+
  \end{grammar}
- 
+
 \LMHash{}
  The effect of a type alias of the form  \code{\TYPEDEF{} $T$ $id (T_1$ $p_1, \ldots, T_n$ $p_n, [T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $p_{n+k}])$} declared in a library $L$ is is to introduce the name $id$ into the scope of $L$, bound to the function type $(T_1, \ldots, T_n, [T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $p_{n+k}])  \rightarrow T$.  The effect of a type alias of the form   \code{\TYPEDEF{} $T$ $id (T_1$ $p_1, \ldots, T_n$ $p_n, \{T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $p_{n+k}\})$} declared in a library $L$ is is to introduce the name $id$ into the scope of $L$, bound to the function type $(T_1, \ldots, T_n, \{T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $p_{n+k}\})  \rightarrow T$. . In either case, iff no return type is specified, it is taken to be \DYNAMIC{}. Likewise, if a type annotation is omitted on a formal parameter, it is taken to be \DYNAMIC{}.
- 
+
 \LMHash{}
-It is a compile-time error if any default values are specified in the signature of a function type alias. 
-%A typedef may only refer to itself  via the bounds of its generic parameters. 
+It is a compile-time error if any default values are specified in the signature of a function type alias.
+%A typedef may only refer to itself  via the bounds of its generic parameters.
 Any  self reference in a typedef, either directly, or recursively via another typedef, is a compile time error.
-%via a chain of references that does not include a class declaration.  
- 
+%via a chain of references that does not include a class declaration.
+
 
 
 \subsection{Interface Types}
@@ -7267,9 +7280,9 @@
 \commentary{The supertypes of an interface are its direct supertypes and their supertypes. }
 
 \LMHash{}
-An interface type $T$ may be assigned to a type $S$, written  $T \Longleftrightarrow S$, iff either $T <: S$ or $S <: T$. 
+An interface type $T$ may be assigned to a type $S$, written  $T \Longleftrightarrow S$, iff either $T <: S$ or $S <: T$.
 
-\rationale{This rule may surprise readers accustomed to conventional typechecking. The intent of the $\Longleftrightarrow$ relation is not to ensure that an assignment is correct. Instead, it aims to only flag assignments that are almost certain to be erroneous, without precluding assignments that may work. 
+\rationale{This rule may surprise readers accustomed to conventional typechecking. The intent of the $\Longleftrightarrow$ relation is not to ensure that an assignment is correct. Instead, it aims to only flag assignments that are almost certain to be erroneous, without precluding assignments that may work.
 
 For example, assigning a value of static type Object to a variable with static type String, while not guaranteed to be correct, might be fine if the runtime value happens to be a string.
 }
@@ -7278,7 +7291,7 @@
 \LMLabel{functionTypes}
 
 \LMHash{}
-Function types come in two variants: 
+Function types come in two variants:
 \begin{enumerate}
 \item
 The types of functions that only have positional parameters.  These have the general form $(T_1, \ldots, T_n, [T_{n+1} \ldots, T_{n+k}]) \rightarrow T$.
@@ -7297,7 +7310,7 @@
 %\end{enumerate}
 
 \LMHash{}
-%A function type $(T_1, \ldots T_n, [T_{n+1}  \ldots, T_{n+k}]) \rightarrow T$ is a subtype of the 
+%A function type $(T_1, \ldots T_n, [T_{n+1}  \ldots, T_{n+k}]) \rightarrow T$ is a subtype of the
 % the line below revises the rule to be more liberal
 A function type $(T_1, \ldots T_{k}, [T_{k+1}  \ldots, T_{n+m}]) \rightarrow T$ is a subtype of the
 function type $(S_1, \ldots, S_{k+j}, [S_{k+j+1} \ldots, S_{n}]) \rightarrow S$, if all of the following conditions are met:
@@ -7322,7 +7335,7 @@
 \item $\forall i \in 1 .. n, T_i \Longleftrightarrow S_i$.
 \item $k \ge m$ and $y_i \in \{x_1,  \ldots, x_k\}, i \in 1 .. m$.
 %\{x_1,  \ldots, x_k\}$ is a superset of $\{y_1,  \ldots, y_m\}$.
-\item For all $y_i \in \{y_1,  \ldots, y_m\}, y_i = x_j \Rightarrow T_j \Longleftrightarrow S_i$
+\item For all $y_i \in \{y_1,  \ldots, y_m\}, y_i = x_j \Rightarrow T_{x_j} \Longleftrightarrow S_{y_i}$
 \end{enumerate}
 
 %In addition, a function type $(T_1, \ldots, Tn, [T_{n+1} x_{n+1}, \ldots, T_{n+k} x_{n+k}]) \rightarrow T$ is a subtype of the function type $(T_1, \ldots, T_n, T_{n+1} , [T_{n+2} x_{n+2}, \ldots, T_{n+k} x_{n+k}]) \rightarrow T$.
@@ -7332,7 +7345,7 @@
 %We write $(T_1, \ldots, T_n) \rightarrow T$ as a shorthand for the type $(T_1, \ldots, T_n, []) \rightarrow T$.
 
 %The rules above need to be sanity checked, but the intent is that we view functions with rest parameters as having type $(T_1, ..., T_n, [\_{Tn+1}[] \_]) \rightarrow T$, where \_ is some magical identifier. Then the rules above may cover everything.
-% This is wrong - from the outside, the type takes an unbounded sequence of types, not a list. This can be modeled as $(T_1, \ldots, T_n, [T_{n+1}, \_ \ldots, T_{n+k} \_]) \rightarrow T$ for some finite $k$. 
+% This is wrong - from the outside, the type takes an unbounded sequence of types, not a list. This can be modeled as $(T_1, \ldots, T_n, [T_{n+1}, \_ \ldots, T_{n+k} \_]) \rightarrow T$ for some finite $k$.
 
 \LMHash{}
 In addition, the following subtype rules apply:
@@ -7351,7 +7364,7 @@
 }
 
 \LMHash{}
-A function type $T$ may be assigned to a function type $S$, written  $T \Longleftrightarrow S$, iff  $T <: S$. 
+A function type $T$ may be assigned to a function type $S$, written  $T \Longleftrightarrow S$, iff  $T <: S$.
 
 \LMHash{}
 % ensure that Object  and dynamic may be assign dot a function type
@@ -7398,7 +7411,7 @@
 \LMLabel{typeDynamic}
 
 \LMHash{}
-The type  \DYNAMIC{}  denotes the unknown type. 
+The type  \DYNAMIC{}  denotes the unknown type.
 
 \LMHash{}
 If no static type annotation has been provided the type system assumes the declaration has the unknown type. If a generic type is used but type arguments are not provided, then the  type arguments default to the unknown type.
@@ -7410,11 +7423,11 @@
 Type  \DYNAMIC{} has methods for every possible identifier and arity, with every possible combination of named parameters. These methods all have  \DYNAMIC{} as their return type, and their formal parameters all have type  \DYNAMIC{}.
 Type  \DYNAMIC{} has properties for every possible identifier. These properties all have type  \DYNAMIC{}.
 
-\rationale{From a usability perspective, we want to ensure that the checker does not issue errors everywhere an unknown type is used. The definitions above ensure that no secondary errors are reported when accessing an unknown type. 
+\rationale{From a usability perspective, we want to ensure that the checker does not issue errors everywhere an unknown type is used. The definitions above ensure that no secondary errors are reported when accessing an unknown type.
 
 The current rules say that missing type arguments are treated as if they were the type  \DYNAMIC{}.  An alternative is to consider them as meaning \code{Object}.  This would lead to earlier error detection in checked mode, and more aggressive errors during static typechecking. For example:
 
-(1)  \code{typedAPI(G\lt{String}\gt g)\{...\}} 
+(1)  \code{typedAPI(G\lt{String}\gt g)\{...\}}
 
 
 (2)  \code{typedAPI(new G()); }
@@ -7433,19 +7446,19 @@
 The name \DYNAMIC{} denotes a \cd{Type} object even though \DYNAMIC{} is not a class.
 
 %\rationale {
-%Type objects reify the runtime types of instances. No instance ever has type \DYNAMIC{}. 
+%Type objects reify the runtime types of instances. No instance ever has type \DYNAMIC{}.
 %}
 
 \subsection{Type Void}
 \LMLabel{typeVoid}
 
 \LMHash{}
-The special type \VOID{} may only be used as the return type of a function: it is a compile-time error to use \VOID{} in any other context. 
+The special type \VOID{} may only be used as the return type of a function: it is a compile-time error to use \VOID{} in any other context.
 
 \commentary{
 For example, as a type argument, or as the type of a variable or parameter
 
-Void is not an interface type. 
+Void is not an interface type.
 
 The only subtype relations that pertain to void are therefore:
 \begin{itemize}
@@ -7468,31 +7481,31 @@
 
 \rationale {
 It is syntacticly illegal to use \VOID{} as an expression, and it would make no sense to do so.
-Type objects reify the runtime types of instances. No instance ever has type \VOID{}.  
+Type objects reify the runtime types of instances. No instance ever has type \VOID{}.
 }
 
 
 
 \subsection{Parameterized Types}
-\LMLabel{parameterizedTypes} 
+\LMLabel{parameterizedTypes}
 
 \LMHash{}
 A {\em parameterized type} is an invocation of a generic type declaration.
 
 \LMHash{}
-Let $T$ be a parameterized type  $G<S_1,  \ldots, S_n>$. If $G$ is not a generic type, the type arguments $S_i$, $1 \le i \le n$ are discarded. If $G$ has $m \ne n$ type parameters, $T$ is treated as as a parameterized type with $m$ arguments, all of which are \DYNAMIC{}. 
+Let $T$ be a parameterized type  $G<S_1,  \ldots, S_n>$. If $G$ is not a generic type, the type arguments $S_i$, $1 \le i \le n$ are discarded. If $G$ has $m \ne n$ type parameters, $T$ is treated as as a parameterized type with $m$ arguments, all of which are \DYNAMIC{}.
 
-\commentary{In short, any arity mismatch results in all type arguments being dropped, and replaced with the correct number of type arguments, all set to \DYNAMIC{}. Of course, a static warning will be issued. 
+\commentary{In short, any arity mismatch results in all type arguments being dropped, and replaced with the correct number of type arguments, all set to \DYNAMIC{}. Of course, a static warning will be issued.
 }
 
 \LMHash{}
 Otherwise, let
- $T_i$ be the type parameters of $G$ and let $B_i$ be the bound of $T_i,  i \in 1.. n$,. $T$ is {\em malbounded} iff either $S_i$ is malbounded  or $S_i$ is not a subtype of $[S_1,  \ldots, S_n/T_1, \ldots, T_n]B_i,   i \in 1.. n$. 
- 
+ $T_i$ be the type parameters of $G$ and let $B_i$ be the bound of $T_i,  i \in 1.. n$,. $T$ is {\em malbounded} iff either $S_i$ is malbounded  or $S_i$ is not a subtype of $[S_1,  \ldots, S_n/T_1, \ldots, T_n]B_i,   i \in 1.. n$.
+
 \commentary{
 Note, that, in checked mode, it is a dynamic type error if a malbounded type is used in a type test as specified in \ref{dynamicTypeSystem}.
 }
- 
+
 \LMHash{}
 Any use of a malbounded type gives rise to a static warning.
 
@@ -7526,14 +7539,14 @@
 
 \LMHash{}
 % does this diverge in some cases?
-Given two interfaces $I$ and $J$, let $S_I$ be the set of superinterfaces of $I$,  let $S_J$ be the set of superinterfaces of $J$ and let $S =  (I \cup S_I) \cap (J \cup S_J)$.  Furthermore, we define $S_n = \{T | T \in S  \wedge depth(T) =n\}$ for any finite $n$ %, and $k=max(depth(T_1), \ldots, depth(T_m)), T_i \in S, i \in 1..m$, 
+Given two interfaces $I$ and $J$, let $S_I$ be the set of superinterfaces of $I$,  let $S_J$ be the set of superinterfaces of $J$ and let $S =  (I \cup S_I) \cap (J \cup S_J)$.  Furthermore, we define $S_n = \{T | T \in S  \wedge depth(T) =n\}$ for any finite $n$ %, and $k=max(depth(T_1), \ldots, depth(T_m)), T_i \in S, i \in 1..m$,
 where $depth(T)$ is the number of steps in the longest inheritance path from $T$ to \code{Object}. Let $q$ be the largest number such that $S_q$ has cardinality one. The least upper bound of $I$ and $J$ is the sole element of  $S_q$.
 
 \LMHash{}
 The least upper bound of \DYNAMIC{} and any type $T$ is \DYNAMIC{}.
 The least upper bound of \VOID{} and any type $T \ne \DYNAMIC{}$ is \VOID{}.
 The least upper bound of $\bot$ and any type $T$ is $T$.
-Let $U$ be a type variable with upper bound $B$. The least upper bound of $U$ and a type $T \ne \bot$ is the least upper bound of $B$ and $T$. 
+Let $U$ be a type variable with upper bound $B$. The least upper bound of $U$ and a type $T \ne \bot$ is the least upper bound of $B$ and $T$.
 
 \LMHash{}
 The least upper bound relation is symmetric and reflexive.
@@ -7544,41 +7557,41 @@
 The least upper bound of a function type and an interface type $T$ is the least upper bound of \cd{Function} and $T$.
 Let $F$ and $G$ be function types. If $F$ and $G$ differ in their number of required parameters, then the least upper bound of $F$ and $G$ is \cd{Function}.  Otherwise:
 \begin{itemize}
-\item If 
-
-$F= (T_1 \ldots T_r, [T_{r+1}, \ldots, T_n]) \longrightarrow T_0$, 
-
-$G= (S_1 \ldots S_r, [S_{r+1}, \ldots, S_k]) \longrightarrow S_0$ 
-
-where $k \le n$ then the least upper bound of $F$ and $G$ is 
-
-$(L_1 \ldots L_r, [L_{r+1}, \ldots, L_k]) \longrightarrow L_0$ 
-
-where $L_i$ is the least upper bound of $T_i$ and $S_i, i \in 0..k$.
-\item If 
+\item If
 
 $F= (T_1 \ldots T_r, [T_{r+1}, \ldots, T_n]) \longrightarrow T_0$,
 
-$G= (S_1 \ldots S_r, \{ \ldots \}) \longrightarrow S_0$ 
+$G= (S_1 \ldots S_r, [S_{r+1}, \ldots, S_k]) \longrightarrow S_0$
 
-then the least upper bound of $F$ and $G$ is 
+where $k \le n$ then the least upper bound of $F$ and $G$ is
 
-$(L_1 \ldots L_r) \longrightarrow L_0$ 
+$(L_1 \ldots L_r, [L_{r+1}, \ldots, L_k]) \longrightarrow L_0$
 
-where $L_i$ 
+where $L_i$ is the least upper bound of $T_i$ and $S_i, i \in 0..k$.
+\item If
+
+$F= (T_1 \ldots T_r, [T_{r+1}, \ldots, T_n]) \longrightarrow T_0$,
+
+$G= (S_1 \ldots S_r, \{ \ldots \}) \longrightarrow S_0$
+
+then the least upper bound of $F$ and $G$ is
+
+$(L_1 \ldots L_r) \longrightarrow L_0$
+
+where $L_i$
 is the least upper bound of $T_i$ and $S_i, i \in 0..r$.
-\item If 
+\item If
 
-$F= (T_1 \ldots T_r, \{T_{r+1}$  $p_{r+1}, \ldots, T_f$ $p_f\}) \longrightarrow T_0$,  
+$F= (T_1 \ldots T_r, \{T_{r+1}$  $p_{r+1}, \ldots, T_f$ $p_f\}) \longrightarrow T_0$,
 
-$G= (S_1 \ldots S_r, \{ S_{r+1}$  $q_{r+1}, \ldots, S_g$ $q_g\}) \longrightarrow S_0$ 
+$G= (S_1 \ldots S_r, \{ S_{r+1}$  $q_{r+1}, \ldots, S_g$ $q_g\}) \longrightarrow S_0$
 
 then let $\{x_m, \ldots x_n\}  = \{p_{r+1}, \ldots, p_f\} \cap \{q_{r+1}, \ldots, q_g\}$ and let $X_j$ be the least upper bound of the types of $x_j$ in $F$ and $G, j \in m..n$. Then
 the least upper bound of $F$ and $G$ is
 
-$(L_1 \ldots L_r, \{ X_m$ $x_m, \ldots, X_n$ $x_n\}) \longrightarrow L_0$ 
+$(L_1 \ldots L_r, \{ X_m$ $x_m, \ldots, X_n$ $x_n\}) \longrightarrow L_0$
 
-where $L_i$ is the least upper bound of $T_i$ and $S_i, i \in 0..r$ 
+where $L_i$ is the least upper bound of $T_i$ and $S_i, i \in 0..r$
 \end{itemize}
 
 
@@ -7591,7 +7604,7 @@
 \LMHash{}
 Dart source text is represented as a sequence of Unicode code points.  This sequence is first converted into a sequence of tokens according to the lexical rules given in this specification.  At any point in the tokenization process, the longest possible token is recognized.
 
-\subsubsection{Reserved Words} 
+\subsubsection{Reserved Words}
 \LMLabel{reservedWords}
 
 \LMHash{}
@@ -7631,15 +7644,15 @@
       `/*' (MULTI\_LINE\_COMMENT $|$ \~{} `*/')* `*/'
     .
  \end{grammar}
-  
-\LMHash{}
-Dart supports both single-line and multi-line comments. A {\em single line comment} begins with the token \code{//}. Everything between \code{//} and the end of line must be ignored by the Dart compiler unless the comment is a documentation comment. . 
 
 \LMHash{}
-A {\em multi-line comment} begins with the token \code{/*} and ends with the token \code{*/}.  Everything between \code{/}* and \code{*}/ must be ignored by the Dart compiler unless the comment is a documentation comment. Comments may nest. 
+Dart supports both single-line and multi-line comments. A {\em single line comment} begins with the token \code{//}. Everything between \code{//} and the end of line must be ignored by the Dart compiler unless the comment is a documentation comment. .
 
 \LMHash{}
-{\em Documentation comments} are comments that begin with the tokens  \code{///} or  \code{/**}. Documentation comments are intended to be processed by a tool that produces human readable documentation. 
+A {\em multi-line comment} begins with the token \code{/*} and ends with the token \code{*/}.  Everything between \code{/}* and \code{*}/ must be ignored by the Dart compiler unless the comment is a documentation comment. Comments may nest.
+
+\LMHash{}
+{\em Documentation comments} are comments that begin with the tokens  \code{///} or  \code{/**}. Documentation comments are intended to be processed by a tool that produces human readable documentation.
 
 
 \LMHash{}
@@ -7665,7 +7678,7 @@
 
 \begin{tabular}{| r | r | r | r |}
 \hline
-Description &  Operator & Associativity & Precedence \\ 
+Description &  Operator & Associativity & Precedence \\
 \hline
 Unary postfix &  ., ?., e++, e--, e1[e2], e1() , () & None & 16 \\
 \hline
@@ -7674,7 +7687,7 @@
 Multiplicative & *, /, \~/,  \%  & Left & 14\\
 \hline
 Additive & +, - & Left & 13\\
-\hline 
+\hline
 Shift &  $<<$, $>>$&  Left & 12\\
 \hline
 Bitwise AND & \& & Left & 11\\
@@ -7710,7 +7723,7 @@
 \LMLabel{namingConventions}
 
 \commentary{
-The following naming conventions are customary in Dart programs. 
+The following naming conventions are customary in Dart programs.
 \begin{itemize}
 \item The names of compile time constant variables never use lower case letters. If they consist of multiple words, those words are separated by underscores. Examples: PI,  I\_AM\_A\_CONSTANT.
 \item The names of functions (including getters, setters, methods and local or library functions) and non-constant variables begin with a lowercase letter. If the name consists of multiple words, each  word (except the first) begins with an uppercase letter.  No other uppercase letters are used. Examples: camlCase, dart4TheWorld
diff --git a/pkg/analysis_server/lib/src/analysis_manager.dart b/pkg/analysis_server/lib/src/analysis_manager.dart
index 126dbb8..28c7488 100644
--- a/pkg/analysis_server/lib/src/analysis_manager.dart
+++ b/pkg/analysis_server/lib/src/analysis_manager.dart
@@ -117,6 +117,7 @@
     } catch (error) {
       onError(error);
     }
+    return null;
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index ae8c50f..d70517b 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -407,10 +407,12 @@
       // Use DirectoryBasedDartSdk.defaultSdkDirectory, which will make a guess.
       defaultSdkDirectory = DirectoryBasedDartSdk.defaultSdkDirectory;
     }
+    bool useSummaries = analysisServerOptions.fileReadMode == 'as-is';
     SdkCreator defaultSdkCreator = (AnalysisOptions options) {
       DirectoryBasedDartSdk sdk =
           new DirectoryBasedDartSdk(defaultSdkDirectory);
       sdk.analysisOptions = options;
+      sdk.useSummary = useSummaries;
       return sdk;
     };
     // TODO(brianwilkerson) It would be nice to avoid creating an SDK that
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 2fcb049..b05cf9c 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -70,7 +70,7 @@
 ''');
     Source barSource = bar.createSource();
     server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    return pumpEventQueue(40).then((_) {
+    return server.onAnalysisComplete.then((_) {
       expect(server.statusAnalyzing, isFalse);
       // Make sure getAnalysisContext returns the proper context for each.
       AnalysisContext fooContext =
@@ -110,7 +110,7 @@
     AnalysisContext barContext = server.getAnalysisContextForSource(barSource);
     expect(barContext, isNotNull);
     expect(fooContext, isNot(same(barContext)));
-    return pumpEventQueue(40).then((_) {
+    return server.onAnalysisComplete.then((_) {
       expect(server.statusAnalyzing, isFalse);
       // Make sure getAnalysisContext returned the proper context for each.
       expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY);
@@ -236,7 +236,7 @@
     File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;');
     Source barSource = bar.createSource();
     server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    return pumpEventQueue(500).then((_) {
+    return server.onAnalysisComplete.then((_) {
       expect(server.statusAnalyzing, isFalse);
       // Make sure getAnalysisContext returns the proper context for each.
       AnalysisContext fooContext =
diff --git a/pkg/analysis_server/test/services/completion/dart/optype_test.dart b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
index eeada57..2fe206b 100644
--- a/pkg/analysis_server/test/services/completion/dart/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
@@ -1572,5 +1572,8 @@
   @override
   Source get source => this;
 
+  @override
+  Uri get uri => new Uri.file(fullName);
+
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index b841a36..0acbc14 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -106,6 +106,14 @@
   Resource getChild(String relPath);
 
   /**
+   * Return a [File] representing a child [Resource] with the given
+   * [relPath].  This call does not check whether a file with the given name
+   * exists on the filesystem - client must call the [File]'s `exists` getter
+   * to determine whether the folder actually exists.
+   */
+  File getChildAssumingFile(String relPath);
+
+  /**
    * Return a [Folder] representing a child [Resource] with the given
    * [relPath].  This call does not check whether a folder with the given name
    * exists on the filesystem--client must call the [Folder]'s `exists` getter
@@ -147,6 +155,13 @@
   String get shortName;
 
   /**
+   * Synchronously deletes this resource and its children.
+   *
+   * Throws an exception if the resource cannot be deleted.
+   */
+  void delete();
+
+  /**
    * Return `true` if absolute [path] references this resource or a resource in
    * this folder.
    */
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 3ec640e..789095c 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -281,6 +281,11 @@
   }
 
   @override
+  void delete() {
+    throw new FileSystemException(path, 'File could not be deleted');
+  }
+
+  @override
   bool isOrContains(String path) {
     return path == this.path;
   }
@@ -342,6 +347,11 @@
   }
 
   @override
+  void delete() {
+    _provider.deleteFile(path);
+  }
+
+  @override
   bool isOrContains(String path) {
     return path == this.path;
   }
@@ -449,7 +459,12 @@
 
   @override
   bool operator ==(other) {
-    return other is _MemoryFileSource && other.id == id;
+    if (other is _MemoryFileSource) {
+      return id == other.id;
+    } else if (other is Source) {
+      return uri == other.uri;
+    }
+    return false;
   }
 
   @override
@@ -483,6 +498,11 @@
   }
 
   @override
+  void delete() {
+    _provider.deleteFolder(path);
+  }
+
+  @override
   Resource getChild(String relPath) {
     String childPath = canonicalizePath(relPath);
     _MemoryResource resource = _provider._pathToResource[childPath];
@@ -493,6 +513,16 @@
   }
 
   @override
+  _MemoryFile getChildAssumingFile(String relPath) {
+    String childPath = canonicalizePath(relPath);
+    _MemoryResource resource = _provider._pathToResource[childPath];
+    if (resource is _MemoryFile) {
+      return resource;
+    }
+    return new _MemoryFile(_provider, childPath);
+  }
+
+  @override
   _MemoryFolder getChildAssumingFolder(String relPath) {
     String childPath = canonicalizePath(relPath);
     _MemoryResource resource = _provider._pathToResource[childPath];
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index e259f75..9cd62b6 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -179,6 +179,13 @@
   }
 
   @override
+  _PhysicalFile getChildAssumingFile(String relPath) {
+    String canonicalPath = canonicalizePath(relPath);
+    io.File file = new io.File(canonicalPath);
+    return new _PhysicalFile(file);
+  }
+
+  @override
   _PhysicalFolder getChildAssumingFolder(String relPath) {
     String canonicalPath = canonicalizePath(relPath);
     io.Directory directory = new io.Directory(canonicalPath);
@@ -256,5 +263,14 @@
   }
 
   @override
+  void delete() {
+    try {
+      _entry.deleteSync(recursive: true);
+    } on io.FileSystemException catch (exception) {
+      throw new FileSystemException(exception.path, exception.message);
+    }
+  }
+
+  @override
   String toString() => path;
 }
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index ae79615..fa7fbad 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -17,6 +17,12 @@
 import 'package:analyzer/task/model.dart';
 
 /**
+ * Return `true` if the [result] of the [target] should be flushed.
+ */
+typedef bool FlushResultFilter<V>(
+    AnalysisTarget target, ResultDescriptor<V> result);
+
+/**
  * Return `true` if the given [target] is a priority one.
  */
 typedef bool IsPriorityAnalysisTarget(AnalysisTarget target);
@@ -103,6 +109,15 @@
   }
 
   /**
+   * Flush results that satisfy the given [filter].
+   */
+  void flush(FlushResultFilter filter) {
+    for (CachePartition partition in _partitions) {
+      partition.flush(filter);
+    }
+  }
+
+  /**
    * Return the entry associated with the given [target].
    */
   CacheEntry get(AnalysisTarget target) {
@@ -392,6 +407,17 @@
   }
 
   /**
+   * Flush results that satisfy the given [filter].
+   */
+  void flush(FlushResultFilter filter) {
+    _resultMap.forEach((ResultDescriptor result, ResultData data) {
+      if (filter(target, result)) {
+        data.flush();
+      }
+    });
+  }
+
+  /**
    * Return the result data associated with the [descriptor], creating one if it
    * isn't there.
    */
@@ -998,6 +1024,15 @@
   }
 
   /**
+   * Flush results that satisfy the given [filter].
+   */
+  void flush(FlushResultFilter filter) {
+    for (CacheEntry entry in entryMap.values) {
+      entry.flush(filter);
+    }
+  }
+
+  /**
    * Return the entry associated with the given [target].
    */
   CacheEntry get(AnalysisTarget target) => entryMap[target];
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 6ad3363..1cc85bc 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -271,6 +271,9 @@
         ((options is AnalysisOptionsImpl)
             ? this._options.strongModeHints != options.strongModeHints
             : false) ||
+        ((options is AnalysisOptionsImpl)
+            ? this._options.implicitCasts != options.implicitCasts
+            : false) ||
         this._options.enableStrictCallChecks !=
             options.enableStrictCallChecks ||
         this._options.enableGenericMethods != options.enableGenericMethods ||
@@ -298,8 +301,10 @@
     this._options.lint = options.lint;
     this._options.preserveComments = options.preserveComments;
     this._options.strongMode = options.strongMode;
+    this._options.trackCacheDependencies = options.trackCacheDependencies;
     if (options is AnalysisOptionsImpl) {
       this._options.strongModeHints = options.strongModeHints;
+      this._options.implicitCasts = options.implicitCasts;
     }
     if (needsRecompute) {
       for (WorkManager workManager in workManagers) {
@@ -487,6 +492,7 @@
     if (coreElement == null) {
       throw new AnalysisException("Could not create an element for dart:core");
     }
+
     LibraryElement asyncElement;
     if (analysisOptions.enableAsync) {
       Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
@@ -499,8 +505,10 @@
             "Could not create an element for dart:async");
       }
     } else {
-      asyncElement = createMockAsyncLib(coreElement);
+      Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+      asyncElement = createMockAsyncLib(coreElement, asyncSource);
     }
+
     _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     return _typeProvider;
   }
@@ -678,6 +686,7 @@
     CacheState state = entry.getState(descriptor);
     if (state == CacheState.FLUSHED || state == CacheState.INVALID) {
       driver.computeResult(target, descriptor);
+      entry = getCacheEntry(target);
     }
     state = entry.getState(descriptor);
     if (state == CacheState.ERROR) {
@@ -725,7 +734,8 @@
    * to stand in for a real one if one does not exist
    * facilitating creation a type provider without dart:async.
    */
-  LibraryElement createMockAsyncLib(LibraryElement coreLibrary) {
+  LibraryElement createMockAsyncLib(
+      LibraryElement coreLibrary, Source asyncSource) {
     InterfaceType objType = coreLibrary.getType('Object').type;
 
     ClassElement _classElement(String typeName, [List<String> parameterNames]) {
@@ -760,6 +770,8 @@
     asyncUnit.types = <ClassElement>[futureType.element, streamType.element];
     LibraryElementImpl mockLib = new LibraryElementImpl.forNode(
         this, AstFactory.libraryIdentifier2(["dart.async"]));
+    asyncUnit.librarySource = asyncSource;
+    asyncUnit.source = asyncSource;
     mockLib.definingCompilationUnit = asyncUnit;
     mockLib.publicNamespace =
         new NamespaceBuilder().createPublicNamespaceForLibrary(mockLib);
@@ -1051,13 +1063,13 @@
     bool changed = newContents != originalContents;
     if (newContents != null) {
       if (changed) {
+        entry.modificationTime = _contentCache.getModificationStamp(source);
         if (!analysisOptions.incremental ||
             !_tryPoorMansIncrementalResolution(source, newContents)) {
           // Don't compare with old contents because the cache has already been
           // updated, and we know at this point that it changed.
           _sourceChanged(source, compareWithOld: false);
         }
-        entry.modificationTime = _contentCache.getModificationStamp(source);
         entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST);
       } else {
         entry.modificationTime = _contentCache.getModificationStamp(source);
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 5c5a74d..da2db55 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1123,56 +1123,52 @@
       }
     }
     // evaluate operator
-    while (true) {
-      if (operatorType == TokenType.AMPERSAND) {
-        return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
-        return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.BANG_EQ) {
-        return _dartObjectComputer.notEqual(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.BAR) {
-        return _dartObjectComputer.bitOr(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.BAR_BAR) {
-        return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.CARET) {
-        return _dartObjectComputer.bitXor(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.EQ_EQ) {
-        return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.GT) {
-        return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.GT_EQ) {
-        return _dartObjectComputer.greaterThanOrEqual(
-            node, leftResult, rightResult);
-      } else if (operatorType == TokenType.GT_GT) {
-        return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.LT) {
-        return _dartObjectComputer.lessThan(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.LT_EQ) {
-        return _dartObjectComputer.lessThanOrEqual(
-            node, leftResult, rightResult);
-      } else if (operatorType == TokenType.LT_LT) {
-        return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.MINUS) {
-        return _dartObjectComputer.minus(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.PERCENT) {
-        return _dartObjectComputer.remainder(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.PLUS) {
-        return _dartObjectComputer.add(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.STAR) {
-        return _dartObjectComputer.times(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.SLASH) {
-        return _dartObjectComputer.divide(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.TILDE_SLASH) {
-        return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
-      } else if (operatorType == TokenType.QUESTION_QUESTION) {
-        return _dartObjectComputer.questionQuestion(
-            node, leftResult, rightResult);
-      } else {
-        // TODO(brianwilkerson) Figure out which error to report.
-        _error(node, null);
-        return null;
-      }
-      break;
+    if (operatorType == TokenType.AMPERSAND) {
+      return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
+      return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.BANG_EQ) {
+      return _dartObjectComputer.notEqual(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.BAR) {
+      return _dartObjectComputer.bitOr(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.BAR_BAR) {
+      return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.CARET) {
+      return _dartObjectComputer.bitXor(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.EQ_EQ) {
+      return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.GT) {
+      return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.GT_EQ) {
+      return _dartObjectComputer.greaterThanOrEqual(
+          node, leftResult, rightResult);
+    } else if (operatorType == TokenType.GT_GT) {
+      return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.LT) {
+      return _dartObjectComputer.lessThan(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.LT_EQ) {
+      return _dartObjectComputer.lessThanOrEqual(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.LT_LT) {
+      return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.MINUS) {
+      return _dartObjectComputer.minus(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.PERCENT) {
+      return _dartObjectComputer.remainder(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.PLUS) {
+      return _dartObjectComputer.add(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.STAR) {
+      return _dartObjectComputer.times(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.SLASH) {
+      return _dartObjectComputer.divide(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.TILDE_SLASH) {
+      return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
+    } else if (operatorType == TokenType.QUESTION_QUESTION) {
+      return _dartObjectComputer.questionQuestion(
+          node, leftResult, rightResult);
+    } else {
+      // TODO(brianwilkerson) Figure out which error to report.
+      _error(node, null);
+      return null;
     }
   }
 
@@ -1399,19 +1395,16 @@
       _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
       return null;
     }
-    while (true) {
-      if (node.operator.type == TokenType.BANG) {
-        return _dartObjectComputer.logicalNot(node, operand);
-      } else if (node.operator.type == TokenType.TILDE) {
-        return _dartObjectComputer.bitNot(node, operand);
-      } else if (node.operator.type == TokenType.MINUS) {
-        return _dartObjectComputer.negated(node, operand);
-      } else {
-        // TODO(brianwilkerson) Figure out which error to report.
-        _error(node, null);
-        return null;
-      }
-      break;
+    if (node.operator.type == TokenType.BANG) {
+      return _dartObjectComputer.logicalNot(node, operand);
+    } else if (node.operator.type == TokenType.TILDE) {
+      return _dartObjectComputer.bitNot(node, operand);
+    } else if (node.operator.type == TokenType.MINUS) {
+      return _dartObjectComputer.negated(node, operand);
+    } else {
+      // TODO(brianwilkerson) Figure out which error to report.
+      _error(node, null);
+      return null;
     }
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 0eb96cf..790fab6 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2264,6 +2264,7 @@
         initializer.constructorName?.staticElement = element;
         return initializer;
     }
+    return null;
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 633fcb0..266853a 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -429,6 +429,9 @@
       actualElement.isAccessibleIn(library);
 
   @override
+  String toString() => actualElement.toString();
+
+  @override
   void visitChildren(ElementVisitor visitor) {
     actualElement.visitChildren(visitor);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index e90ba86..04da23d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -994,7 +994,7 @@
 
   @override
   Element get(String name) {
-    if (name.startsWith(_prefix)) {
+    if (name.length > _length && name.startsWith(_prefix)) {
       if (name.codeUnitAt(_length) == '.'.codeUnitAt(0)) {
         return _definedNames[name.substring(_length + 1)];
       }
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 2a49090..dcb40d6 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -1768,36 +1768,33 @@
    * [operator].
    */
   TokenType _operatorFromCompoundAssignment(TokenType operator) {
-    while (true) {
-      if (operator == TokenType.AMPERSAND_EQ) {
-        return TokenType.AMPERSAND;
-      } else if (operator == TokenType.BAR_EQ) {
-        return TokenType.BAR;
-      } else if (operator == TokenType.CARET_EQ) {
-        return TokenType.CARET;
-      } else if (operator == TokenType.GT_GT_EQ) {
-        return TokenType.GT_GT;
-      } else if (operator == TokenType.LT_LT_EQ) {
-        return TokenType.LT_LT;
-      } else if (operator == TokenType.MINUS_EQ) {
-        return TokenType.MINUS;
-      } else if (operator == TokenType.PERCENT_EQ) {
-        return TokenType.PERCENT;
-      } else if (operator == TokenType.PLUS_EQ) {
-        return TokenType.PLUS;
-      } else if (operator == TokenType.SLASH_EQ) {
-        return TokenType.SLASH;
-      } else if (operator == TokenType.STAR_EQ) {
-        return TokenType.STAR;
-      } else if (operator == TokenType.TILDE_SLASH_EQ) {
-        return TokenType.TILDE_SLASH;
-      } else {
-        // Internal error: Unmapped assignment operator.
-        AnalysisEngine.instance.logger.logError(
-            "Failed to map ${operator.lexeme} to it's corresponding operator");
-        return operator;
-      }
-      break;
+    if (operator == TokenType.AMPERSAND_EQ) {
+      return TokenType.AMPERSAND;
+    } else if (operator == TokenType.BAR_EQ) {
+      return TokenType.BAR;
+    } else if (operator == TokenType.CARET_EQ) {
+      return TokenType.CARET;
+    } else if (operator == TokenType.GT_GT_EQ) {
+      return TokenType.GT_GT;
+    } else if (operator == TokenType.LT_LT_EQ) {
+      return TokenType.LT_LT;
+    } else if (operator == TokenType.MINUS_EQ) {
+      return TokenType.MINUS;
+    } else if (operator == TokenType.PERCENT_EQ) {
+      return TokenType.PERCENT;
+    } else if (operator == TokenType.PLUS_EQ) {
+      return TokenType.PLUS;
+    } else if (operator == TokenType.SLASH_EQ) {
+      return TokenType.SLASH;
+    } else if (operator == TokenType.STAR_EQ) {
+      return TokenType.STAR;
+    } else if (operator == TokenType.TILDE_SLASH_EQ) {
+      return TokenType.TILDE_SLASH;
+    } else {
+      // Internal error: Unmapped assignment operator.
+      AnalysisEngine.instance.logger.logError(
+          "Failed to map ${operator.lexeme} to it's corresponding operator");
+      return operator;
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 6d41c4fb..61816ab 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1144,6 +1144,14 @@
   bool get strongMode;
 
   /**
+   * Return `true` if dependencies between computed results should be tracked
+   * by analysis cache.  This option should only be set to `false` if analysis
+   * is performed in such a way that none of the inputs is ever changed
+   * during the life time of the context.
+   */
+  bool get trackCacheDependencies;
+
+  /**
    * Return an integer encoding of the values of the options that need to be the
    * same across all of the contexts associated with partitions that are to be
    * shared by a single analysis context.
@@ -1283,6 +1291,17 @@
   // TODO(leafp): replace this with something more general
   bool strongModeHints = false;
 
+  @override
+  bool trackCacheDependencies = true;
+
+  /**
+   * A flag indicating whether implicit casts are allowed in [strongMode]
+   * (they are always allowed in Dart 1.0 mode).
+   *
+   * This option is experimental and subject to change.
+   */
+  bool implicitCasts = true;
+
   /**
    * Initialize a newly created set of analysis options to have their default
    * values.
@@ -1314,7 +1333,9 @@
     strongMode = options.strongMode;
     if (options is AnalysisOptionsImpl) {
       strongModeHints = options.strongModeHints;
+      implicitCasts = options.implicitCasts;
     }
+    trackCacheDependencies = options.trackCacheDependencies;
   }
 
   bool get analyzeFunctionBodies {
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 633243a..074a6aa 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -2851,6 +2851,24 @@
     StaticWarningCode.UNDEFINED_SUPER_SETTER,
     StaticWarningCode.VOID_RETURN_FOR_GETTER,
     StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
+    StrongModeCode.ASSIGNMENT_CAST,
+    StrongModeCode.DOWN_CAST_COMPOSITE,
+    StrongModeCode.DOWN_CAST_IMPLICIT,
+    StrongModeCode.DYNAMIC_CAST,
+    StrongModeCode.DYNAMIC_INVOKE,
+    StrongModeCode.INFERRED_TYPE,
+    StrongModeCode.INFERRED_TYPE_ALLOCATION,
+    StrongModeCode.INFERRED_TYPE_CLOSURE,
+    StrongModeCode.INFERRED_TYPE_LITERAL,
+    StrongModeCode.INVALID_FIELD_OVERRIDE,
+    StrongModeCode.INVALID_METHOD_OVERRIDE,
+    StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE,
+    StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN,
+    StrongModeCode.INVALID_PARAMETER_DECLARATION,
+    StrongModeCode.INVALID_SUPER_INVOCATION,
+    StrongModeCode.NON_GROUND_TYPE_CHECK_INFO,
+    StrongModeCode.STATIC_TYPE_ERROR,
+
     TodoCode.TODO,
 
     //
@@ -5807,6 +5825,117 @@
 }
 
 /**
+ * This class has Strong Mode specific error codes.
+ *
+ * These error codes tend to use the same message across different severity
+ * levels, so they are grouped for clarity.
+ *
+ * All of these error codes also use the "STRONG_MODE_" prefix in their name.
+ */
+class StrongModeCode extends ErrorCode {
+  static const String _implicitCastMessage =
+      'Unsound implicit cast from {0} to {1}';
+
+  static const String _typeCheckMessage =
+      'Type check failed: {0} is not of type {1}';
+
+  static const String _invalidOverrideMessage =
+      'The type of {0}.{1} ({2}) is not a '
+      'subtype of {3}.{1} ({4}).';
+
+  static const String _inferredTypeMessage = '{0} has inferred type {1}';
+
+  static const StrongModeCode DOWN_CAST_COMPOSITE = const StrongModeCode(
+      ErrorType.STATIC_WARNING, 'DOWN_CAST_COMPOSITE', _implicitCastMessage);
+
+  static const StrongModeCode DOWN_CAST_IMPLICIT = const StrongModeCode(
+      ErrorType.HINT, 'DOWN_CAST_IMPLICIT', _implicitCastMessage);
+
+  static const StrongModeCode DYNAMIC_CAST = const StrongModeCode(
+      ErrorType.HINT, 'DYNAMIC_CAST', _implicitCastMessage);
+
+  static const StrongModeCode ASSIGNMENT_CAST = const StrongModeCode(
+      ErrorType.HINT, 'ASSIGNMENT_CAST', _implicitCastMessage);
+
+  static const StrongModeCode INVALID_PARAMETER_DECLARATION =
+      const StrongModeCode(ErrorType.COMPILE_TIME_ERROR,
+          'INVALID_PARAMETER_DECLARATION', _typeCheckMessage);
+
+  static const StrongModeCode INFERRED_TYPE = const StrongModeCode(
+      ErrorType.HINT, 'INFERRED_TYPE', _inferredTypeMessage);
+
+  static const StrongModeCode INFERRED_TYPE_LITERAL = const StrongModeCode(
+      ErrorType.HINT, 'INFERRED_TYPE_LITERAL', _inferredTypeMessage);
+
+  static const StrongModeCode INFERRED_TYPE_ALLOCATION = const StrongModeCode(
+      ErrorType.HINT, 'INFERRED_TYPE_ALLOCATION', _inferredTypeMessage);
+
+  static const StrongModeCode INFERRED_TYPE_CLOSURE = const StrongModeCode(
+      ErrorType.HINT, 'INFERRED_TYPE_CLOSURE', _inferredTypeMessage);
+
+  static const StrongModeCode STATIC_TYPE_ERROR = const StrongModeCode(
+      ErrorType.COMPILE_TIME_ERROR,
+      'STATIC_TYPE_ERROR',
+      'Type check failed: {0} ({1}) is not of type {2}');
+
+  static const StrongModeCode INVALID_SUPER_INVOCATION = const StrongModeCode(
+      ErrorType.COMPILE_TIME_ERROR,
+      'INVALID_SUPER_INVOCATION',
+      "super call must be last in an initializer "
+      "list (see https://goo.gl/EY6hDP): {0}");
+
+  static const StrongModeCode NON_GROUND_TYPE_CHECK_INFO = const StrongModeCode(
+      ErrorType.HINT,
+      'NON_GROUND_TYPE_CHECK_INFO',
+      "Runtime check on non-ground type {0} may throw StrongModeError");
+
+  static const StrongModeCode DYNAMIC_INVOKE = const StrongModeCode(
+      ErrorType.HINT, 'DYNAMIC_INVOKE', '{0} requires a dynamic invoke');
+
+  static const StrongModeCode INVALID_METHOD_OVERRIDE = const StrongModeCode(
+      ErrorType.COMPILE_TIME_ERROR,
+      'INVALID_METHOD_OVERRIDE',
+      'Invalid override. $_invalidOverrideMessage');
+
+  static const StrongModeCode INVALID_METHOD_OVERRIDE_FROM_BASE =
+      const StrongModeCode(
+          ErrorType.COMPILE_TIME_ERROR,
+          'INVALID_METHOD_OVERRIDE_FROM_BASE',
+          'Base class introduces an invalid override. '
+          '$_invalidOverrideMessage');
+
+  static const StrongModeCode INVALID_METHOD_OVERRIDE_FROM_MIXIN =
+      const StrongModeCode(
+          ErrorType.COMPILE_TIME_ERROR,
+          'INVALID_METHOD_OVERRIDE_FROM_MIXIN',
+          'Mixin introduces an invalid override. $_invalidOverrideMessage');
+
+  static const StrongModeCode INVALID_FIELD_OVERRIDE = const StrongModeCode(
+      ErrorType.COMPILE_TIME_ERROR,
+      'INVALID_FIELD_OVERRIDE',
+      'Field declaration {3}.{1} cannot be '
+      'overridden in {0}.');
+
+  @override
+  final ErrorType type;
+
+  /**
+   * Initialize a newly created error code to have the given [type] and [name].
+   *
+   * The message associated with the error will be created from the given
+   * [message] template. The correction associated with the error will be
+   * created from the optional [correction] template.
+   */
+  const StrongModeCode(ErrorType type, String name, String message,
+      [String correction])
+      : type = type,
+        super('STRONG_MODE_$name', message, correction);
+
+  @override
+  ErrorSeverity get errorSeverity => type.severity;
+}
+
+/**
  * The error code indicating a marker in code for work that needs to be finished
  * or revisited.
  */
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4bf1d0e..eca427d 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -30,7 +30,8 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/strong/info.dart' show StaticInfo;
+import 'package:analyzer/src/task/strong/checker.dart' as checker
+    show isKnownFunction;
 
 /**
  * A visitor used to traverse an AST structure looking for additional errors and
@@ -5743,8 +5744,7 @@
 
   bool _expressionIsAssignableAtType(Expression expression,
       DartType actualStaticType, DartType expectedStaticType) {
-    bool concrete =
-        _options.strongMode && StaticInfo.isKnownFunction(expression);
+    bool concrete = _options.strongMode && checker.isKnownFunction(expression);
     if (concrete) {
       actualStaticType =
           _typeSystem.typeToConcreteType(_typeProvider, actualStaticType);
@@ -6222,6 +6222,13 @@
   RequiredConstantsComputer(this.source);
 
   @override
+  Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    _checkForMissingRequiredParam(
+        node.staticInvokeType, node.argumentList, node);
+    return super.visitFunctionExpressionInvocation(node);
+  }
+
+  @override
   Object visitInstanceCreationExpression(InstanceCreationExpression node) {
     DartType type = node.constructorName.type.type;
     if (type is InterfaceType) {
@@ -6238,6 +6245,25 @@
     return super.visitMethodInvocation(node);
   }
 
+  @override
+  Object visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    DartType type = node.staticElement?.type;
+    if (type != null) {
+      _checkForMissingRequiredParam(type, node.argumentList, node);
+    }
+    return super.visitRedirectingConstructorInvocation(node);
+  }
+
+  @override
+  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    DartType type = node.staticElement?.type;
+    if (type != null) {
+      _checkForMissingRequiredParam(type, node.argumentList, node);
+    }
+    return super.visitSuperConstructorInvocation(node);
+  }
+
   void _checkForMissingRequiredParam(
       DartType type, ArgumentList argumentList, AstNode node) {
     if (type is FunctionType) {
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index b23d188..37d3801 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -1806,10 +1806,7 @@
   }
 
   static _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) {
-    while (true) {
-      if (oldToken.type == TokenType.EOF && newToken.type == TokenType.EOF) {
-        return null;
-      }
+    while (oldToken.type != TokenType.EOF || newToken.type != TokenType.EOF) {
       if (oldToken.type == TokenType.EOF || newToken.type == TokenType.EOF) {
         return new _TokenPair(_TokenDifferenceKind.CONTENT, oldToken, newToken);
       }
@@ -2109,8 +2106,7 @@
         (element as ElementImpl).nameOffset = nameOffset + updateDelta;
       }
       if (element is ConstVariableElement) {
-        ConstVariableElement constVariable = element as ConstVariableElement;
-        Expression initializer = constVariable.constantInitializer;
+        Expression initializer = element.constantInitializer;
         if (initializer != null) {
           _shiftTokens(initializer.beginToken);
         }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d74e925..889e156 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -30,8 +30,6 @@
 import 'package:analyzer/src/generated/static_type_analyzer.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/task/strong/info.dart'
-    show InferredType, StaticInfo;
 
 export 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 export 'package:analyzer/src/dart/resolver/scope.dart';
@@ -1915,13 +1913,13 @@
 
   @override
   Object visitSwitchCase(SwitchCase node) {
-    _checkForDeadStatementsInNodeList(node.statements);
+    _checkForDeadStatementsInNodeList(node.statements, allowMandated: true);
     return super.visitSwitchCase(node);
   }
 
   @override
   Object visitSwitchDefault(SwitchDefault node) {
-    _checkForDeadStatementsInNodeList(node.statements);
+    _checkForDeadStatementsInNodeList(node.statements, allowMandated: true);
     return super.visitSwitchDefault(node);
   }
 
@@ -2047,8 +2045,12 @@
    * [SwitchMember], this loops through the list searching for dead statements.
    *
    * @param statements some ordered list of statements in a [Block] or [SwitchMember]
+   * @param allowMandated allow dead statements mandated by the language spec.
+   *            This allows for a final break, continue, return, or throw statement
+   *            at the end of a switch case, that are mandated by the language spec.
    */
-  void _checkForDeadStatementsInNodeList(NodeList<Statement> statements) {
+  void _checkForDeadStatementsInNodeList(
+      NodeList<Statement> statements, {bool allowMandated: false}) {
     bool statementExits(Statement statement) {
       if (statement is BreakStatement) {
         return statement.label == null;
@@ -2065,6 +2067,13 @@
       if (statementExits(currentStatement) && i != size - 1) {
         Statement nextStatement = statements[i + 1];
         Statement lastStatement = statements[size - 1];
+        // If mandated statements are allowed, and only the last statement is
+        // dead, and it's a BreakStatement, then assume it is a statement
+        // mandated by the language spec, there to avoid a
+        // CASE_BLOCK_NOT_TERMINATED error.
+        if (allowMandated && i == size - 2 && nextStatement is BreakStatement) {
+          return;
+        }
         int offset = nextStatement.offset;
         int length = lastStatement.end - offset;
         _errorReporter.reportErrorForOffset(HintCode.DEAD_CODE, offset, length);
@@ -3757,24 +3766,29 @@
     _enclosingBlockContainsBreak = false;
     try {
       bool hasDefault = false;
+      bool hasNonExitingCase = false;
       List<SwitchMember> members = node.members;
       for (int i = 0; i < members.length; i++) {
         SwitchMember switchMember = members[i];
         if (switchMember is SwitchDefault) {
           hasDefault = true;
-          // If this is the last member and there are no statements, return
-          // false
+          // If this is the last member and there are no statements, then it
+          // does not exit.
           if (switchMember.statements.isEmpty && i + 1 == members.length) {
-            return false;
+            hasNonExitingCase = true;
+            continue;
           }
         }
-        // For switch members with no statements, don't visit the children,
-        // otherwise, return false if no return is found in the children
-        // statements.
+        // For switch members with no statements, don't visit the children.
+        // Otherwise, if there children statements don't exit, mark this as a
+        // non-exiting case.
         if (!switchMember.statements.isEmpty && !switchMember.accept(this)) {
-          return false;
+          hasNonExitingCase = true;
         }
       }
+      if (hasNonExitingCase) {
+        return false;
+      }
       // As all cases exit, return whether that list includes `default`.
       return hasDefault;
     } finally {
@@ -3790,14 +3804,18 @@
 
   @override
   bool visitTryStatement(TryStatement node) {
-    if (_nodeExits(node.body)) {
+    if (_nodeExits(node.finallyBlock)) {
       return true;
     }
-    Block finallyBlock = node.finallyBlock;
-    if (_nodeExits(finallyBlock)) {
-      return true;
+    if (!_nodeExits(node.body)) {
+      return false;
     }
-    return false;
+    for (CatchClause c in node.catchClauses) {
+      if (!_nodeExits(c.body)) {
+        return false;
+      }
+    }
+    return true;
   }
 
   @override
@@ -4642,7 +4660,7 @@
   /**
    * The error listener on which to record inference information.
    */
-  final AnalysisErrorListener _errorListener;
+  final ErrorReporter _errorReporter;
 
   /**
    * If true, emit hints when types are inferred
@@ -4675,7 +4693,7 @@
   // https://github.com/dart-lang/sdk/issues/25322
   final List<DartType> _returnStack = <DartType>[];
 
-  InferenceContext._(this._errorListener, TypeProvider typeProvider,
+  InferenceContext._(this._errorReporter, TypeProvider typeProvider,
       this._typeSystem, this._inferenceHints)
       : _typeProvider = typeProvider;
 
@@ -4754,12 +4772,22 @@
    * [type] has been inferred as the type of [node].
    */
   void recordInference(Expression node, DartType type) {
-    StaticInfo info = InferredType.create(_typeSystem, node, type);
-    if (!_inferenceHints || info == null) {
+    if (!_inferenceHints) {
       return;
     }
-    AnalysisError error = info.toAnalysisError();
-    _errorListener.onError(error);
+
+    ErrorCode error;
+    if (node is Literal) {
+      error = StrongModeCode.INFERRED_TYPE_LITERAL;
+    } else if (node is InstanceCreationExpression) {
+      error = StrongModeCode.INFERRED_TYPE_ALLOCATION;
+    } else if (node is FunctionExpression) {
+      error = StrongModeCode.INFERRED_TYPE_CLOSURE;
+    } else {
+      error = StrongModeCode.INFERRED_TYPE;
+    }
+
+    _errorReporter.reportErrorForNode(error, node, [node, type]);
   }
 
   List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) {
@@ -5573,7 +5601,7 @@
       strongModeHints = options.strongModeHints;
     }
     this.inferenceContext = new InferenceContext._(
-        errorListener, typeProvider, typeSystem, strongModeHints);
+        errorReporter, typeProvider, typeSystem, strongModeHints);
     this.typeAnalyzer = new StaticTypeAnalyzer(this);
   }
 
@@ -9992,18 +10020,15 @@
         TypeName typeName = node.type;
         if (typeName == null) {
           element.hasImplicitType = true;
-          type = _dynamicType;
           if (element is FieldFormalParameterElement) {
             FieldElement fieldElement =
                 (element as FieldFormalParameterElement).field;
-            if (fieldElement != null) {
-              type = fieldElement.type;
-            }
+            type = fieldElement?.type;
           }
         } else {
           type = _typeNameResolver._getType(typeName);
         }
-        element.type = type;
+        element.type = type ?? _dynamicType;
       } else {
         _setFunctionTypedParameterType(element, node.type, node.parameters);
       }
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index cd813a0..8705867 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -129,12 +129,7 @@
    */
   DartSdk getSdkForOptions(AnalysisOptions options) {
     int encoding = options.encodeCrossContextOptions();
-    DartSdk sdk = sdkMap[encoding];
-    if (sdk == null) {
-      sdk = sdkCreator(options);
-      sdkMap[encoding] = sdk;
-    }
-    return sdk;
+    return sdkMap.putIfAbsent(encoding, () => sdkCreator(options));
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 491e3eb..b7cb0fd 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -239,8 +239,14 @@
   }
 
   @override
-  bool operator ==(Object object) =>
-      object is FileBasedSource && id == object.id;
+  bool operator ==(Object object) {
+    if (object is FileBasedSource) {
+      return id == object.id;
+    } else if (object is Source) {
+      return uri == object.uri;
+    }
+    return false;
+  }
 
   @override
   bool exists() => file.isFile();
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index fefd3eb..5c57bb8 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -662,8 +662,12 @@
       // elements
       if (node.elements.isNotEmpty) {
         // Infer the list type from the arguments.
-        DartType staticType =
-            node.elements.map((e) => e.staticType).reduce(_leastUpperBound);
+        Iterable<DartType> types =
+            node.elements.map((e) => e.staticType).where((t) => t != null);
+        if (types.isEmpty) {
+          return null;
+        }
+        DartType staticType = types.reduce(_leastUpperBound);
         if (staticType.isBottom) {
           staticType = _dynamicType;
         }
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 7e4103d..74e3fd2 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -12,7 +12,8 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/engine.dart'
+    show AnalysisContext, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
@@ -23,6 +24,15 @@
  * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
  */
 class StrongTypeSystemImpl extends TypeSystem {
+  /**
+   * True if implicit casts should be allowed, otherwise false.
+   *
+   * This affects the behavior of [isAssignableTo].
+   */
+  final bool implicitCasts;
+
+  StrongTypeSystemImpl({this.implicitCasts: true});
+
   bool anyParameterType(FunctionType ft, bool predicate(DartType t)) {
     return ft.parameters.any((p) => predicate(p.type));
   }
@@ -290,6 +300,10 @@
       return true;
     }
 
+    if (!implicitCasts) {
+      return false;
+    }
+
     // Don't allow implicit downcasts between function types
     // and call method objects, as these will almost always fail.
     if ((fromType is FunctionType && getCallMethodType(toType) != null) ||
@@ -309,16 +323,13 @@
       return false;
     }
 
-    // If the subtype relation goes the other way, allow the implicit downcast.
-    // TODO(leafp): Emit warnings and hints for these in some way.
-    // TODO(leafp): Consider adding a flag to disable these?  Or just rely on
-    //   --warnings-as-errors?
+    // If the subtype relation goes the other way, allow the implicit
+    // downcast.
     if (isSubtypeOf(toType, fromType) || toType.isAssignableTo(fromType)) {
-      // TODO(leafp): error if type is known to be exact (literal,
-      //  instance creation).
-      // TODO(leafp): Warn on composite downcast.
-      // TODO(leafp): hint on object/dynamic downcast.
-      // TODO(leafp): Consider allowing assignment casts.
+      // TODO(leafp,jmesserly): we emit warnings/hints for these in
+      // src/task/strong/checker.dart, which is a bit inconsistent. That
+      // code should be handled into places that use isAssignableTo, such as
+      // ErrorVerifier.
       return true;
     }
 
@@ -1180,8 +1191,9 @@
    * Create either a strong mode or regular type system based on context.
    */
   static TypeSystem create(AnalysisContext context) {
-    return (context.analysisOptions.strongMode)
-        ? new StrongTypeSystemImpl()
+    var options = context.analysisOptions as AnalysisOptionsImpl;
+    return options.strongMode
+        ? new StrongTypeSystemImpl(implicitCasts: options.implicitCasts)
         : new TypeSystemImpl();
   }
 }
diff --git a/pkg/analyzer/lib/src/summary/incremental_cache.dart b/pkg/analyzer/lib/src/summary/incremental_cache.dart
index cadeffb..6370234 100644
--- a/pkg/analyzer/lib/src/summary/incremental_cache.dart
+++ b/pkg/analyzer/lib/src/summary/incremental_cache.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:collection';
 import 'dart:convert';
 import 'dart:core' hide Resource;
 
@@ -17,10 +18,52 @@
 import 'package:crypto/crypto.dart';
 
 /**
+ * The version of the incremental cache.  It should be incremented every time
+ * when any cache data structure is changed.
+ */
+const int _VERSION = 1;
+
+/**
+ * Compare the given file paths [a] and [b].  Because paths usually have long
+ * equal prefix, comparison is done not as comparision of two generic [String]s.
+ * Instead it starts from the ends of each strings.
+ *
+ * Return `-1` if [a] is ordered before [b], `1` if `this` is ordered after [b],
+ * and zero if [a] and [b] are ordered together.
+ */
+int comparePaths(String a, String b) {
+  int thisLength = a.length;
+  int otherLength = b.length;
+  int len = (thisLength < otherLength) ? thisLength : otherLength;
+  for (int i = 0; i < len; i++) {
+    int thisCodeUnit = a.codeUnitAt(thisLength - 1 - i);
+    int otherCodeUnit = b.codeUnitAt(otherLength - 1 - i);
+    if (thisCodeUnit < otherCodeUnit) {
+      return -1;
+    }
+    if (thisCodeUnit > otherCodeUnit) {
+      return 1;
+    }
+  }
+  if (thisLength < otherLength) {
+    return -1;
+  }
+  if (thisLength > otherLength) {
+    return 1;
+  }
+  return 0;
+}
+
+/**
  * Storage for cache data.
  */
 abstract class CacheStorage {
   /**
+   * Compact the storage, e.g. remove unused entries.
+   */
+  void compact();
+
+  /**
    * Return bytes for the given [key], `null` if [key] is not in the storage.
    */
   List<int> get(String key);
@@ -43,6 +86,11 @@
  */
 class FolderCacheStorage implements CacheStorage {
   /**
+   * The maximum number of entries to keep in the cache.
+   */
+  static const MAX_ENTRIES = 20000;
+
+  /**
    * The folder to read and write files.
    */
   final Folder folder;
@@ -54,14 +102,46 @@
    */
   final String tempFileName;
 
-  FolderCacheStorage(this.folder, this.tempFileName);
+  /**
+   * The set of recently used entries, with the most recently used entries
+   * on the bottom.
+   */
+  final LinkedHashSet<String> _recentEntries = new LinkedHashSet<String>();
+
+  FolderCacheStorage(this.folder, this.tempFileName) {
+    try {
+      File file = folder.getChildAssumingFile('.entries');
+      if (file.exists) {
+        String entriesString = file.readAsStringSync();
+        List<String> entriesLists = entriesString.split('\n');
+        _recentEntries.addAll(entriesLists);
+      }
+    } catch (_) {}
+  }
+
+  @override
+  void compact() {
+    while (_recentEntries.length > MAX_ENTRIES) {
+      String key = _recentEntries.first;
+      _recentEntries.remove(key);
+      try {
+        folder.getChildAssumingFile(key).delete();
+      } catch (_) {}
+    }
+    try {
+      List<int> bytes = UTF8.encode(_recentEntries.join('\n'));
+      folder.getChildAssumingFile('.entries').writeAsBytesSync(bytes);
+    } catch (_) {}
+  }
 
   @override
   List<int> get(String key) {
     Resource file = folder.getChild(key);
     if (file is File) {
       try {
-        return file.readAsBytesSync();
+        List<int> bytes = file.readAsBytesSync();
+        _accessedKey(key);
+        return bytes;
       } on FileSystemException {}
     }
     return null;
@@ -74,8 +154,17 @@
     tempFile.writeAsBytesSync(bytes);
     try {
       tempFile.renameSync(absPath);
+      _accessedKey(key);
     } catch (e) {}
   }
+
+  /**
+   * The given [key] was accessed, update recently used entries.
+   */
+  void _accessedKey(String key) {
+    _recentEntries.remove(key);
+    _recentEntries.add(key);
+  }
 }
 
 /**
@@ -269,7 +358,17 @@
         if (refSource == null) {
           throw new StateError('Unable to resolve $refUri in $librarySource');
         }
-        _appendLibraryClosure(closure, refSource);
+        // If we have already the closure for the 'refSource', use it.
+        // Otherwise, continue computing recursively.
+        // It's not the most efficient algorithm, but in practice we might
+        // visit each library multiple times only for the first top-level
+        // bundle requested in `getLibraryClosureBundles`.
+        List<Source> refClosure = _libraryClosureMap[refSource];
+        if (refClosure != null) {
+          closure.addAll(refClosure);
+        } else {
+          _appendLibraryClosure(closure, refSource);
+        }
       }
       contentSource.importedUris.forEach(appendLibrarySources);
       contentSource.exportedUris.forEach(appendLibrarySources);
@@ -285,6 +384,7 @@
     ByteConversionSink byteSink = md5.startChunkedConversion(digestSink);
     // Add data.
     addData(byteSink);
+    byteSink.add(const <int>[_VERSION]);
     byteSink.add(configSalt);
     // Done.
     byteSink.close();
@@ -368,6 +468,10 @@
         return null;
       }
       bundle = new PackageBundle.fromBuffer(bytes);
+      if (bundle.majorVersion != PackageBundleAssembler.currentMajorVersion ||
+          bundle.minorVersion != PackageBundleAssembler.currentMinorVersion) {
+        return null;
+      }
       _bundleMap[key] = bundle;
     }
     return bundle;
@@ -389,9 +493,11 @@
    */
   List<Source> _getLibraryClosure(Source librarySource) {
     return _libraryClosureMap.putIfAbsent(librarySource, () {
-      Set<Source> closure = new Set<Source>();
-      _appendLibraryClosure(closure, librarySource);
-      return closure.toList();
+      Set<Source> closureSet = new Set<Source>();
+      _appendLibraryClosure(closureSet, librarySource);
+      List<Source> closureList = closureSet.toList();
+      closureList.sort((a, b) => comparePaths(a.fullName, b.fullName));
+      return closureList;
     });
   }
 
@@ -407,6 +513,15 @@
           List<int> sourceHash = _getSourceContentHash(source);
           byteSink.add(sourceHash);
         }
+        // When we sort closure sources for two libraries (A, B) we get exactly
+        // the same list of sources for both A and B. So, their hash is exactly
+        // the same. But we use it to store separate summary bundles for
+        // separate libraries. Ideally would be nice to group these libraries
+        // into a single summary bundle. But this would require delaying
+        // saving bundles until we know all of them.
+        // So, for now we make hashes for separate libraries unique be mixing
+        // in the library source again.
+        byteSink.add(_getSourceContentHash(librarySource));
       });
     });
   }
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 81ae854..57dccf1 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2700,6 +2700,7 @@
       case UnlinkedExprAssignOperator.postfixDecrement:
         return TokenType.MINUS_MINUS;
     }
+    return null;
   }
 }
 
@@ -3917,6 +3918,7 @@
       case UnlinkedParamKind.named:
         return ParameterKind.NAMED;
     }
+    return null;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index a3c1d0c..21102db 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -103,8 +103,7 @@
   UriKind get uriKind => UriKind.PACKAGE_URI;
 
   @override
-  bool operator ==(Object object) =>
-      object is InSummarySource && object.uri == uri;
+  bool operator ==(Object object) => object is Source && object.uri == uri;
 
   @override
   bool exists() => true;
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index d757b80..e929b67 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -950,6 +950,7 @@
         // and they always refer to defined top-level entities.
         throw new StateError('Unexpected export name kind: ${exportName.kind}');
     }
+    return null;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
new file mode 100644
index 0000000..0d340b9
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.summary.summary_file_builder;
+
+import 'dart:collection';
+import 'dart:io';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/index_unit.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:path/path.dart';
+
+class BuilderOutput {
+  final List<int> sum;
+  final List<int> index;
+
+  BuilderOutput(this.sum, this.index);
+
+  void writeMultiple(String outputDirectoryPath, String modeName) {
+    // Write summary.
+    {
+      String outputPath = join(outputDirectoryPath, '$modeName.sum');
+      File file = new File(outputPath);
+      file.writeAsBytesSync(sum, mode: FileMode.WRITE_ONLY);
+    }
+    // Write index.
+    {
+      String outputPath = join(outputDirectoryPath, '$modeName.index');
+      File file = new File(outputPath);
+      file.writeAsBytesSync(index, mode: FileMode.WRITE_ONLY);
+    }
+  }
+}
+
+class SummaryBuilder {
+  final AnalysisContext _context;
+  final Iterable<Source> _librarySources;
+
+  SummaryBuilder(this._librarySources, this._context);
+
+  factory SummaryBuilder.forSdk(String sdkPath, bool strongMode) {
+    //
+    // Prepare SDK.
+    //
+    DirectoryBasedDartSdk sdk =
+        new DirectoryBasedDartSdk(new JavaFile(sdkPath), strongMode);
+    sdk.useSummary = false;
+    sdk.analysisOptions = new AnalysisOptionsImpl()..strongMode = strongMode;
+
+    //
+    // Prepare 'dart:' URIs to serialize.
+    //
+    Set<String> uriSet =
+        sdk.sdkLibraries.map((SdkLibrary library) => library.shortName).toSet();
+    if (!strongMode) {
+      uriSet.add('dart:html/nativewrappers.dart');
+    }
+    uriSet.add('dart:html_common/html_common_dart2js.dart');
+
+    Set<Source> librarySources = new HashSet<Source>();
+    for (String uri in uriSet) {
+      librarySources.add(sdk.mapDartUri(uri));
+    }
+
+    return new SummaryBuilder(librarySources, sdk.context);
+  }
+
+  BuilderOutput build() => new _Builder(_context, _librarySources).build();
+}
+
+class _Builder {
+  final Set<Source> processedSources = new Set<Source>();
+
+  final PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
+  final PackageIndexAssembler indexAssembler = new PackageIndexAssembler();
+
+  final AnalysisContext context;
+  final Iterable<Source> librarySources;
+
+  _Builder(this.context, this.librarySources);
+
+  /**
+   * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
+   */
+  BuilderOutput build() {
+    //
+    // Serialize each source.
+    //
+    for (Source source in librarySources) {
+      _serializeLibrary(source);
+    }
+    //
+    // Assemble the output.
+    //
+    List<int> sumBytes = bundleAssembler.assemble().toBuffer();
+    List<int> indexBytes = indexAssembler.assemble().toBuffer();
+    return new BuilderOutput(sumBytes, indexBytes);
+  }
+
+  /**
+   * Serialize the library with the given [source] and all its direct or
+   * indirect imports and exports.
+   */
+  void _serializeLibrary(Source source) {
+    if (!processedSources.add(source)) {
+      return;
+    }
+    LibraryElement element = context.computeLibraryElement(source);
+    bundleAssembler.serializeLibraryElement(element);
+    element.importedLibraries.forEach((e) => _serializeLibrary(e.source));
+    element.exportedLibraries.forEach((e) => _serializeLibrary(e.source));
+    // Index every unit of the library.
+    for (CompilationUnitElement unitElement in element.units) {
+      Source unitSource = unitElement.source;
+      CompilationUnit unit =
+          context.resolveCompilationUnit2(unitSource, source);
+      indexAssembler.indexUnit(unit);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index ea97f79..148499e 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -51,6 +51,17 @@
     const SimpleResultCachingPolicy(16384, 16384);
 
 /**
+ * The [ResultCachingPolicy] for ASTs that can be reused when a library
+ * on which the source depends is changed.  It is worth to keep some number
+ * of these ASTs in memory in order to avoid parsing sources.  In contrast,
+ * none of [AST_CACHING_POLICY] managed ASTs can be reused after a change, so
+ * it is worth to keep them in memory while analysis is being performed, but
+ * once analysis is done, they can be flushed.
+ */
+const ResultCachingPolicy<CompilationUnit> AST_REUSABLE_CACHING_POLICY =
+    const SimpleResultCachingPolicy(1024, 1024);
+
+/**
  * The [ResultCachingPolicy] for lists of [ConstantEvaluationTarget]s.
  */
 const ResultCachingPolicy<List<ConstantEvaluationTarget>>
@@ -518,6 +529,23 @@
         cachingPolicy: ELEMENT_CACHING_POLICY);
 
 /**
+ * List of all `LIBRARY_ELEMENT` results.
+ */
+final List<ResultDescriptor<LibraryElement>> LIBRARY_ELEMENT_RESULTS =
+    <ResultDescriptor<LibraryElement>>[
+  LIBRARY_ELEMENT1,
+  LIBRARY_ELEMENT2,
+  LIBRARY_ELEMENT3,
+  LIBRARY_ELEMENT4,
+  LIBRARY_ELEMENT5,
+  LIBRARY_ELEMENT6,
+  LIBRARY_ELEMENT7,
+  LIBRARY_ELEMENT8,
+  LIBRARY_ELEMENT9,
+  LIBRARY_ELEMENT
+];
+
+/**
  * The flag specifying whether all analysis errors are computed in a specific
  * library.
  *
@@ -717,7 +745,7 @@
  */
 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
     new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null,
-        cachingPolicy: AST_CACHING_POLICY);
+        cachingPolicy: AST_REUSABLE_CACHING_POLICY);
 
 /**
  * The partially resolved [CompilationUnit] associated with a compilation unit.
@@ -868,6 +896,27 @@
         cachingPolicy: AST_CACHING_POLICY);
 
 /**
+ * List of all `RESOLVED_UNITx` results.
+ */
+final List<ResultDescriptor<CompilationUnit>> RESOLVED_UNIT_RESULTS =
+    <ResultDescriptor<CompilationUnit>>[
+  RESOLVED_UNIT1,
+  RESOLVED_UNIT2,
+  RESOLVED_UNIT3,
+  RESOLVED_UNIT4,
+  RESOLVED_UNIT5,
+  RESOLVED_UNIT6,
+  RESOLVED_UNIT7,
+  RESOLVED_UNIT8,
+  RESOLVED_UNIT9,
+  RESOLVED_UNIT10,
+  RESOLVED_UNIT11,
+  RESOLVED_UNIT12,
+  RESOLVED_UNIT13,
+  RESOLVED_UNIT
+];
+
+/**
  * The errors produced while scanning a compilation unit.
  *
  * The list will be empty if there were no errors, but will not be `null`.
@@ -1804,8 +1853,9 @@
     LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
     LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
     if (asyncLibrary == null) {
-      asyncLibrary =
-          (context as AnalysisContextImpl).createMockAsyncLib(coreLibrary);
+      Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC);
+      asyncLibrary = (context as AnalysisContextImpl)
+          .createMockAsyncLib(coreLibrary, asyncSource);
     }
     Namespace coreNamespace = coreLibrary.publicNamespace;
     Namespace asyncNamespace = asyncLibrary.publicNamespace;
@@ -1814,7 +1864,8 @@
     //
     if (!context.analysisOptions.enableAsync) {
       AnalysisContextImpl contextImpl = context;
-      asyncLibrary = contextImpl.createMockAsyncLib(coreLibrary);
+      Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC);
+      asyncLibrary = contextImpl.createMockAsyncLib(coreLibrary, asyncSource);
       asyncNamespace = asyncLibrary.publicNamespace;
     }
     TypeProvider typeProvider =
@@ -3135,8 +3186,10 @@
     IgnoreInfo ignoreInfo = new IgnoreInfo();
     for (Match match in matches) {
       // See _IGNORE_MATCHER for format --- note the possibility of error lists.
-      Iterable<String> codes =
-          match.group(1).split(',').map((String code) => code.trim());
+      Iterable<String> codes = match
+          .group(1)
+          .split(',')
+          .map((String code) => code.trim().toLowerCase());
       ignoreInfo.addAll(info.getLocation(match.start).lineNumber, codes);
     }
     return ignoreInfo;
@@ -3257,19 +3310,20 @@
    */
   VariableDeclaration getDeclaration(CompilationUnit unit) {
     VariableElement variable = target;
-    AstNode node = new NodeLocator2(variable.nameOffset).searchWithin(unit);
+    int offset = variable.nameOffset;
+    AstNode node = new NodeLocator2(offset).searchWithin(unit);
     if (node == null) {
       Source variableSource = variable.source;
       Source unitSource = unit.element.source;
       if (variableSource != unitSource) {
         throw new AnalysisException(
             "Failed to find the AST node for the variable "
-            "${variable.displayName} in $variableSource "
+            "${variable.displayName} at $offset in $variableSource "
             "because we were looking in $unitSource");
       }
       throw new AnalysisException(
           "Failed to find the AST node for the variable "
-          "${variable.displayName} in $variableSource");
+          "${variable.displayName} at $offset in $variableSource");
     }
     VariableDeclaration declaration =
         node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
@@ -3277,14 +3331,28 @@
       Source variableSource = variable.source;
       Source unitSource = unit.element.source;
       if (variableSource != unitSource) {
+        if (declaration == null) {
+          throw new AnalysisException(
+              "Failed to find the declaration of the variable "
+              "${variable.displayName} at $offset in $variableSource "
+              "because the node was not in a variable declaration "
+              "possibly because we were looking in $unitSource");
+        }
         throw new AnalysisException(
             "Failed to find the declaration of the variable "
-            "${variable.displayName} in $variableSource"
+            "${variable.displayName} at $offset in $variableSource "
             "because we were looking in $unitSource");
       }
+      if (declaration == null) {
+        throw new AnalysisException(
+            "Failed to find the declaration of the variable "
+            "${variable.displayName} at $offset in $variableSource "
+            "because the node was not in a variable declaration");
+      }
       throw new AnalysisException(
           "Failed to find the declaration of the variable "
-          "${variable.displayName} in $variableSource");
+          "${variable.displayName} at $offset in $variableSource "
+          "because the node was not the name in a variable declaration");
     }
     return declaration;
   }
@@ -4500,11 +4568,12 @@
 
 /**
  * A builder for creating [ReferencedNames].
- *
- * TODO(scheglov) Record dependencies for all other top-level declarations.
  */
-class ReferencedNamesBuilder extends RecursiveAstVisitor {
+class ReferencedNamesBuilder extends GeneralizingAstVisitor {
   final ReferencedNames names;
+
+  ReferencedNamesScope scope = new ReferencedNamesScope(null);
+
   int bodyLevel = 0;
   Set<String> dependsOn;
 
@@ -4516,41 +4585,205 @@
   }
 
   @override
-  visitBlockFunctionBody(BlockFunctionBody node) {
+  visitBlock(Block node) {
+    ReferencedNamesScope outerScope = scope;
     try {
-      bodyLevel++;
-      super.visitBlockFunctionBody(node);
+      scope = new ReferencedNamesScope.forBlock(scope, node);
+      super.visitBlock(node);
     } finally {
-      bodyLevel--;
+      scope = outerScope;
     }
   }
 
   @override
   visitClassDeclaration(ClassDeclaration node) {
-    dependsOn = new Set<String>();
-    super.visitClassDeclaration(node);
-    names.userToDependsOn[node.name.name] = dependsOn;
-    dependsOn = null;
+    ReferencedNamesScope outerScope = scope;
+    try {
+      scope = new ReferencedNamesScope.forClass(scope, node);
+      dependsOn = new Set<String>();
+      super.visitClassDeclaration(node);
+      names.userToDependsOn[node.name.name] = dependsOn;
+    } finally {
+      dependsOn = null;
+      scope = outerScope;
+    }
   }
 
   @override
-  visitExpressionFunctionBody(ExpressionFunctionBody node) {
+  visitConstructorName(ConstructorName node) {
+    if (node.parent is! ConstructorDeclaration) {
+      super.visitConstructorName(node);
+    }
+  }
+
+  @override
+  visitFunctionBody(FunctionBody node) {
     try {
       bodyLevel++;
-      super.visitExpressionFunctionBody(node);
+      super.visitFunctionBody(node);
     } finally {
       bodyLevel--;
     }
   }
 
   @override
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    if (!node.inDeclarationContext()) {
-      String name = node.name;
-      names.names.add(name);
-      if (dependsOn != null && bodyLevel == 0) {
-        dependsOn.add(name);
+  visitFunctionDeclaration(FunctionDeclaration node) {
+    if (bodyLevel == 0) {
+      ReferencedNamesScope outerScope = scope;
+      try {
+        scope = new ReferencedNamesScope.forFunction(scope, node);
+        dependsOn = new Set<String>();
+        super.visitFunctionDeclaration(node);
+        names.userToDependsOn[node.name.name] = dependsOn;
+      } finally {
+        dependsOn = null;
+        scope = outerScope;
       }
+    } else {
+      super.visitFunctionDeclaration(node);
+    }
+  }
+
+  @override
+  visitFunctionTypeAlias(FunctionTypeAlias node) {
+    if (bodyLevel == 0) {
+      ReferencedNamesScope outerScope = scope;
+      try {
+        scope = new ReferencedNamesScope.forFunctionTypeAlias(scope, node);
+        dependsOn = new Set<String>();
+        super.visitFunctionTypeAlias(node);
+        names.userToDependsOn[node.name.name] = dependsOn;
+      } finally {
+        dependsOn = null;
+        scope = outerScope;
+      }
+    } else {
+      super.visitFunctionTypeAlias(node);
+    }
+  }
+
+  @override
+  visitMethodDeclaration(MethodDeclaration node) {
+    ReferencedNamesScope outerScope = scope;
+    try {
+      scope = new ReferencedNamesScope.forMethod(scope, node);
+      super.visitMethodDeclaration(node);
+    } finally {
+      scope = outerScope;
+    }
+  }
+
+  @override
+  visitSimpleIdentifier(SimpleIdentifier node) {
+    // Ignore all declarations.
+    if (node.inDeclarationContext()) {
+      return;
+    }
+    // Ignore class names references from constructors.
+    AstNode parent = node.parent;
+    if (parent is ConstructorDeclaration && parent.returnType == node) {
+      return;
+    }
+    // Prepare name.
+    String name = node.name;
+    // Ignore unqualified names shadowed by local elements.
+    if (!node.isQualified && scope.contains(name)) {
+      return;
+    }
+    // Do add the dependency.
+    names.names.add(name);
+    if (dependsOn != null && bodyLevel == 0) {
+      dependsOn.add(name);
+    }
+  }
+}
+
+class ReferencedNamesScope {
+  final ReferencedNamesScope enclosing;
+  Set<String> names;
+
+  ReferencedNamesScope(this.enclosing);
+
+  factory ReferencedNamesScope.forBlock(
+      ReferencedNamesScope enclosing, Block node) {
+    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+    for (Statement statement in node.statements) {
+      if (statement is FunctionDeclarationStatement) {
+        scope.add(statement.functionDeclaration.name.name);
+      } else if (statement is VariableDeclarationStatement) {
+        for (VariableDeclaration variable in statement.variables.variables) {
+          scope.add(variable.name.name);
+        }
+      }
+    }
+    return scope;
+  }
+
+  factory ReferencedNamesScope.forClass(
+      ReferencedNamesScope enclosing, ClassDeclaration node) {
+    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+    scope._addTypeParameters(node.typeParameters);
+    for (ClassMember member in node.members) {
+      if (member is FieldDeclaration) {
+        for (VariableDeclaration variable in member.fields.variables) {
+          scope.add(variable.name.name);
+        }
+      } else if (member is MethodDeclaration) {
+        scope.add(member.name.name);
+      }
+    }
+    return scope;
+  }
+
+  factory ReferencedNamesScope.forFunction(
+      ReferencedNamesScope enclosing, FunctionDeclaration node) {
+    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+    scope._addTypeParameters(node.functionExpression.typeParameters);
+    scope._addFormalParameters(node.functionExpression.parameters);
+    return scope;
+  }
+
+  factory ReferencedNamesScope.forFunctionTypeAlias(
+      ReferencedNamesScope enclosing, FunctionTypeAlias node) {
+    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+    scope._addTypeParameters(node.typeParameters);
+    return scope;
+  }
+
+  factory ReferencedNamesScope.forMethod(
+      ReferencedNamesScope enclosing, MethodDeclaration node) {
+    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+    scope._addTypeParameters(node.typeParameters);
+    scope._addFormalParameters(node.parameters);
+    return scope;
+  }
+
+  void add(String name) {
+    names ??= new Set<String>();
+    names.add(name);
+  }
+
+  bool contains(String name) {
+    if (names != null && names.contains(name)) {
+      return true;
+    }
+    if (enclosing != null) {
+      return enclosing.contains(name);
+    }
+    return false;
+  }
+
+  void _addFormalParameters(FormalParameterList parameterList) {
+    if (parameterList != null) {
+      parameterList.parameters
+          .map((p) => p is NormalFormalParameter ? p.identifier.name : '')
+          .forEach(add);
+    }
+  }
+
+  void _addTypeParameters(TypeParameterList typeParameterList) {
+    if (typeParameterList != null) {
+      typeParameterList.typeParameters.map((p) => p.name.name).forEach(add);
     }
   }
 }
@@ -5561,7 +5794,7 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     if (target is Source) {
       return <String, TaskInput>{
-        CONTENT_INPUT_NAME: CONTENT.of(target),
+        CONTENT_INPUT_NAME: CONTENT.of(target, flushOnAccess: true),
         MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(target)
       };
     } else if (target is DartScript) {
@@ -5644,9 +5877,12 @@
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
     AnalysisOptionsImpl options = context.analysisOptions;
     if (options.strongMode) {
-      unit.accept(new CodeChecker(
-          typeProvider, new StrongTypeSystemImpl(), errorListener,
-          hints: options.strongModeHints));
+      CodeChecker checker = new CodeChecker(
+          typeProvider,
+          new StrongTypeSystemImpl(implicitCasts: options.implicitCasts),
+          errorListener,
+          options);
+      checker.visitCompilationUnit(unit);
     }
     //
     // Record outputs.
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index 70ebe3b..07083d8 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -101,15 +101,18 @@
     try {
       isTaskRunning = true;
       AnalysisTask task;
-      WorkOrder workOrder = createWorkOrderForResult(target, result);
-      if (workOrder != null) {
-        while (workOrder.moveNext()) {
-//          AnalysisTask previousTask = task;
-//          String message = workOrder.current.toString();
-          task = performWorkItem(workOrder.current);
-//          if (task == null) {
-//            throw new AnalysisException(message, previousTask.caughtException);
-//          }
+      while (true) {
+        try {
+          WorkOrder workOrder = createWorkOrderForResult(target, result);
+          if (workOrder != null) {
+            while (workOrder.moveNext()) {
+              task = performWorkItem(workOrder.current);
+            }
+          }
+          break;
+        } on ModificationTimeMismatchError {
+          // Cache inconsistency was detected and fixed by invalidating
+          // corresponding results in cache. Computation must be restarted.
         }
       }
       return task;
@@ -248,7 +251,12 @@
       if (currentWorkOrder == null) {
         currentWorkOrder = createNextWorkOrder();
       } else if (currentWorkOrder.moveNext()) {
-        performWorkItem(currentWorkOrder.current);
+        try {
+          performWorkItem(currentWorkOrder.current);
+        } on ModificationTimeMismatchError {
+          reset();
+          return true;
+        }
       } else {
         currentWorkOrder = createNextWorkOrder();
       }
@@ -278,7 +286,10 @@
       AnalysisTarget target = task.target;
       CacheEntry entry = context.getCacheEntry(target);
       if (task.caughtException == null) {
-        List<TargetedResult> dependedOn = item.inputTargetedResults.toList();
+        List<TargetedResult> dependedOn =
+            context.analysisOptions.trackCacheDependencies
+                ? item.inputTargetedResults.toList()
+                : const <TargetedResult>[];
         Map<ResultDescriptor, dynamic> outputs = task.outputs;
         List<ResultDescriptor> results = task.descriptor.results;
         int resultLength = results.length;
@@ -761,7 +772,6 @@
             throw new AnalysisException(
                 'Cannot create work order to build $inputResult for $inputTarget',
                 this.exception);
-            return null;
           }
         }
       } else {
diff --git a/pkg/analyzer/lib/src/task/general.dart b/pkg/analyzer/lib/src/task/general.dart
index 38d67df..064fd20 100644
--- a/pkg/analyzer/lib/src/task/general.dart
+++ b/pkg/analyzer/lib/src/task/general.dart
@@ -4,6 +4,7 @@
 
 library analyzer.src.task.general;
 
+import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/task/general.dart';
@@ -33,13 +34,36 @@
   @override
   internalPerform() {
     Source source = getRequiredSource();
+    String content;
+    int modificationTime;
     try {
       TimestampedData<String> data = context.getContents(source);
-      outputs[CONTENT] = data.data;
-      outputs[MODIFICATION_TIME] = data.modificationTime;
+      content = data.data;
+      modificationTime = data.modificationTime;
     } catch (exception) {
-      outputs[CONTENT] = '';
-      outputs[MODIFICATION_TIME] = -1;
+      content = '';
+      modificationTime = -1;
+    }
+    _validateModificationTime(source, modificationTime);
+    outputs[CONTENT] = content;
+    outputs[MODIFICATION_TIME] = modificationTime;
+  }
+
+  /**
+   * Validate that the [target] cache entry has the same modification time
+   * as the given.  Otherwise throw a new [ModificationTimeMismatchError] and
+   * instruct to invalidate targets content.
+   */
+  void _validateModificationTime(Source source, int modificationTime) {
+    AnalysisContext context = this.context;
+    if (context is InternalAnalysisContext) {
+      CacheEntry entry = context.getCacheEntry(target);
+      if (entry != null && entry.modificationTime != modificationTime) {
+        entry.modificationTime = modificationTime;
+        entry.setState(CONTENT, CacheState.INVALID);
+        entry.setState(MODIFICATION_TIME, CacheState.INVALID);
+        throw new ModificationTimeMismatchError(source);
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index 93e00ed..0478bdb 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -80,7 +80,8 @@
   String get shortName => source.shortName;
 
   @override
-  Uri get uri => throw new StateError('uri not supported for scripts');
+  Uri get uri => source.uri
+      .replace(queryParameters: {'offset': fragments[0].offset.toString()});
 
   @override
   UriKind get uriKind =>
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index d7156e4..66a5bbe 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -242,7 +242,7 @@
   }
 
   /**
-   * Replaces contents of the [to] unit with the contenxts of the [from] unit.
+   * Replaces contents of the [to] unit with the contexts of the [from] unit.
    */
   static void _replaceUnitContents(CompilationUnit to, CompilationUnit from) {
     to.directives.clear();
@@ -317,7 +317,7 @@
   }
 
   /**
-   * Returns all tokends (including comments) of the given [node].
+   * Returns all tokens (including comments) of the given [node].
    */
   static List<Token> getTokens(AstNode node) {
     List<Token> tokens = <Token>[];
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index fd1c224..0f47c44 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -15,7 +15,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/task/general.dart';
-import 'package:analyzer/src/task/strong/info.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:source_span/source_span.dart';
@@ -161,8 +160,6 @@
       _errorCodes = new HashSet<String>();
       // Engine codes.
       _errorCodes.addAll(ErrorCode.values.map((ErrorCode code) => code.name));
-      // Strong-mode codes.
-      _errorCodes.addAll(StaticInfo.names);
     }
     return _errorCodes;
   }
diff --git a/pkg/analyzer/lib/src/task/strong/ast_properties.dart b/pkg/analyzer/lib/src/task/strong/ast_properties.dart
new file mode 100644
index 0000000..52f27f1
--- /dev/null
+++ b/pkg/analyzer/lib/src/task/strong/ast_properties.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Properties that result from Strong Mode analysis on an AST.
+///
+/// These properties are not public, but provided by use of back-ends such as
+/// Dart Dev Compiler.
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/element/type.dart';
+
+const String _implicitCast = '_implicitCast';
+const String _hasImplicitCasts = '_hasImplicitCasts';
+const String _isDynamicInvoke = '_isDynamicInvoke';
+
+/// True if this compilation unit has any implicit casts, otherwise false.
+///
+/// See also [getImplicitCast].
+bool hasImplicitCasts(CompilationUnit node) {
+  return node.getProperty/*<bool>*/(_hasImplicitCasts) ?? false;
+}
+
+/// Sets [hasImplicitCasts] property for this compilation unit.
+void setHasImplicitCasts(CompilationUnit node, bool value) {
+  node.setProperty(_hasImplicitCasts, value == true ? true : null);
+}
+
+/// If this expression has an implicit cast, returns the type it is coerced to,
+/// otherwise returns null.
+DartType getImplicitCast(Expression node) {
+  return node.getProperty/*<DartType>*/(_implicitCast);
+}
+
+/// Sets the result of [getImplicitCast] for this node.
+void setImplicitCast(Expression node, DartType type) {
+  node.setProperty(_implicitCast, type);
+}
+
+/// True if this node is a dynamic operation that requires dispatch and/or
+/// checking at runtime.
+bool isDynamicInvoke(Expression node) {
+  return node.getProperty/*<bool>*/(_isDynamicInvoke) ?? false;
+}
+
+/// Sets [isDynamicInvoke] property for this expression
+void setIsDynamicInvoke(Expression node, bool value) {
+  node.setProperty(_isDynamicInvoke, value == true ? true : null);
+}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 4566e6a..783cdf0 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -13,10 +13,12 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
+import 'package:analyzer/src/generated/error.dart' show StrongModeCode;
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/type_system.dart';
 
-import 'info.dart';
+import 'ast_properties.dart';
 
 DartType _elementType(Element e) {
   if (e == null) {
@@ -100,20 +102,21 @@
   final StrongTypeSystemImpl rules;
   final TypeProvider typeProvider;
   final AnalysisErrorListener reporter;
-  final _OverrideChecker _overrideChecker;
-  final bool _hints;
+  final AnalysisOptionsImpl _options;
+  _OverrideChecker _overrideChecker;
 
   bool _failure = false;
+  bool _hasImplicitCasts;
+
   CodeChecker(TypeProvider typeProvider, StrongTypeSystemImpl rules,
-      AnalysisErrorListener reporter,
-      {bool hints: false})
+      AnalysisErrorListener reporter, this._options)
       : typeProvider = typeProvider,
         rules = rules,
-        reporter = reporter,
-        _hints = hints,
-        _overrideChecker = new _OverrideChecker(typeProvider, rules, reporter);
+        reporter = reporter {
+    _overrideChecker = new _OverrideChecker(this);
+  }
 
-  bool get failure => _failure || _overrideChecker._failure;
+  bool get failure => _failure;
 
   void checkArgument(Expression arg, DartType expectedType) {
     // Preserve named argument structure, so their immediate parent is the
@@ -170,7 +173,13 @@
 
   void reset() {
     _failure = false;
-    _overrideChecker._failure = false;
+  }
+
+  @override
+  void visitCompilationUnit(CompilationUnit node) {
+    _hasImplicitCasts = false;
+    node.visitChildren(this);
+    setHasImplicitCasts(node, _hasImplicitCasts);
   }
 
   @override
@@ -264,7 +273,7 @@
     for (int i = 0, last = init.length - 1; i < last; i++) {
       final node = init[i];
       if (node is SuperConstructorInvocation) {
-        _recordMessage(new InvalidSuperInvocation(node));
+        _recordMessage(node, StrongModeCode.INVALID_SUPER_INVOCATION, [node]);
       }
     }
   }
@@ -315,9 +324,8 @@
           node.identifier.staticElement as FieldFormalParameterElement;
       var fieldType = _elementType(fieldElement.field);
       if (!rules.isSubtypeOf(type, fieldType)) {
-        var staticInfo =
-            new InvalidParameterDeclaration(rules, node, fieldType);
-        _recordMessage(staticInfo);
+        _recordMessage(node, StrongModeCode.INVALID_PARAMETER_DECLARATION,
+            [node, fieldType]);
       }
     }
     node.visitChildren(this);
@@ -345,8 +353,7 @@
             sequenceInterface.instantiate([DynamicTypeImpl.instance]);
 
         if (rules.isSubtypeOf(sequenceType, iterableType)) {
-          _recordMessage(DownCast.create(
-              rules, node.iterable, iterableType, sequenceType));
+          _recordImplicitCast(node.iterable, iterableType, sequenceType);
           elementType = DynamicTypeImpl.instance;
         }
       }
@@ -500,7 +507,7 @@
       //
       // The first case is handled here, the second case is handled below when
       // we call [checkFunctionApplication].
-      DynamicInvoke.set(node.methodName, true);
+      setIsDynamicInvoke(node.methodName, true);
     } else {
       checkFunctionApplication(node, node.methodName, node.argumentList);
     }
@@ -619,7 +626,6 @@
       assert(functionType.optionalParameterTypes.isEmpty);
 
       // Check the LHS type.
-      var staticInfo;
       var rhsType = _getStaticType(expr.rightHandSide);
       var lhsType = _getStaticType(expr.leftHandSide);
       var returnType = rules.refineBinaryExpressionType(
@@ -632,19 +638,17 @@
             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, rhsType, lhsType);
-          rhsType = lhsType;
+          _recordImplicitCast(expr.rightHandSide, rhsType, lhsType);
         } else {
-          staticInfo = new StaticTypeError(rules, expr, lhsType);
+          _recordMessage(expr, StrongModeCode.STATIC_TYPE_ERROR,
+              [expr, returnType, lhsType]);
         }
-        _recordMessage(staticInfo);
-      }
-
-      // Check the rhs type
-      if (staticInfo is! CoercionInfo) {
-        var paramType = paramTypes.first;
-        _checkDowncast(expr.rightHandSide, paramType);
+      } else {
+        // Check the RHS type.
+        //
+        // This is only needed if we didn't already need a cast, and avoids
+        // emitting two messages for the same expression.
+        _checkDowncast(expr.rightHandSide, paramTypes.first);
       }
     }
   }
@@ -679,7 +683,7 @@
 
     // Downcast if toT <: fromT
     if (rules.isSubtypeOf(to, from)) {
-      _recordMessage(DownCast.create(rules, expr, from, to));
+      _recordImplicitCast(expr, from, to);
       return;
     }
 
@@ -694,7 +698,7 @@
     // Iterable<T> for some concrete T (e.g. Object).  These are unrelated
     // in the restricted system, but List<dynamic> <: Iterable<T> in dart.
     if (from.isAssignableTo(to)) {
-      _recordMessage(DownCast.create(rules, expr, from, to));
+      _recordImplicitCast(expr, from, to);
     }
   }
 
@@ -731,7 +735,7 @@
   void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) {
     var type = getType(typeName);
     if (!rules.isGroundType(type)) {
-      _recordMessage(new NonGroundTypeCheckInfo(node, type));
+      _recordMessage(node, StrongModeCode.NON_GROUND_TYPE_CHECK_INFO, [type]);
     }
   }
 
@@ -749,6 +753,86 @@
     }
   }
 
+  /// Records an implicit cast for the [expression] from [fromType] to [toType].
+  ///
+  /// This will emit the appropriate error/warning/hint message as well as mark
+  /// the AST node.
+  void _recordImplicitCast(
+      Expression expression, DartType fromType, DartType 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(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
+
+    // Inference "casts":
+    if (expression is Literal || expression is FunctionExpression) {
+      // fromT should be an exact type - this will almost certainly fail at
+      // runtime.
+      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+          [expression, fromType, toType]);
+      return;
+    }
+
+    if (expression is InstanceCreationExpression) {
+      ConstructorElement e = expression.staticElement;
+      if (e == null || !e.isFactory) {
+        // fromT should be an exact type - this will almost certainly fail at
+        // runtime.
+
+        _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+            [expression, fromType, toType]);
+        return;
+      }
+    }
+
+    if (isKnownFunction(expression)) {
+      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+          [expression, fromType, toType]);
+      return;
+    }
+
+    // TODO(vsm): Change this to an assert when we have generic methods and
+    // fix TypeRules._coerceTo to disallow implicit sideways casts.
+    bool downCastComposite = false;
+    if (!rules.isSubtypeOf(toType, fromType)) {
+      assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
+      downCastComposite = true;
+    }
+
+    // Composite cast: these are more likely to fail.
+    if (!rules.isGroundType(toType)) {
+      // This cast is (probably) due to our different treatment of dynamic.
+      // It may be more likely to fail at runtime.
+      if (fromType is InterfaceType) {
+        // For class types, we'd like to allow non-generic down casts, e.g.,
+        // Iterable<T> to List<T>.  The intuition here is that raw (generic)
+        // casts are problematic, and we should complain about those.
+        var typeArgs = fromType.typeArguments;
+        downCastComposite =
+            typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic);
+      } else {
+        downCastComposite = true;
+      }
+    }
+
+    var parent = expression.parent;
+    ErrorCode errorCode;
+    if (downCastComposite) {
+      errorCode = StrongModeCode.DOWN_CAST_COMPOSITE;
+    } else if (fromType.isDynamic) {
+      errorCode = StrongModeCode.DYNAMIC_CAST;
+    } else if (parent is VariableDeclaration &&
+        parent.initializer == expression) {
+      errorCode = StrongModeCode.ASSIGNMENT_CAST;
+    } else {
+      errorCode = StrongModeCode.DOWN_CAST_IMPLICIT;
+    }
+
+    _recordMessage(expression, errorCode, [fromType, toType]);
+    setImplicitCast(expression, toType);
+    _hasImplicitCasts = true;
+  }
+
   // Produce a coercion which coerces something of type fromT
   // to something of type toT.
   // Returns the error coercion if the types cannot be coerced
@@ -811,7 +895,7 @@
     DartType t = expr.staticType ?? DynamicTypeImpl.instance;
 
     // Remove fuzzy arrow if possible.
-    if (t is FunctionType && StaticInfo.isKnownFunction(expr)) {
+    if (t is FunctionType && isKnownFunction(expr)) {
       t = rules.functionTypeToConcreteType(typeProvider, t);
     }
 
@@ -893,46 +977,57 @@
     return _isObjectGetter(target, id) || _isObjectMethod(target, id);
   }
 
-  void _recordDynamicInvoke(AstNode node, AstNode target) {
-    if (_hints) {
-      reporter.onError(new DynamicInvoke(rules, node).toAnalysisError());
-    }
+  void _recordDynamicInvoke(AstNode node, Expression target) {
+    _recordMessage(node, StrongModeCode.DYNAMIC_INVOKE, [node]);
     // 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);
+    setIsDynamicInvoke(target, true);
   }
 
-  void _recordMessage(StaticInfo info) {
-    if (info == null) return;
-    var error = info.toAnalysisError();
-    var severity = error.errorCode.errorSeverity;
+  void _recordMessage(AstNode node, ErrorCode errorCode, List arguments) {
+    var severity = errorCode.errorSeverity;
     if (severity == ErrorSeverity.ERROR) _failure = true;
-    if (severity != ErrorSeverity.INFO || _hints) {
+    if (severity != ErrorSeverity.INFO || _options.strongModeHints) {
+      int begin = node is AnnotatedNode
+          ? node.firstTokenAfterCommentAndMetadata.offset
+          : node.offset;
+      int length = node.end - begin;
+      var source = (node.root as CompilationUnit).element.source;
+      var error =
+          new AnalysisError(source, begin, length, errorCode, arguments);
       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);
-    }
   }
 }
 
+bool isKnownFunction(Expression expression) {
+  Element element = null;
+  if (expression is FunctionExpression) {
+    return true;
+  } else if (expression is PropertyAccess) {
+    element = expression.propertyName.staticElement;
+  } else if (expression is Identifier) {
+    element = expression.staticElement;
+  }
+// First class functions and static methods, where we know the original
+// declaration, will have an exact type, so we know a downcast will fail.
+  return element is FunctionElement ||
+      element is MethodElement && element.isStatic;
+}
+
 /// 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 StrongTypeSystemImpl rules;
   final TypeProvider _typeProvider;
-  final AnalysisErrorListener _reporter;
+  final CodeChecker _checker;
 
-  _OverrideChecker(this._typeProvider, this.rules, this._reporter);
+  _OverrideChecker(CodeChecker checker)
+      : _checker = checker,
+        rules = checker.rules,
+        _typeProvider = checker.typeProvider;
 
   void check(ClassDeclaration node) {
     if (node.element.type.isObject) return;
@@ -1196,8 +1291,14 @@
       // as a field.  We effectively treat fields as final / non-virtual.
       PropertyInducingElement field = _getMemberField(type, element);
       if (field != null) {
-        _recordMessage(new InvalidFieldOverride(
-            errorLocation, element, type, subType, baseType));
+        _checker._recordMessage(
+            errorLocation, StrongModeCode.INVALID_FIELD_OVERRIDE, [
+          element.enclosingElement.name,
+          element.name,
+          subType,
+          type,
+          baseType
+        ]);
       }
     }
     FunctionType concreteSubType = subType;
@@ -1225,8 +1326,23 @@
       //     get foo => e; // no type specified.
       //     toString() { ... } // no return type specified.
       //   }
-      _recordMessage(new InvalidMethodOverride(
-          errorLocation, element, type, subType, baseType));
+
+      ErrorCode errorCode;
+      if (errorLocation is ExtendsClause) {
+        errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE;
+      } else if (errorLocation.parent is WithClause) {
+        errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN;
+      } else {
+        errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE;
+      }
+
+      _checker._recordMessage(errorLocation, errorCode, [
+        element.enclosingElement.name,
+        element.name,
+        subType,
+        type,
+        baseType
+      ]);
     }
     return true;
   }
@@ -1265,11 +1381,4 @@
       current = current.superclass;
     } while (!current.isObject && !visited.contains(current));
   }
-
-  void _recordMessage(StaticInfo info) {
-    if (info == null) return;
-    var error = info.toAnalysisError();
-    if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) _failure = true;
-    _reporter.onError(error);
-  }
 }
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
deleted file mode 100644
index ec8626f..0000000
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Defines static information collected by the type checker and used later by
-/// emitters to generate code.
-// TODO(jmesserly): this was ported from package:dev_compiler, and needs to be
-// refactored to fit into analyzer.
-library analyzer.src.task.strong.info;
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-
-/// A down cast due to a variable declaration to a ground type:
-///
-///     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(TypeSystem rules, Expression expression, DartType fromType,
-      DartType toType)
-      : super._internal(rules, expression, fromType, toType);
-
-  @override
-  String get name => 'STRONG_MODE_ASSIGNMENT_CAST';
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-/// Implicitly injected expression conversion.
-abstract class CoercionInfo extends StaticInfo {
-  static const String _propertyName = 'dev_compiler.src.info.CoercionInfo';
-
-  final TypeSystem rules;
-
-  final Expression node;
-
-  CoercionInfo(this.rules, this.node);
-
-  DartType get baseType => node.staticType ?? DynamicTypeImpl.instance;
-  DartType get convertedType;
-
-  String get message;
-  DartType get staticType => convertedType;
-
-  toErrorCode() => new HintCode(name, message);
-
-  /// 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 {
-  final DartType _fromType;
-  final DartType _toType;
-
-  DownCast._internal(
-      TypeSystem rules, Expression expression, this._fromType, this._toType)
-      : super(rules, expression);
-
-  @override
-  List<Object> get arguments => [baseType, convertedType];
-
-  /// The type being cast from.
-  ///
-  /// This is usually the static type of the associated expression, but may not
-  /// be if the cast is attached to a variable in a for-in loop.
-  @override
-  DartType get baseType => _fromType;
-
-  DartType get convertedType => _toType;
-
-  @override
-  String get message => 'Unsound implicit cast from {0} to {1}';
-
-  /// Factory to create correct DownCast variant.
-  static StaticInfo create(StrongTypeSystemImpl rules, Expression expression,
-      DartType fromType, DartType 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(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
-
-    // Inference "casts":
-    if (expression is Literal || expression is FunctionExpression) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      return new StaticTypeError(rules, expression, toType);
-    }
-
-    if (expression is InstanceCreationExpression) {
-      ConstructorElement e = expression.staticElement;
-      if (e == null || !e.isFactory) {
-        // fromT should be an exact type - this will almost certainly fail at
-        // runtime.
-        return new StaticTypeError(rules, expression, toType);
-      }
-    }
-
-    if (StaticInfo.isKnownFunction(expression)) {
-      return new StaticTypeError(rules, expression, toType);
-    }
-
-    // TODO(vsm): Change this to an assert when we have generic methods and
-    // fix TypeRules._coerceTo to disallow implicit sideways casts.
-    if (!rules.isSubtypeOf(toType, fromType)) {
-      assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
-      return new DownCastComposite(rules, expression, fromType, toType);
-    }
-
-    // Composite cast: these are more likely to fail.
-    if (!rules.isGroundType(toType)) {
-      // This cast is (probably) due to our different treatment of dynamic.
-      // It may be more likely to fail at runtime.
-      if (fromType is InterfaceType) {
-        // For class types, we'd like to allow non-generic down casts, e.g.,
-        // Iterable<T> to List<T>.  The intuition here is that raw (generic)
-        // casts are problematic, and we should complain about those.
-        var typeArgs = fromType.typeArguments;
-        if (typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic)) {
-          return new DownCastComposite(rules, expression, fromType, toType);
-        }
-      } else {
-        return new DownCastComposite(rules, expression, fromType, toType);
-      }
-    }
-
-    // Dynamic cast
-    if (fromType.isDynamic) {
-      return new DynamicCast(rules, expression, fromType, toType);
-    }
-
-    // Assignment cast
-    var parent = expression.parent;
-    if (parent is VariableDeclaration && (parent.initializer == expression)) {
-      return new AssignmentCast(rules, expression, fromType, toType);
-    }
-
-    // Other casts
-    return new DownCastImplicit(rules, expression, fromType, toType);
-  }
-}
-
-/// 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(TypeSystem rules, Expression expression, DartType fromType,
-      DartType toType)
-      : super._internal(rules, expression, fromType, toType);
-
-  @override
-  String get name => 'STRONG_MODE_DOWN_CAST_COMPOSITE';
-
-  toErrorCode() => new StaticWarningCode(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(TypeSystem rules, Expression expression, DartType fromType,
-      DartType toType)
-      : super._internal(rules, expression, fromType, toType);
-
-  @override
-  String get name => 'STRONG_MODE_DOWN_CAST_IMPLICIT';
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-/// A down cast from dynamic to T.
-class DynamicCast extends DownCast {
-  DynamicCast(TypeSystem rules, Expression expression, DartType fromType,
-      DartType toType)
-      : super._internal(rules, expression, fromType, toType);
-
-  @override
-  String get name => 'STRONG_MODE_DYNAMIC_CAST';
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-class DynamicInvoke extends CoercionInfo {
-  static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke';
-
-  DynamicInvoke(TypeSystem rules, Expression expression)
-      : super(rules, expression);
-  DartType get convertedType => DynamicTypeImpl.instance;
-  String get message => '{0} requires dynamic invoke';
-
-  @override
-  String get name => 'STRONG_MODE_DYNAMIC_INVOKE';
-
-  toErrorCode() => new HintCode(name, message);
-
-  /// Whether this [node] is the target of a dynamic operation.
-  static bool get(AstNode node) => node.getProperty(_propertyName) ?? 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;
-  }
-}
-
-/// Standard / unspecialized inferred type.
-class InferredType extends InferredTypeBase {
-  InferredType(TypeSystem rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-
-  @override
-  String get name => 'STRONG_MODE_INFERRED_TYPE';
-
-  /// Factory to create correct InferredType variant.
-  static InferredTypeBase create(
-      TypeSystem 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 inferred type for a non-literal allocation site.
-class InferredTypeAllocation extends InferredTypeBase {
-  InferredTypeAllocation(TypeSystem rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-
-  @override
-  String get name => 'STRONG_MODE_INFERRED_TYPE_ALLOCATION';
-}
-
-/// 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(
-      TypeSystem rules, Expression expression, this._type)
-      : super(rules, expression);
-
-  @override
-  List get arguments => [node, type];
-  DartType get convertedType => type;
-  @override
-  String get message => '{0} has inferred type {1}';
-  DartType get type => _type;
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-/// An inferred type for a closure expression.
-class InferredTypeClosure extends InferredTypeBase {
-  InferredTypeClosure(TypeSystem rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-
-  @override
-  String get name => 'STRONG_MODE_INFERRED_TYPE_CLOSURE';
-}
-
-/// An inferred type for a literal expression.
-class InferredTypeLiteral extends InferredTypeBase {
-  InferredTypeLiteral(TypeSystem rules, Expression expression, DartType type)
-      : super._internal(rules, expression, type);
-
-  @override
-  String get name => 'STRONG_MODE_INFERRED_TYPE_LITERAL';
-}
-
-class InvalidFieldOverride extends InvalidOverride {
-  InvalidFieldOverride(AstNode node, ExecutableElement element,
-      InterfaceType base, DartType subType, DartType baseType)
-      : super(node, element, base, subType, baseType);
-
-  String get message => 'Field declaration {3}.{1} cannot be '
-      'overridden in {0}.';
-
-  @override
-  String get name => 'STRONG_MODE_INVALID_FIELD_OVERRIDE';
-}
-
-/// 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');
-
-  @override
-  String get name => 'STRONG_MODE_INVALID_METHOD_OVERRIDE';
-}
-
-/// 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);
-
-  @override
-  List<Object> get arguments =>
-      [parent.name, element.name, subType, base, baseType];
-
-  ClassElement get parent => element.enclosingElement;
-
-  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}).';
-  }
-}
-
-class InvalidParameterDeclaration extends StaticError {
-  final DartType expectedType;
-
-  InvalidParameterDeclaration(
-      TypeSystem 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}';
-  @override
-  String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION';
-}
-
-/// 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:
-/// <https://goo.gl/EY6hDP>
-///
-/// 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 https://goo.gl/EY6hDP): {0}";
-
-  @override
-  String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION';
-}
-
-class InvalidVariableDeclaration extends StaticError {
-  final DartType expectedType;
-
-  InvalidVariableDeclaration(
-      TypeSystem 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}';
-
-  @override
-  String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION';
-}
-
-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";
-
-  @override
-  String get name => 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO';
-
-  toErrorCode() => new HintCode(name, message);
-}
-
-abstract class StaticError extends StaticInfo {
-  final AstNode node;
-
-  StaticError(this.node);
-
-  String get message;
-
-  toErrorCode() => new CompileTimeErrorCode(name, message);
-}
-
-// 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 {
-  /// Strong-mode error code names.
-  ///
-  /// Used for error code configuration validation in an analysis options file.
-  static const List<String> names = const [
-    //
-    // Manually populated.
-    //
-    'STRONG_MODE_ASSIGNMENT_CAST',
-    'STRONG_MODE_DOWN_CAST_COMPOSITE',
-    'STRONG_MODE_DOWN_CAST_IMPLICIT',
-    'STRONG_MODE_DYNAMIC_CAST',
-    'STRONG_MODE_DYNAMIC_INVOKE',
-    'STRONG_MODE_INFERRED_TYPE',
-    'STRONG_MODE_INFERRED_TYPE_ALLOCATION',
-    'STRONG_MODE_INFERRED_TYPE_CLOSURE',
-    'STRONG_MODE_INFERRED_TYPE_LITERAL',
-    'STRONG_MODE_INVALID_FIELD_OVERRIDE',
-    'STRONG_MODE_INVALID_METHOD_OVERRIDE',
-    'STRONG_MODE_INVALID_PARAMETER_DECLARATION',
-    'STRONG_MODE_INVALID_SUPER_INVOCATION',
-    'STRONG_MODE_INVALID_VARIABLE_DECLARATION',
-    'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO',
-    'STRONG_MODE_STATIC_TYPE_ERROR',
-    'STRONG_MODE_UNINFERRED_CLOSURE',
-  ];
-
-  List<Object> get arguments => [node];
-
-  String get name;
-
-  /// AST Node this info is attached to.
-  AstNode get 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);
-  }
-
-  // TODO(jmesserly): review the usage of error codes. We probably want our own,
-  // as well as some DDC specific [ErrorType]s.
-  ErrorCode toErrorCode();
-
-  static bool isKnownFunction(Expression expression) {
-    Element element = null;
-    if (expression is FunctionExpression) {
-      return true;
-    } else if (expression is PropertyAccess) {
-      element = expression.propertyName.staticElement;
-    } else if (expression is Identifier) {
-      element = expression.staticElement;
-    }
-    // First class functions and static methods, where we know the original
-    // declaration, will have an exact type, so we know a downcast will fail.
-    return element is FunctionElement ||
-        element is MethodElement && element.isStatic;
-  }
-}
-
-class StaticTypeError extends StaticError {
-  final DartType baseType;
-  final DartType expectedType;
-
-  StaticTypeError(TypeSystem rules, Expression expression, this.expectedType)
-      : baseType = expression.staticType ?? DynamicTypeImpl.instance,
-        super(expression);
-
-  @override
-  List<Object> get arguments => [node, baseType, expectedType];
-  @override
-  String get message => 'Type check failed: {0} ({1}) is not of type {2}';
-
-  @override
-  String get name => 'STRONG_MODE_STATIC_TYPE_ERROR';
-}
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index dd1062f..4f64bc9 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -335,6 +335,8 @@
 //      }
     } on AnalysisException {
       rethrow;
+    } on ModificationTimeMismatchError {
+      rethrow;
     } catch (exception, stackTrace) {
       throw new AnalysisException(
           'Unexpected exception while performing $description',
@@ -423,6 +425,18 @@
 }
 
 /**
+ * Instances of this class are thrown when a task detects that the modification
+ * time of a cache entry is not the same as the actual modification time.  This
+ * means that any analysis results based on the content of the target cannot be
+ * used anymore and must be invalidated.
+ */
+class ModificationTimeMismatchError {
+  final Source source;
+
+  ModificationTimeMismatchError(this.source);
+}
+
+/**
  * A policy object that can compute sizes of results and provide the maximum
  * active and idle sizes that can be kept in the cache.
  *
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 4c65104..36d7e4c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.4-alpha.10
+version: 0.27.4-alpha.12
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -10,7 +10,7 @@
   crypto: '>=1.1.1 <3.0.0'
   glob: ^1.0.3
   html: ^0.12.0
-  package_config: ^0.1.1
+  package_config: ^0.1.5
   path: '>=0.9.0 <2.0.0'
   plugin: ^0.2.0
   watcher: '>=0.9.6 <0.10.0'
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index b40be43..a6adddd 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -48,6 +48,14 @@
 class FileTest {
   MemoryResourceProvider provider = new MemoryResourceProvider();
 
+  void test_delete() {
+    File file = provider.newFile('/foo/file.txt', 'content');
+    expect(file.exists, isTrue);
+    // delete
+    file.delete();
+    expect(file.exists, isFalse);
+  }
+
   void test_equals_beforeAndAfterCreate() {
     String path = '/file.txt';
     File file1 = provider.getResource(path);
@@ -241,6 +249,23 @@
     expect(folder.contains('/foo/bar'), isFalse);
   }
 
+  void test_delete() {
+    Folder folder = provider.newFolder('/foo');
+    Folder barFolder = provider.newFolder('/foo/bar');
+    File aFile = provider.newFile('/foo/bar/a.txt', '');
+    File bFile = provider.newFile('/foo/b.txt', '');
+    expect(folder.exists, isTrue);
+    expect(barFolder.exists, isTrue);
+    expect(aFile.exists, isTrue);
+    expect(bFile.exists, isTrue);
+    // delete 'folder'
+    folder.delete();
+    expect(folder.exists, isFalse);
+    expect(barFolder.exists, isFalse);
+    expect(aFile.exists, isFalse);
+    expect(bFile.exists, isFalse);
+  }
+
   void test_equal_false() {
     String path2 = '/foo/baz';
     Folder folder2 = provider.newFolder(path2);
@@ -272,6 +297,26 @@
     expect(child.exists, isTrue);
   }
 
+  void test_getChildAssumingFile_doesNotExist() {
+    File child = folder.getChildAssumingFile('name');
+    expect(child, isNotNull);
+    expect(child.exists, isFalse);
+  }
+
+  void test_getChildAssumingFile_file() {
+    provider.newFile('/foo/bar/name', 'content');
+    File child = folder.getChildAssumingFile('name');
+    expect(child, isNotNull);
+    expect(child.exists, isTrue);
+  }
+
+  void test_getChildAssumingFile_folder() {
+    provider.newFolder('/foo/bar/name');
+    File child = folder.getChildAssumingFile('name');
+    expect(child, isNotNull);
+    expect(child.exists, isFalse);
+  }
+
   void test_getChildAssumingFolder_doesNotExist() {
     Folder child = folder.getChildAssumingFolder('foldername');
     expect(child, isNotNull);
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 5bf3256..790eff7 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -50,6 +50,14 @@
     expect(source.contents.data, 'contents');
   }
 
+  void test_delete() {
+    new io.File(path).writeAsStringSync('contents');
+    expect(file.exists, isTrue);
+    // delete
+    file.delete();
+    expect(file.exists, isFalse);
+  }
+
   void test_equals_differentPaths() {
     String path2 = join(tempPath, 'file2.txt');
     File file2 = PhysicalResourceProvider.INSTANCE.getResource(path2);
@@ -222,6 +230,16 @@
     expect(folder.contains(path), isFalse);
   }
 
+  void test_delete() {
+    new io.File(join(path, 'myFile')).createSync();
+    var child = folder.getChild('myFile');
+    expect(child, _isFile);
+    expect(child.exists, isTrue);
+    // delete "folder"
+    folder.delete();
+    expect(child.exists, isFalse);
+  }
+
   void test_equals_differentPaths() {
     String path2 = join(tempPath, 'folder2');
     new io.Directory(path2).createSync();
@@ -254,6 +272,26 @@
     expect(child.exists, isTrue);
   }
 
+  void test_getChildAssumingFile_doesNotExist() {
+    File child = folder.getChildAssumingFile('no-such-resource');
+    expect(child, isNotNull);
+    expect(child.exists, isFalse);
+  }
+
+  void test_getChildAssumingFile_file() {
+    new io.File(join(path, 'myFile')).createSync();
+    File child = folder.getChildAssumingFile('myFile');
+    expect(child, isNotNull);
+    expect(child.exists, isTrue);
+  }
+
+  void test_getChildAssumingFile_folder() {
+    new io.Directory(join(path, 'myFolder')).createSync();
+    File child = folder.getChildAssumingFile('myFolder');
+    expect(child, isNotNull);
+    expect(child.exists, isFalse);
+  }
+
   void test_getChildAssumingFolder_doesNotExist() {
     Folder child = folder.getChildAssumingFolder('no-such-resource');
     expect(child, isNotNull);
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index fcf09de..ba1ba00 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -3479,14 +3479,14 @@
     expect(new ExitDetector(), isNotNull);
   }
 
-  void test_doStatement_throwCondition() {
-    _assertTrue("{ do {} while (throw ''); }");
-  }
-
   void test_doStatement_return() {
     _assertTrue("{ do { return null; } while (1 == 2); }");
   }
 
+  void test_doStatement_throwCondition() {
+    _assertTrue("{ do {} while (throw ''); }");
+  }
+
   void test_doStatement_true_break() {
     _assertFalse("{ do { break; } while (true); }");
   }
@@ -3779,16 +3779,85 @@
     _assertFalse("try {} catch (e, s) {} finally {}");
   }
 
+  void test_tryStatement_noReturn_noFinally() {
+    _assertFalse("try {} catch (e, s) {}");
+  }
+
   void test_tryStatement_return_catch() {
     _assertFalse("try {} catch (e, s) { return 1; } finally {}");
   }
 
+  void test_tryStatement_return_catch_noFinally() {
+    _assertFalse("try {} catch (e, s) { return 1; }");
+  }
+
   void test_tryStatement_return_finally() {
     _assertTrue("try {} catch (e, s) {} finally { return 1; }");
   }
 
-  void test_tryStatement_return_try() {
-    _assertTrue("try { return 1; } catch (e, s) {} finally {}");
+  void test_tryStatement_return_try_noCatch() {
+    _assertTrue("try { return 1; } finally {}");
+  }
+
+  void test_tryStatement_return_try_oneCatchDoesNotExit() {
+    _assertFalse("try { return 1; } catch (e, s) {} finally {}");
+  }
+
+  void test_tryStatement_return_try_oneCatchDoesNotExit_noFinally() {
+    _assertFalse("try { return 1; } catch (e, s) {}");
+  }
+
+  void test_tryStatement_return_try_oneCatchExits() {
+    _assertTrue("try { return 1; } catch (e, s) { return 1; } finally {}");
+  }
+
+  void test_tryStatement_return_try_oneCatchExits_noFinally() {
+    _assertTrue("try { return 1; } catch (e, s) { return 1; }");
+  }
+
+  void test_tryStatement_return_try_twoCatchesDoExit() {
+    _assertTrue('''
+try { return 1; }
+on int catch (e, s) { return 1; }
+on String catch (e, s) { return 1; }
+finally {}''');
+  }
+
+  void test_tryStatement_return_try_twoCatchesDoExit_noFinally() {
+    _assertTrue('''
+try { return 1; }
+on int catch (e, s) { return 1; }
+on String catch (e, s) { return 1; }''');
+  }
+
+  void test_tryStatement_return_try_twoCatchesDoNotExit() {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) {}
+finally {}''');
+  }
+
+  void test_tryStatement_return_try_twoCatchesDoNotExit_noFinally() {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) {}''');
+  }
+
+  void test_tryStatement_return_try_twoCatchesMixed() {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) { return 1; }
+finally {}''');
+  }
+
+  void test_tryStatement_return_try_twoCatchesMixed_noFinally() {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) { return 1; }''');
   }
 
   void test_variableDeclarationStatement_noInitializer() {
@@ -3964,6 +4033,20 @@
     _assertNthStatementDoesNotExit(source, 0);
   }
 
+  void test_whileStatement_switchWithBreakWithLabel() {
+    Source source = addSource(r'''
+void f() {
+  x: while (true) {
+    switch (true) {
+      case false: break;
+      case true: break x;
+    }
+  }
+}
+''');
+    _assertNthStatementDoesNotExit(source, 0);
+  }
+
   void test_whileStatement_breakWithLabel_afterExting() {
     Source source = addSource(r'''
 void f() {
@@ -3987,15 +4070,6 @@
     _assertNthStatementDoesNotExit(source, 0);
   }
 
-  void test_yieldStatement_throw() {
-    Source source = addSource(r'''
-void f() sync* {
-  yield throw '';
-}
-''');
-    _assertNthStatementExits(source, 0);
-  }
-
   void test_yieldStatement_star_plain() {
     Source source = addSource(r'''
 void f() sync* {
@@ -4014,6 +4088,15 @@
     _assertNthStatementExits(source, 0);
   }
 
+  void test_yieldStatement_throw() {
+    Source source = addSource(r'''
+void f() sync* {
+  yield throw '';
+}
+''');
+    _assertNthStatementExits(source, 0);
+  }
+
   void _assertHasReturn(bool expectedResult, Source source, int n) {
     LibraryElement element = resolve2(source);
     CompilationUnit unit = resolveCompilationUnit(source, element);
@@ -4025,14 +4108,14 @@
 
   // Assert that the [n]th statement in the last function declaration of
   // [source] exits.
-  void _assertNthStatementExits(Source source, int n) {
-    _assertHasReturn(true, source, n);
+  void _assertNthStatementDoesNotExit(Source source, int n) {
+    _assertHasReturn(false, source, n);
   }
 
   // Assert that the [n]th statement in the last function declaration of
   // [source] does not exit.
-  void _assertNthStatementDoesNotExit(Source source, int n) {
-    _assertHasReturn(false, source, n);
+  void _assertNthStatementExits(Source source, int n) {
+    _assertHasReturn(true, source, n);
   }
 }
 
diff --git a/pkg/analyzer/test/generated/error_suppression_test.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
index 275e94c..edcfaf2 100644
--- a/pkg/analyzer/test/generated/error_suppression_test.dart
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -82,6 +82,14 @@
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
   }
 
+  void test_ignore_upper_case() {
+    Source source = addSource('''
+int x = ''; // ignore: INVALID_ASSIGNMENT
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
   void test_invalid_error_code() {
     Source source = addSource('''
 // ignore: right_format_wrong_code
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 77b127f..bd01388 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -473,6 +473,49 @@
     verify([source]);
   }
 
+  void test_deadCode_deadFinalReturnInCase() {
+    Source source = addSource(r'''
+f() {
+  switch (true) {
+  case true:
+    try {
+      int a = 1;
+    } finally {
+      return;
+    }
+    return;
+  default:
+    break;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.DEAD_CODE]);
+    verify([source]);
+  }
+
+  void test_deadCode_deadFinalStatementInCase() {
+    Source source = addSource(r'''
+f() {
+  switch (true) {
+  case true:
+    try {
+      int a = 1;
+    } finally {
+      return;
+    }
+    int b = 1;
+  default:
+    break;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    // A single dead statement at the end of a switch case that is not a
+    // terminating statement will yield two errors.
+    assertErrors(source,
+        [HintCode.DEAD_CODE, StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
+    verify([source]);
+  }
+
   void test_deadCode_statementAfterBreak_inWhileStatement() {
     Source source = addSource(r'''
 f(v) {
@@ -1830,6 +1873,37 @@
     verify([source]);
   }
 
+  void test_required_constructor_param_redirecting_cons_call() {
+    Source source = addSource(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  C({@required int x});
+  C.named() : this();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM]);
+    verify([source]);
+  }
+
+  void test_required_constructor_param_super_call() {
+    Source source = addSource(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  C({@Required('must specify an `a`') int a}) {}
+}
+
+class D extends C {
+  D() : super();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
+    verify([source]);
+  }
+
   void test_required_function_param() {
     Source source = addSource(r'''
 import 'package:meta/meta.dart';
@@ -1883,6 +1957,23 @@
     verify([source]);
   }
 
+  void test_required_typedef_function_param() {
+    Source source = addSource(r'''
+import 'package:meta/meta.dart';
+
+String test(C c) => c.m()();
+
+typedef String F({@required String x});
+
+class C {
+  F m() => ({@required String x}) => null;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.MISSING_REQUIRED_PARAM]);
+    verify([source]);
+  }
+
   void test_typeCheck_type_is_Null() {
     Source source = addSource(r'''
 m(i) {
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 226f5e5..13abb03 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -18,6 +18,25 @@
 
 @reflectiveTest
 class NonHintCodeTest extends ResolverTestCase {
+  void test_deadCode_afterTryCatch() {
+    Source source = addSource('''
+main() {
+  try {
+    return f();
+  } catch (e) {
+    print(e);
+  }
+  print('not dead');
+}
+f() {
+  throw 'foo';
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_deadCode_deadBlock_conditionalElse_debugConst() {
     Source source = addSource(r'''
 const bool DEBUG = true;
@@ -171,6 +190,26 @@
     verify([source]);
   }
 
+  void test_deadCode_deadFinalBreakInCase() {
+    Source source = addSource(r'''
+f() {
+  switch (true) {
+  case true:
+    try {
+      int a = 1;
+    } finally {
+      return;
+    }
+    break;
+  default:
+    break;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_deprecatedMemberUse_inDeprecatedClass() {
     Source source = addSource(r'''
 @deprecated
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 11eee0b..e3756ac 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -42,6 +42,7 @@
   runReflectiveTests(ErrorResolverTest);
   runReflectiveTests(LibraryImportScopeTest);
   runReflectiveTests(LibraryScopeTest);
+  runReflectiveTests(PrefixedNamespaceTest);
   runReflectiveTests(ScopeTest);
   runReflectiveTests(StrictModeTest);
   runReflectiveTests(SubtypeManagerTest);
@@ -535,6 +536,35 @@
   }
 }
 
+@reflectiveTest
+class PrefixedNamespaceTest extends ResolverTestCase {
+  void test_lookup_missing() {
+    ClassElement element = ElementFactory.classElement2('A');
+    PrefixedNamespace namespace = new PrefixedNamespace('p', _toMap([element]));
+    expect(namespace.get('p.B'), isNull);
+  }
+
+  void test_lookup_missing_matchesPrefix() {
+    ClassElement element = ElementFactory.classElement2('A');
+    PrefixedNamespace namespace = new PrefixedNamespace('p', _toMap([element]));
+    expect(namespace.get('p'), isNull);
+  }
+
+  void test_lookup_valid() {
+    ClassElement element = ElementFactory.classElement2('A');
+    PrefixedNamespace namespace = new PrefixedNamespace('p', _toMap([element]));
+    expect(namespace.get('p.A'), same(element));
+  }
+
+  HashMap<String, Element> _toMap(List<Element> elements) {
+    HashMap<String, Element> map = new HashMap<String, Element>();
+    for (Element element in elements) {
+      map[element.name] = element;
+    }
+    return map;
+  }
+}
+
 class Scope_EnclosedScopeTest_test_define_duplicate extends Scope {
   GatheringErrorListener listener;
 
@@ -2890,8 +2920,12 @@
         context, AstFactory.libraryIdentifier2(["dart.core"]));
     coreLibrary.definingCompilationUnit = coreUnit;
 
-    LibraryElementImpl mockAsyncLib =
-        (context as AnalysisContextImpl).createMockAsyncLib(coreLibrary);
+    Source asyncSource = new NonExistingSource(
+        'async.dart', Uri.parse('dart:async'), UriKind.DART_URI);
+    LibraryElementImpl mockAsyncLib = (context as AnalysisContextImpl)
+        .createMockAsyncLib(coreLibrary, asyncSource);
+    expect(mockAsyncLib.source, same(asyncSource));
+    expect(mockAsyncLib.definingCompilationUnit.source, same(asyncSource));
     expect(mockAsyncLib.publicNamespace, isNotNull);
 
     //
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index a8f9105..23fac6b 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -1078,6 +1078,29 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitListLiteral_unresolved() {
+    _analyzer = _createAnalyzer(strongMode: true);
+    // [a] // where 'a' is not resolved
+    Identifier identifier = AstFactory.identifier3('a');
+    Expression node = AstFactory.listLiteral([identifier]);
+    DartType resultType = _analyze(node);
+    expect(resultType, isNull);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitListLiteral_unresolved_multiple() {
+    _analyzer = _createAnalyzer(strongMode: true);
+    // [0, a, 1] // where 'a' is not resolved
+    Identifier identifier = AstFactory.identifier3('a');
+    Expression node = AstFactory
+        .listLiteral([_resolvedInteger(0), identifier, _resolvedInteger(1)]);
+    DartType resultType = _analyze(node);
+    _assertType2(
+        _typeProvider.listType.instantiate(<DartType>[_typeProvider.intType]),
+        resultType);
+    _listener.assertNoErrors();
+  }
+
   void test_visitMapLiteral_empty() {
     // {}
     Expression node = AstFactory.mapLiteral2();
@@ -1488,11 +1511,16 @@
 
   /**
    * Create the analyzer used by the tests.
-   *
-   * @return the analyzer to be used by the tests
    */
-  StaticTypeAnalyzer _createAnalyzer() {
-    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
+  StaticTypeAnalyzer _createAnalyzer({bool strongMode: false}) {
+    InternalAnalysisContext context;
+    if (strongMode) {
+      AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+      options.strongMode = true;
+      context = AnalysisContextFactory.contextWithCoreAndOptions(options);
+    } else {
+      context = AnalysisContextFactory.contextWithCore();
+    }
     FileBasedSource source =
         new FileBasedSource(FileUtilities2.createFile("/lib.dart"));
     CompilationUnitElementImpl definingCompilationUnit =
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 1168c8b..93da8f0 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -600,9 +600,7 @@
     return _name;
   }
 
-  Uri get uri {
-    throw new UnsupportedOperationException();
-  }
+  Uri get uri => new Uri.file(_name);
 
   UriKind get uriKind {
     throw new UnsupportedOperationException();
diff --git a/pkg/analyzer/test/reflective_tests.dart b/pkg/analyzer/test/reflective_tests.dart
index 4788776..9a8bb66 100644
--- a/pkg/analyzer/test/reflective_tests.dart
+++ b/pkg/analyzer/test/reflective_tests.dart
@@ -30,6 +30,11 @@
 const ReflectiveTest reflectiveTest = const ReflectiveTest();
 
 /**
+ * Test classes annotated with this annotation are run using [solo_group].
+ */
+const _SoloTest soloTest = const _SoloTest();
+
+/**
  * Is `true` the application is running in the checked mode.
  */
 final bool _isCheckedMode = () {
@@ -65,8 +70,7 @@
     throw new Exception('Class $name must have annotation "@reflectiveTest" '
         'in order to be run by runReflectiveTests.');
   }
-  String className = MirrorSystem.getName(classMirror.simpleName);
-  group(className, () {
+  void runMembers() {
     classMirror.instanceMembers
         .forEach((Symbol symbol, MethodMirror memberMirror) {
       // we need only methods
@@ -105,7 +109,13 @@
         });
       }
     });
-  });
+  }
+  String className = MirrorSystem.getName(classMirror.simpleName);
+  if (_hasAnnotationInstance(classMirror, soloTest)) {
+    solo_group(className, runMembers);
+  } else {
+    group(className, runMembers);
+  }
 }
 
 bool _hasAnnotationInstance(DeclarationMirror declaration, instance) =>
@@ -178,3 +188,11 @@
 class _FailingTest {
   const _FailingTest();
 }
+
+/**
+ * A marker annotation used to annotate a test class to run it using
+ * [solo_group].
+ */
+class _SoloTest {
+  const _SoloTest();
+}
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index 57ff94e..2726eef 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -52,6 +52,27 @@
     expect(cache, isNotNull);
   }
 
+  test_flush() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor resultA = new ResultDescriptor('A', null);
+    ResultDescriptor resultB = new ResultDescriptor('B', null);
+    CacheEntry entry = new CacheEntry(target);
+    cache.put(entry);
+    // put values
+    entry.setValue(resultA, 'a', TargetedResult.EMPTY_LIST);
+    entry.setValue(resultB, 'b', TargetedResult.EMPTY_LIST);
+    expect(cache.getState(target, resultA), CacheState.VALID);
+    expect(cache.getState(target, resultB), CacheState.VALID);
+    expect(cache.getValue(target, resultA), 'a');
+    expect(cache.getValue(target, resultB), 'b');
+    // flush A
+    cache.flush((target, result) => result == resultA);
+    expect(cache.getState(target, resultA), CacheState.FLUSHED);
+    expect(cache.getState(target, resultB), CacheState.VALID);
+    expect(cache.getValue(target, resultA), isNull);
+    expect(cache.getValue(target, resultB), 'b');
+  }
+
   void test_get() {
     AnalysisTarget target = new TestSource();
     expect(cache.get(target), isNull);
@@ -297,6 +318,27 @@
     expect(entry.exception, isNull);
   }
 
+  test_flush() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor resultA = new ResultDescriptor('A', null);
+    ResultDescriptor resultB = new ResultDescriptor('B', null);
+    CacheEntry entry = new CacheEntry(target);
+    cache.put(entry);
+    // put values
+    entry.setValue(resultA, 'a', TargetedResult.EMPTY_LIST);
+    entry.setValue(resultB, 'b', TargetedResult.EMPTY_LIST);
+    expect(entry.getState(resultA), CacheState.VALID);
+    expect(entry.getState(resultB), CacheState.VALID);
+    expect(entry.getValue(resultA), 'a');
+    expect(entry.getValue(resultB), 'b');
+    // flush A
+    entry.flush((target, result) => result == resultA);
+    expect(entry.getState(resultA), CacheState.FLUSHED);
+    expect(entry.getState(resultB), CacheState.VALID);
+    expect(entry.getValue(resultA), isNull);
+    expect(entry.getValue(resultB), 'b');
+  }
+
   test_getState() {
     AnalysisTarget target = new TestSource();
     ResultDescriptor result = new ResultDescriptor('test', null);
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index ea41470..c9c8c28 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -856,6 +856,57 @@
         isTrue);
   }
 
+  void test_flushResolvedUnit_updateFile_dontNotify() {
+    String oldCode = '';
+    String newCode = r'''
+import 'dart:async';
+''';
+    String path = '/test.dart';
+    Source source = resourceProvider.newFile(path, oldCode).createSource();
+    context.applyChanges(new ChangeSet()..addedSource(source));
+    context.resolveCompilationUnit2(source, source);
+    // Flush all results units.
+    context.analysisCache.flush((target, result) {
+      if (target.source == source) {
+        return RESOLVED_UNIT_RESULTS.contains(result);
+      }
+      return false;
+    });
+    // Update the file, but don't notify the context.
+    resourceProvider.updateFile(path, newCode);
+    // Driver must detect that the file was changed and recover.
+    CompilationUnit unit = context.resolveCompilationUnit2(source, source);
+    expect(unit, isNotNull);
+  }
+
+  void test_flushResolvedUnit_updateFile_dontNotify2() {
+    String oldCode = r'''
+main() {}
+''';
+    String newCode = r'''
+import 'dart:async';
+main() {}
+''';
+    String path = '/test.dart';
+    Source source = resourceProvider.newFile(path, oldCode).createSource();
+    context.applyChanges(new ChangeSet()..addedSource(source));
+    context.resolveCompilationUnit2(source, source);
+    // Flush all results units.
+    context.analysisCache.flush((target, result) {
+      if (target.source == source) {
+        if (target.source == source) {
+          return RESOLVED_UNIT_RESULTS.contains(result);
+        }
+      }
+      return false;
+    });
+    // Update the file, but don't notify the context.
+    resourceProvider.updateFile(path, newCode);
+    // Driver must detect that the file was changed and recover.
+    CompilationUnit unit = context.resolveCompilationUnit2(source, source);
+    expect(unit, isNotNull);
+  }
+
   void test_getAnalysisOptions() {
     expect(context.analysisOptions, isNotNull);
   }
@@ -1094,7 +1145,7 @@
     List<Source> sources = context.launchableClientLibrarySources;
     expect(sources, isEmpty);
     addSource(
-        "/a.dart",
+        '/a.dart',
         r'''
 import 'dart:html';
 ''');
@@ -1112,7 +1163,7 @@
     List<Source> sources = context.launchableClientLibrarySources;
     expect(sources, isEmpty);
     addSource(
-        "/a.dart",
+        '/a.dart',
         r'''
 export 'dart:html';
 ''');
@@ -1922,7 +1973,7 @@
 
   void test_performAnalysisTask_interruptBy_setContents() {
     Source sourceA = addSource(
-        "/a.dart",
+        '/a.dart',
         r'''
 library expectedToFindSemicolon
 ''');
@@ -1956,7 +2007,7 @@
     if (AnalysisEngine.instance.limitInvalidationInTaskModel) {
       expect(source.readCount, 7);
     } else {
-      expect(source.readCount, 5);
+      expect(source.readCount, 4);
     }
   }
 
@@ -2171,6 +2222,17 @@
         ["dart.core", "dart.async", "dart.math", "libA", "libB"]);
   }
 
+//  void test_resolveCompilationUnit_sourceChangeDuringResolution() {
+//    _context = new _AnalysisContext_sourceChangeDuringResolution();
+//    AnalysisContextFactory.initContextWithCore(_context);
+//    _sourceFactory = _context.sourceFactory;
+//    Source source = _addSource("/lib.dart", "library lib;");
+//    CompilationUnit compilationUnit =
+//        _context.resolveCompilationUnit2(source, source);
+//    expect(compilationUnit, isNotNull);
+//    expect(_context.getLineInfo(source), isNotNull);
+//  }
+
   void test_resolveCompilationUnit_library() {
     Source source = addSource("/lib.dart", "library lib;");
     LibraryElement library = context.computeLibraryElement(source);
@@ -2187,17 +2249,6 @@
     expect(compilationUnit, isNotNull);
   }
 
-//  void test_resolveCompilationUnit_sourceChangeDuringResolution() {
-//    _context = new _AnalysisContext_sourceChangeDuringResolution();
-//    AnalysisContextFactory.initContextWithCore(_context);
-//    _sourceFactory = _context.sourceFactory;
-//    Source source = _addSource("/lib.dart", "library lib;");
-//    CompilationUnit compilationUnit =
-//        _context.resolveCompilationUnit2(source, source);
-//    expect(compilationUnit, isNotNull);
-//    expect(_context.getLineInfo(source), isNotNull);
-//  }
-
   void test_setAnalysisOptions() {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.cacheSize = 42;
@@ -2438,16 +2489,24 @@
    * Perform analysis tasks up to 512 times and assert that it was enough.
    */
   void _analyzeAll_assertFinished([int maxIterations = 512]) {
+    bool finishedAnalyzing = false;
     for (int i = 0; i < maxIterations; i++) {
       List<ChangeNotice> notice = context.performAnalysisTask().changeNotices;
       if (notice == null) {
+        finishedAnalyzing = true;
         bool inconsistent = context.validateCacheConsistency();
         if (!inconsistent) {
           return;
         }
       }
     }
-    fail("performAnalysisTask failed to terminate after analyzing all sources");
+    if (finishedAnalyzing) {
+      fail(
+          "performAnalysisTask failed to finish analyzing all sources after $maxIterations iterations");
+    } else {
+      fail(
+          "performAnalysisTask failed to terminate after analyzing all sources");
+    }
   }
 
   void _assertNoExceptions() {
@@ -2533,6 +2592,11 @@
 }
 
 @reflectiveTest
+/**
+ * TODO(scheglov) After changes that affect only resolution in method bodies,
+ * it is theoretically possible to keep the same element model and resolve
+ * only corresponding method bodies.
+ */
 class LimitedInvalidateTest extends AbstractContextTest {
   @override
   void setUp() {
@@ -2550,145 +2614,17 @@
     super.tearDown();
   }
 
-  void test_noChange_thenChange() {
-    Source sourceA = addSource(
-        "/a.dart",
+  void test_sequence_class_give_take() {
+    Source a = addSource(
+        '/a.dart',
         r'''
-library lib_a;
-
-class A {
-  A();
-}
-class B {
-  B();
-}
-''');
-    Source sourceB = addSource(
-        "/b.dart",
-        r'''
-library lib_b;
-import 'a.dart';
-main() {
-  new A();
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceA).errors, hasLength(0));
-    expect(context.getErrors(sourceB).errors, hasLength(0));
-    var unitA = context.getResolvedCompilationUnit2(sourceA, sourceA);
-    var unitElementA = unitA.element;
-    var libraryElementA = unitElementA.library;
-    // Update a.dart, no declaration changes.
-    context.setContents(
-        sourceA,
-        r'''
-library lib_a;
-class A {
-  A();
-}
-class B {
-  B();
-}
-''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertValid(sourceB, LIBRARY_ELEMENT);
-    // The a.dart's unit and element are updated incrementally.
-    // They are the same instances as initially.
-    // So, all the references from other units are still valid.
-    {
-      LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA);
-      expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA));
-      expect(unitA.element, same(unitElementA));
-      expect(unitElementA.library, same(libraryElementA));
-    }
-    // Analyze.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceA).errors, hasLength(0));
-    expect(context.getErrors(sourceB).errors, hasLength(0));
-    // The a.dart's unit and element are the same.
-    {
-      LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA);
-      expect(analysisCache.getValue(target, RESOLVED_UNIT), same(unitA));
-      expect(unitA.element, same(unitElementA));
-      expect(unitElementA.library, same(libraryElementA));
-    }
-    // Add method to a.dart. This invalidates b.dart, so
-    // we know that the previous update did not damage dependencies.
-    context.setContents(
-        sourceA,
-        r'''
-library lib_a;
-class A {
-  A();
-  m() {}
-}
-class B {
-  B();
-}
-''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceB, LIBRARY_ELEMENT);
-    // The a.dart's unit and element are the same.
-    {
-      LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA);
-      expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA));
-      expect(unitA.element, same(unitElementA));
-      expect(unitElementA.library, same(libraryElementA));
-    }
-    // Analyze.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceA).errors, hasLength(0));
-    expect(context.getErrors(sourceB).errors, hasLength(0));
-  }
-
-  void test_unusedName() {
-    Source sourceA = addSource(
-        "/a.dart",
-        r'''
-library lib_a;
 class A {}
 class B {}
 class C {}
 ''');
-    Source sourceB = addSource(
-        "/b.dart",
+    Source b = addSource(
+        '/b.dart',
         r'''
-library lib_b;
-import 'a.dart';
-main() {
-  new A();
-  new C();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update A.
-    context.setContents(
-        sourceA,
-        r'''
-library lib_a;
-class A {}
-class B2 {}
-class C {}
-''');
-    // Only a.dart is invalidated.
-    // Because b.dart does not use B, so it is valid.
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertValid(sourceB, LIBRARY_ERRORS_READY);
-  }
-
-  void test_usedName_directUser() {
-    Source sourceA = addSource(
-        "/a.dart",
-        r'''
-library lib_a;
-class A {}
-class B {}
-class C {}
-''');
-    Source sourceB = addSource(
-        "/b.dart",
-        r'''
-library lib_b;
 import 'a.dart';
 main() {
   new A();
@@ -2696,50 +2632,290 @@
 }
 ''');
     _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceB).errors, hasLength(1));
-    // Update a.dart, invalidates b.dart because it references "C2".
+    expect(context.getErrors(b).errors, hasLength(1));
+    // Update a.dart: remove C, add C2.
+    //   b.dart is invalid, because it references C2.
     context.setContents(
-        sourceA,
+        a,
         r'''
-library lib_a;
 class A {}
 class B {}
 class C2 {}
 ''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceB, LIBRARY_ERRORS_READY);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertUnitInvalid(b, RESOLVED_UNIT);
     // Now b.dart is analyzed and the error is fixed.
     _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceB).errors, hasLength(0));
-    // Update a.dart, invalidates b.dart because it references "C".
+    expect(context.getErrors(b).errors, hasLength(0));
+    // Update a.dart: remove C2, add C.
+    //   b.dart is invalid, because it references C2.
     context.setContents(
-        sourceA,
+        a,
         r'''
-library lib_a;
 class A {}
 class B {}
 class C {}
 ''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceB, LIBRARY_ERRORS_READY);
-    _performPendingAnalysisTasks();
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
     // Now b.dart is analyzed and it again has the error.
-    expect(context.getErrors(sourceB).errors, hasLength(1));
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(1));
   }
 
-  void test_usedName_directUser_withIncremental() {
-    Source sourceA = addSource(
-        "/a.dart",
+  void test_sequence_noChange_thenChange() {
+    Source a = addSource(
+        '/a.dart',
         r'''
-library lib_a;
+class A {
+  A();
+}
+class B {
+  B();
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, hasLength(0));
+    expect(context.getErrors(b).errors, hasLength(0));
+    var unitA = context.getResolvedCompilationUnit2(a, a);
+    var unitElementA = unitA.element;
+    var libraryElementA = unitElementA.library;
+    // Update a.dart, no declaration changes.
+    context.setContents(
+        a,
+        r'''
+class A {
+  A();
+}
+class B {
+  B();
+}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValid(b, LIBRARY_ELEMENT);
+    // The a.dart's unit and element are updated incrementally.
+    // They are the same instances as initially.
+    // So, all the references from other units are still valid.
+    {
+      LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
+      expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA));
+      expect(unitA.element, same(unitElementA));
+      expect(unitElementA.library, same(libraryElementA));
+    }
+    // Analyze.
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, hasLength(0));
+    expect(context.getErrors(b).errors, hasLength(0));
+    // The a.dart's unit and element are the same.
+    {
+      LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
+      expect(analysisCache.getValue(target, RESOLVED_UNIT), same(unitA));
+      expect(unitA.element, same(unitElementA));
+      expect(unitElementA.library, same(libraryElementA));
+    }
+    // Add a new method to a.dart. This invalidates b.dart, so
+    // we know that the previous update did not damage dependencies.
+    context.setContents(
+        a,
+        r'''
+class A {
+  A();
+  m() {}
+}
+class B {
+  B();
+}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ELEMENT);
+    // The a.dart's unit and element are the same.
+    {
+      LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
+      expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA));
+      expect(unitA.element, same(unitElementA));
+      expect(unitElementA.library, same(libraryElementA));
+    }
+    // Analyze.
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, hasLength(0));
+    expect(context.getErrors(b).errors, hasLength(0));
+  }
+
+  void test_unusedName_class_add() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+class B {}
+class C {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+  new C();
+}
+''');
+    _performPendingAnalysisTasks();
+    // The class B is not referenced.
+    //   a.dart is invalid.
+    //   b.dart is valid.
+    context.setContents(
+        a,
+        r'''
+class A {}
+class B2 {}
+class C {}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertUnitValid(a, RESOLVED_UNIT1);
+    _assertUnitInvalid(a, RESOLVED_UNIT);
+    _assertValid(b, LIBRARY_ERRORS_READY);
+    _assertUnitValid(b, RESOLVED_UNIT);
+  }
+
+  void test_usedName_class_name_asHole_inBody() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+class B {}
+class C {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+  new C2();
+}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: remove C, add C2.
+    //   b.dart is invalid, because it references C2.
+    context.setContents(
+        a,
+        r'''
+class A {}
+class B {}
+class C2 {}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
+  }
+
+  void test_usedName_class_name_asSuper() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+class B extends A {}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: remove A, add A2.
+    //   b.dart is invalid, because it references A.
+    context.setContents(
+        a,
+        r'''
+class A2 {}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
+  }
+
+  void test_usedName_class_name_asTypeBound() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+class B<T extends A> {
+  T f;
+}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: remove A, add A2.
+    //   b.dart is invalid, because it references A.
+    context.setContents(
+        a,
+        r'''
+class A2 {}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
+  }
+
+  void test_usedName_class_name_inBody() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+class B {}
+class C {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+  new C();
+}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: remove C, add C2.
+    //   b.dart is invalid, because it references C.
+    context.setContents(
+        a,
+        r'''
+class A {}
+class B {}
+class C2 {}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
+  }
+
+  void test_usedName_classMethod_name_inBody() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
 class A {
   m() {}
 }
 ''');
-    Source sourceB = addSource(
-        "/b.dart",
+    Source b = addSource(
+        '/b.dart',
         r'''
-library lib_b;
 import 'a.dart';
 main() {
   A a = new A();
@@ -2747,80 +2923,111 @@
 }
 ''');
     _performPendingAnalysisTasks();
-    // Update A.
+    // Update a.dart: remove C.m, add C.m2.
+    //   b.dart is invalid, because it references c.m.
     context.setContents(
-        sourceA,
+        a,
         r'''
-library lib_a;
 class A {
   m2() {}
 }
 ''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceB, LIBRARY_ERRORS_READY);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
   }
 
-  void test_usedName_indirectUser() {
-    Source sourceA = addSource(
-        "/a.dart",
+  void test_usedName_indirect_classMethod_name_inBody() {
+    Source a = addSource(
+        '/a.dart',
         r'''
-library lib_a;
 class A {
   m() {}
 }
 ''');
-    Source sourceB = addSource(
-        "/b.dart",
+    Source b = addSource(
+        '/b.dart',
         r'''
-library lib_b;
 import 'a.dart';
 class B extends A {}
 ''');
-    Source sourceC = addSource(
-        "/c.dart",
+    Source c = addSource(
+        '/c.dart',
         r'''
-library lib_c;
 import 'b.dart';
-class C extends B {
-  main() {
-    m();
-  }
+main() {
+  B b = new B();
+  b.m();
 }
 ''');
-    // No errors, "A.m" exists.
     _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceC).errors, hasLength(0));
-    // Replace "A.m" with "A.m2", invalidate both b.dart and c.dart files.
+    // Update a.dart: remove C.m, add C.m2.
+    //   b.dart is invalid, because B extends A.
+    //   c.dart is invalid, because 'main' references B.
     context.setContents(
-        sourceA,
+        a,
         r'''
-library lib_a;
 class A {
   m2() {}
 }
 ''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceB, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceC, LIBRARY_ERRORS_READY);
-    // There is an error in c.dart, "A.m" does not exist.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceB).errors, hasLength(0));
-    expect(context.getErrors(sourceC).errors, hasLength(1));
-    // Restore "A.m", invalidate both b.dart and c.dart files.
-    context.setContents(
-        sourceA,
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalid(c, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
+    _assertInvalidUnits(c, RESOLVED_UNIT4);
+    _assertInvalidLibraryElements(c, LIBRARY_ELEMENT5);
+  }
+
+  void test_usedName_indirect_classMethod_returnType_inBody() {
+    Source a = addSource(
+        '/a.dart',
         r'''
-library lib_a;
 class A {
-  m() {}
+  int m() {
+    return 1;
+  }
 }
 ''');
-    _assertInvalid(sourceA, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceB, LIBRARY_ERRORS_READY);
-    _assertInvalid(sourceC, LIBRARY_ERRORS_READY);
-    // No errors, "A.m" exists.
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+class B extends A {}
+''');
+    Source c = addSource(
+        '/c.dart',
+        r'''
+import 'b.dart';
+main() {
+  B b = new B();
+  b.m();
+}
+''');
     _performPendingAnalysisTasks();
-    expect(context.getErrors(sourceC).errors, hasLength(0));
+    // Update a.dart: remove C.m, add C.m2.
+    //   b.dart is invalid, because B extends A.
+    //   c.dart is invalid, because 'main' references B.m.
+    context.setContents(
+        a,
+        r'''
+class A {
+  double m() {
+    return 1.2;
+  }
+}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalid(c, LIBRARY_ERRORS_READY);
+    // TODO(scheglov) In theory b.dart is not affected, because it does not
+    // call A.m, does not override it, etc.
+    _assertInvalidUnits(b, RESOLVED_UNIT2);
+    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT2);
+    _assertInvalidUnits(c, RESOLVED_UNIT4);
+    _assertInvalidLibraryElements(c, LIBRARY_ELEMENT5);
   }
 
   void _assertInvalid(AnalysisTarget target, ResultDescriptor descriptor) {
@@ -2830,9 +3037,49 @@
     }
   }
 
+  /**
+   * Assert that [LIBRARY_ELEMENT_RESULTS] for [first] and after it are invalid.
+   */
+  void _assertInvalidLibraryElements(
+      Source source, ResultDescriptor<LibraryElement> first) {
+    bool foundFirst = false;
+    for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) {
+      foundFirst = foundFirst || result == first;
+      if (foundFirst) {
+        _assertInvalid(source, result);
+      }
+    }
+  }
+
+  void _assertInvalidUnits(Source unit, ResultDescriptor<CompilationUnit> first,
+      {Source library}) {
+    var target = new LibrarySpecificUnit(library ?? unit, unit);
+    bool foundFirst = false;
+    for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) {
+      foundFirst = foundFirst || result == first;
+      if (foundFirst) {
+        _assertInvalid(target, result);
+      }
+    }
+  }
+
+  void _assertUnitInvalid(Source unitSource, ResultDescriptor descriptor,
+      {Source librarySource}) {
+    librarySource ??= unitSource;
+    _assertInvalid(
+        new LibrarySpecificUnit(librarySource, unitSource), descriptor);
+  }
+
+  void _assertUnitValid(Source unitSource, ResultDescriptor descriptor,
+      {Source librarySource}) {
+    librarySource ??= unitSource;
+    _assertValid(
+        new LibrarySpecificUnit(librarySource, unitSource), descriptor);
+  }
+
   void _assertValid(AnalysisTarget target, ResultDescriptor descriptor) {
     CacheState state = analysisCache.getState(target, descriptor);
-    expect(state, CacheState.VALID);
+    expect(state, CacheState.VALID, reason: '$descriptor in $target');
   }
 
   void _performPendingAnalysisTasks([int maxTasks = 512]) {
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 3de6bdf..a6e718d 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -4190,7 +4190,7 @@
   void test_matchesHandle_getter() {
     CompilationUnitElementImpl compilationUnitElement =
         ElementFactory.compilationUnit('foo.dart');
-    LibraryElementImpl libraryElement = ElementFactory.library(null, '')
+    ElementFactory.library(null, '')
       ..definingCompilationUnit = compilationUnitElement;
     PropertyAccessorElementImpl element =
         ElementFactory.getterElement('x', true, DynamicTypeImpl.instance);
@@ -4205,7 +4205,7 @@
   void test_matchesHandle_setter() {
     CompilationUnitElementImpl compilationUnitElement =
         ElementFactory.compilationUnit('foo.dart');
-    LibraryElementImpl libraryElement = ElementFactory.library(null, '')
+    ElementFactory.library(null, '')
       ..definingCompilationUnit = compilationUnitElement;
     PropertyAccessorElementImpl element =
         ElementFactory.setterElement('x', true, DynamicTypeImpl.instance);
diff --git a/pkg/analyzer/test/src/summary/incremental_cache_test.dart b/pkg/analyzer/test/src/summary/incremental_cache_test.dart
index 695cb51..19a6197 100644
--- a/pkg/analyzer/test/src/summary/incremental_cache_test.dart
+++ b/pkg/analyzer/test/src/summary/incremental_cache_test.dart
@@ -14,9 +14,57 @@
 
 main() {
   groupSep = ' | ';
+  runReflectiveTests(ComparePathsTest);
   runReflectiveTests(IncrementalCacheTest);
 }
 
+@reflectiveTest
+class ComparePathsTest extends AbstractSingleUnitTest {
+  void test_empty() {
+    expect(comparePaths('', ''), 0);
+  }
+
+  void test_equal() {
+    expect(comparePaths('abc', 'abc'), 0);
+  }
+
+  void test_longer_suffixAfter() {
+    expect(comparePaths('aab', 'aa'), 1);
+  }
+
+  void test_longer_suffixBefore() {
+    expect(comparePaths('aaa', 'ab'), -1);
+  }
+
+  void test_longer_suffixSame() {
+    expect(comparePaths('aaa', 'aa'), 1);
+  }
+
+  void test_sameLength_before0() {
+    expect(comparePaths('aaa', 'bbb'), -1);
+  }
+
+  void test_sameLength_before1() {
+    expect(comparePaths('aaa', 'bba'), -1);
+  }
+
+  void test_sameLength_before2() {
+    expect(comparePaths('aaa', 'bba'), -1);
+  }
+
+  void test_shorter_suffixAfter() {
+    expect(comparePaths('ab', 'aaa'), 1);
+  }
+
+  void test_shorter_suffixBefore() {
+    expect(comparePaths('aa', 'aab'), -1);
+  }
+
+  void test_shorter_suffixSame() {
+    expect(comparePaths('aa', 'aaa'), -1);
+  }
+}
+
 /**
  * TODO(scheglov) write more tests for invalidation.
  */
@@ -235,6 +283,9 @@
   final Map<String, List<int>> map = <String, List<int>>{};
 
   @override
+  void compact() {}
+
+  @override
   List<int> get(String key) {
     return map[key];
   }
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index f71c6ff..89cbfbc 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -21,7 +21,7 @@
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/html.dart';
-import 'package:analyzer/src/task/strong/info.dart';
+import 'package:analyzer/src/task/strong/ast_properties.dart' as strong_ast;
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
@@ -68,6 +68,7 @@
   runReflectiveTests(PropagateVariableTypeTaskTest);
   runReflectiveTests(ResolveDirectiveElementsTaskTest);
   runReflectiveTests(ResolveInstanceFieldsInUnitTaskTest);
+  runReflectiveTests(ResolveLibraryReferencesTaskTest);
   runReflectiveTests(ResolveLibraryTaskTest);
   runReflectiveTests(ResolveLibraryTypeNamesTaskTest);
   runReflectiveTests(ResolveTopLevelUnitTypeBoundsTaskTest);
@@ -134,6 +135,8 @@
     new isInstanceOf<PropagateVariableTypeTask>();
 isInstanceOf isResolveDirectiveElementsTask =
     new isInstanceOf<ResolveDirectiveElementsTask>();
+isInstanceOf isResolveLibraryReferencesTask =
+    new isInstanceOf<ResolveLibraryReferencesTask>();
 isInstanceOf isResolveLibraryTask = new isInstanceOf<ResolveLibraryTask>();
 isInstanceOf isResolveLibraryTypeNamesTask =
     new isInstanceOf<ResolveLibraryTypeNamesTask>();
@@ -1573,6 +1576,7 @@
     AnalysisTarget lib1Target = new LibrarySpecificUnit(lib1Source, lib1Source);
     AnalysisTarget lib2Target = new LibrarySpecificUnit(lib2Source, lib2Source);
     AnalysisTarget lib3Target = new LibrarySpecificUnit(lib3Source, lib3Source);
+
     computeResult(lib1Target, LIBRARY_CYCLE);
     expect(outputs[LIBRARY_CYCLE], hasLength(1));
     computeResult(lib2Target, LIBRARY_CYCLE);
@@ -1580,13 +1584,17 @@
     computeResult(lib3Target, LIBRARY_CYCLE);
     expect(outputs[LIBRARY_CYCLE], hasLength(1));
 
-    // complete the cycle
+    // create a cycle
     context.setContents(
         lib1Source,
         '''
 library my_lib1;
 import 'my_lib3.dart';
 ''');
+    _expectInvalid(lib1Target);
+    _expectInvalid(lib2Target);
+    _expectInvalid(lib3Target);
+
     computeResult(lib1Target, LIBRARY_CYCLE);
     expect(outputs[LIBRARY_CYCLE], hasLength(3));
     computeResult(lib2Target, LIBRARY_CYCLE);
@@ -1600,6 +1608,10 @@
         '''
 library my_lib1;
 ''');
+    _expectInvalid(lib1Target);
+    _expectInvalid(lib2Target);
+    _expectInvalid(lib3Target);
+
     computeResult(lib1Target, LIBRARY_CYCLE);
     expect(outputs[LIBRARY_CYCLE], hasLength(1));
     computeResult(lib2Target, LIBRARY_CYCLE);
@@ -1630,6 +1642,7 @@
     AnalysisTarget lib1Target = new LibrarySpecificUnit(lib1Source, lib1Source);
     AnalysisTarget lib2Target = new LibrarySpecificUnit(lib2Source, lib2Source);
     AnalysisTarget lib3Target = new LibrarySpecificUnit(lib3Source, lib3Source);
+
     computeResult(lib1Target, LIBRARY_CYCLE);
     expect(outputs[LIBRARY_CYCLE], hasLength(1));
     computeResult(lib2Target, LIBRARY_CYCLE);
@@ -1644,6 +1657,10 @@
 library my_lib1;
 import 'my_lib3.dart';
 ''');
+    _expectInvalid(lib1Target);
+    _expectInvalid(lib2Target);
+    _expectInvalid(lib3Target);
+
     // Ensure that invalidation correctly invalidated everything reachable
     // through lib3
     computeResult(lib1Target, LIBRARY_CYCLE);
@@ -1763,6 +1780,9 @@
 import 'my_lib3.dart';
 var foo = 123;
 ''');
+    _expectInvalid(lib1Target);
+    _expectInvalid(lib2Target);
+    _expectInvalid(lib3Target);
 
     computeResult(lib1Target, RESOLVED_UNIT);
     computeResult(lib2Target, RESOLVED_UNIT);
@@ -1999,6 +2019,11 @@
     expect(dep6, hasLength(5)); // dart:core, a.dart, aa.dart, ab.dart, b.dart
     expect(dep7, hasLength(5)); // dart:core, a.dart, aa.dart, ab.dart, b.dart
   }
+
+  void _expectInvalid(LibrarySpecificUnit target) {
+    CacheEntry entry = context.getCacheEntry(target);
+    expect(entry.getState(LIBRARY_CYCLE), CacheState.INVALID);
+  }
 }
 
 @reflectiveTest
@@ -3974,6 +3999,308 @@
 }
 
 @reflectiveTest
+class ResolveLibraryReferencesTaskTest extends _AbstractDartTaskTest {
+  void setUp() {
+    super.setUp();
+    context.analysisOptions = new AnalysisOptionsImpl()
+      ..enableGenericMethods = true
+      ..strongMode = true;
+  }
+
+  test_referencedNames_class_constructor() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  U.named(A a, B b) {
+    C c = null;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_class_field() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  A f = new B();
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_class_getter() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  A get a => new B();
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_class_members() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  int a;
+  int get b;
+  set c(_) {}
+  m(D d) {
+    a;
+    b;
+    c = 1;
+    m();
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['int', 'D']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['int', 'D']));
+  }
+
+  test_referencedNames_class_members_dontHideQualified() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  int a;
+  int get b;
+  set c(_) {}
+  m(D d) {
+    d.a;
+    d.b;
+    d.c;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['int', 'D', 'a', 'b', 'c']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['int', 'D']));
+  }
+
+  test_referencedNames_class_method() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  A m(B p) {
+    C v = 0;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_class_method_localVariables() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  A m() {
+    B b = null;
+    b;
+    {
+      C c = null;
+      b;
+      c;
+    }
+    d;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C', 'd']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_class_method_parameters() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  m(A a) {
+    a;
+    b;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'b']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_class_method_typeParameters() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  A m<T>(B b, T t) {
+    C c = 0;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_class_setter() {
+    ReferencedNames info = _computeReferencedNames('''
+class U {
+  set a(A a) {
+    B b = null;
+  }
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_class_typeParameters() {
+    ReferencedNames info = _computeReferencedNames('''
+class U<T> {
+  T f = new A<T>();
+}
+''');
+    expect(info.names, unorderedEquals(['A']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_localFunction() {
+    ReferencedNames info = _computeReferencedNames('''
+f(A a) {
+  g(B b) {}
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_unit_function() {
+    ReferencedNames info = _computeReferencedNames('''
+A f(B b) {
+  C c = 0;
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_unit_function_localFunctions() {
+    ReferencedNames info = _computeReferencedNames('''
+A f() {
+  B b = null;
+  C g() {}
+  g();
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_unit_function_localsDontHideQualified() {
+    ReferencedNames info = _computeReferencedNames('''
+f(A a, B b) {
+  var v = 0;
+  a.v;
+  a.b;
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'v', 'b']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_unit_function_localVariables() {
+    ReferencedNames info = _computeReferencedNames('''
+A f() {
+  B b = null;
+  b;
+  {
+    C c = null;
+    b;
+    c;
+  }
+  d;
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C', 'd']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_unit_function_parameters() {
+    ReferencedNames info = _computeReferencedNames('''
+A f(B b) {
+  C c = 0;
+  b;
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_unit_function_typeParameters() {
+    ReferencedNames info = _computeReferencedNames('''
+A f<T>(B b, T t) {
+  C c = 0;
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
+    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_unit_functionTypeAlias() {
+    ReferencedNames info = _computeReferencedNames('''
+typedef A F(B B, C c(D d));
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C', 'D']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['F']));
+    expect(info.userToDependsOn['F'], unorderedEquals(['A', 'B', 'C', 'D']));
+  }
+
+  test_referencedNames_unit_functionTypeAlias_typeParameters() {
+    ReferencedNames info = _computeReferencedNames('''
+typedef A F<T>(B b, T t);
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['F']));
+    expect(info.userToDependsOn['F'], unorderedEquals(['A', 'B']));
+  }
+
+  test_referencedNames_unit_getter() {
+    ReferencedNames info = _computeReferencedNames('''
+A get aaa {
+  return new B();
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['aaa']));
+    expect(info.userToDependsOn['aaa'], unorderedEquals(['A']));
+  }
+
+  test_referencedNames_unit_setter() {
+    ReferencedNames info = _computeReferencedNames('''
+set aaa(A a) {
+  B b = null;
+}
+''');
+    expect(info.names, unorderedEquals(['A', 'B']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['aaa']));
+    expect(info.userToDependsOn['aaa'], unorderedEquals(['A']));
+  }
+
+  ReferencedNames _computeReferencedNames(String code) {
+    Source source = newSource('/test.dart', code);
+    computeResult(source, REFERENCED_NAMES,
+        matcher: isResolveLibraryReferencesTask);
+    return outputs[REFERENCED_NAMES];
+  }
+}
+
+@reflectiveTest
 class ResolveLibraryTaskTest extends _AbstractDartTaskTest {
   test_perform() {
     Source sourceLib = newSource(
@@ -5068,9 +5395,7 @@
         AstFinder.getStatementsInTopLevelFunction(unit, "main");
     ExpressionStatement statement = statements[1];
     IndexExpression idx = statement.expression;
-    expect(DynamicInvoke.get(idx.target), isNotNull);
-    expect(DynamicInvoke.get(idx.target), isNotNull);
-    expect(DynamicInvoke.get(idx.target), isTrue);
+    expect(strong_ast.isDynamicInvoke(idx.target), isTrue);
   }
 
   void test_perform_verifyError() {
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index efbf9ee..39e513b 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -819,6 +819,9 @@
   AnalysisCache analysisCache;
 
   @override
+  final AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
+
+  @override
   List<AnalysisTarget> explicitTargets = <AnalysisTarget>[];
 
   @override
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 8a6376d..a86658c 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2,9 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// TODO(jmesserly): this file needs to be refactored, it's a port from
-// package:dev_compiler's tests
-/// General type checking tests
 library analyzer.test.src.task.strong.checker_test;
 
 import '../../../reflective_tests.dart';
@@ -22,7 +19,7 @@
 import 'dart:async';
 main() async {
   // Don't choke if sequence is not stream.
-  await for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {}
+  await for (var i in /*severe:FOR_IN_OF_INVALID_TYPE*/1234) {}
 
   // Dynamic cast.
   await for (String /*info:DYNAMIC_CAST*/s in new Stream<dynamic>()) {}
@@ -86,7 +83,7 @@
   a = a + b;
   a = a + /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a;
   a = a - b;
-  b = /*warning:INVALID_ASSIGNMENT*/b - b;
+  b = /*severe:INVALID_ASSIGNMENT*/b - b;
   a = a << b;
   a = a >> b;
   a = a & b;
@@ -105,7 +102,7 @@
   p = p && /*info:DYNAMIC_CAST*/c;
   p = (/*info:DYNAMIC_CAST*/c) && p;
   p = (/*info:DYNAMIC_CAST*/c) && /*info:DYNAMIC_CAST*/c;
-  p = /*warning:NON_BOOL_OPERAND*/y && p;
+  p = /*severe:NON_BOOL_OPERAND*/y && p;
   p = c == y;
 
   a = a[b];
@@ -299,7 +296,7 @@
   a += b;
   a += /*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/a;
   a -= b;
-  /*severe:STATIC_TYPE_ERROR*/b -= /*warning:INVALID_ASSIGNMENT*/b;
+  /*severe:STATIC_TYPE_ERROR*/b -= /*severe:INVALID_ASSIGNMENT*/b;
   a <<= b;
   a >>= b;
   a &= b;
@@ -352,6 +349,16 @@
 ''');
   }
 
+  void test_constructorInvalid() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/26695
+    checkFile('''
+class A {
+  B({ /*severe:FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR*/this.test: 1.0 }) {}
+  final double test = 0.0;
+}
+''');
+  }
+
   void test_conversionAndDynamicInvoke() {
     addFile(
         '''
@@ -447,8 +454,8 @@
     int x;
     double y;
     x = f(3);
-    x = /*warning:INVALID_ASSIGNMENT*/f.col(3.0);
-    y = /*warning:INVALID_ASSIGNMENT*/f(3);
+    x = /*severe:INVALID_ASSIGNMENT*/f.col(3.0);
+    y = /*severe:INVALID_ASSIGNMENT*/f(3);
     y = f.col(3.0);
     f(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3.0);
     f.col(/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3);
@@ -483,7 +490,7 @@
     A f = new B();
     /*info:DYNAMIC_INVOKE*/f.col(42.0);
     /*info:DYNAMIC_INVOKE*/f.foo(42.0);
-    /*info:DYNAMIC_INVOKE*/f./*warning:UNDEFINED_GETTER*/x;
+    /*info:DYNAMIC_INVOKE*/f./*severe:UNDEFINED_GETTER*/x;
   }
 }
 ''');
@@ -630,7 +637,7 @@
     checkFile('''
 main() {
   // Don't choke if sequence is not iterable.
-  for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {}
+  for (var i in /*severe:FOR_IN_OF_INVALID_TYPE*/1234) {}
 
   // Dynamic cast.
   for (String /*info:DYNAMIC_CAST*/s in <dynamic>[]) {}
@@ -663,7 +670,7 @@
     checkFile('''
 foo() {
   for (int i = 0; i < 10; i++) {
-    i = /*warning:INVALID_ASSIGNMENT*/"hi";
+    i = /*severe:INVALID_ASSIGNMENT*/"hi";
   }
 }
 bar() {
@@ -686,14 +693,14 @@
 Future<int> foo3() async => /*info:DYNAMIC_CAST*/x;
 Future<int> foo4() async => new Future<int>.value(/*info:DYNAMIC_CAST*/x);
 Future<int> foo5() async =>
-    /*warning:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CAST*/x);
+    /*severe:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CAST*/x);
 
 bar1() async { return x; }
 Future bar2() async { return x; }
 Future<int> bar3() async { return /*info:DYNAMIC_CAST*/x; }
 Future<int> bar4() async { return new Future<int>.value(/*info:DYNAMIC_CAST*/x); }
 Future<int> bar5() async {
-  return /*warning:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CAST*/x);
+  return /*severe:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CAST*/x);
 }
 
 int y;
@@ -703,7 +710,7 @@
   int a = /*info:DYNAMIC_CAST*/await x;
   int b = await y;
   int c = await z;
-  String d = /*warning:INVALID_ASSIGNMENT*/await z;
+  String d = /*severe:INVALID_ASSIGNMENT*/await z;
 }
 
 Future<bool> get issue_264 async {
@@ -726,7 +733,7 @@
 bar1() async* { yield x; }
 Stream bar2() async* { yield x; }
 Stream<int> bar3() async* { yield /*info:DYNAMIC_CAST*/x; }
-Stream<int> bar4() async* { yield /*warning:YIELD_OF_INVALID_TYPE*/new Stream<int>(); }
+Stream<int> bar4() async* { yield /*severe:YIELD_OF_INVALID_TYPE*/new Stream<int>(); }
 
 baz1() async* { yield* /*info:DYNAMIC_CAST*/x; }
 Stream baz2() async* { yield* /*info:DYNAMIC_CAST*/x; }
@@ -743,7 +750,7 @@
 bar1() sync* { yield x; }
 Iterable bar2() sync* { yield x; }
 Iterable<int> bar3() sync* { yield /*info:DYNAMIC_CAST*/x; }
-Iterable<int> bar4() sync* { yield /*warning:YIELD_OF_INVALID_TYPE*/bar3(); }
+Iterable<int> bar4() sync* { yield /*severe:YIELD_OF_INVALID_TYPE*/bar3(); }
 
 baz1() sync* { yield* /*info:DYNAMIC_CAST*/x; }
 Iterable baz2() sync* { yield* /*info:DYNAMIC_CAST*/x; }
@@ -1502,91 +1509,91 @@
 
    r = r;
    r = o;
-   r = /*warning:INVALID_ASSIGNMENT*/n;
-   r = /*warning:INVALID_ASSIGNMENT*/rr;
+   r = /*severe:INVALID_ASSIGNMENT*/n;
+   r = /*severe:INVALID_ASSIGNMENT*/rr;
    r = ro;
    r = rn;
    r = oo;
-   r = /*warning:INVALID_ASSIGNMENT*/nn;
-   r = /*warning:INVALID_ASSIGNMENT*/nnn;
+   r = /*severe:INVALID_ASSIGNMENT*/nn;
+   r = /*severe:INVALID_ASSIGNMENT*/nnn;
 
    o = /*warning:DOWN_CAST_COMPOSITE*/r;
    o = o;
-   o = /*warning:INVALID_ASSIGNMENT*/n;
-   o = /*warning:INVALID_ASSIGNMENT*/rr;
-   o = /*warning:INVALID_ASSIGNMENT*/ro;
-   o = /*warning:INVALID_ASSIGNMENT*/rn;
+   o = /*severe:INVALID_ASSIGNMENT*/n;
+   o = /*severe:INVALID_ASSIGNMENT*/rr;
+   o = /*severe:INVALID_ASSIGNMENT*/ro;
+   o = /*severe:INVALID_ASSIGNMENT*/rn;
    o = oo;
-   o = /*warning:INVALID_ASSIGNMENT*/nn;
-   o = /*warning:INVALID_ASSIGNMENT*/nnn;
+   o = /*severe:INVALID_ASSIGNMENT*/nn;
+   o = /*severe:INVALID_ASSIGNMENT*/nnn;
 
-   n = /*warning:INVALID_ASSIGNMENT*/r;
-   n = /*warning:INVALID_ASSIGNMENT*/o;
+   n = /*severe:INVALID_ASSIGNMENT*/r;
+   n = /*severe:INVALID_ASSIGNMENT*/o;
    n = n;
-   n = /*warning:INVALID_ASSIGNMENT*/rr;
-   n = /*warning:INVALID_ASSIGNMENT*/ro;
-   n = /*warning:INVALID_ASSIGNMENT*/rn;
-   n = /*warning:INVALID_ASSIGNMENT*/oo;
+   n = /*severe:INVALID_ASSIGNMENT*/rr;
+   n = /*severe:INVALID_ASSIGNMENT*/ro;
+   n = /*severe:INVALID_ASSIGNMENT*/rn;
+   n = /*severe:INVALID_ASSIGNMENT*/oo;
    n = nn;
    n = nnn;
 
-   rr = /*warning:INVALID_ASSIGNMENT*/r;
-   rr = /*warning:INVALID_ASSIGNMENT*/o;
-   rr = /*warning:INVALID_ASSIGNMENT*/n;
+   rr = /*severe:INVALID_ASSIGNMENT*/r;
+   rr = /*severe:INVALID_ASSIGNMENT*/o;
+   rr = /*severe:INVALID_ASSIGNMENT*/n;
    rr = rr;
    rr = ro;
-   rr = /*warning:INVALID_ASSIGNMENT*/rn;
+   rr = /*severe:INVALID_ASSIGNMENT*/rn;
    rr = oo;
-   rr = /*warning:INVALID_ASSIGNMENT*/nn;
-   rr = /*warning:INVALID_ASSIGNMENT*/nnn;
+   rr = /*severe:INVALID_ASSIGNMENT*/nn;
+   rr = /*severe:INVALID_ASSIGNMENT*/nnn;
 
    ro = /*warning:DOWN_CAST_COMPOSITE*/r;
-   ro = /*warning:INVALID_ASSIGNMENT*/o;
-   ro = /*warning:INVALID_ASSIGNMENT*/n;
+   ro = /*severe:INVALID_ASSIGNMENT*/o;
+   ro = /*severe:INVALID_ASSIGNMENT*/n;
    ro = /*warning:DOWN_CAST_COMPOSITE*/rr;
    ro = ro;
-   ro = /*warning:INVALID_ASSIGNMENT*/rn;
+   ro = /*severe:INVALID_ASSIGNMENT*/rn;
    ro = oo;
-   ro = /*warning:INVALID_ASSIGNMENT*/nn;
-   ro = /*warning:INVALID_ASSIGNMENT*/nnn;
+   ro = /*severe:INVALID_ASSIGNMENT*/nn;
+   ro = /*severe:INVALID_ASSIGNMENT*/nnn;
 
    rn = /*warning:DOWN_CAST_COMPOSITE*/r;
-   rn = /*warning:INVALID_ASSIGNMENT*/o;
-   rn = /*warning:INVALID_ASSIGNMENT*/n;
-   rn = /*warning:INVALID_ASSIGNMENT*/rr;
-   rn = /*warning:INVALID_ASSIGNMENT*/ro;
+   rn = /*severe:INVALID_ASSIGNMENT*/o;
+   rn = /*severe:INVALID_ASSIGNMENT*/n;
+   rn = /*severe:INVALID_ASSIGNMENT*/rr;
+   rn = /*severe:INVALID_ASSIGNMENT*/ro;
    rn = rn;
-   rn = /*warning:INVALID_ASSIGNMENT*/oo;
-   rn = /*warning:INVALID_ASSIGNMENT*/nn;
-   rn = /*warning:INVALID_ASSIGNMENT*/nnn;
+   rn = /*severe:INVALID_ASSIGNMENT*/oo;
+   rn = /*severe:INVALID_ASSIGNMENT*/nn;
+   rn = /*severe:INVALID_ASSIGNMENT*/nnn;
 
    oo = /*warning:DOWN_CAST_COMPOSITE*/r;
    oo = /*warning:DOWN_CAST_COMPOSITE*/o;
-   oo = /*warning:INVALID_ASSIGNMENT*/n;
+   oo = /*severe:INVALID_ASSIGNMENT*/n;
    oo = /*warning:DOWN_CAST_COMPOSITE*/rr;
    oo = /*warning:DOWN_CAST_COMPOSITE*/ro;
-   oo = /*warning:INVALID_ASSIGNMENT*/rn;
+   oo = /*severe:INVALID_ASSIGNMENT*/rn;
    oo = oo;
-   oo = /*warning:INVALID_ASSIGNMENT*/nn;
-   oo = /*warning:INVALID_ASSIGNMENT*/nnn;
+   oo = /*severe:INVALID_ASSIGNMENT*/nn;
+   oo = /*severe:INVALID_ASSIGNMENT*/nnn;
 
-   nn = /*warning:INVALID_ASSIGNMENT*/r;
-   nn = /*warning:INVALID_ASSIGNMENT*/o;
+   nn = /*severe:INVALID_ASSIGNMENT*/r;
+   nn = /*severe:INVALID_ASSIGNMENT*/o;
    nn = /*warning:DOWN_CAST_COMPOSITE*/n;
-   nn = /*warning:INVALID_ASSIGNMENT*/rr;
-   nn = /*warning:INVALID_ASSIGNMENT*/ro;
-   nn = /*warning:INVALID_ASSIGNMENT*/rn;
-   nn = /*warning:INVALID_ASSIGNMENT*/oo;
+   nn = /*severe:INVALID_ASSIGNMENT*/rr;
+   nn = /*severe:INVALID_ASSIGNMENT*/ro;
+   nn = /*severe:INVALID_ASSIGNMENT*/rn;
+   nn = /*severe:INVALID_ASSIGNMENT*/oo;
    nn = nn;
    nn = nnn;
 
-   nnn = /*warning:INVALID_ASSIGNMENT*/r;
-   nnn = /*warning:INVALID_ASSIGNMENT*/o;
+   nnn = /*severe:INVALID_ASSIGNMENT*/r;
+   nnn = /*severe:INVALID_ASSIGNMENT*/o;
    nnn = /*warning:DOWN_CAST_COMPOSITE*/n;
-   nnn = /*warning:INVALID_ASSIGNMENT*/rr;
-   nnn = /*warning:INVALID_ASSIGNMENT*/ro;
-   nnn = /*warning:INVALID_ASSIGNMENT*/rn;
-   nnn = /*warning:INVALID_ASSIGNMENT*/oo;
+   nnn = /*severe:INVALID_ASSIGNMENT*/rr;
+   nnn = /*severe:INVALID_ASSIGNMENT*/ro;
+   nnn = /*severe:INVALID_ASSIGNMENT*/rn;
+   nnn = /*severe:INVALID_ASSIGNMENT*/oo;
    nnn = /*warning:DOWN_CAST_COMPOSITE*/nn;
    nnn = nnn;
 }
@@ -1609,7 +1616,7 @@
    {
      I2I f;
      f = new A();
-     f = /*warning:INVALID_ASSIGNMENT*/new B();
+     f = /*severe:INVALID_ASSIGNMENT*/new B();
      f = i2i;
      f = /*severe:STATIC_TYPE_ERROR*/n2n;
      f = /*warning:DOWN_CAST_COMPOSITE*/i2i as Object;
@@ -1617,7 +1624,7 @@
    }
    {
      N2N f;
-     f = /*warning:INVALID_ASSIGNMENT*/new A();
+     f = /*severe:INVALID_ASSIGNMENT*/new A();
      f = new B();
      f = /*severe:STATIC_TYPE_ERROR*/i2i;
      f = n2n;
@@ -1627,18 +1634,18 @@
    {
      A f;
      f = new A();
-     f = /*warning:INVALID_ASSIGNMENT*/new B();
-     f = /*warning:INVALID_ASSIGNMENT*/i2i;
-     f = /*warning:INVALID_ASSIGNMENT*/n2n;
+     f = /*severe:INVALID_ASSIGNMENT*/new B();
+     f = /*severe:INVALID_ASSIGNMENT*/i2i;
+     f = /*severe:INVALID_ASSIGNMENT*/n2n;
      f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object;
      f = /*info:DOWN_CAST_IMPLICIT*/n2n as Function;
    }
    {
      B f;
-     f = /*warning:INVALID_ASSIGNMENT*/new A();
+     f = /*severe:INVALID_ASSIGNMENT*/new A();
      f = new B();
-     f = /*warning:INVALID_ASSIGNMENT*/i2i;
-     f = /*warning:INVALID_ASSIGNMENT*/n2n;
+     f = /*severe:INVALID_ASSIGNMENT*/i2i;
+     f = /*severe:INVALID_ASSIGNMENT*/n2n;
      f = /*info:DOWN_CAST_IMPLICIT*/i2i as Object;
      f = /*info:DOWN_CAST_IMPLICIT*/n2n as Function;
    }
@@ -1714,8 +1721,8 @@
     local = g; // valid
 
     // Non-generic function cannot subtype a generic one.
-    local = /*warning:INVALID_ASSIGNMENT*/(x) => null;
-    local = /*warning:INVALID_ASSIGNMENT*/nonGenericFn;
+    local = /*severe:INVALID_ASSIGNMENT*/(x) => null;
+    local = /*severe:INVALID_ASSIGNMENT*/nonGenericFn;
   }
   {
     Iterable/*<R>*/ f/*<P, R>*/(List/*<P>*/ p) => null;
@@ -1730,8 +1737,8 @@
     local2 = /*warning:DOWN_CAST_COMPOSITE*/local;
 
     // Non-generic function cannot subtype a generic one.
-    local = /*warning:INVALID_ASSIGNMENT*/(x) => null;
-    local = /*warning:INVALID_ASSIGNMENT*/nonGenericFn;
+    local = /*severe:INVALID_ASSIGNMENT*/(x) => null;
+    local = /*severe:INVALID_ASSIGNMENT*/nonGenericFn;
   }
 }
 ''');
@@ -1880,26 +1887,35 @@
   if (b) {}
   if (/*info:DYNAMIC_CAST*/dyn) {}
   if (/*info:DOWN_CAST_IMPLICIT*/obj) {}
-  if (/*warning:NON_BOOL_CONDITION*/i) {}
+  if (/*severe:NON_BOOL_CONDITION*/i) {}
 
   while (b) {}
   while (/*info:DYNAMIC_CAST*/dyn) {}
   while (/*info:DOWN_CAST_IMPLICIT*/obj) {}
-  while (/*warning:NON_BOOL_CONDITION*/i) {}
+  while (/*severe:NON_BOOL_CONDITION*/i) {}
 
   do {} while (b);
   do {} while (/*info:DYNAMIC_CAST*/dyn);
   do {} while (/*info:DOWN_CAST_IMPLICIT*/obj);
-  do {} while (/*warning:NON_BOOL_CONDITION*/i);
+  do {} while (/*severe:NON_BOOL_CONDITION*/i);
 
   for (;b;) {}
   for (;/*info:DYNAMIC_CAST*/dyn;) {}
   for (;/*info:DOWN_CAST_IMPLICIT*/obj;) {}
-  for (;/*warning:NON_BOOL_CONDITION*/i;) {}
+  for (;/*severe:NON_BOOL_CONDITION*/i;) {}
 }
 ''');
   }
 
+  void test_implicitCasts() {
+    addFile('num n; int i = /*info:ASSIGNMENT_CAST*/n;');
+    check();
+    // TODO(jmesserly): should not be emitting the hint as well as the error.
+    addFile(
+        'num n; int i = /*info:ASSIGNMENT_CAST,severe:INVALID_ASSIGNMENT*/n;');
+    check(implicitCasts: false);
+  }
+
   void test_invalidOverrides_baseClassOverrideToChildInterface() {
     checkFile('''
 class A {}
@@ -1913,8 +1929,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base implements I {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base implements I {}
 ''');
   }
 
@@ -2073,8 +2089,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    extends Object with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M
     implements I {}
 ''');
   }
@@ -2097,12 +2113,12 @@
     int x;
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
-    with /*severe:INVALID_METHOD_OVERRIDE*/M1 {}
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2 extends Base
-    with /*severe:INVALID_METHOD_OVERRIDE*/M1, /*severe:INVALID_FIELD_OVERRIDE*/M2 {}
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3 extends Base
-    with /*severe:INVALID_FIELD_OVERRIDE*/M2, /*severe:INVALID_METHOD_OVERRIDE*/M1 {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
+    with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M1 {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T2 extends Base
+    with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M1, /*severe:INVALID_FIELD_OVERRIDE*/M2 {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T3 extends Base
+    with /*severe:INVALID_FIELD_OVERRIDE*/M2, /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M1 {}
 ''');
   }
 
@@ -2124,9 +2140,9 @@
     int x;
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
     with M1,
-    /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_FIELD_OVERRIDE*/M2 {}
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN,severe:INVALID_FIELD_OVERRIDE*/M2 {}
 ''');
   }
 
@@ -2154,8 +2170,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
-    with M1, /*severe:INVALID_METHOD_OVERRIDE*/M2, M3 {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
+    with M1, /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M2, M3 {}
 ''');
   }
 
@@ -2175,16 +2191,16 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base
     implements I1 {}
 
 class T2 extends Base implements I1 {
     m(a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3
-    extends Object with /*severe:INVALID_METHOD_OVERRIDE*/Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T3
+    extends Object with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/Base
     implements I1 {}
 
 class T4 extends Object with Base implements I1 {
@@ -2257,9 +2273,9 @@
     S s;
     T t;
     if (b) {
-      return /*warning:RETURN_OF_INVALID_TYPE*/b ? s : t;
+      return /*severe:RETURN_OF_INVALID_TYPE*/b ? s : t;
     } else {
-      return /*warning:RETURN_OF_INVALID_TYPE*/s ?? t;
+      return /*severe:RETURN_OF_INVALID_TYPE*/s ?? t;
     }
   }
 }
@@ -2268,7 +2284,7 @@
   T t;
   S s;
   int test(bool b) {
-    return /*warning:RETURN_OF_INVALID_TYPE*/b ? t : s;
+    return /*severe:RETURN_OF_INVALID_TYPE*/b ? t : s;
   }
 }
 
@@ -2279,7 +2295,7 @@
   int test1(bool b) {
     List<int> li;
     List<double> ld;
-    return /*warning:RETURN_OF_INVALID_TYPE*/b ? li : ld;
+    return /*severe:RETURN_OF_INVALID_TYPE*/b ? li : ld;
   }
   // TODO(leafp): This case isn't handled yet.  This test checks
   // the case where two related classes are instantiated with related
@@ -2288,7 +2304,7 @@
     List<int> li;
     Iterable<double> id;
     int x =
-        /*info:ASSIGNMENT_CAST should be warning:INVALID_ASSIGNMENT*/
+        /*info:ASSIGNMENT_CAST should be severe:INVALID_ASSIGNMENT*/
         b ? li : id;
     return /*warning:DOWN_CAST_COMPOSITE should be pass*/b ? li : id;
   }
@@ -2371,8 +2387,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
-    with /*severe:INVALID_METHOD_OVERRIDE*/M {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
+    with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M {}
 ''');
   }
 
@@ -2392,7 +2408,7 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Base
     with M {}
 ''');
   }
@@ -2411,8 +2427,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    extends Object with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M
     implements I2 {}
 ''');
   }
@@ -2431,8 +2447,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    extends Object with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M
     implements I2 {}
 ''');
   }
@@ -2451,8 +2467,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    extends Object with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M
     implements I2 {}
 ''');
   }
@@ -2478,9 +2494,9 @@
 // Here we want to report both, because the error location is
 // different.
 // TODO(sigmund): should we merge these as well?
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base
-    with /*severe:INVALID_METHOD_OVERRIDE*/M
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base
+    with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M
     implements I1 {}
 ''');
   }
@@ -2505,11 +2521,11 @@
 class Parent2 extends Grandparent {}
 
 // Note: otherwise both errors would be reported on this line
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Parent1
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Parent1
     implements I1 {}
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Parent2
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T2
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Parent2
     implements I1 {}
 ''');
   }
@@ -2535,9 +2551,9 @@
 // Here we want to report both, because the error location is
 // different.
 // TODO(sigmund): should we merge these as well?
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Object
-    with /*severe:INVALID_METHOD_OVERRIDE*/M1,
-    /*severe:INVALID_METHOD_OVERRIDE*/M2
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1 extends Object
+    with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M1,
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M2
     implements I1 {}
 ''');
   }
@@ -2565,8 +2581,8 @@
 
 // If there is no error in the class, we do report the error at
 // the base class:
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T2
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base
     implements I1 {}
 ''');
   }
@@ -2590,8 +2606,8 @@
       /*warning:INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE*/B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T2
-    extends Object with /*severe:INVALID_METHOD_OVERRIDE*/M
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T2
+    extends Object with /*severe:INVALID_METHOD_OVERRIDE_FROM_MIXIN*/M
     implements I1 {}
 ''');
   }
@@ -2725,7 +2741,7 @@
   }
   {
     lOfAs = /*warning:DOWN_CAST_COMPOSITE*/mOfDs;
-    lOfAs = /*warning:INVALID_ASSIGNMENT*/mOfOs;
+    lOfAs = /*severe:INVALID_ASSIGNMENT*/mOfOs;
     lOfAs = mOfAs;
     lOfAs = /*warning:DOWN_CAST_COMPOSITE*/lOfDs;
     lOfAs = /*info:DOWN_CAST_IMPLICIT*/lOfOs;
@@ -2747,7 +2763,7 @@
     mOfOs = mOfAs;
     mOfOs = /*info:DOWN_CAST_IMPLICIT*/lOfDs;
     mOfOs = /*info:DOWN_CAST_IMPLICIT*/lOfOs;
-    mOfOs = /*warning:INVALID_ASSIGNMENT*/lOfAs;
+    mOfOs = /*severe:INVALID_ASSIGNMENT*/lOfAs;
     mOfOs = new M<Object>(); // Reset type propagation.
   }
   {
@@ -2794,13 +2810,13 @@
 class A {
   set a(y) => 4;
   set b(y) => voidFn();
-  void set c(y) => /*warning:RETURN_OF_INVALID_TYPE*/4;
+  void set c(y) => /*severe:RETURN_OF_INVALID_TYPE*/4;
   void set d(y) => voidFn();
   /*warning:NON_VOID_RETURN_FOR_SETTER*/int set e(y) => 4;
   /*warning:NON_VOID_RETURN_FOR_SETTER*/int set f(y) =>
-      /*warning:RETURN_OF_INVALID_TYPE*/voidFn();
-  set g(y) {return /*warning:RETURN_OF_INVALID_TYPE*/4;}
-  void set h(y) {return /*warning:RETURN_OF_INVALID_TYPE*/4;}
+      /*severe:RETURN_OF_INVALID_TYPE*/voidFn();
+  set g(y) {return /*severe:RETURN_OF_INVALID_TYPE*/4;}
+  void set h(y) {return /*severe:RETURN_OF_INVALID_TYPE*/4;}
   /*warning:NON_VOID_RETURN_FOR_SETTER*/int set i(y) {return 4;}
 }
 ''');
@@ -2924,8 +2940,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base implements I2 {}
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base implements I2 {}
 ''');
   }
 
@@ -2943,8 +2959,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base
     implements I2 {}
 ''');
   }
@@ -2963,8 +2979,8 @@
     m(B a) {}
 }
 
-class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T1
-    /*severe:INVALID_METHOD_OVERRIDE*/extends Base
+class /*severe:INCONSISTENT_METHOD_INHERITANCE*/T1
+    /*severe:INVALID_METHOD_OVERRIDE_FROM_BASE*/extends Base
     implements I2 {}
 ''');
   }
@@ -3019,7 +3035,7 @@
   int i = 42;
 
   // Check the boolean conversion of the condition.
-  print(/*warning:NON_BOOL_CONDITION*/i ? false : true);
+  print(/*severe:NON_BOOL_CONDITION*/i ? false : true);
   print((/*info:DOWN_CAST_IMPLICIT*/obj) ? false : true);
   print((/*info:DYNAMIC_CAST*/dyn) ? false : true);
 }
@@ -3077,14 +3093,14 @@
   dynamic x;
   if (x is int) {
     int y = x;
-    String z = /*warning:INVALID_ASSIGNMENT*/x;
+    String z = /*severe:INVALID_ASSIGNMENT*/x;
   }
 }
 g() {
   Object x;
   if (x is int) {
     int y = x;
-    String z = /*warning:INVALID_ASSIGNMENT*/x;
+    String z = /*severe:INVALID_ASSIGNMENT*/x;
   }
 }
 ''');
@@ -3105,9 +3121,9 @@
    B b;
    y = a;
    o = a;
-   i = /*warning:INVALID_ASSIGNMENT*/a;
-   d = /*warning:INVALID_ASSIGNMENT*/a;
-   n = /*warning:INVALID_ASSIGNMENT*/a;
+   i = /*severe:INVALID_ASSIGNMENT*/a;
+   d = /*severe:INVALID_ASSIGNMENT*/a;
+   n = /*severe:INVALID_ASSIGNMENT*/a;
    a = a;
    b = /*info:DOWN_CAST_IMPLICIT*/a;
 }
@@ -3131,12 +3147,12 @@
    C c;
    y = b;
    o = b;
-   i = /*warning:INVALID_ASSIGNMENT*/b;
-   d = /*warning:INVALID_ASSIGNMENT*/b;
-   n = /*warning:INVALID_ASSIGNMENT*/b;
+   i = /*severe:INVALID_ASSIGNMENT*/b;
+   d = /*severe:INVALID_ASSIGNMENT*/b;
+   n = /*severe:INVALID_ASSIGNMENT*/b;
    a = b;
    b = b;
-   c = /*warning:INVALID_ASSIGNMENT*/b;
+   c = /*severe:INVALID_ASSIGNMENT*/b;
 }
 ''');
   }
@@ -3208,12 +3224,12 @@
    {
      left = /*info:DOWN_CAST_IMPLICIT*/top;
      left = left;
-     left = /*warning:INVALID_ASSIGNMENT*/right;
+     left = /*severe:INVALID_ASSIGNMENT*/right;
      left = bot;
    }
    {
      right = /*info:DOWN_CAST_IMPLICIT*/top;
-     right = /*warning:INVALID_ASSIGNMENT*/left;
+     right = /*severe:INVALID_ASSIGNMENT*/left;
      right = right;
      right = bot;
    }
@@ -3246,7 +3262,7 @@
   ~a;
   (/*info:DYNAMIC_INVOKE*/~d);
 
-  !/*warning:NON_BOOL_NEGATION_EXPRESSION*/a;
+  !/*severe:NON_BOOL_NEGATION_EXPRESSION*/a;
   !/*info:DYNAMIC_CAST*/d;
 
   -a;
@@ -3295,7 +3311,7 @@
 typedef int Foo();
 void foo() {}
 void main () {
-  Foo x = /*warning:INVALID_ASSIGNMENT,info:USE_OF_VOID_RESULT*/foo();
+  Foo x = /*severe:INVALID_ASSIGNMENT,info:USE_OF_VOID_RESULT*/foo();
 }
 ''');
   }
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 46e7434e..d11b584 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -269,8 +269,8 @@
 
   f = /*info:INFERRED_TYPE_CLOSURE*/(x) => 'hello';
 
-  foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) { return null; });
-  foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) { throw "not implemented"; });
+  foo(/*info:INFERRED_TYPE_CLOSURE*/(x) { return null; });
+  foo(/*info:INFERRED_TYPE_CLOSURE*/(x) { throw "not implemented"; });
 }
 ''');
 
@@ -318,7 +318,7 @@
 main() {
   String f() => null;
   var g = f;
-  g = /*info:INFERRED_TYPE_CLOSURE*/() { return /*warning:RETURN_OF_INVALID_TYPE*/1; };
+  g = /*info:INFERRED_TYPE_CLOSURE*/() { return /*severe:RETURN_OF_INVALID_TYPE*/1; };
 }
 ''');
     var f = mainUnit.functions[0].localVariables[0];
@@ -340,7 +340,7 @@
 import 'dart:math' show Random;
 test2() {
   List<num> o;
-  var y = o.map(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) {
+  var y = o.map(/*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/(x) {
     if (new Random().nextBool()) {
       return x.toInt() + 1;
     } else {
@@ -619,11 +619,11 @@
 
 test() {
   x = "hi";
-  y = /*warning:INVALID_ASSIGNMENT*/"hi";
+  y = /*severe:INVALID_ASSIGNMENT*/"hi";
   A.x = "hi";
-  A.y = /*warning:INVALID_ASSIGNMENT*/"hi";
+  A.y = /*severe:INVALID_ASSIGNMENT*/"hi";
   new A().x2 = "hi";
-  new A().y2 = /*warning:INVALID_ASSIGNMENT*/"hi";
+  new A().y2 = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -820,29 +820,29 @@
   {
     Function2<int, String> l0 = /*info:INFERRED_TYPE_CLOSURE*/(int x) => null;
     Function2<int, String> l1 = (int x) => "hello";
-    Function2<int, String> l2 = /*warning:INVALID_ASSIGNMENT*/(String x) => "hello";
-    Function2<int, String> l3 = /*warning:INVALID_ASSIGNMENT*/(int x) => 3;
-    Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(int x) {return /*warning:RETURN_OF_INVALID_TYPE*/3;};
+    Function2<int, String> l2 = /*severe:INVALID_ASSIGNMENT*/(String x) => "hello";
+    Function2<int, String> l3 = /*severe:INVALID_ASSIGNMENT*/(int x) => 3;
+    Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(int x) {return /*severe:RETURN_OF_INVALID_TYPE*/3;};
   }
   {
-    Function2<int, String> l0 = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/(x) => null;
+    Function2<int, String> l0 = /*info:INFERRED_TYPE_CLOSURE*/(x) => null;
     Function2<int, String> l1 = /*info:INFERRED_TYPE_CLOSURE*/(x) => "hello";
-    Function2<int, String> l2 = /*info:INFERRED_TYPE_CLOSURE, warning:INVALID_ASSIGNMENT*/(x) => 3;
-    Function2<int, String> l3 = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/(x) {return /*warning:RETURN_OF_INVALID_TYPE*/3;};
-    Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/(x) {return /*warning:RETURN_OF_INVALID_TYPE*/x;};
+    Function2<int, String> l2 = /*info:INFERRED_TYPE_CLOSURE, severe:INVALID_ASSIGNMENT*/(x) => 3;
+    Function2<int, String> l3 = /*info:INFERRED_TYPE_CLOSURE*/(x) {return /*severe:RETURN_OF_INVALID_TYPE*/3;};
+    Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(x) {return /*severe:RETURN_OF_INVALID_TYPE*/x;};
   }
   {
     Function2<int, List<String>> l0 = /*info:INFERRED_TYPE_CLOSURE*/(int x) => null;
     Function2<int, List<String>> l1 = (int x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
-    Function2<int, List<String>> l2 = /*warning:INVALID_ASSIGNMENT*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+    Function2<int, List<String>> l2 = /*severe:INVALID_ASSIGNMENT*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
     Function2<int, List<String>> l3 = (int x) => /*info:INFERRED_TYPE_LITERAL*/[/*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/3];
     Function2<int, List<String>> l4 = /*info:INFERRED_TYPE_CLOSURE*/(int x) {return /*info:INFERRED_TYPE_LITERAL*/[/*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/3];};
   }
   {
     Function2<int, int> l0 = /*info:INFERRED_TYPE_CLOSURE*/(x) => x;
     Function2<int, int> l1 = /*info:INFERRED_TYPE_CLOSURE*/(x) => x+1;
-    Function2<int, String> l2 = /*info:INFERRED_TYPE_CLOSURE, warning:INVALID_ASSIGNMENT*/(x) => x;
-    Function2<int, String> l3 = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/(x) => /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/x.substring(3);
+    Function2<int, String> l2 = /*info:INFERRED_TYPE_CLOSURE, severe:INVALID_ASSIGNMENT*/(x) => x;
+    Function2<int, String> l3 = /*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/x.substring(3);
     Function2<String, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(x) => x.substring(3);
   }
 }
@@ -940,25 +940,25 @@
     var v = f;
     v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
     v = /*<T>*/(int x) => "hello";
-    v = /*warning:INVALID_ASSIGNMENT*//*<T>*/(String x) => "hello";
-    v = /*warning:INVALID_ASSIGNMENT*//*<T>*/(int x) => 3;
-    v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*warning:RETURN_OF_INVALID_TYPE*/3;};
+    v = /*severe:INVALID_ASSIGNMENT*//*<T>*/(String x) => "hello";
+    v = /*severe:INVALID_ASSIGNMENT*//*<T>*/(int x) => 3;
+    v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*severe:RETURN_OF_INVALID_TYPE*/3;};
   }
   {
     String f/*<S>*/(int x) => null;
     var v = f;
     v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => null;
     v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => "hello";
-    v = /*info:INFERRED_TYPE_CLOSURE, warning:INVALID_ASSIGNMENT*//*<T>*/(x) => 3;
-    v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*warning:RETURN_OF_INVALID_TYPE*/3;};
-    v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*warning:RETURN_OF_INVALID_TYPE*/x;};
+    v = /*info:INFERRED_TYPE_CLOSURE, severe:INVALID_ASSIGNMENT*//*<T>*/(x) => 3;
+    v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:RETURN_OF_INVALID_TYPE*/3;};
+    v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:RETURN_OF_INVALID_TYPE*/x;};
   }
   {
     List<String> f/*<S>*/(int x) => null;
     var v = f;
     v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
     v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
-    v = /*warning:INVALID_ASSIGNMENT*//*<T>*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+    v = /*severe:INVALID_ASSIGNMENT*//*<T>*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
     v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/[/*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/3];
     v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*info:INFERRED_TYPE_LITERAL*/[/*warning:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/3];};
   }
@@ -970,7 +970,7 @@
     x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x;
     x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x+1;
     var y = int2String;
-    y = /*info:INFERRED_TYPE_CLOSURE, warning:INVALID_ASSIGNMENT*//*<T>*/(x) => x;
+    y = /*info:INFERRED_TYPE_CLOSURE, severe:INVALID_ASSIGNMENT*//*<T>*/(x) => x;
     y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => /*info:DYNAMIC_INVOKE, info:DYNAMIC_CAST*/x.substring(3);
     var z = string2String;
     z = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x.substring(3);
@@ -1281,15 +1281,15 @@
 import 'dart:async';
 Stream<List<int>> foo() async* {
   yield /*info:INFERRED_TYPE_LITERAL*/[];
-  yield /*warning:YIELD_OF_INVALID_TYPE*/new Stream();
-  yield* /*warning:YIELD_OF_INVALID_TYPE*/[];
+  yield /*severe:YIELD_OF_INVALID_TYPE*/new Stream();
+  yield* /*severe:YIELD_OF_INVALID_TYPE*/[];
   yield* /*info:INFERRED_TYPE_ALLOCATION*/new Stream();
 }
 
 Iterable<Map<int, int>> bar() sync* {
   yield /*info:INFERRED_TYPE_LITERAL*/{};
-  yield /*warning:YIELD_OF_INVALID_TYPE*/new List();
-  yield* /*warning:YIELD_OF_INVALID_TYPE*/{};
+  yield /*severe:YIELD_OF_INVALID_TYPE*/new List();
+  yield* /*severe:YIELD_OF_INVALID_TYPE*/{};
   yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
 }
   ''');
@@ -1397,7 +1397,7 @@
 /*severe:INVALID_METHOD_OVERRIDE*/m(x) => x;
 }
 main() {
-  int y = /*info:DYNAMIC_CAST*/new D()./*warning:WRONG_NUMBER_OF_TYPE_ARGUMENTS*/m/*<int>*/(42);
+  int y = /*info:DYNAMIC_CAST*/new D()./*severe:WRONG_NUMBER_OF_TYPE_ARGUMENTS*/m/*<int>*/(42);
   print(y);
 }
 ''');
@@ -1605,10 +1605,10 @@
     checkFile('''
 import 'dart:_foreign_helper' show JS;
 main() {
-  String x = /*warning:INVALID_ASSIGNMENT*/JS('int', '42');
+  String x = /*severe:INVALID_ASSIGNMENT*/JS('int', '42');
   var y = JS('String', '"hello"');
   y = "world";
-  y = /*warning:INVALID_ASSIGNMENT*/42;
+  y = /*severe:INVALID_ASSIGNMENT*/42;
 }
 ''');
   }
@@ -1901,13 +1901,13 @@
   int i;
 
   s = /*info:DYNAMIC_CAST*/new B().x;
-  s = /*warning:INVALID_ASSIGNMENT*/new B().y;
+  s = /*severe:INVALID_ASSIGNMENT*/new B().y;
   s = new B().z;
-  s = /*warning:INVALID_ASSIGNMENT*/new B().w;
+  s = /*severe:INVALID_ASSIGNMENT*/new B().w;
 
   i = /*info:DYNAMIC_CAST*/new B().x;
   i = new B().y;
-  i = /*warning:INVALID_ASSIGNMENT*/new B().z;
+  i = /*severe:INVALID_ASSIGNMENT*/new B().z;
   i = new B().w;
 }
 ''');
@@ -2078,32 +2078,32 @@
                         // conected component.
 var g = -3;
 var h = new A() + 3;
-var i = /*warning:UNDEFINED_OPERATOR*/- new A();
+var i = /*severe:UNDEFINED_OPERATOR*/- new A();
 var j = null as B;
 
 test1() {
-  a = /*warning:INVALID_ASSIGNMENT*/"hi";
+  a = /*severe:INVALID_ASSIGNMENT*/"hi";
   a = new B(3);
-  b = /*warning:INVALID_ASSIGNMENT*/"hi";
+  b = /*severe:INVALID_ASSIGNMENT*/"hi";
   b = new B(3);
   c1 = [];
-  c1 = /*warning:INVALID_ASSIGNMENT*/{};
+  c1 = /*severe:INVALID_ASSIGNMENT*/{};
   c2 = [];
-  c2 = /*warning:INVALID_ASSIGNMENT*/{};
+  c2 = /*severe:INVALID_ASSIGNMENT*/{};
   d = {};
-  d = /*warning:INVALID_ASSIGNMENT*/3;
+  d = /*severe:INVALID_ASSIGNMENT*/3;
   e = new A();
-  e = /*warning:INVALID_ASSIGNMENT*/{};
+  e = /*severe:INVALID_ASSIGNMENT*/{};
   f = 3;
-  f = /*warning:INVALID_ASSIGNMENT*/false;
+  f = /*severe:INVALID_ASSIGNMENT*/false;
   g = 1;
-  g = /*warning:INVALID_ASSIGNMENT*/false;
-  h = /*warning:INVALID_ASSIGNMENT*/false;
+  g = /*severe:INVALID_ASSIGNMENT*/false;
+  h = /*severe:INVALID_ASSIGNMENT*/false;
   h = new B('b');
   i = false;
   j = new B('b');
-  j = /*warning:INVALID_ASSIGNMENT*/false;
-  j = /*warning:INVALID_ASSIGNMENT*/[];
+  j = /*severe:INVALID_ASSIGNMENT*/false;
+  j = /*severe:INVALID_ASSIGNMENT*/[];
 }
 ''');
   }
@@ -2136,7 +2136,7 @@
 }
 
 foo() {
-  String y = /*warning:INVALID_ASSIGNMENT*/new B().x;
+  String y = /*severe:INVALID_ASSIGNMENT*/new B().x;
   int z = new B().x;
 }
 ''');
@@ -2191,8 +2191,8 @@
 var y = x;
 
 test1() {
-  x = /*warning:INVALID_ASSIGNMENT*/"hi";
-  y = /*warning:INVALID_ASSIGNMENT*/"hi";
+  x = /*severe:INVALID_ASSIGNMENT*/"hi";
+  y = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -2208,8 +2208,8 @@
 class B { static var y = A.x; }
 
 test1() {
-  A.x = /*warning:INVALID_ASSIGNMENT*/"hi";
-  B.y = /*warning:INVALID_ASSIGNMENT*/"hi";
+  A.x = /*severe:INVALID_ASSIGNMENT*/"hi";
+  B.y = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -2353,7 +2353,7 @@
     checkFile('''
 class Foo {
   var x = 1;
-  Foo([this.x = /*warning:INVALID_ASSIGNMENT*/"1"]);
+  Foo([this.x = /*severe:INVALID_ASSIGNMENT*/"1"]);
 }''');
   }
 
@@ -2798,7 +2798,7 @@
 }
 
 foo() {
-  String y = /*warning:INVALID_ASSIGNMENT*/new B().x;
+  String y = /*severe:INVALID_ASSIGNMENT*/new B().x;
   int z = new B().x;
 }
 ''');
@@ -2815,7 +2815,7 @@
 }
 
 foo() {
-  String y = /*warning:INVALID_ASSIGNMENT*/new B().x;
+  String y = /*severe:INVALID_ASSIGNMENT*/new B().x;
   int z = new B().x;
 }
 ''');
@@ -2826,7 +2826,7 @@
     checkFile('''
 test1() {
   int x = 3;
-  x = /*warning:INVALID_ASSIGNMENT*/"hi";
+  x = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -2835,7 +2835,7 @@
     checkFile('''
 test2() {
   var x = 3;
-  x = /*warning:INVALID_ASSIGNMENT*/"hi";
+  x = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -2847,13 +2847,13 @@
 
   test1() {
     var a = x;
-    a = /*warning:INVALID_ASSIGNMENT*/"hi";
+    a = /*severe:INVALID_ASSIGNMENT*/"hi";
     a = 3;
     var b = y;
-    b = /*warning:INVALID_ASSIGNMENT*/"hi";
+    b = /*severe:INVALID_ASSIGNMENT*/"hi";
     b = 4;
     var c = z;
-    c = /*warning:INVALID_ASSIGNMENT*/"hi";
+    c = /*severe:INVALID_ASSIGNMENT*/"hi";
     c = 4;
   }
 
@@ -2869,13 +2869,13 @@
 
 test1() {
   var a = x;
-  a = /*warning:INVALID_ASSIGNMENT*/"hi";
+  a = /*severe:INVALID_ASSIGNMENT*/"hi";
   a = 3;
   var b = y;
-  b = /*warning:INVALID_ASSIGNMENT*/"hi";
+  b = /*severe:INVALID_ASSIGNMENT*/"hi";
   b = 4;
   var c = z;
-  c = /*warning:INVALID_ASSIGNMENT*/"hi";
+  c = /*severe:INVALID_ASSIGNMENT*/"hi";
   c = 4;
 }
 
@@ -2902,7 +2902,7 @@
 }
 foo() {
   int y = new C().x;
-  String z = /*warning:INVALID_ASSIGNMENT*/new C().x;
+  String z = /*severe:INVALID_ASSIGNMENT*/new C().x;
 }
 ''');
   }
@@ -2916,11 +2916,11 @@
 
 class B implements A<int> {
   get x => 3;
-  get w => /*warning:RETURN_OF_INVALID_TYPE*/"hello";
+  get w => /*severe:RETURN_OF_INVALID_TYPE*/"hello";
 }
 
 foo() {
-  String y = /*warning:INVALID_ASSIGNMENT*/new B().x;
+  String y = /*severe:INVALID_ASSIGNMENT*/new B().x;
   int z = new B().x;
 }
 ''');
@@ -2938,7 +2938,7 @@
 }
 
 foo() {
-  int y = /*warning:INVALID_ASSIGNMENT*/new B<String>().x;
+  int y = /*severe:INVALID_ASSIGNMENT*/new B<String>().x;
   String z = new B<String>().x;
 }
 ''');
@@ -2967,7 +2967,7 @@
 }
 
 foo () {
-  int y = /*warning:INVALID_ASSIGNMENT*/new B().m(null, null);
+  int y = /*severe:INVALID_ASSIGNMENT*/new B().m(null, null);
   String z = new B().m(null, null);
 }
 ''');
@@ -3023,7 +3023,7 @@
 }
 
 foo () {
-  int y = /*warning:INVALID_ASSIGNMENT*/new B<String>().m(null, null).value;
+  int y = /*severe:INVALID_ASSIGNMENT*/new B<String>().m(null, null).value;
   String z = new B<String>().m(null, null).value;
 }
 ''');
@@ -3038,7 +3038,7 @@
 class Bar<T extends Iterable<String>> {
   void foo(T t) {
     for (var i in t) {
-      int x = /*warning:INVALID_ASSIGNMENT*/i;
+      int x = /*severe:INVALID_ASSIGNMENT*/i;
     }
   }
 }
@@ -3046,7 +3046,7 @@
 class Baz<T, E extends Iterable<T>, S extends E> {
   void foo(S t) {
     for (var i in t) {
-      int x = /*warning:INVALID_ASSIGNMENT*/i;
+      int x = /*severe:INVALID_ASSIGNMENT*/i;
       T y = i;
     }
   }
@@ -3055,7 +3055,7 @@
 test() {
   var list = <Foo>[];
   for (var x in list) {
-    String y = /*warning:INVALID_ASSIGNMENT*/x;
+    String y = /*severe:INVALID_ASSIGNMENT*/x;
   }
 
   for (dynamic x in list) {
@@ -3064,7 +3064,7 @@
     String y = /*info:DYNAMIC_CAST,info:INVALID_ASSIGNMENT*/x;
   }
 
-  for (String x in /*warning:FOR_IN_OF_INVALID_ELEMENT_TYPE*/list) {
+  for (String x in /*severe:FOR_IN_OF_INVALID_ELEMENT_TYPE*/list) {
     String y = x;
   }
 
@@ -3085,7 +3085,7 @@
 
   var map = <String, Foo>{};
   // Error: map must be an Iterable.
-  for (var x in /*warning:FOR_IN_OF_INVALID_TYPE*/map) {
+  for (var x in /*severe:FOR_IN_OF_INVALID_TYPE*/map) {
     String y = /*info:DYNAMIC_CAST*/x;
   }
 
@@ -3132,7 +3132,7 @@
 import 'a.dart';
 import 'b.dart';
 main() {
-  new A().x = /*warning:INVALID_ASSIGNMENT*/'foo';
+  new A().x = /*severe:INVALID_ASSIGNMENT*/'foo';
   new B().x = 'foo';
 }
 ''');
@@ -3304,7 +3304,7 @@
   x[3] = 'z';
   x[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
   x[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/4.0] = 'u';
-  x[3] = /*warning:INVALID_ASSIGNMENT*/42;
+  x[3] = /*severe:INVALID_ASSIGNMENT*/42;
   Map<num, String> y = x;
 }
 
@@ -3313,7 +3313,7 @@
   x[3] = 'z';
   x[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
   x[4.0] = 'u';
-  x[3] = /*warning:INVALID_ASSIGNMENT*/42;
+  x[3] = /*severe:INVALID_ASSIGNMENT*/42;
   Pattern p = null;
   x[2] = p;
   Map<int, String> y = /*info:ASSIGNMENT_CAST*/x;
@@ -3328,7 +3328,7 @@
   x1[3] = 'z';
   x1[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
   x1[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/4.0] = 'u';
-  x1[3] = /*warning:INVALID_ASSIGNMENT*/42;
+  x1[3] = /*severe:INVALID_ASSIGNMENT*/42;
   Map<num, String> y = x1;
 }
 
@@ -3337,7 +3337,7 @@
   x2[3] = 'z';
   x2[/*warning:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'] = 'w';
   x2[4.0] = 'u';
-  x2[3] = /*warning:INVALID_ASSIGNMENT*/42;
+  x2[3] = /*severe:INVALID_ASSIGNMENT*/42;
   Pattern p = null;
   x2[2] = p;
   Map<int, String> y = /*info:ASSIGNMENT_CAST*/x2;
@@ -3443,8 +3443,8 @@
   h = 'hello';
   (/*info:DYNAMIC_INVOKE*/h.foo());
 
-  foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) => null);
-  foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) => throw "not implemented");
+  foo(/*info:INFERRED_TYPE_CLOSURE*/(x) => null);
+  foo(/*info:INFERRED_TYPE_CLOSURE*/(x) => throw "not implemented");
 }
 ''');
   }
@@ -3487,10 +3487,10 @@
 
 test5() {
   var a1 = new A();
-  a1.x = /*warning:INVALID_ASSIGNMENT*/"hi";
+  a1.x = /*severe:INVALID_ASSIGNMENT*/"hi";
 
   A a2 = new A();
-  a2.x = /*warning:INVALID_ASSIGNMENT*/"hi";
+  a2.x = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -3643,7 +3643,7 @@
     checkFile('''
 import 'a.dart';
 test() {
-  x = /*warning:INVALID_ASSIGNMENT*/"hi";
+  x = /*severe:INVALID_ASSIGNMENT*/"hi";
 }
 ''');
   }
@@ -3701,7 +3701,7 @@
     // Check that type inference dependencies are properly checked when a top
     // level variable appears at the beginning of a string of identifiers
     // separated by '.'.
-    var mainUnit = checkFile('''
+    checkFile('''
 final a = /*info:DYNAMIC_INVOKE*/c.i;
 final c = new C(a);
 class C {
@@ -3724,9 +3724,9 @@
   ///   * all expected failures are listed in the source code using comments
   ///     immediately in front of the AST node that should contain the error.
   ///
-  ///   * errors are formatted as a token `level:Type`, where `level` is the
-  ///     logging level were the error would be reported at, and `Type` is the
-  ///     concrete subclass of [StaticInfo] that denotes the error.
+  ///   * errors are formatted as a token `severity:ErrorCode`, where
+  ///     `severity` is the ErrorSeverity the error would be reported at, and
+  ///     `ErrorCode` is the error code's name.
   ///
   /// For example to check that an assignment produces a type error, you can
   /// create a file like:
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 079bda1..d9778c7 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -29,9 +30,9 @@
 ///   * all expected failures are listed in the source code using comments
 ///     immediately in front of the AST node that should contain the error.
 ///
-///   * errors are formatted as a token `level:Type`, where `level` is the
-///     logging level were the error would be reported at, and `Type` is the
-///     concrete subclass of [StaticInfo] that denotes the error.
+///   * errors are formatted as a token `severity:ErrorCode`, where
+///     `severity` is the ErrorSeverity the error would be reported at, and
+///     `ErrorCode` is the error code's name.
 ///
 /// For example to check that an assignment produces a type error, you can
 /// create a file like:
@@ -54,7 +55,7 @@
 /// the file text.
 ///
 /// Returns the main resolved library. This can be used for further checks.
-CompilationUnit check() {
+CompilationUnit check({bool implicitCasts: true}) {
   _checkCalled = true;
 
   expect(files.getFile('/main.dart').exists, true,
@@ -66,6 +67,7 @@
   AnalysisOptionsImpl options = context.analysisOptions as AnalysisOptionsImpl;
   options.strongMode = true;
   options.strongModeHints = true;
+  options.implicitCasts = implicitCasts;
   var mockSdk = new MockSdk();
   mockSdk.context.analysisOptions.strongMode = true;
   context.sourceFactory =
@@ -75,7 +77,7 @@
   Source mainSource = uriResolver.resolveAbsolute(new Uri.file('/main.dart'));
   var initialLibrary = context.resolveCompilationUnit2(mainSource, mainSource);
 
-  var collector = new _ErrorCollector();
+  var collector = new _ErrorCollector(context);
 
   // Extract expectations from the comments in the test files, and
   // check that all errors we emit are included in the expected map.
@@ -101,7 +103,7 @@
           e.errorCode != HintCode.UNUSED_IMPORT &&
           e.errorCode != HintCode.UNUSED_LOCAL_VARIABLE &&
           e.errorCode != TodoCode.TODO));
-      _expectErrors(resolved, errors);
+      _expectErrors(context, resolved, errors);
     }
   }
 
@@ -130,12 +132,12 @@
   });
 }
 
-Level _actualErrorLevel(AnalysisError actual) {
+Level _actualErrorLevel(AnalysisContext context, AnalysisError actual) {
   return const <ErrorSeverity, Level>{
     ErrorSeverity.ERROR: Level.SEVERE,
     ErrorSeverity.WARNING: Level.WARNING,
     ErrorSeverity.INFO: Level.INFO
-  }[actual.errorCode.errorSeverity];
+  }[_errorSeverity(context, actual)];
 }
 
 SourceSpanWithContext _createSpanHelper(
@@ -174,7 +176,14 @@
   }
 }
 
-void _expectErrors(CompilationUnit unit, List<AnalysisError> actualErrors) {
+ErrorSeverity _errorSeverity(AnalysisContext context, AnalysisError error) {
+  // Attempt to process severity in a similar way to analyzer_cli and server.
+  return ErrorProcessor.getProcessor(context, error)?.severity ??
+      error.errorCode.errorSeverity;
+}
+
+void _expectErrors(AnalysisContext context, CompilationUnit unit,
+    List<AnalysisError> actualErrors) {
   var expectedErrors = _findExpectedErrors(unit.beginToken);
 
   // Sort both lists: by offset, then level, then name.
@@ -182,7 +191,7 @@
     int delta = x.offset.compareTo(y.offset);
     if (delta != 0) return delta;
 
-    delta = x.errorCode.errorSeverity.compareTo(y.errorCode.errorSeverity);
+    delta = _errorSeverity(context, x).compareTo(_errorSeverity(context, y));
     if (delta != 0) return delta;
 
     return _errorCodeName(x.errorCode).compareTo(_errorCodeName(y.errorCode));
@@ -204,7 +213,7 @@
   for (var expected in expectedErrors) {
     AnalysisError actual = expected._removeMatchingActual(actualErrors);
     if (actual != null) {
-      if (_actualErrorLevel(actual) != expected.level ||
+      if (_actualErrorLevel(context, actual) != expected.level ||
           _errorCodeName(actual.errorCode) != expected.typeName) {
         different[expected] = actual;
       }
@@ -217,7 +226,7 @@
   List<AnalysisError> unexpected = actualErrors;
 
   if (unreported.isNotEmpty || unexpected.isNotEmpty || different.isNotEmpty) {
-    _reportFailure(unit, unreported, unexpected, different);
+    _reportFailure(context, unit, unreported, unexpected, different);
   }
 }
 
@@ -271,6 +280,7 @@
 }
 
 void _reportFailure(
+    AnalysisContext context,
     CompilationUnit unit,
     List<_ErrorExpectation> unreported,
     List<AnalysisError> unexpected,
@@ -285,7 +295,7 @@
     var span = _createSpanHelper(
         unit.lineInfo, offset, unit.element.source, sourceCode,
         end: offset + length);
-    var levelName = _actualErrorLevel(error).name.toLowerCase();
+    var levelName = _actualErrorLevel(context, error).name.toLowerCase();
     return '@$offset $levelName:${_errorCodeName(error.errorCode)}\n' +
         span.message(error.message);
   }
@@ -321,15 +331,16 @@
 }
 
 class _ErrorCollector implements AnalysisErrorListener {
+  final AnalysisContext _context;
   List<AnalysisError> errors;
   final bool hints;
 
-  _ErrorCollector({this.hints: true});
+  _ErrorCollector(this._context, {this.hints: true});
 
   void onError(AnalysisError error) {
     // Unless DDC hints are requested, filter them out.
     var HINT = ErrorSeverity.INFO.ordinal;
-    if (hints || error.errorCode.errorSeverity.ordinal > HINT) {
+    if (hints || _errorSeverity(_context, error).ordinal > HINT) {
       errors.add(error);
     }
   }
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index 1bbd4da..fc7ec0e 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -1,16 +1,8 @@
 import 'dart:io';
 
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/java_io.dart';
-import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/sdk_io.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/flat_buffers.dart' as fb;
-import 'package:analyzer/src/summary/index_unit.dart';
-import 'package:analyzer/src/summary/summarize_elements.dart';
-import 'package:path/path.dart';
+import 'package:analyzer/src/summary/summary_file_builder.dart';
 
 main(List<String> args) {
   if (args.length < 1) {
@@ -124,15 +116,24 @@
   } else {
     sdkPath = DirectoryBasedDartSdk.defaultSdkDirectory.getAbsolutePath();
   }
+
   //
   // Build spec and strong outputs.
   //
-  _BuilderOutput spec =
-      includeSpec ? new _Builder(sdkPath, false).build() : null;
-  _BuilderOutput strong = new _Builder(sdkPath, true).build();
+  BuilderOutput spec = includeSpec ? _buildOutput(sdkPath, false) : null;
+  BuilderOutput strong = _buildOutput(sdkPath, true);
   return new _Output(spec, strong);
 }
 
+BuilderOutput _buildOutput(String sdkPath, bool strongMode) {
+  String modeName = strongMode ? 'strong' : 'spec';
+  print('Generating $modeName mode summary and index.');
+  Stopwatch sw = new Stopwatch()..start();
+  BuilderOutput output = new SummaryBuilder.forSdk(sdkPath, strongMode).build();
+  print('\tDone in ${sw.elapsedMilliseconds} ms.');
+  return output;
+}
+
 /**
  * Open the flat buffer in [inputPath] and extract the byte array in the [field]
  * into the [outputPath] file.
@@ -169,105 +170,9 @@
   print('    Extract the strong-mode index file.');
 }
 
-class _Builder {
-  final String sdkPath;
-  final bool strongMode;
-
-  AnalysisContext context;
-  final Set<Source> processedSources = new Set<Source>();
-
-  final PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
-  final PackageIndexAssembler indexAssembler = new PackageIndexAssembler();
-
-  _Builder(this.sdkPath, this.strongMode);
-
-  /**
-   * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
-   */
-  _BuilderOutput build() {
-    String modeName = strongMode ? 'strong' : 'spec';
-    print('Generating $modeName mode summary and index.');
-    Stopwatch sw = new Stopwatch()..start();
-    //
-    // Prepare SDK.
-    //
-    DirectoryBasedDartSdk sdk =
-        new DirectoryBasedDartSdk(new JavaFile(sdkPath), strongMode);
-    sdk.useSummary = false;
-    sdk.analysisOptions = new AnalysisOptionsImpl()..strongMode = strongMode;
-    context = sdk.context;
-    //
-    // Prepare 'dart:' URIs to serialize.
-    //
-    Set<String> uriSet =
-        sdk.sdkLibraries.map((SdkLibrary library) => library.shortName).toSet();
-    if (!strongMode) {
-      uriSet.add('dart:html/nativewrappers.dart');
-    }
-    uriSet.add('dart:html_common/html_common_dart2js.dart');
-    //
-    // Serialize each SDK library.
-    //
-    for (String uri in uriSet) {
-      Source libSource = sdk.mapDartUri(uri);
-      _serializeLibrary(libSource);
-    }
-    //
-    // Assemble the output.
-    //
-    List<int> sumBytes = bundleAssembler.assemble().toBuffer();
-    List<int> indexBytes = indexAssembler.assemble().toBuffer();
-    print('\tDone in ${sw.elapsedMilliseconds} ms.');
-    return new _BuilderOutput(sumBytes, indexBytes);
-  }
-
-  /**
-   * Serialize the library with the given [source] and all its direct or
-   * indirect imports and exports.
-   */
-  void _serializeLibrary(Source source) {
-    if (!processedSources.add(source)) {
-      return;
-    }
-    LibraryElement element = context.computeLibraryElement(source);
-    bundleAssembler.serializeLibraryElement(element);
-    element.importedLibraries.forEach((e) => _serializeLibrary(e.source));
-    element.exportedLibraries.forEach((e) => _serializeLibrary(e.source));
-    // Index every unit of the library.
-    for (CompilationUnitElement unitElement in element.units) {
-      Source unitSource = unitElement.source;
-      CompilationUnit unit =
-          context.resolveCompilationUnit2(unitSource, source);
-      indexAssembler.indexUnit(unit);
-    }
-  }
-}
-
-class _BuilderOutput {
-  final List<int> sum;
-  final List<int> index;
-
-  _BuilderOutput(this.sum, this.index);
-
-  void writeMultiple(String outputDirectoryPath, String modeName) {
-    // Write summary.
-    {
-      String outputPath = join(outputDirectoryPath, '$modeName.sum');
-      File file = new File(outputPath);
-      file.writeAsBytesSync(sum, mode: FileMode.WRITE_ONLY);
-    }
-    // Write index.
-    {
-      String outputPath = join(outputDirectoryPath, '$modeName.index');
-      File file = new File(outputPath);
-      file.writeAsBytesSync(index, mode: FileMode.WRITE_ONLY);
-    }
-  }
-}
-
 class _Output {
-  final _BuilderOutput spec;
-  final _BuilderOutput strong;
+  final BuilderOutput spec;
+  final BuilderOutput strong;
 
   _Output(this.spec, this.strong);
 }
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
index 1ff2c6e..676ecd6 100644
--- a/pkg/analyzer/tool/summary/dump_inferred_types.dart
+++ b/pkg/analyzer/tool/summary/dump_inferred_types.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:convert';
-import 'dart:io';
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index b776d51..a116073 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -664,6 +664,7 @@
   static AnalysisOptionsImpl createAnalysisOptionsForCommandLineOptions(
       CommandLineOptions options) {
     AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
+    contextOptions.trackCacheDependencies = false;
     contextOptions.hint = !options.disableHints;
     contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
     contextOptions.enableSuperMixins = options.enableSuperMixins;
diff --git a/pkg/analyzer_cli/lib/src/incremental_analyzer.dart b/pkg/analyzer_cli/lib/src/incremental_analyzer.dart
index f9d8d4c..d57327a 100644
--- a/pkg/analyzer_cli/lib/src/incremental_analyzer.dart
+++ b/pkg/analyzer_cli/lib/src/incremental_analyzer.dart
@@ -48,7 +48,7 @@
     context.resultProvider = new _CacheBasedResultProvider(context, cache);
     // Listen for new libraries to put into the cache.
     _IncrementalAnalysisSession session =
-        new _IncrementalAnalysisSession(options, context, cache);
+        new _IncrementalAnalysisSession(options, storage, context, cache);
     context
         .onResultChanged(LIBRARY_ELEMENT1)
         .listen((ResultChangedEvent event) {
@@ -172,13 +172,14 @@
 
 class _IncrementalAnalysisSession implements IncrementalAnalysisSession {
   final CommandLineOptions commandLineOptions;
+  final CacheStorage cacheStorage;
   final AnalysisContext context;
   final IncrementalCache cache;
 
   final Set<Source> newLibrarySources = new Set<Source>();
 
   _IncrementalAnalysisSession(
-      this.commandLineOptions, this.context, this.cache);
+      this.commandLineOptions, this.cacheStorage, this.context, this.cache);
 
   @override
   void finish() {
@@ -189,6 +190,8 @@
       }
       _putLibrary(librarySource);
     }
+    // Compact the cache.
+    cacheStorage.compact();
   }
 
   @override
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index a0ded9b..4e45320 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -11,7 +11,7 @@
   bazel_worker: ^0.1.0
   cli_util: ^0.0.1
   linter: ^0.1.16
-  package_config: ^0.1.1
+  package_config: ^0.1.5
   plugin: '>=0.1.0 <0.3.0'
   protobuf: ^0.5.0
   yaml: ^2.1.2
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 080a03b..5bbb2f0 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -44,7 +44,7 @@
 import 'tasks.dart' show CompilerTask;
 import 'work.dart' show ItemCompilationContext;
 
-abstract class Backend implements Target {
+abstract class Backend extends Target {
   final Compiler compiler;
 
   Backend(this.compiler);
@@ -404,6 +404,12 @@
   EnqueueTask makeEnqueuer() => new EnqueueTask(compiler);
 }
 
+/// Interface for resolving native data for a target specific element.
+abstract class NativeRegistry {
+  /// Registers [nativeData] as part of the resolution impact.
+  void registerNativeData(dynamic nativeData);
+}
+
 /// Interface for resolving calls to foreign functions.
 abstract class ForeignResolver {
   /// Returns the constant expression of [node], or `null` if [node] is not
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index 97b5b2d..515aa68 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -202,6 +202,10 @@
   /// have special treatment, such as being allowed to extends blacklisted
   /// classes or members being eagerly resolved.
   bool isTargetSpecificLibrary(LibraryElement element);
+
+  /// Resolve target specific information for [element] and register it with
+  /// [registry].
+  void resolveNativeElement(Element element, NativeRegistry registry) {}
 }
 
 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`.
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 18eeb52..28cc94a 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -3859,7 +3859,7 @@
     if (Elements.isLocal(element)) {
       LocalElement local = element;
       if (insideInitializer &&
-          local.isParameter &&
+          (local.isParameter || local.isInitializingFormal) &&
           local.enclosingElement == currentFunction) {
         assert(local.enclosingElement.isConstructor);
         // Initializers in an initializer-list can communicate via parameters.
@@ -3871,7 +3871,9 @@
         // outlive the activation of the function).
         markAsCaptured(local);
       } else if (inTryStatement) {
-        assert(local.isParameter || local.isVariable);
+        assert(local.isParameter ||
+            local.isVariable ||
+            local.isInitializingFormal);
         // Search for the position of the try block containing the variable
         // declaration, or -1 if it is declared outside the outermost try.
         int i = tryNestingStack.length - 1;
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 0020393..5ff8341 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -608,34 +608,48 @@
   }
 }
 
+enum _FromEnvironmentState { NOT, BOOL, INT, STRING, }
+
 abstract class ConstructorElementCommon implements ConstructorElement {
+  _FromEnvironmentState _fromEnvironmentState;
+
+  _FromEnvironmentState get fromEnvironmentState {
+    if (_fromEnvironmentState == null) {
+      _fromEnvironmentState = _FromEnvironmentState.NOT;
+      if (name == Identifiers.fromEnvironment && library.isDartCore) {
+        switch (enclosingClass.name) {
+          case 'bool':
+            _fromEnvironmentState = _FromEnvironmentState.BOOL;
+            break;
+          case 'int':
+            _fromEnvironmentState = _FromEnvironmentState.INT;
+            break;
+          case 'String':
+            _fromEnvironmentState = _FromEnvironmentState.STRING;
+            break;
+        }
+      }
+    }
+    return _fromEnvironmentState;
+  }
+
   @override
   bool get isFromEnvironmentConstructor {
-    return name == Identifiers.fromEnvironment &&
-        library.isDartCore &&
-        (enclosingClass.name == 'bool' ||
-            enclosingClass.name == 'int' ||
-            enclosingClass.name == 'String');
+    return fromEnvironmentState != _FromEnvironmentState.NOT;
   }
 
   @override
   bool get isIntFromEnvironmentConstructor {
-    return name == Identifiers.fromEnvironment &&
-        library.isDartCore &&
-        enclosingClass.name == 'int';
+    return fromEnvironmentState == _FromEnvironmentState.INT;
   }
 
   @override
   bool get isBoolFromEnvironmentConstructor {
-    return name == Identifiers.fromEnvironment &&
-        library.isDartCore &&
-        enclosingClass.name == 'bool';
+    return fromEnvironmentState == _FromEnvironmentState.BOOL;
   }
 
   @override
   bool get isStringFromEnvironmentConstructor {
-    return name == Identifiers.fromEnvironment &&
-        library.isDartCore &&
-        enclosingClass.name == 'String';
+    return fromEnvironmentState == _FromEnvironmentState.STRING;
   }
 }
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 29ae8ea..bcaec4a 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -199,25 +199,12 @@
       // classes, which may not be the case when a native class is subclassed.
       if (compiler.backend.isNative(cls)) {
         compiler.world.registerUsedElement(member);
-        nativeEnqueuer.handleFieldAnnotations(member);
         if (universe.hasInvokedGetter(member, compiler.world) ||
             universe.hasInvocation(member, compiler.world)) {
-          nativeEnqueuer.registerFieldLoad(member);
-          // In handleUnseenSelector we can't tell if the field is loaded or
-          // stored.  We need the basic algorithm to be Church-Rosser, since the
-          // resolution 'reduction' order is different to the codegen order. So
-          // register that the field is also stored.  In other words: if we
-          // don't register the store here during resolution, the store could be
-          // registered during codegen on the handleUnseenSelector path, and
-          // cause the set of codegen elements to include unresolved elements.
-          nativeEnqueuer.registerFieldStore(member);
           addToWorkList(member);
           return;
         }
         if (universe.hasInvokedSetter(member, compiler.world)) {
-          nativeEnqueuer.registerFieldStore(member);
-          // See comment after registerFieldLoad above.
-          nativeEnqueuer.registerFieldLoad(member);
           addToWorkList(member);
           return;
         }
@@ -549,25 +536,6 @@
         if (member.isFunction && selector.isGetter) {
           registerClosurizedMember(member);
         }
-        if (member.isField &&
-            compiler.backend.isNative(member.enclosingClass)) {
-          if (selector.isGetter || selector.isCall) {
-            nativeEnqueuer.registerFieldLoad(member);
-            // We have to also handle storing to the field because we only get
-            // one look at each member and there might be a store we have not
-            // seen yet.
-            // TODO(sra): Process fields for storing separately.
-            nativeEnqueuer.registerFieldStore(member);
-          } else {
-            assert(selector.isSetter);
-            nativeEnqueuer.registerFieldStore(member);
-            // We have to also handle loading from the field because we only get
-            // one look at each member and there might be a load we have not
-            // seen yet.
-            // TODO(sra): Process fields for storing separately.
-            nativeEnqueuer.registerFieldLoad(member);
-          }
-        }
         addToWorkList(member);
         return true;
       }
@@ -810,7 +778,6 @@
       compiler.enabledFunctionApply = true;
     }
 
-    nativeEnqueuer.registerElement(element);
     return true;
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index a65d3e3..c2956ff 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -290,10 +290,7 @@
   }
 
   bool isNativeElement(Element element) {
-    if (compiler.backend.isNative(element)) return true;
-    return element.isClassMember &&
-        compiler.backend.isNative(element.enclosingClass) &&
-        element.isField;
+    return compiler.backend.isNative(element);
   }
 
   void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments);
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index ea9e893..3b0127a 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -473,7 +473,7 @@
       if (element.isField) {
         return inferrer
             .typeOfNativeBehavior(
-                native.NativeBehavior.ofFieldLoad(element, inferrer.compiler))
+                inferrer.backend.getNativeFieldLoadBehavior(element))
             .type;
       } else {
         assert(element.isFunction ||
@@ -487,7 +487,7 @@
         } else {
           return inferrer
               .typeOfNativeBehavior(
-                  native.NativeBehavior.ofMethod(element, inferrer.compiler))
+                  inferrer.backend.getNativeMethodBehavior(element))
               .type;
         }
       }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index e8f43ca..e04aa6c 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -736,6 +736,56 @@
   @override
   bool isNative(Element element) => nativeData.isNative(element);
 
+  /// Returns the [NativeBehavior] for calling the native [method].
+  native.NativeBehavior getNativeMethodBehavior(FunctionElement method) {
+    return nativeData.getNativeMethodBehavior(method);
+  }
+
+  /// Returns the [NativeBehavior] for reading from the native [field].
+  native.NativeBehavior getNativeFieldLoadBehavior(FieldElement field) {
+    return nativeData.getNativeFieldLoadBehavior(field);
+  }
+
+  /// Returns the [NativeBehavior] for writing to the native [field].
+  native.NativeBehavior getNativeFieldStoreBehavior(FieldElement field) {
+    return nativeData.getNativeFieldStoreBehavior(field);
+  }
+
+  @override
+  void resolveNativeElement(Element element, NativeRegistry registry) {
+    if (element.isFunction ||
+        element.isConstructor ||
+        element.isGetter ||
+        element.isSetter) {
+      compiler.enqueuer.resolution.nativeEnqueuer
+          .handleMethodAnnotations(element);
+      if (isNative(element)) {
+        native.NativeBehavior behavior =
+            native.NativeBehavior.ofMethod(element, compiler);
+        nativeData.setNativeMethodBehavior(element, behavior);
+        registry.registerNativeData(behavior);
+      }
+    } else if (element.isField) {
+      compiler.enqueuer.resolution.nativeEnqueuer
+          .handleFieldAnnotations(element);
+      if (isNative(element)) {
+        native.NativeBehavior fieldLoadBehavior =
+            native.NativeBehavior.ofFieldLoad(element, compiler);
+        native.NativeBehavior fieldStoreBehavior =
+            native.NativeBehavior.ofFieldStore(element, compiler);
+        nativeData.setNativeFieldLoadBehavior(element, fieldLoadBehavior);
+        nativeData.setNativeFieldStoreBehavior(element, fieldStoreBehavior);
+
+        // TODO(sra): Process fields for storing separately.
+        // We have to handle both loading and storing to the field because we
+        // only get one look at each member and there might be a load or store
+        // we have not seen yet.
+        registry.registerNativeData(fieldLoadBehavior);
+        registry.registerNativeData(fieldStoreBehavior);
+      }
+    }
+  }
+
   bool isNativeOrExtendsNative(ClassElement element) {
     if (element == null) return false;
     if (isNative(element) || isJsInterop(element)) {
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 900a965..5e5424f 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -13,7 +13,7 @@
 import '../closure.dart';
 import '../common.dart';
 import '../common/backend_api.dart'
-    show Backend, ImpactTransformer, ForeignResolver;
+    show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
 import '../common/names.dart' show Identifiers, Names, Selectors, Uris;
 import '../common/registry.dart' show EagerRegistry, Registry;
@@ -38,8 +38,6 @@
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../dump_info.dart' show DumpInfoTask;
 import '../elements/elements.dart';
-import '../elements/modelx.dart'
-    show ConstructorBodyElementX, FieldElementX, DeferredLoaderGetterElementX;
 import '../elements/visitor.dart' show BaseElementVisitor;
 import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
 import '../io/code_output.dart';
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index 49a207d..42712f0 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -6,7 +6,8 @@
 
 import '../common.dart';
 import '../elements/elements.dart'
-    show ClassElement, Element, FunctionElement, MemberElement;
+    show ClassElement, Element, FieldElement, FunctionElement, MemberElement;
+import '../native/behavior.dart' show NativeBehavior;
 
 /// Additional element information for native classes and methods and js-interop
 /// methods.
@@ -22,6 +23,19 @@
   /// [setNativeClassTagInfo].
   Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
 
+  // TODO(johnniwinther): Serialize these.
+  /// Cache for [NativeBehavior]s for calling native methods.
+  Map<FunctionElement, NativeBehavior> nativeMethodBehavior =
+      <FunctionElement, NativeBehavior>{};
+
+  /// Cache for [NativeBehavior]s for reading from native fields.
+  Map<MemberElement, NativeBehavior> nativeFieldLoadBehavior =
+      <FieldElement, NativeBehavior>{};
+
+  /// Cache for [NativeBehavior]s for writing to native fields.
+  Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior =
+      <FieldElement, NativeBehavior>{};
+
   /// Returns `true` if [element] is explicitly marked as part of JsInterop.
   bool _isJsInterop(Element element) {
     return jsInteropNames.containsKey(element.declaration);
@@ -163,4 +177,44 @@
   bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
     return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
   }
+
+  /// Returns the [NativeBehavior] for calling the native [method].
+  NativeBehavior getNativeMethodBehavior(FunctionElement method) {
+    assert(invariant(method, nativeMethodBehavior.containsKey(method),
+        message: "No native method behavior has been computed for $method."));
+    return nativeMethodBehavior[method];
+  }
+
+  /// Returns the [NativeBehavior] for reading from the native [field].
+  NativeBehavior getNativeFieldLoadBehavior(FieldElement field) {
+    assert(invariant(field, nativeFieldLoadBehavior.containsKey(field),
+        message: "No native field load behavior has been "
+            "computed for $field."));
+    return nativeFieldLoadBehavior[field];
+  }
+
+  /// Returns the [NativeBehavior] for writing to the native [field].
+  NativeBehavior getNativeFieldStoreBehavior(FieldElement field) {
+    assert(invariant(field, nativeFieldStoreBehavior.containsKey(field),
+        message: "No native field store behavior has been "
+            "computed for $field."));
+    return nativeFieldStoreBehavior[field];
+  }
+
+  /// Registers the [behavior] for calling the native [method].
+  void setNativeMethodBehavior(
+      FunctionElement method, NativeBehavior behavior) {
+    nativeMethodBehavior[method] = behavior;
+  }
+
+  /// Registers the [behavior] for reading from the native [field].
+  void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior) {
+    nativeFieldLoadBehavior[field] = behavior;
+  }
+
+  /// Registers the [behavior] for writing to the native [field].
+  void setNativeFieldStoreBehavior(
+      FieldElement field, NativeBehavior behavior) {
+    nativeFieldStoreBehavior[field] = behavior;
+  }
 }
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index daa6ddc..a4e2922 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -705,13 +705,12 @@
     behavior._capture(type, compiler.resolution,
         isInterop: isInterop, compiler: compiler);
 
-    // TODO(sra): Optional arguments are currently missing from the
-    // DartType. This should be fixed so the following work-around can be
-    // removed.
-    method.functionSignature
-        .forEachOptionalParameter((ParameterElement parameter) {
-      behavior._escape(parameter.type, compiler.resolution);
-    });
+    for (DartType type in type.optionalParameterTypes) {
+      behavior._escape(type, compiler.resolution);
+    }
+    for (DartType type in type.namedParameterTypes) {
+      behavior._escape(type, compiler.resolution);
+    }
 
     behavior._overrideWithAnnotations(method, compiler);
     return behavior;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index f38ccc4..63b601d 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -34,19 +34,17 @@
   /// types to the world.
   void registerNativeBehavior(NativeBehavior nativeBehavior, cause) {}
 
-  /// Notification of a main Enqueuer worklist element.  For methods, adds
-  /// information from metadata attributes, and computes types instantiated due
-  /// to calling the method.
-  void registerElement(Element element) {}
-
-  /// Notification of native field.  Adds information from metadata attributes.
+  // TODO(johnniwinther): Move [handleFieldAnnotations] and
+  // [handleMethodAnnotations] to [JavaScriptBackend] or [NativeData].
+  // TODO(johnniwinther): Change the return type to 'bool' and rename them to
+  // something like `computeNativeField`.
+  /// Process the potentially native [field]. Adds information from metadata
+  /// attributes.
   void handleFieldAnnotations(Element field) {}
 
-  /// Computes types instantiated due to getting a native field.
-  void registerFieldLoad(Element field) {}
-
-  /// Computes types instantiated due to setting a native field.
-  void registerFieldStore(Element field) {}
+  /// Process the potentially native [method]. Adds information from metadata
+  /// attributes.
+  void handleMethodAnnotations(Element method) {}
 
   /// Returns whether native classes are being used.
   bool hasInstantiatedNativeClasses() => false;
@@ -371,26 +369,6 @@
     }
   }
 
-  registerElement(Element element) {
-    reporter.withCurrentElement(element, () {
-      if (element.isFunction ||
-          element.isFactoryConstructor ||
-          element.isGetter ||
-          element.isSetter) {
-        handleMethodAnnotations(element);
-        if (backend.isNative(element)) {
-          registerMethodUsed(element);
-        }
-      } else if (element.isField) {
-        handleFieldAnnotations(element);
-        if (backend.isNative(element)) {
-          registerFieldLoad(element);
-          registerFieldStore(element);
-        }
-      }
-    });
-  }
-
   void handleFieldAnnotations(Element element) {
     if (compiler.serialization.isDeserialized(element)) {
       return;
@@ -475,18 +453,6 @@
     flushQueue();
   }
 
-  void registerMethodUsed(Element method) {
-    registerNativeBehavior(NativeBehavior.ofMethod(method, compiler), method);
-  }
-
-  void registerFieldLoad(Element field) {
-    registerNativeBehavior(NativeBehavior.ofFieldLoad(field, compiler), field);
-  }
-
-  void registerFieldStore(Element field) {
-    registerNativeBehavior(NativeBehavior.ofFieldStore(field, compiler), field);
-  }
-
   processNativeBehavior(NativeBehavior behavior, cause) {
     // TODO(ahe): Is this really a global dependency?
     Registry registry = compiler.globalDependencies;
diff --git a/pkg/compiler/lib/src/parser/listener.dart b/pkg/compiler/lib/src/parser/listener.dart
index afd2997..ce29d16 100644
--- a/pkg/compiler/lib/src/parser/listener.dart
+++ b/pkg/compiler/lib/src/parser/listener.dart
@@ -319,9 +319,7 @@
 
   void endWhileStatement(Token whileKeyword, Token endToken) {}
 
-  void handleAsOperator(Token operathor, Token endToken) {
-    // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
-  }
+  void handleAsOperator(Token operator, Token endToken) {}
 
   void handleAssignmentExpression(Token token) {}
 
@@ -338,9 +336,7 @@
   void handleIndexedExpression(
       Token openCurlyBracket, Token closeCurlyBracket) {}
 
-  void handleIsOperator(Token operathor, Token not, Token endToken) {
-    // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
-  }
+  void handleIsOperator(Token operator, Token not, Token endToken) {}
 
   void handleLiteralBool(Token token) {}
 
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index b5cb91d..feaa44c 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -265,11 +265,11 @@
     pushNode(new Cascade(popNode()));
   }
 
-  void handleAsOperator(Token operathor, Token endToken) {
+  void handleAsOperator(Token operator, Token endToken) {
     TypeAnnotation type = popNode();
     Expression expression = popNode();
     NodeList arguments = new NodeList.singleton(type);
-    pushNode(new Send(expression, new Operator(operathor), arguments));
+    pushNode(new Send(expression, new Operator(operator), arguments));
   }
 
   void handleAssignmentExpression(Token token) {
@@ -759,7 +759,7 @@
         Modifiers.EMPTY, null, null, asyncModifier));
   }
 
-  void handleIsOperator(Token operathor, Token not, Token endToken) {
+  void handleIsOperator(Token operator, Token not, Token endToken) {
     TypeAnnotation type = popNode();
     Expression expression = popNode();
     Node argument;
@@ -770,7 +770,7 @@
     }
 
     NodeList arguments = new NodeList.singleton(argument);
-    pushNode(new Send(expression, new Operator(operathor), arguments));
+    pushNode(new Send(expression, new Operator(operator), arguments));
   }
 
   void handleLabel(Token colon) {
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 3658a7d..871f6af 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -2573,6 +2573,11 @@
       } else {
         semantics = new StaticAccess.parameter(element);
       }
+    } else if (element.isInitializingFormal &&
+        compiler.options.enableInitializingFormalAccess) {
+      error = reportAndCreateErroneousElement(node.selector, name.text,
+          MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER, {'name': name});
+      semantics = new StaticAccess.finalParameter(element);
     } else if (element.isVariable) {
       if (element.isFinal || element.isConst) {
         error = reportAndCreateErroneousElement(node.selector, name.text,
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 6d56c8e..54bd495 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -5,7 +5,8 @@
 library dart2js.resolution.registry;
 
 import '../common.dart';
-import '../common/backend_api.dart' show Backend, ForeignResolver;
+import '../common/backend_api.dart'
+    show Backend, ForeignResolver, NativeRegistry;
 import '../common/resolution.dart'
     show Feature, ListLiteralUse, MapLiteralUse, ResolutionImpact;
 import '../common/registry.dart' show Registry;
@@ -28,7 +29,9 @@
 import 'members.dart' show ResolverVisitor;
 import 'tree_elements.dart' show TreeElementMapping;
 
-class _ResolutionWorldImpact extends ResolutionImpact with WorldImpactBuilder {
+class _ResolutionWorldImpact extends ResolutionImpact
+    with WorldImpactBuilder
+    implements NativeRegistry {
   final String name;
   EnumSet<Feature> _features;
   Setlet<MapLiteralUse> _mapLiterals;
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 9317d30..f1ca6d0 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -285,6 +285,8 @@
         reporter.reportErrorMessage(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE);
       }
 
+      resolution.target.resolveNativeElement(element, registry.worldImpact);
+
       return registry.worldImpact;
     });
   }
@@ -414,6 +416,8 @@
     // Perform various checks as side effect of "computing" the type.
     element.computeType(resolution);
 
+    resolution.target.resolveNativeElement(element, registry.worldImpact);
+
     return registry.worldImpact;
   }
 
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 20aaf32..e1eee00c 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -505,7 +505,7 @@
     // Strengthen instruction type from annotations to help optimize
     // dependent instructions.
     native.NativeBehavior nativeBehavior =
-        native.NativeBehavior.ofMethod(method, compiler);
+        backend.getNativeMethodBehavior(method);
     TypeMask returnType =
         TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
     HInvokeDynamicMethod result =
@@ -869,7 +869,7 @@
     TypeMask type;
     if (backend.isNative(field.enclosingClass)) {
       type = TypeMaskFactory.fromNativeBehavior(
-          native.NativeBehavior.ofFieldLoad(field, compiler), compiler);
+          backend.getNativeFieldLoadBehavior(field), compiler);
     } else {
       type = TypeMaskFactory.inferredTypeForElement(field, compiler);
     }
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 2a8ab08..69137ab 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -681,7 +681,12 @@
       assert(invariant(node, element != null,
           message: 'Missing element for identifier'));
       assert(invariant(
-          node, element.isVariable || element.isParameter || element.isField,
+          node,
+          element.isVariable ||
+              element.isParameter ||
+              element.isField ||
+              (element.isInitializingFormal &&
+                  compiler.options.enableInitializingFormalAccess),
           message: 'Unexpected context element ${element}'));
       return element.computeType(resolution);
     }
@@ -766,7 +771,10 @@
       return access;
     }
     if (receiverElement != null &&
-        (receiverElement.isVariable || receiverElement.isParameter)) {
+        (receiverElement.isVariable ||
+            receiverElement.isParameter ||
+            (receiverElement.isInitializingFormal &&
+                compiler.options.enableInitializingFormalAccess))) {
       Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
       if (typePromotions != null) {
         while (!typePromotions.isEmpty) {
@@ -1082,7 +1090,10 @@
   }
 
   ElementAccess createPromotedAccess(Element element) {
-    if (element.isVariable || element.isParameter) {
+    if (element.isVariable ||
+        element.isParameter ||
+        (element.isInitializingFormal &&
+            compiler.options.enableInitializingFormalAccess)) {
       TypePromotion typePromotion = getKnownTypePromotion(element);
       if (typePromotion != null) {
         return new PromotedAccess(element, typePromotion.type);
@@ -1217,7 +1228,11 @@
           }
         }
 
-        if (variable != null && (variable.isVariable || variable.isParameter)) {
+        if (variable != null &&
+            (variable.isVariable ||
+                variable.isParameter ||
+                (variable.isInitializingFormal &&
+                    compiler.options.enableInitializingFormalAccess))) {
           DartType knownType = getKnownType(variable);
           if (!knownType.isDynamic) {
             DartType shownType = elements.getType(node.arguments.head);
diff --git a/pkg/dart_messages/lib/shared_messages.dart b/pkg/dart_messages/lib/shared_messages.dart
index c2e73c7..ae91711 100644
--- a/pkg/dart_messages/lib/shared_messages.dart
+++ b/pkg/dart_messages/lib/shared_messages.dart
@@ -682,6 +682,8 @@
       template: "The setter '#{memberName}' is not defined for the "
           "class '#{className}'.",
       usedBy: [dart2js, analyzer],
+      // TODO(eernst): When this.x access is available, add examples here,
+      // e.g., "class A { var x; A(this.x) : x = 3; } main() => new A(2);"
       examples: const ["class A {} main() { new A().x = 499; }",]),
 
   'NO_SUCH_SUPER_MEMBER': new Message(
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index 6d83624..6e1655ae 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 1.0.0
+* First stable API release.
+
 ## 0.12.2
 * Updated `@protected` to include implemented interfaces (linter#252).
 
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index 7daaa74..a629570 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
 name: meta
-version: 0.12.2
+version: 1.0.0
 author: Dart Team <misc@dartlang.org>
 homepage: http://www.dartlang.org
 description: >
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 9fa4651..4ddace9 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -84,6 +84,7 @@
 analyzer/test/generated/strong_mode_test: Pass, Slow # Issue 21628
 analyzer/test/generated/type_system_test: Pass, Slow # Issue 21628
 analyzer/test/generated/utilities_test: Pass, Slow # Issue 21628
+analyzer/test/source/package_map_provider_test: Skip # Issue 21628
 analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
 analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
 analyzer/test/src/dart/ast/utilities_test: Pass, Slow # Issue 24914
@@ -117,6 +118,7 @@
 analyzer/test/src/task/strong/checker_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/strong/inferred_type_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/yaml_test: Pass, Slow # Issue 21628
+analyzer/tool/task_dependency_graph/check_test: Skip # Issue 21628
 collection/test/equality_test/01: Fail # Issue 1533
 collection/test/equality_test/02: Fail # Issue 1533
 collection/test/equality_test/03: Fail # Issue 1533
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index c0d6072..a57ef87 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -408,11 +408,12 @@
 Dart_Handle DartUtils::LibraryTagHandler(Dart_LibraryTag tag,
                                          Dart_Handle library,
                                          Dart_Handle url) {
-  if (tag == Dart_kCanonicalizeUrl) {
-    return Dart_DefaultCanonicalizeUrl(library, url);
+  Dart_Handle library_url = Dart_LibraryUrl(library);
+  if (Dart_IsError(library_url)) {
+    return library_url;
   }
-  if (!Dart_IsLibrary(library)) {
-    return Dart_NewApiError("not a library");
+  if (tag == Dart_kCanonicalizeUrl) {
+    return Dart_DefaultCanonicalizeUrl(library_url, url);
   }
   if (!Dart_IsString(url)) {
     return Dart_NewApiError("url is not a string");
@@ -422,7 +423,6 @@
   if (Dart_IsError(result)) {
     return result;
   }
-  Dart_Handle library_url = Dart_LibraryUrl(library);
   const char* library_url_string = NULL;
   result = Dart_StringToCString(library_url, &library_url_string);
   if (Dart_IsError(result)) {
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 2c153bc..6b22793 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -81,7 +81,9 @@
     kLockUnlock = 0,
     kLockShared = 1,
     kLockExclusive = 2,
-    kLockMax = 2
+    kLockBlockingShared = 3,
+    kLockBlockingExclusive = 4,
+    kLockMax = 4
   };
 
   intptr_t GetFD();
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 8b86121..9bcf44c 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -139,9 +139,11 @@
       fl.l_type = F_UNLCK;
       break;
     case File::kLockShared:
+    case File::kLockBlockingShared:
       fl.l_type = F_RDLCK;
       break;
     case File::kLockExclusive:
+    case File::kLockBlockingExclusive:
       fl.l_type = F_WRLCK;
       break;
     default:
@@ -150,9 +152,12 @@
   fl.l_whence = SEEK_SET;
   fl.l_start = start;
   fl.l_len = end == -1 ? 0 : end - start;
-  // fcntl does not block, but fails if the lock cannot be acquired.
-  int rc = fcntl(handle_->fd(), F_SETLK, &fl);
-  return rc != -1;
+  int cmd = F_SETLK;
+  if ((lock == File::kLockBlockingShared) ||
+      (lock == File::kLockBlockingExclusive)) {
+    cmd = F_SETLKW;
+  }
+  return TEMP_FAILURE_RETRY(fcntl(handle_->fd(), cmd, &fl)) != -1;
 }
 
 
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 2e47d74..eab92d5 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -136,9 +136,11 @@
       fl.l_type = F_UNLCK;
       break;
     case File::kLockShared:
+    case File::kLockBlockingShared:
       fl.l_type = F_RDLCK;
       break;
     case File::kLockExclusive:
+    case File::kLockBlockingExclusive:
       fl.l_type = F_WRLCK;
       break;
     default:
@@ -147,9 +149,12 @@
   fl.l_whence = SEEK_SET;
   fl.l_start = start;
   fl.l_len = end == -1 ? 0 : end - start;
-  // fcntl does not block, but fails if the lock cannot be acquired.
-  int rc = fcntl(handle_->fd(), F_SETLK, &fl);
-  return rc != -1;
+  int cmd = F_SETLK;
+  if ((lock == File::kLockBlockingShared) ||
+      (lock == File::kLockBlockingExclusive)) {
+    cmd = F_SETLKW;
+  }
+  return TEMP_FAILURE_RETRY(fcntl(handle_->fd(), cmd, &fl)) != -1;
 }
 
 
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 941d419..a43b14e 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -139,9 +139,11 @@
       fl.l_type = F_UNLCK;
       break;
     case File::kLockShared:
+    case File::kLockBlockingShared:
       fl.l_type = F_RDLCK;
       break;
     case File::kLockExclusive:
+    case File::kLockBlockingExclusive:
       fl.l_type = F_WRLCK;
       break;
     default:
@@ -150,9 +152,12 @@
   fl.l_whence = SEEK_SET;
   fl.l_start = start;
   fl.l_len = end == -1 ? 0 : end - start;
-  // fcntl does not block, but fails if the lock cannot be acquired.
-  int rc = fcntl(handle_->fd(), F_SETLK, &fl);
-  return rc != -1;
+  int cmd = F_SETLK;
+  if ((lock == File::kLockBlockingShared) ||
+      (lock == File::kLockBlockingExclusive)) {
+    cmd = F_SETLKW;
+  }
+  return TEMP_FAILURE_RETRY(fcntl(handle_->fd(), cmd, &fl)) != -1;
 }
 
 
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index db3aef8..8d45a17 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -138,9 +138,15 @@
       rc = UnlockFileEx(handle, 0, length_low, length_high, &overlapped);
       break;
     case File::kLockShared:
-    case File::kLockExclusive: {
-      DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
-      if (lock == File::kLockExclusive) {
+    case File::kLockExclusive:
+    case File::kLockBlockingShared:
+    case File::kLockBlockingExclusive: {
+      DWORD flags = 0;
+      if ((lock == File::kLockShared) || (lock == File::kLockExclusive)) {
+        flags |= LOCKFILE_FAIL_IMMEDIATELY;
+      }
+      if ((lock == File::kLockExclusive) ||
+          (lock == File::kLockBlockingExclusive)) {
         flags |= LOCKFILE_EXCLUSIVE_LOCK;
       }
       rc = LockFileEx(handle, flags, 0,
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index f43cf30..4b887ad 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -212,18 +212,20 @@
 }
 
 
-bool Loader::ProcessResultLocked(Loader::IOResult* result) {
-  // A negative result tag indicates a loading error occurred in the service
-  // isolate. The payload is a C string of the error message.
-  if (result->tag < 0) {
-    error_ =
-        Dart_NewUnhandledExceptionError(
-            Dart_NewStringFromUTF8(result->payload,
-                                   result->payload_length));
-
-    return false;
+static bool LibraryHandleError(Dart_Handle library, Dart_Handle error) {
+  if (!Dart_IsNull(library) && !Dart_IsError(library)) {
+    ASSERT(Dart_IsLibrary(library));
+    Dart_Handle res = Dart_LibraryHandleError(library, error);
+    if (Dart_IsNull(res)) {
+      // Error was handled by library.
+      return true;
+    }
   }
+  return false;
+}
 
+
+bool Loader::ProcessResultLocked(Loader::IOResult* result) {
   // We have to copy everything we care about out of |result| because after
   // dropping the lock below |result| may no longer valid.
   Dart_Handle uri =
@@ -233,6 +235,25 @@
     library_uri =
         Dart_NewStringFromCString(reinterpret_cast<char*>(result->library_uri));
   }
+
+  // A negative result tag indicates a loading error occurred in the service
+  // isolate. The payload is a C string of the error message.
+  if (result->tag < 0) {
+    Dart_Handle library = Dart_LookupLibrary(uri);
+    Dart_Handle error = Dart_NewStringFromUTF8(result->payload,
+                                               result->payload_length);
+    // If a library with the given uri exists, give it a chance to handle
+    // the error. If the load requests stems from a deferred library load,
+    // an IO error is not fatal.
+    if (LibraryHandleError(library, error)) {
+      return true;
+    }
+    // Fall through
+    error_ = Dart_NewUnhandledExceptionError(error);
+    return false;
+  }
+
+
   // Check for payload and load accordingly.
   bool is_snapshot = false;
   const uint8_t* payload = result->payload;
@@ -341,7 +362,11 @@
                                       Dart_Handle library,
                                       Dart_Handle url) {
   if (tag == Dart_kCanonicalizeUrl) {
-    return Dart_DefaultCanonicalizeUrl(library, url);
+    Dart_Handle library_url = Dart_LibraryUrl(library);
+    if (Dart_IsError(library_url)) {
+      return library_url;
+    }
+    return Dart_DefaultCanonicalizeUrl(library_url, url);
   }
   const char* url_string = NULL;
   Dart_Handle result = Dart_StringToCString(url, &url_string);
@@ -353,6 +378,9 @@
   if (tag != Dart_kScriptTag) {
     // Grab the library's url.
     Dart_Handle library_url = Dart_LibraryUrl(library);
+    if (Dart_IsError(library_url)) {
+      return library_url;
+    }
     const char* library_url_string = NULL;
     result = Dart_StringToCString(library_url, &library_url_string);
     if (Dart_IsError(result)) {
@@ -378,6 +406,9 @@
                                  url_string);
     }
     Dart_Handle library_url = Dart_LibraryUrl(library);
+    if (Dart_IsError(library_url)) {
+      return library_url;
+    }
     Dart_Handle library_file_path = DartUtils::LibraryFilePath(library_url);
     const char* lib_path_str = NULL;
     Dart_StringToCString(library_file_path, &lib_path_str);
@@ -402,8 +433,11 @@
 
   // The outer invocation of the tag handler for this isolate. We make the outer
   // invocation block and allow any nested invocations to operate in parallel.
-  bool blocking_call = !isolate_data->HasLoader();
+  const bool blocking_call = !isolate_data->HasLoader();
 
+  // If we are the outer invocation of the tag handler and the tag is an import
+  // this means that we are starting a deferred library load.
+  const bool is_deferred_import = blocking_call && (tag == Dart_kImportTag);
   if (!isolate_data->HasLoader()) {
     // The isolate doesn't have a loader -- this is the outer invocation which
     // will block.
@@ -440,8 +474,23 @@
     delete loader;
 
     // An error occurred during loading.
-    if (Dart_IsError(error)) {
-      return error;
+    if (!Dart_IsNull(error)) {
+      if (false && is_deferred_import) {
+        // This blocks handles transitive load errors caused by a deferred
+        // import. Non-transitive load errors are handled above (see callers of
+        // |LibraryHandleError|). To handle the transitive case, we give the
+        // originating deferred library an opportunity to handle it.
+        Dart_Handle deferred_library = Dart_LookupLibrary(url);
+        if (!LibraryHandleError(deferred_library, error)) {
+          // Library did not handle it, return to caller as an unhandled
+          // exception.
+          return Dart_NewUnhandledExceptionError(error);
+        }
+      } else {
+        // We got an error during loading but we aren't loading a deferred
+        // library, return the error to the caller.
+        return error;
+      }
     }
 
     // Finalize loading. This will complete any futures for completed deferred
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index bab237b..792ea45 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -38,7 +38,6 @@
   IsolateData* isolate_data_;
   // Remember the first error that occurs during loading.
   Dart_Handle error_;
-
   // This monitor is used to protect the pending operations count and the
   // I/O result queue.
   Monitor* monitor_;
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index 42bc6f9..82fbe5e 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -115,15 +115,17 @@
   Map<String, Uri> _packageMap = null;
 
   _setPackageRoot(String packageRoot) {
-    packageRoot = _enforceTrailingSlash(packageRoot);
+    packageRoot = _sanitizeWindowsPath(packageRoot);
     if (packageRoot.startsWith('file:') ||
         packageRoot.startsWith('http:') ||
         packageRoot.startsWith('https:')) {
+      packageRoot = _enforceTrailingSlash(packageRoot);
       _packageRoot = _workingDirectory.resolve(packageRoot);
     } else {
       packageRoot = _sanitizeWindowsPath(packageRoot);
       packageRoot = _trimWindowsPath(packageRoot);
-      _packageRoot = _workingDirectory.resolveUri(new Uri.file(packageRoot));
+      _packageRoot =
+          _workingDirectory.resolveUri(new Uri.directory(packageRoot));
     }
   }
 
@@ -162,12 +164,12 @@
   List<Function> _pendingPackageLoads = [];
 
   // Given a uri with a 'package' scheme, return a Uri that is prefixed with
-  // the package root.
+  // the package root or resolved relative to the package configuration.
   Uri _resolvePackageUri(Uri uri) {
     assert(uri.scheme == "package");
     assert(_packagesReady);
 
-    if (!uri.host.isEmpty) {
+    if (uri.host.isNotEmpty) {
       var path = '${uri.host}${uri.path}';
       var right = 'package:$path';
       var wrong = 'package://$path';
@@ -176,6 +178,12 @@
             "'$right', not '$wrong'.";
     }
 
+    var packageNameEnd = uri.path.indexOf('/');
+    if (packageNameEnd == 0) {
+      // Package URIs must have a non-empty package name (not start with "/").
+      throw "URIS using the 'package:' scheme should look like "
+            "'package:packageName${uri.path}', not 'package:${uri.path}'";
+    }
     if (_traceLoading) {
       _log('Resolving package with uri path: ${uri.path}');
     }
@@ -188,7 +196,13 @@
     } else if (_packageRoot != null) {
       resolvedUri = _packageRoot.resolve(uri.path);
     } else {
-      var packageName = uri.pathSegments[0];
+      if (packageNameEnd < 0) {
+        // Package URIs must have a path after the package name, even if it's
+        // just "/".
+        throw "URIS using the 'package:' scheme should look like "
+              "'package:${uri.path}/', not 'package:${uri.path}'";
+      }
+      var packageName = uri.path.substring(0, packageNameEnd);
       var mapping = _packageMap[packageName];
       if (_traceLoading) {
         _log("Mapped '$packageName' package to '$mapping'");
@@ -197,14 +211,8 @@
         throw "No mapping for '$packageName' package when resolving '$uri'.";
       }
       var path;
-      if (uri.path.length > packageName.length) {
-        path = uri.path.substring(packageName.length + 1);
-      } else {
-        // Handle naked package resolution to the default package name:
-        // package:foo is equivalent to package:foo/foo.dart
-        assert(uri.path.length == packageName.length);
-        path = "$packageName.dart";
-      }
+      assert(uri.path.length > packageName.length);
+      path = uri.path.substring(packageName.length + 1);
       if (_traceLoading) {
         _log("Path to be resolved in package: $path");
       }
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index e27d70e..123064c 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2692,15 +2692,15 @@
  * This canonicalization function should be sufficient for most
  * embedders to implement the Dart_kCanonicalizeUrl tag.
  *
- * \param library The library relative to which the url is being
- *                resolved.
+ * \param base_url The base url relative to which the url is
+ *                being resolved.
  * \param url The url being resolved and canonicalized.  This
  *            parameter is a string handle.
  *
  * \return If no error occurs, a String object is returned.  Otherwise
  *   an error handle is returned.
  */
-DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle library,
+DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
                                                     Dart_Handle url);
 
 /**
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 98814f8..8c995a4 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -26,6 +26,11 @@
   static _throwNew(int assertionStart, int assertionEnd)
       native "AssertionError_throwNew";
 
+  static _handleCondition(condition) {
+    if (condition is Function) return condition();
+    return condition;
+  }
+
   String toString() {
     if (_url == null) {
       return _failedAssertion;
diff --git a/runtime/lib/lib_prefix.dart b/runtime/lib/lib_prefix.dart
index 9d5af28..f457b02 100644
--- a/runtime/lib/lib_prefix.dart
+++ b/runtime/lib/lib_prefix.dart
@@ -8,7 +8,7 @@
 // This type corresponds to the VM-internal class LibraryPrefix.
 class _LibraryPrefix {
   bool _load() native "LibraryPrefix_load";
-  Error _loadError() native "LibraryPrefix_loadError";
+  Object _loadError() native "LibraryPrefix_loadError";
   bool isLoaded() native "LibraryPrefix_isLoaded";
   bool _invalidateDependentCode()
       native "LibraryPrefix_invalidateDependentCode";
@@ -32,7 +32,7 @@
       // prefix. If that is the case, we must invalidate the dependent
       // code and complete the future now since there will be no callback
       // from the VM.
-      if (hasCompleted) {
+      if (hasCompleted && !completer.isCompleted) {
         _invalidateDependentCode();
         completer.complete(true);
         _outstandingLoadRequests.remove(pair);
@@ -53,19 +53,27 @@
   // which have not completed, remember them for next time in
   // stillOutstandingLoadRequests.
   var stillOutstandingLoadRequests = new List<List>();
-  for (int i = 0; i < _outstandingLoadRequests.length; i++) {
-    var prefix = _outstandingLoadRequests[i][0];
-    if (prefix._load()) {
-      var completer = _outstandingLoadRequests[i][1];
-      var error = prefix._loadError();
-      if (error != null) {
-        completer.completeError(error);
-      } else {
-        prefix._invalidateDependentCode();
-        completer.complete(true);
-      }
+  var completedLoadRequests = new List<List>();
+
+  // Make a copy of the outstandingRequests because the call to _load below
+  // may recursively trigger another call to |_completeDeferredLoads|, which
+  // can cause |_outstandingLoadRequests| to be modified.
+  var outstandingRequests = _outstandingLoadRequests.toList();
+  for (int i = 0; i < outstandingRequests.length; i++) {
+    var prefix = outstandingRequests[i][0];
+    var completer = outstandingRequests[i][1];
+    var error = prefix._loadError();
+    if (completer.isCompleted) {
+      // Already completed. Skip.
+      continue;
+    }
+    if (error != null) {
+      completer.completeError(error);
+    } else if (prefix._load()) {
+      prefix._invalidateDependentCode();
+      completer.complete(true);
     } else {
-      stillOutstandingLoadRequests.add(_outstandingLoadRequests[i]);
+      stillOutstandingLoadRequests.add(outstandingRequests[i]);
     }
   }
   _outstandingLoadRequests = stillOutstandingLoadRequests;
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 9c4fc7f..831b9b8 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -116,6 +116,15 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(VMService_SendObjectRootServiceMessage, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0));
+  if (FLAG_support_service) {
+    Service::HandleObjectRootMessage(message);
+  }
+  return Object::null();
+}
+
+
 DEFINE_NATIVE_ENTRY(VMService_OnStart, 0) {
   if (FLAG_trace_service) {
     OS::Print("vm-service: Booting dart:vmservice library.\n");
diff --git a/runtime/lib/vmservice_patch.dart b/runtime/lib/vmservice_patch.dart
index f26b93d..e0a85ae 100644
--- a/runtime/lib/vmservice_patch.dart
+++ b/runtime/lib/vmservice_patch.dart
@@ -25,6 +25,8 @@
     native "VMService_SendIsolateServiceMessage";
 patch void sendRootServiceMessage(List m)
     native "VMService_SendRootServiceMessage";
+patch void sendObjectRootServiceMessage(List m)
+    native "VMService_SendObjectRootServiceMessage";
 patch void _onStart() native "VMService_OnStart";
 patch void _onExit() native "VMService_OnExit";
 patch void onServerAddressChange(String address)
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index 7a034da..be95803 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -185,7 +185,7 @@
   void _installPage(Page page) {
     assert(page != null);
     if (currentPage == page) {
-      // Already isntalled.
+      // Already installed.
       return;
     }
     if (currentPage != null) {
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index bcaf2f8..a839728 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -42,7 +42,10 @@
   static const kStreamNotSubscribed     = 104;
   static const kIsolateMustBeRunnable   = 105;
   static const kIsolateMustBePaused     = 106;
-  static const kIsolateIsReloading      = 107;
+  static const kIsolateIsReloading      = 1000;
+  static const kFileSystemAlreadyExists = 1001;
+  static const kFileSystemDoesNotExist  = 1002;
+  static const kFileDoesNotExist        = 1003;
 
   int code;
   Map data;
diff --git a/runtime/observatory/tests/service/dev_fs_test.dart b/runtime/observatory/tests/service/dev_fs_test.dart
new file mode 100644
index 0000000..9f23396
--- /dev/null
+++ b/runtime/observatory/tests/service/dev_fs_test.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:async';
+import 'dart:convert';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var tests = [
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade('_listDevFS', {});
+    expect(result['type'], equals('FSList'));
+    expect(result['fsNames'].toString(), equals("[]"));
+
+    var params = {
+      'fsName': 'alpha'
+    };
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', params);
+    expect(result['type'], equals('Success'));
+
+    result = await vm.invokeRpcNoUpgrade('_listDevFS', {});
+    expect(result['type'], equals('FSList'));
+    expect(result['fsNames'].toString(), equals('[alpha]'));
+
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('_createDevFS', params);
+      expect(false, isTrue, reason:'Unreachable');
+    } on ServerRpcException catch(e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kFileSystemAlreadyExists));
+      expect(e.message, "_createDevFS: file system 'alpha' already exists");
+    }
+    expect(caughtException, isTrue);
+
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', params);
+    expect(result['type'], equals('Success'));
+
+    result = await vm.invokeRpcNoUpgrade('_listDevFS', {});
+    expect(result['type'], equals('FSList'));
+    expect(result['fsNames'].toString(), equals("[]"));
+
+    caughtException = false;
+    try {
+      await vm.invokeRpcNoUpgrade('_deleteDevFS', params);
+      expect(false, isTrue, reason:'Unreachable');
+    } on ServerRpcException catch(e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kFileSystemDoesNotExist));
+      expect(e.message, "_deleteDevFS: file system 'alpha' does not exist");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  (VM vm) async {
+    var fsId = 'banana';
+    var filePath = '/foobar.dat';
+    var fileContents = BASE64.encode(UTF8.encode('fileContents'));
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', {
+        'fsName': fsId
+            });
+    expect(result['type'], equals('Success'));
+
+    bool caughtException = false;
+    try {
+      await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+      });
+      expect(false, isTrue, reason:'Unreachable');
+    } on ServerRpcException catch(e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kFileDoesNotExist));
+      expect(e.message,
+             "_readDevFSFile: file 'dart-devfs://banana//foobar.dat' "
+             "does not exist");
+    }
+    expect(caughtException, isTrue);
+
+    // Write a file.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+        'fileContents': fileContents
+    });
+    expect(result['type'], equals('Success'));
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContents));
+
+    // Read a malformed path back.
+    caughtException = false;
+    try {
+      result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+          'fsName': fsId,
+          'path': filePath.substring(1)  // Strip the leading '/'.
+      });
+    } on ServerRpcException catch(e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+             "_readDevFSFile: file system path \'foobar.dat\' "
+             "must begin with a /");
+    }
+    expect(caughtException, isTrue);
+
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContents));
+
+    // Write a set of files.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFiles', {
+        'fsName': fsId,
+        'files': [
+          ['/a', BASE64.encode(UTF8.encode('a_contents'))],
+          ['/b', BASE64.encode(UTF8.encode('b_contents'))]
+        ]
+    });
+    expect(result['type'], equals('Success'));
+
+    // Read one of the files back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': '/b',
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'],
+           equals(BASE64.encode(UTF8.encode('b_contents'))));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFilesList'));
+    expect(result['files'].length, equals(3));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/platform/assert.h b/runtime/platform/assert.h
index a60d85d5..9d6d67c 100644
--- a/runtime/platform/assert.h
+++ b/runtime/platform/assert.h
@@ -281,6 +281,12 @@
 #endif  // if defined(DEBUG)
 
 
+#define RELEASE_ASSERT(cond)                                                   \
+  do {                                                                         \
+    if (!(cond)) dart::Assert(__FILE__, __LINE__).Fail("expected: %s", #cond); \
+  } while (false)
+
+
 // The COMPILE_ASSERT macro can be used to verify that a compile time
 // expression is true. For example, you could use it to verify the
 // size of a static array:
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 5debbc1..2313aab 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -141,6 +141,7 @@
 cc/SourceReport_CallSites_SimpleCall: Skip
 cc/SourceReport_Coverage_AllFunctions: Skip
 cc/SourceReport_Coverage_ForceCompile: Skip
+cc/SourceReport_Coverage_AllFunctions_ForceCompile: Skip
 cc/SourceReport_Coverage_NestedFunctions: Skip
 cc/SourceReport_Coverage_SimpleCall: Skip
 cc/SourceReport_Coverage_UnusedClass_NoForceCompile: Skip
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 2507451..7cae460 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -76,7 +76,7 @@
           const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New(
               function(), call->function_name(),
               arguments_descriptor, call->deopt_id(),
-              call->checked_argument_count()));
+              call->checked_argument_count(), false));
           call->set_ic_data(&ic_data);
         }
       }
@@ -256,7 +256,7 @@
         String::Handle(Z, ic_data.target_name()),
         Object::empty_array(),  // Dummy argument descriptor.
         ic_data.deopt_id(),
-        ic_data.NumArgsTested()));
+        ic_data.NumArgsTested(), false));
     new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
     new_ic_data.AddReceiverCheck(cid, function);
     return new_ic_data;
@@ -2447,7 +2447,8 @@
                         instr->function_name(),
                         args_desc_array,
                         Thread::kNoDeoptId,
-                        /* args_tested = */ 1));
+                        /* args_tested = */ 1,
+                        false));
         ic_data.AddReceiverCheck(receiver_class.id(), function);
         PolymorphicInstanceCallInstr* call =
             new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
@@ -2465,58 +2466,104 @@
       flow_graph_->IsReceiver(callee_receiver)) {
     // Call receiver is method receiver.
     Class& receiver_class = Class::Handle(Z, function.Owner());
+
     GrowableArray<intptr_t> class_ids(6);
     if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
-      if (class_ids.length() <= FLAG_max_exhaustive_polymorphic_checks) {
-        if (FLAG_trace_cha) {
-          THR_Print("  **(CHA) Only %" Pd " concrete subclasses of %s for %s\n",
-                    class_ids.length(),
-                    receiver_class.ToCString(),
-                    instr->function_name().ToCString());
-        }
+      // First check if all subclasses end up calling the same method.
+      // If this is the case we will replace instance call with a direct
+      // static call.
+      // Otherwise we will try to create ICData that contains all possible
+      // targets with appropriate checks.
+      Function& single_target = Function::Handle(Z);
+      ICData& ic_data = ICData::Handle(Z);
 
-        const Array& args_desc_array = Array::Handle(Z,
-            ArgumentsDescriptor::New(instr->ArgumentCount(),
-                                     instr->argument_names()));
-        ArgumentsDescriptor args_desc(args_desc_array);
+      const Array& args_desc_array = Array::Handle(Z,
+          ArgumentsDescriptor::New(instr->ArgumentCount(),
+                                   instr->argument_names()));
+      ArgumentsDescriptor args_desc(args_desc_array);
 
-        const ICData& ic_data = ICData::Handle(
-            ICData::New(function,
-                        instr->function_name(),
-                        args_desc_array,
-                        Thread::kNoDeoptId,
-                        /* args_tested = */ 1));
+      Function& target = Function::Handle(Z);
+      Class& cls = Class::Handle(Z);
+      for (intptr_t i = 0; i < class_ids.length(); i++) {
+        const intptr_t cid = class_ids[i];
+        cls = isolate()->class_table()->At(cid);
+        target = Resolver::ResolveDynamicForReceiverClass(
+            cls,
+            instr->function_name(),
+            args_desc);
 
-        Function& target = Function::Handle(Z);
-        Class& cls = Class::Handle(Z);
-        bool includes_dispatcher_case = false;
-        for (intptr_t i = 0; i < class_ids.length(); i++) {
-          intptr_t cid = class_ids[i];
-          cls = isolate()->class_table()->At(cid);
-          target = Resolver::ResolveDynamicForReceiverClass(
-              cls,
-              instr->function_name(),
-              args_desc);
-          if (target.IsNull()) {
-            // noSuchMethod, call through getter or closurization
-            includes_dispatcher_case = true;
-          } else {
-            ic_data.AddReceiverCheck(cid, target);
+        if (target.IsNull()) {
+          // Can't resolve the target. It might be a noSuchMethod,
+          // call through getter or closurization.
+          single_target = Function::null();
+          ic_data = ICData::null();
+          break;
+        } else if (ic_data.IsNull()) {
+          // First we are trying to compute a single target for all subclasses.
+          if (single_target.IsNull()) {
+            ASSERT(i == 0);
+            single_target = target.raw();
+            continue;
+          } else if (single_target.raw() == target.raw()) {
+            continue;
           }
+
+          // The call does not resolve to a single target within the hierarchy.
+          // If we have too many subclasses abort the optimization.
+          if (class_ids.length() > FLAG_max_exhaustive_polymorphic_checks) {
+            single_target = Function::null();
+            break;
+          }
+
+          // Create an ICData and map all previously seen classes (< i) to
+          // the computed single_target.
+          ic_data = ICData::New(function,
+                                instr->function_name(),
+                                args_desc_array,
+                                Thread::kNoDeoptId,
+                                /* args_tested = */ 1, false);
+          for (intptr_t j = 0; j < i; j++) {
+            ic_data.AddReceiverCheck(class_ids[j], single_target);
+          }
+
+          single_target = Function::null();
         }
-        if (!includes_dispatcher_case && (ic_data.NumberOfChecks() > 0)) {
-          PolymorphicInstanceCallInstr* call =
-              new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
-                                                  /* with_checks = */ true,
-                                                  /* complete = */ true);
-          instr->ReplaceWith(call, current_iterator());
-          return;
+
+        ASSERT(ic_data.raw() != ICData::null());
+        ASSERT(single_target.raw() == Function::null());
+        ic_data.AddReceiverCheck(cid, target);
+      }
+
+      if (single_target.raw() != Function::null()) {
+        // We have computed that there is only a single target for this call
+        // within the whole hierarchy. Replace InstanceCall with StaticCall.
+        ZoneGrowableArray<PushArgumentInstr*>* args =
+            new (Z) ZoneGrowableArray<PushArgumentInstr*>(
+                instr->ArgumentCount());
+        for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
+          args->Add(instr->PushArgumentAt(i));
         }
+        StaticCallInstr* call = new (Z) StaticCallInstr(
+            instr->token_pos(),
+            Function::ZoneHandle(Z, single_target.raw()),
+            instr->argument_names(),
+            args,
+            instr->deopt_id());
+        instr->ReplaceWith(call, current_iterator());
+        return;
+      } else if ((ic_data.raw() != ICData::null()) &&
+                 (ic_data.NumberOfChecks() > 0)) {
+        PolymorphicInstanceCallInstr* call =
+            new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
+                                                /* with_checks = */ true,
+                                                /* complete = */ true);
+        instr->ReplaceWith(call, current_iterator());
+        return;
       }
     }
   }
 
-  // More than one targets. Generate generic polymorphic call without
+  // More than one target. Generate generic polymorphic call without
   // deoptimization.
   if (instr->ic_data()->NumberOfUsedChecks() > 0) {
     ASSERT(!FLAG_polymorphic_with_deopt);
diff --git a/runtime/vm/assembler_dbc_test.cc b/runtime/vm/assembler_dbc_test.cc
index 3d5b751..5baa5d6 100644
--- a/runtime/vm/assembler_dbc_test.cc
+++ b/runtime/vm/assembler_dbc_test.cc
@@ -88,7 +88,8 @@
       String::Handle(dummy_instance_function.name()),
       dummy_arguments_descriptor,
       Thread::kNoDeoptId,
-      2));
+      2,
+      /* is_static_call= */ false));
 
   // Wire up the Function in the ICData.
   GrowableArray<intptr_t> cids(2);
@@ -1132,6 +1133,39 @@
   EXPECT_EQ(10, array.Length());
 }
 
+
+//  - CheckSmi rA
+//
+//    If FP[rA] is a Smi, then skip the next instruction.
+ASSEMBLER_TEST_GENERATE(CheckSmiPass, assembler) {
+  __ Frame(1);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ LoadConstant(0, Smi::Handle(Smi::New(0)));
+  __ CheckSmi(0);
+  __ PushConstant(Smi::Handle(Smi::New(-1)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(CheckSmiPass, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckSmiFail, assembler) {
+  __ Frame(1);
+  __ PushConstant(Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(0, Bool::True());
+  __ CheckSmi(0);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(CheckSmiFail, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 3855eaa..d214b1b 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -356,6 +356,7 @@
   V(ClassID_getID, 1)                                                          \
   V(VMService_SendIsolateServiceMessage, 2)                                    \
   V(VMService_SendRootServiceMessage, 1)                                       \
+  V(VMService_SendObjectRootServiceMessage, 1)                                 \
   V(VMService_OnStart, 0)                                                      \
   V(VMService_OnExit, 0)                                                       \
   V(VMService_OnServerAddressChange, 1)                                        \
diff --git a/runtime/vm/code_patcher_arm64_test.cc b/runtime/vm/code_patcher_arm64_test.cc
index 3b5e61e..b1cdfdd 100644
--- a/runtime/vm/code_patcher_arm64_test.cc
+++ b/runtime/vm/code_patcher_arm64_test.cc
@@ -40,7 +40,8 @@
                                                          target_name,
                                                          args_descriptor,
                                                          15,
-                                                         1));
+                                                         1,
+                                                         false));
 
   // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
   __ set_constant_pool_allowed(true);
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index b1ca06f..3671eb8 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -40,7 +40,8 @@
                                                          target_name,
                                                          args_descriptor,
                                                          15,
-                                                         1));
+                                                         1,
+                                                         false));
 
   // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
   __ set_constant_pool_allowed(true);
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index c035345..e7a6fab 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -40,7 +40,8 @@
                                                          target_name,
                                                          args_descriptor,
                                                          15,
-                                                         1));
+                                                         1,
+                                                         false));
 
   __ LoadObject(ECX, ic_data);
   __ Call(*StubCode::OneArgCheckInlineCache_entry());
diff --git a/runtime/vm/code_patcher_mips_test.cc b/runtime/vm/code_patcher_mips_test.cc
index c8d65bf..b6d4109 100644
--- a/runtime/vm/code_patcher_mips_test.cc
+++ b/runtime/vm/code_patcher_mips_test.cc
@@ -40,7 +40,8 @@
                                                          target_name,
                                                          args_descriptor,
                                                          15,
-                                                         1));
+                                                         1,
+                                                         false));
 
   __ LoadObject(S5, ic_data);
   __ BranchLinkPatchable(*StubCode::OneArgCheckInlineCache_entry());
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index 410ba1a..c6e88c2 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -40,7 +40,7 @@
                                                          target_name,
                                                          args_descriptor,
                                                          15,
-                                                         1));
+                                                         1, false));
 
   // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
   __ set_constant_pool_allowed(true);
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 4449cb1..1518bfa 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -323,6 +323,10 @@
 //
 //    Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0).
 //
+//  - CheckSmi rA
+//
+//    If FP[rA] is a Smi, then skip the next instruction.
+//
 //  - CheckStack
 //
 //    Compare SP against isolate stack limit and call StackOverflow handler if
@@ -359,7 +363,7 @@
 //    e.g. in bytecode sequences like
 //
 //    InstanceCall ... <- lazy deopt inside first call
-//    InstanceCall ... <- patches seconds call with Deopt
+//    InstanceCall ... <- patches second call with Deopt
 //
 // BYTECODE LIST FORMAT
 //
@@ -453,6 +457,7 @@
   V(InstantiateTypeArgumentsTOS,   A_D, num, lit, ___) \
   V(AssertAssignable,                D, num, lit, ___) \
   V(AssertBoolean,                   A, num, ___, ___) \
+  V(CheckSmi,                        A, reg, ___, ___) \
   V(CheckStack,                      0, ___, ___, ___) \
   V(DebugStep,                       0, ___, ___, ___) \
   V(DebugBreak,                      A, num, ___, ___) \
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index fe8154b..93cac99 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -310,6 +310,24 @@
 }
 
 
+// This waits until only the VM isolate and the service isolate remains in the
+// list, i.e. list length == 2.
+void Dart::WaitForApplicationIsolateShutdown() {
+  ASSERT(!Isolate::creation_enabled_);
+  MonitorLocker ml(Isolate::isolates_list_monitor_);
+  while ((Isolate::isolates_list_head_ != NULL) &&
+         (Isolate::isolates_list_head_->next_ != NULL) &&
+         (Isolate::isolates_list_head_->next_->next_ != NULL)) {
+    ml.Wait();
+  }
+  ASSERT(
+      ((Isolate::isolates_list_head_ == Dart::vm_isolate()) &&
+       ServiceIsolate::IsServiceIsolate(Isolate::isolates_list_head_->next_)) ||
+      ((Isolate::isolates_list_head_->next_ == Dart::vm_isolate()) &&
+       ServiceIsolate::IsServiceIsolate(Isolate::isolates_list_head_)));
+}
+
+
 // This waits until only the VM isolate remains in the list.
 void Dart::WaitForIsolateShutdown() {
   ASSERT(!Isolate::creation_enabled_);
@@ -371,6 +389,16 @@
     }
     Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
 
+    // Wait for all isolates, but the service and the vm isolate to shut down.
+    // Only do that if there is a service isolate running.
+    if (ServiceIsolate::IsRunning()) {
+      if (FLAG_trace_shutdown) {
+        OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down app isolates\n",
+                     timestamp());
+      }
+      WaitForApplicationIsolateShutdown();
+    }
+
     // Shutdown the service isolate.
     if (FLAG_trace_shutdown) {
       OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
@@ -378,7 +406,7 @@
     }
     ServiceIsolate::Shutdown();
 
-    // Wait for all application isolates and the service isolate to shutdown
+    // Wait for the remaining isolate (service isolate) to shutdown
     // before shutting down the thread pool.
     if (FLAG_trace_shutdown) {
       OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Waiting for isolate shutdown\n",
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index ea40e43..10ffea3 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -117,6 +117,7 @@
 
  private:
   static void WaitForIsolateShutdown();
+  static void WaitForApplicationIsolateShutdown();
 
   static Isolate* vm_isolate_;
   static int64_t start_time_;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 254d829..b9e9f55 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -16,6 +16,7 @@
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
+#include "vm/dev_fs.h"
 #include "vm/exceptions.h"
 #include "vm/flags.h"
 #include "vm/growable_array.h"
@@ -5170,24 +5171,23 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle library,
+DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
                                                     Dart_Handle url) {
   API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
   CHECK_CALLBACK_STATE(T);
 
-  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
-  if (lib.IsNull()) {
-    RETURN_TYPE_ERROR(Z, library, Library);
+  const String& base_uri = Api::UnwrapStringHandle(Z, base_url);
+  if (base_uri.IsNull()) {
+    RETURN_TYPE_ERROR(Z, base_url, String);
   }
   const String& uri = Api::UnwrapStringHandle(Z, url);
   if (uri.IsNull()) {
     RETURN_TYPE_ERROR(Z, url, String);
   }
 
-  const String& lib_uri = String::Handle(Z, lib.url());
   const char* resolved_uri;
-  if (!ResolveUri(uri.ToCString(), lib_uri.ToCString(), &resolved_uri)) {
+  if (!ResolveUri(uri.ToCString(), base_uri.ToCString(), &resolved_uri)) {
     return Api::NewError("%s: Unable to canonicalize uri '%s'.",
                          CURRENT_FUNC, uri.ToCString());
   }
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index fcc4e79..5498bd7 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -14,6 +14,7 @@
 #include "vm/class_finalizer.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_api_state.h"
+#include "vm/dev_fs.h"
 #include "vm/lockers.h"
 #include "vm/timeline.h"
 #include "vm/unit_test.h"
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 1839f7f..ce668f4 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -67,13 +67,17 @@
   // return-address. This section is copied as well, so that its contained
   // values can be updated before returning to the deoptimized function.
   // Note: on DBC stack grows upwards unlike on all other architectures.
+#if defined(TARGET_ARCH_DBC)
+  ASSERT(frame->sp() >= frame->fp());
+  const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize;
+#else
+  ASSERT(frame->fp() >= frame->sp());
+  const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize;
+#endif
+
   source_frame_size_ =
       + kDartFrameFixedSize  // For saved values below sp.
-#if !defined(TARGET_ARCH_DBC)
-      + ((frame->fp() - frame->sp()) / kWordSize)  // For frame size incl. sp.
-#else
-      + ((frame->sp() - frame->fp()) / kWordSize)  // For frame size incl. sp.
-#endif  // !defined(TARGET_ARCH_DBC)
+      + frame_size  // For frame size incl. sp.
       + 1  // For fp.
       + kParamEndSlotFromFp  // For saved values above fp.
       + num_args_;  // For arguments.
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 5dfab38..79a2c50 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -115,7 +115,7 @@
 #else
     // First argument is the lowest slot because stack is growing upwards.
     return reinterpret_cast<intptr_t*>(
-      frame->fp() - (kDartFrameFixedSize + num_args_) * kWordSize);
+        frame->fp() - (kDartFrameFixedSize + num_args_) * kWordSize);
 #endif  // !defined(TARGET_ARCH_DBC)
   }
 
diff --git a/runtime/vm/dev_fs.cc b/runtime/vm/dev_fs.cc
new file mode 100644
index 0000000..afbb23b
--- /dev/null
+++ b/runtime/vm/dev_fs.cc
@@ -0,0 +1,375 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "vm/dev_fs.h"
+
+#include "vm/hash_table.h"
+#include "vm/json_stream.h"
+#include "vm/lockers.h"
+#include "vm/object.h"
+#include "vm/unicode.h"
+
+namespace dart {
+
+#ifndef PRODUCT
+
+static const uint8_t decode_table[256] = {
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+  64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+  64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+};
+
+class Base64 {
+ public:
+  static void decode(const char* base64,
+                     std::vector<uint8_t>* output) {
+    ASSERT(output != NULL);
+    ASSERT(base64 != NULL);
+    const intptr_t base64_len = strlen(base64);
+    int b[4];
+    for (intptr_t i = 0; i < base64_len; i += 4) {
+      b[0] = decode_table[static_cast<uint8_t>(base64[i])];
+      b[1] = decode_table[static_cast<uint8_t>(base64[i + 1])];
+      b[2] = decode_table[static_cast<uint8_t>(base64[i + 2])];
+      b[3] = decode_table[static_cast<uint8_t>(base64[i + 3])];
+      output->push_back((b[0] << 2) | (b[1] >> 4));
+      if (b[2] < 64) {
+        output->push_back((b[1] << 4) | (b[2] >> 2));
+        if (b[3] < 64)  {
+          output->push_back((b[2] << 6) | b[3]);
+        }
+      }
+    }
+  }
+};
+
+
+class FileSystem {
+ public:
+  explicit FileSystem(const std::string& name)
+    : name_(name) {
+  }
+
+  ~FileSystem() {
+  }
+
+  bool ReadFile(const std::string& path,
+                std::vector<uint8_t>** file_contents) {
+    *file_contents = NULL;
+    std::map<std::string, std::vector<uint8_t>*>::iterator iter;
+    iter = files_.find(path);
+    if (iter == files_.end()) {
+      return false;
+    }
+    *file_contents = iter->second;
+    return true;
+  }
+
+  void DeleteFile(const std::string& path) {
+    std::map<std::string, std::vector<uint8_t>*>::iterator iter;
+    iter = files_.find(path);
+    if (iter == files_.end()) {
+      return;
+    }
+    std::vector<uint8_t>* contents = iter->second;
+    files_.erase(iter);
+    delete contents;
+  }
+
+  void WriteFile(const std::string& path,
+                 const char* file_contents) {
+    DeleteFile(path);
+    std::vector<uint8_t>* data = new std::vector<uint8_t>();
+    Base64::decode(file_contents, data);
+    files_[path] = data;
+  }
+
+  void ListFiles(JSONStream* js) {
+    JSONObject jsobj(js);
+    jsobj.AddProperty("type", "FSFilesList");
+    JSONArray jsarr(&jsobj, "files");
+    std::map<std::string, std::vector<uint8_t>*>::iterator iter;
+    for (iter = files_.begin(); iter != files_.end(); iter++) {
+      JSONObject file_info(&jsarr);
+      file_info.AddProperty("name", iter->first.c_str());
+      file_info.AddProperty64("size",
+                              static_cast<int64_t>(iter->second->size()));
+    }
+  }
+
+ private:
+  std::string name_;
+
+  std::map<std::string, std::vector<uint8_t>*> files_;
+};
+
+// Some static state is held outside of the DevFS class so that we don't
+// have to include stl headers in our vm/ headers.
+static std::map<std::string, FileSystem*>* file_systems_;
+
+Mutex* DevFS::mutex_ = NULL;
+
+
+void DevFS::Init() {
+  if (mutex_ != NULL) {
+    // Already initialized.
+    ASSERT(file_systems_ != NULL);
+    return;
+  }
+  mutex_ = new Mutex();
+  file_systems_ = new std::map<std::string, FileSystem*>();
+  ASSERT(mutex_ != NULL);
+  ASSERT(file_systems_ != NULL);
+}
+
+
+void DevFS::Cleanup() {
+  delete mutex_;
+  mutex_ = NULL;
+  std::map<std::string, FileSystem*>::iterator iter;
+  for (iter = file_systems_->begin(); iter != file_systems_->end(); iter++) {
+    FileSystem* fs = iter->second;
+    delete fs;
+  }
+  delete file_systems_;
+  file_systems_ = NULL;
+}
+
+
+void DevFS::ListFileSystems(JSONStream* js) {
+  SafepointMutexLocker ml(mutex_);
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "FSList");
+  JSONArray jsarr(&jsobj, "fsNames");
+
+  std::map<std::string, FileSystem*>::iterator iter;
+  for (iter = file_systems_->begin(); iter != file_systems_->end(); iter++) {
+    const std::string& key = iter->first;
+    jsarr.AddValue(key.c_str());
+  }
+}
+
+
+FileSystem* DevFS::LookupFileSystem(const char* fs_name) {
+  std::string key = std::string(fs_name);
+  std::map<std::string, FileSystem*>::iterator iter;
+  iter = file_systems_->find(key);
+  if (iter != file_systems_->end()) {
+    return iter->second;
+  }
+  return NULL;
+}
+
+
+FileSystem* DevFS::LookupFileSystem(const String& fs_name) {
+  return LookupFileSystem(fs_name.ToCString());
+}
+
+
+void DevFS::CreateFileSystem(JSONStream* js, const String& fs_name) {
+  SafepointMutexLocker ml(mutex_);
+  // TODO(turnidge): Ensure that fs_name is a legal URI host value, i.e. ascii.
+  if (LookupFileSystem(fs_name) != NULL) {
+    js->PrintError(kFileSystemAlreadyExists,
+                   "%s: file system '%s' already exists",
+                   js->method(), fs_name.ToCString());
+    return;
+  }
+
+  std::string key = std::string(fs_name.ToCString());
+  FileSystem* file_system = new FileSystem(key);
+  (*file_systems_)[key] = file_system;
+
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+}
+
+
+void DevFS::DeleteFileSystem(JSONStream* js, const String& fs_name) {
+  SafepointMutexLocker ml(mutex_);
+  FileSystem* file_system = LookupFileSystem(fs_name);
+  if (file_system == NULL) {
+    js->PrintError(kFileSystemDoesNotExist,
+                   "%s: file system '%s' does not exist",
+                   js->method(), fs_name.ToCString());
+    return;
+  }
+  std::string key = std::string(fs_name.ToCString());
+  file_systems_->erase(key);
+  delete file_system;
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+}
+
+
+void DevFS::ListFiles(JSONStream* js, const String& fs_name) {
+  SafepointMutexLocker ml(mutex_);
+  FileSystem* file_system = LookupFileSystem(fs_name);
+  if (file_system == NULL) {
+    js->PrintError(kFileSystemDoesNotExist,
+                   "%s: file system '%s' does not exist",
+                   js->method(), fs_name.ToCString());
+    return;
+  }
+
+  file_system->ListFiles(js);
+}
+
+
+static void PrintWriteFilesError(JSONStream* js,
+                                 intptr_t i) {
+  js->PrintError(kInvalidParams,
+                 "%s: files array invalid at index '%" Pd "'",
+                 js->method(), i);
+}
+
+
+void DevFS::WriteFiles(JSONStream* js,
+                       const String& fs_name,
+                       const Array& files) {
+  SafepointMutexLocker ml(mutex_);
+  FileSystem* file_system = LookupFileSystem(fs_name);
+  if (file_system == NULL) {
+    js->PrintError(kFileSystemDoesNotExist,
+                   "%s: file system '%s' does not exist",
+                   js->method(), fs_name.ToCString());
+    return;
+  }
+
+  Object& test = Object::Handle();
+  GrowableObjectArray& file_info = GrowableObjectArray::Handle();
+  String& path = String::Handle();
+  String& file_contents = String::Handle();
+
+  // First, validate the array of files is properly formed.
+  for (intptr_t i = 0; i < files.Length(); i++) {
+    test = files.At(i);
+    if (!test.IsGrowableObjectArray()) {
+      PrintWriteFilesError(js, i);
+      return;
+    }
+    file_info ^= test.raw();
+    if (file_info.Length() != 2) {
+      PrintWriteFilesError(js, i);
+      return;
+    }
+    test = file_info.At(0);
+    if (!test.IsString()) {
+      PrintWriteFilesError(js, i);
+      return;
+    }
+    std::string key = std::string(String::Cast(test).ToCString());
+    if ((key.size() == 0) || (key[0] != '/')) {
+      js->PrintError(kInvalidParams,
+                     "%s: file system path '%s' must begin with a /",
+                     js->method(), String::Cast(test).ToCString());
+      return;
+    }
+    test = file_info.At(1);
+    if (!test.IsString()) {
+      PrintWriteFilesError(js, i);
+      return;
+    }
+  }
+
+  // Now atomically update the file system.
+  for (intptr_t i = 0; i < files.Length(); i++) {
+    file_info = GrowableObjectArray::RawCast(files.At(i));
+    path = String::RawCast(file_info.At(0));
+    file_contents = String::RawCast(file_info.At(1));
+    file_system->WriteFile(path.ToCString(),
+                           file_contents.ToCString());
+  }
+
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+}
+
+
+void DevFS::WriteFile(JSONStream* js,
+                      const String& fs_name,
+                      const String& path,
+                      const String& file_contents) {
+  SafepointMutexLocker ml(mutex_);
+  FileSystem* file_system = LookupFileSystem(fs_name);
+  if (file_system == NULL) {
+    js->PrintError(kFileSystemDoesNotExist,
+                   "%s: file system '%s' does not exist",
+                   js->method(), fs_name.ToCString());
+    return;
+  }
+
+  std::string key = std::string(path.ToCString());
+  if ((key.size() == 0) || (key[0] != '/')) {
+    js->PrintError(kInvalidParams,
+                   "%s: file system path '%s' must begin with a /",
+                   js->method(), path.ToCString());
+    return;
+  }
+
+  file_system->WriteFile(path.ToCString(),
+                         file_contents.ToCString());
+
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+}
+
+
+void DevFS::ReadFile(JSONStream* js,
+                     const String& fs_name,
+                     const String& path) {
+  SafepointMutexLocker ml(mutex_);
+  FileSystem* file_system = LookupFileSystem(fs_name);
+  if (file_system == NULL) {
+    js->PrintError(kFileSystemDoesNotExist,
+                   "%s: file system '%s' does not exist",
+                   js->method(), fs_name.ToCString());
+    return;
+  }
+
+  std::string key = std::string(path.ToCString());
+  if ((key.size() == 0) || (key[0] != '/')) {
+    js->PrintError(kInvalidParams,
+                   "%s: file system path '%s' must begin with a /",
+                   js->method(), path.ToCString());
+    return;
+  }
+  std::vector<uint8_t>* file_contents;
+
+  bool success = file_system->ReadFile(key, &file_contents);
+
+  if (!success) {
+    js->PrintError(kFileDoesNotExist,
+                   "%s: file 'dart-devfs://%s/%s' does not exist",
+                   js->method(), fs_name.ToCString(), path.ToCString());
+    return;
+  }
+
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "FSFile");
+  jsobj.AddPropertyBase64("fileContents",
+                          &((*file_contents)[0]),
+                          file_contents->size());
+}
+
+#endif  // !PRODUCT
+
+}  // namespace dart
diff --git a/runtime/vm/dev_fs.h b/runtime/vm/dev_fs.h
new file mode 100644
index 0000000..75032bd
--- /dev/null
+++ b/runtime/vm/dev_fs.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_DEV_FS_H_
+#define VM_DEV_FS_H_
+
+#include "vm/globals.h"
+
+#include "vm/dart_api_impl.h"
+
+namespace dart {
+
+class Array;
+class FileSystem;
+class JSONStream;
+class Mutex;
+class ObjectPointerVisitor;
+class RawArray;
+class RawObject;
+class String;
+
+
+// Manages dart-devfs:// file systems. These file systems are "virtual"
+// and accessed via the service protocol.
+class DevFS {
+ public:
+  static void Init();
+  static void Cleanup();
+
+  static void ListFileSystems(JSONStream* js);
+  static void CreateFileSystem(JSONStream* js, const String& fs_name);
+  static void DeleteFileSystem(JSONStream* js, const String& fs_name);
+  static void ListFiles(JSONStream* js,
+                        const String& fs_name);
+  static void WriteFiles(JSONStream* js,
+                         const String& fs_name,
+                         const Array& files);
+  static void WriteFile(JSONStream* js,
+                        const String& fs_name,
+                        const String& path,
+                        const String& file_contents);
+  static void ReadFile(JSONStream* js,
+                       const String& fs_name,
+                       const String& path);
+
+ private:
+  static Mutex* mutex_;
+  static FileSystem* LookupFileSystem(const String& fs_name);
+  static FileSystem* LookupFileSystem(const char* fs_name);
+};
+
+}  // namespace dart
+
+#endif  // VM_DEV_FS_H_
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 5818624..367cdcc 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -156,6 +156,8 @@
   "Support the disassembler.")                                                 \
 R(support_il_printer, false, bool, true,                                       \
   "Support the IL printer.")                                                   \
+R(support_reload, false, bool, true,                                           \
+  "Support isolate reload.")                                                   \
 R(support_service, false, bool, true,                                          \
   "Support the service protocol.")                                             \
 R(support_timeline, false, bool, true,                                         \
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index b403bbf..13159ba 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -987,6 +987,25 @@
 }
 
 
+#if defined(TARGET_ARCH_DBC)
+void FlowGraphCompiler::EmitDeopt(intptr_t deopt_id,
+                                  ICData::DeoptReasonId reason,
+                                  uint32_t flags) {
+  ASSERT(is_optimizing());
+  ASSERT(!intrinsic_mode());
+  CompilerDeoptInfo* info =
+      new(zone()) CompilerDeoptInfo(deopt_id,
+                                    reason,
+                                    flags,
+                                    pending_deoptimization_env_);
+
+  deopt_infos_.Add(info);
+  assembler()->Deopt(0, /*is_eager =*/ 1);
+  info->set_pc_offset(assembler()->CodeSize());
+}
+#endif  // defined(TARGET_ARCH_DBC)
+
+
 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) {
   ASSERT(exception_handlers_list_ != NULL);
   const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
@@ -1717,17 +1736,19 @@
     ASSERT(res->deopt_id() == deopt_id);
     ASSERT(res->target_name() == target_name.raw());
     ASSERT(res->NumArgsTested() == num_args_tested);
+    ASSERT(!res->is_static_call());
     return res;
   }
   const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New(
       parsed_function().function(), target_name,
-      arguments_descriptor, deopt_id, num_args_tested));
+      arguments_descriptor, deopt_id, num_args_tested, false));
 #if defined(TAG_IC_DATA)
   ic_data.set_tag(Instruction::kInstanceCall);
 #endif
   if (deopt_id_to_ic_data_ != NULL) {
     (*deopt_id_to_ic_data_)[deopt_id] = &ic_data;
   }
+  ASSERT(!ic_data.is_static_call());
   return &ic_data;
 }
 
@@ -1743,11 +1764,12 @@
     ASSERT(res->deopt_id() == deopt_id);
     ASSERT(res->target_name() == target.name());
     ASSERT(res->NumArgsTested() == num_args_tested);
+    ASSERT(res->is_static_call());
     return res;
   }
   const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New(
       parsed_function().function(), String::Handle(zone(), target.name()),
-      arguments_descriptor, deopt_id, num_args_tested));
+      arguments_descriptor, deopt_id, num_args_tested, true));
   ic_data.AddTarget(target);
 #if defined(TAG_IC_DATA)
   ic_data.set_tag(Instruction::kStaticCall);
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index a94eaa6..e728582 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -528,6 +528,12 @@
                       ICData::DeoptReasonId reason,
                       uint32_t flags = 0);
 
+#if defined(TARGET_ARCH_DBC)
+  void EmitDeopt(intptr_t deopt_id,
+                 ICData::DeoptReasonId reason,
+                 uint32_t flags = 0);
+#endif  // defined(TARGET_ARCH_DBC)
+
   void AddDeoptIndexAtCall(intptr_t deopt_id, TokenPosition token_pos);
 
   void AddSlowPathCode(SlowPathCode* slow_path);
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
index 86352cc..eae97e2 100644
--- a/runtime/vm/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -209,7 +209,7 @@
 
 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
                                              intptr_t stub_ix) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
 }
 
 
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index e92bc3f..b51cfe8 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -1773,7 +1773,8 @@
                     String::Handle(old_checks.target_name()),
                     Array::Handle(old_checks.arguments_descriptor()),
                     old_checks.deopt_id(),
-                    1));  // Number of args tested.
+                    1,        // Number of args tested.
+                    false));  // is_static_call
     for (intptr_t i = 0; i < non_inlined_variants_.length(); ++i) {
       new_checks.AddReceiverCheck(non_inlined_variants_[i].cid,
                                   *non_inlined_variants_[i].target,
@@ -2651,7 +2652,8 @@
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Thread::kNoDeoptId,
-                                1);
+                                1,
+                                false);
       value_check.AddReceiverCheck(kSmiCid, target);
       break;
     }
@@ -2663,7 +2665,8 @@
                                   i_call->function_name(),
                                   Object::empty_array(),  // Dummy args. descr.
                                   Thread::kNoDeoptId,
-                                  1);
+                                  1,
+                                  false);
         value_check.AddReceiverCheck(kSmiCid, target);
       }
       break;
@@ -2674,7 +2677,8 @@
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Thread::kNoDeoptId,
-                                1);
+                                1,
+                                false);
       value_check.AddReceiverCheck(kDoubleCid, target);
       break;
     }
@@ -2684,7 +2688,8 @@
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Thread::kNoDeoptId,
-                                1);
+                                1,
+                                false);
       value_check.AddReceiverCheck(kInt32x4Cid, target);
       break;
     }
@@ -2694,7 +2699,8 @@
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Thread::kNoDeoptId,
-                                1);
+                                1,
+                                false);
       value_check.AddReceiverCheck(kFloat32x4Cid, target);
       break;
     }
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 069f341..2ac946a 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -177,12 +177,43 @@
     return class_stats_size_[class_id];
   }
 
-  // Returns true if some non-zero amount of work was performed.
-  bool DrainMarkingStack() {
+  bool ProcessPendingWeakProperties() {
+    bool marked = false;
+    RawWeakProperty* cur_weak = delayed_weak_properties_;
+    delayed_weak_properties_ = NULL;
+    while (cur_weak != NULL) {
+      uword next_weak = cur_weak->ptr()->next_;
+      RawObject* raw_key = cur_weak->ptr()->key_;
+      // Reset the next pointer in the weak property.
+      cur_weak->ptr()->next_ = 0;
+      if (raw_key->IsMarked()) {
+        RawObject* raw_val = cur_weak->ptr()->value_;
+        marked = marked || (raw_val->IsHeapObject() && !raw_val->IsMarked());
+
+        // The key is marked so we make sure to properly visit all pointers
+        // originating from this weak property.
+        VisitingOldObject(cur_weak);
+        cur_weak->VisitPointers(this);
+      } else {
+        // Requeue this weak property to be handled later.
+        EnqueueWeakProperty(cur_weak);
+      }
+      // Advance to next weak property in the queue.
+      cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
+    }
+    VisitingOldObject(NULL);
+    return marked;
+  }
+
+  void DrainMarkingStack() {
     RawObject* raw_obj = work_list_.Pop();
+    if ((raw_obj == NULL) && ProcessPendingWeakProperties()) {
+      raw_obj = work_list_.Pop();
+    }
+
     if (raw_obj == NULL) {
       ASSERT(visiting_old_object_ == NULL);
-      return false;
+      return;
     }
     do {
       do {
@@ -200,33 +231,13 @@
       } while (raw_obj != NULL);
 
       // Marking stack is empty.
-      // Process all the pending weak properties in this visitor.
-      RawWeakProperty* cur_weak = delayed_weak_properties_;
-      delayed_weak_properties_ = NULL;
-      while (cur_weak != NULL) {
-        uword next_weak = cur_weak->ptr()->next_;
-        RawObject* raw_key = cur_weak->ptr()->key_;
-        // Reset the next pointer in the weak property.
-        cur_weak->ptr()->next_ = 0;
-        if (raw_key->IsMarked()) {
-          // The key is marked so we make sure to properly visit all pointers
-          // originating from this weak property.
-          VisitingOldObject(cur_weak);
-          cur_weak->VisitPointers(this);
-        } else {
-          // Requeue this weak property to be handled later.
-          EnqueueWeakProperty(cur_weak);
-        }
-        // Advance to next weak property in the queue.
-        cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
-      }
+      ProcessPendingWeakProperties();
 
       // Check whether any further work was pushed either by other markers or
       // by the handling of weak properties.
       raw_obj = work_list_.Pop();
     } while (raw_obj != NULL);
     VisitingOldObject(NULL);
-    return true;
   }
 
   void VisitPointers(RawObject** first, RawObject** last) {
@@ -282,6 +293,7 @@
     while (cur_weak != NULL) {
       uword next_weak = cur_weak->ptr()->next_;
       cur_weak->ptr()->next_ = 0;
+      RELEASE_ASSERT(!cur_weak->ptr()->key_->IsMarked());
       WeakProperty::Clear(cur_weak);
       weak_properties_cleared++;
       // Advance to next weak property in the queue.
@@ -569,28 +581,54 @@
                                  skipped_code_functions);
       // Phase 1: Iterate over roots and drain marking stack in tasks.
       marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_);
+
+      bool more_to_mark = false;
       do {
-        visitor.DrainMarkingStack();
+        do {
+          visitor.DrainMarkingStack();
 
-        // I can't find more work right now. If no other task is busy,
-        // then there will never be more work (NB: 1 is *before* decrement).
-        if (AtomicOperations::FetchAndDecrement(num_busy_) == 1) break;
+          // I can't find more work right now. If no other task is busy,
+          // then there will never be more work (NB: 1 is *before* decrement).
+          if (AtomicOperations::FetchAndDecrement(num_busy_) == 1) break;
 
-        // Wait for some work to appear.
-        // TODO(iposva): Replace busy-waiting with a solution using Monitor,
-        // and redraw the boundaries between stack/visitor/task as needed.
-        while (marking_stack_->IsEmpty() &&
-               AtomicOperations::LoadRelaxed(num_busy_) > 0) {
+          // Wait for some work to appear.
+          // TODO(iposva): Replace busy-waiting with a solution using Monitor,
+          // and redraw the boundaries between stack/visitor/task as needed.
+          while (marking_stack_->IsEmpty() &&
+                 AtomicOperations::LoadRelaxed(num_busy_) > 0) {
+          }
+
+          // If no tasks are busy, there will never be more work.
+          if (AtomicOperations::LoadRelaxed(num_busy_) == 0) break;
+
+          // I saw some work; get busy and compete for it.
+          AtomicOperations::FetchAndIncrement(num_busy_);
+        } while (true);
+        // Wait for all markers to stop.
+        barrier_->Sync();
+        ASSERT(AtomicOperations::LoadRelaxed(num_busy_) == 0);
+
+        // Check if we have any pending properties with marked keys.
+        // Those might have been marked by another marker.
+        more_to_mark = visitor.ProcessPendingWeakProperties();
+        if (more_to_mark) {
+          // We have more work to do. Notify others.
+          AtomicOperations::FetchAndIncrement(num_busy_);
         }
 
-        // If no tasks are busy, there will never be more work.
-        if (AtomicOperations::LoadRelaxed(num_busy_) == 0) break;
-
-        // I saw some work; get busy and compete for it.
-        AtomicOperations::FetchAndIncrement(num_busy_);
-      } while (true);
-      ASSERT(AtomicOperations::LoadRelaxed(num_busy_) == 0);
-      barrier_->Sync();
+        // Wait for all other markers to finish processing their pending
+        // weak properties and decide if they need to continue marking.
+        // Caveat: we need two barriers here to make this decision in lock step
+        // between all markers and the main thread.
+        barrier_->Sync();
+        if (!more_to_mark && (AtomicOperations::LoadRelaxed(num_busy_) > 0)) {
+          // All markers continue to marker as long as any single marker has
+          // some work to do.
+          AtomicOperations::FetchAndIncrement(num_busy_);
+          more_to_mark = true;
+        }
+        barrier_->Sync();
+      } while (more_to_mark);
 
       // Phase 2: Weak processing and follow-up marking on main thread.
       barrier_->Sync();
@@ -688,7 +726,19 @@
         ThreadPool* pool = Dart::thread_pool();
         pool->Run(mark_task);
       }
-      barrier.Sync();
+      bool more_to_mark = false;
+      do {
+        // Wait for all markers to stop.
+        barrier.Sync();
+
+        // Wait for all markers to go through weak properties and verify
+        // that there are no more objects to mark.
+        // Note: we need to have two barriers here because we want all markers
+        // and main thread to make decisions in lock step.
+        barrier.Sync();
+        more_to_mark = AtomicOperations::LoadRelaxed(&num_busy) > 0;
+        barrier.Sync();
+      } while (more_to_mark);
 
       // Phase 2: Weak processing on main thread.
       {
diff --git a/runtime/vm/instructions_dbc.cc b/runtime/vm/instructions_dbc.cc
index 3656722..4dc73be 100644
--- a/runtime/vm/instructions_dbc.cc
+++ b/runtime/vm/instructions_dbc.cc
@@ -15,13 +15,54 @@
 
 namespace dart {
 
+static bool HasLoadFromPool(Instr instr) {
+  switch (Bytecode::DecodeOpcode(instr)) {
+    case Bytecode::kLoadConstant:
+    case Bytecode::kPushConstant:
+    case Bytecode::kStaticCall:
+    case Bytecode::kInstanceCall1:
+    case Bytecode::kInstanceCall2:
+    case Bytecode::kInstanceCall1Opt:
+    case Bytecode::kInstanceCall2Opt:
+    case Bytecode::kStoreStaticTOS:
+    case Bytecode::kPushStatic:
+    case Bytecode::kAllocate:
+    case Bytecode::kInstantiateType:
+    case Bytecode::kInstantiateTypeArgumentsTOS:
+    case Bytecode::kAssertAssignable:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+static bool GetLoadedObjectAt(
+    uword pc, const ObjectPool& object_pool, Object* obj) {
+  Instr instr = Bytecode::At(pc);
+  if (HasLoadFromPool(instr)) {
+    uint16_t index = Bytecode::DecodeD(instr);
+    if (object_pool.InfoAt(index) == ObjectPool::kTaggedObject) {
+      *obj = object_pool.ObjectAt(index);
+      return true;
+    }
+  }
+  return false;
+}
+
+
 CallPattern::CallPattern(uword pc, const Code& code)
     : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
       end_(pc),
       ic_data_load_end_(0),
       target_code_pool_index_(-1),
       ic_data_(ICData::Handle()) {
-  UNIMPLEMENTED();
+  ASSERT(code.ContainsInstructionAt(end_));
+  const uword call_pc = end_ - sizeof(Instr);
+  Instr call_instr = Bytecode::At(call_pc);
+  ASSERT(Bytecode::IsCallOpcode(call_instr));
+  ic_data_load_end_ = call_pc;
+  target_code_pool_index_ = Bytecode::DecodeD(call_instr);
 }
 
 
@@ -30,6 +71,7 @@
   return 0;
 }
 
+
 int CallPattern::DeoptCallPatternLengthInBytes() {
   UNIMPLEMENTED();
   return 0;
@@ -109,48 +151,21 @@
 }
 
 
-static bool HasLoadFromPool(Instr instr) {
-  switch (Bytecode::DecodeOpcode(instr)) {
-    case Bytecode::kLoadConstant:
-    case Bytecode::kPushConstant:
-    case Bytecode::kStaticCall:
-    case Bytecode::kInstanceCall1:
-    case Bytecode::kInstanceCall2:
-    case Bytecode::kInstanceCall1Opt:
-    case Bytecode::kInstanceCall2Opt:
-    case Bytecode::kStoreStaticTOS:
-    case Bytecode::kPushStatic:
-    case Bytecode::kAllocate:
-    case Bytecode::kInstantiateType:
-    case Bytecode::kInstantiateTypeArgumentsTOS:
-    case Bytecode::kAssertAssignable:
-      return true;
-    default:
-      return false;
-  }
-}
-
-
 bool DecodeLoadObjectFromPoolOrThread(uword pc,
                                       const Code& code,
                                       Object* obj) {
   ASSERT(code.ContainsInstructionAt(pc));
-  Instr instr = Bytecode::At(pc);
-  if (HasLoadFromPool(instr)) {
-    uint16_t index = Bytecode::DecodeD(instr);
-    const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-    if (pool.InfoAt(index) == ObjectPool::kTaggedObject) {
-      *obj = pool.ObjectAt(index);
-      return true;
-    }
-  }
-  return false;
+  const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
+  return GetLoadedObjectAt(pc, pool, obj);
 }
 
 
 RawICData* CallPattern::IcData() {
-  UNIMPLEMENTED();
-  return ICData::null();
+  if (ic_data_.IsNull()) {
+    bool found = GetLoadedObjectAt(ic_data_load_end_, object_pool_, &ic_data_);
+    ASSERT(found);
+  }
+  return ic_data_.raw();
 }
 
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 27fe9a1..d048c0e 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -3267,6 +3267,25 @@
     ASSERT(argument_names.IsZoneHandle() ||  argument_names.InVMHeap());
   }
 
+  StaticCallInstr(TokenPosition token_pos,
+                  const Function& function,
+                  const Array& argument_names,
+                  ZoneGrowableArray<PushArgumentInstr*>* arguments,
+                  intptr_t deopt_id)
+      : TemplateDefinition(deopt_id),
+        ic_data_(NULL),
+        token_pos_(token_pos),
+        function_(function),
+        argument_names_(argument_names),
+        arguments_(arguments),
+        result_cid_(kDynamicCid),
+        is_known_list_constructor_(false),
+        is_native_list_factory_(false),
+        identity_(AliasIdentity::Unknown()) {
+    ASSERT(function.IsZoneHandle());
+    ASSERT(argument_names.IsZoneHandle() ||  argument_names.InVMHeap());
+  }
+
   // ICData for static calls carries call count.
   const ICData* ic_data() const { return ic_data_; }
   bool HasICData() const {
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 4af998e..0e1afc6 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -108,7 +108,6 @@
   M(UnboxInteger32)                                                            \
   M(CheckedSmiOp)                                                              \
   M(CheckArrayBound)                                                           \
-  M(CheckSmi)                                                                  \
   M(CheckClassId)                                                              \
   M(CheckClass)                                                                \
   M(BinarySmiOp)                                                               \
@@ -850,8 +849,12 @@
 Representation StoreIndexedInstr::RequiredInputRepresentation(
     intptr_t idx) const {
   // Array can be a Dart object or a pointer to external data.
-  if (idx == 0)  return kNoRepresentation;  // Flexible input representation.
-  if (idx == 1) return kTagged;  // Index is a smi.
+  if (idx == 0) {
+    return kNoRepresentation;  // Flexible input representation.
+  }
+  if (idx == 1) {
+    return kTagged;  // Index is a smi.
+  }
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
@@ -903,6 +906,13 @@
 }
 
 
+EMIT_NATIVE_CODE(CheckSmi, 1) {
+  __ CheckSmi(locs()->in(0).reg());
+  compiler->EmitDeopt(deopt_id(),
+                      ICData::kDeoptCheckSmi,
+                      licm_hoisted_ ? ICData::kHoisted : 0);
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 03ffd48..9e049d0 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -607,7 +607,8 @@
       String::Handle(flow_graph->function().name()),
       Object::empty_array(),  // Dummy args. descr.
       Thread::kNoDeoptId,
-      1));
+      1,
+      false));
   value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
   builder.AddInstruction(
       new CheckClassInstr(new Value(value),
@@ -740,7 +741,8 @@
       String::Handle(flow_graph->function().name()),
       Object::empty_array(),  // Dummy args. descr.
       Thread::kNoDeoptId,
-      1));
+      1,
+      false));
   value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function());
   // Check argument. Receiver (left) is known to be a Float32x4.
   builder.AddInstruction(
@@ -982,7 +984,8 @@
       String::Handle(flow_graph->function().name()),
       Object::empty_array(),  // Dummy args. descr.
       Thread::kNoDeoptId,
-      1));
+      1,
+      false));
   value_check.AddReceiverCheck(kArrayCid, flow_graph->function());
   builder.AddInstruction(
       new CheckClassInstr(new Value(data),
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 8ed0873..69578c9 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1067,7 +1067,7 @@
 
 
 void Isolate::OnStackReload() {
-  UNREACHABLE();
+  ReloadSources();
 }
 
 
@@ -1776,6 +1776,9 @@
     if (reload_context() != NULL) {
       reload_context()->VisitObjectPointers(visitor);
     }
+    if (ServiceIsolate::IsServiceIsolate(this)) {
+      ServiceIsolate::VisitObjectPointers(visitor);
+    }
   )
 
   // Visit objects that are being used for deoptimization.
@@ -2626,7 +2629,9 @@
   const String& lib_url = String::Handle(lib.url());
   library_url_ = NewConstChar(lib_url.ToCString());
 
-  const String& func_name = String::Handle(func.name());
+  String& func_name = String::Handle();
+  func_name ^= func.name();
+  func_name ^= String::ScrubName(func_name);
   function_name_ = NewConstChar(func_name.ToCString());
   if (!cls.IsTopLevel()) {
     const String& class_name = String::Handle(cls.Name());
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 5913789..1232ef6 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -257,9 +257,6 @@
   DeoptimizeDependentCode();
   Checkpoint();
 
-  // Block class finalization attempts when calling into the library
-  // tag handler.
-  I->BlockClassFinalization();
   Object& result = Object::Handle(thread->zone());
   {
     TransitionVMToNative transition(thread);
@@ -267,11 +264,10 @@
 
     Dart_Handle retval =
         (I->library_tag_handler())(Dart_kScriptTag,
-                                Api::NewHandle(thread, Library::null()),
-                                Api::NewHandle(thread, root_lib_url.raw()));
+                                   Api::NewHandle(thread, Library::null()),
+                                   Api::NewHandle(thread, root_lib_url.raw()));
     result = Api::UnwrapHandle(retval);
   }
-  I->UnblockClassFinalization();
   if (result.IsError()) {
     ReportError(Error::Cast(result));
   }
@@ -885,46 +881,6 @@
 }
 
 
-static void ResetICs(const Function& function, const Code& code) {
-  // TODO(johnmccutchan): Relying on the function's ICData Map can miss ICDatas.
-  // Use the code's object pool instead.
-  if (function.ic_data_array() == Array::null()) {
-    // TODO(johnmccutchan): Even in this case, we need to scan the code's object
-    // pool instead.
-    return;  // Already reset in an earlier round.
-  }
-
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-
-  ZoneGrowableArray<const ICData*>* ic_data_array =
-      new(zone) ZoneGrowableArray<const ICData*>();
-  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
-  const intptr_t ic_data_array_length = ic_data_array->length();
-  if (ic_data_array_length == 0) {
-    return;
-  }
-  const PcDescriptors& descriptors =
-      PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kIcCall |
-                                            RawPcDescriptors::kUnoptStaticCall);
-  while (iter.MoveNext()) {
-    const intptr_t index = iter.DeoptId();
-    if (index >= ic_data_array_length) {
-      // TODO(johnmccutchan): Investigate how this can happen.
-      continue;
-    }
-    const ICData* ic_data = (*ic_data_array)[index];
-    if (ic_data == NULL) {
-      // TODO(johnmccutchan): Investigate how this can happen.
-      continue;
-    }
-    bool is_static_call = iter.Kind() == RawPcDescriptors::kUnoptStaticCall;
-    ic_data->Reset(is_static_call);
-  }
-}
-
-
 void IsolateReloadContext::ResetUnoptimizedICsOnStack() {
   Code& code = Code::Handle();
   Function& function = Function::Handle();
@@ -939,10 +895,9 @@
       function = code.function();
       code = function.unoptimized_code();
       ASSERT(!code.IsNull());
-      ResetICs(function, code);
+      code.ResetICDatas();
     } else {
-      function = code.function();
-      ResetICs(function, code);
+      code.ResetICDatas();
     }
     frame = iterator.NextFrame();
   }
@@ -995,7 +950,7 @@
         if (clear_code) {
           ClearAllCode(func);
         } else {
-          PreserveUnoptimizedCode(func);
+          PreserveUnoptimizedCode();
         }
       }
 
@@ -1015,11 +970,11 @@
     func.set_was_compiled(false);
   }
 
-  void PreserveUnoptimizedCode(const Function& func) {
+  void PreserveUnoptimizedCode() {
     ASSERT(!code_.IsNull());
     // We are preserving the unoptimized code, fill all ICData arrays with
     // the sentinel values so that we have no stale type feedback.
-    func.FillICDataWithSentinels(code_);
+    code_.ResetICDatas();
   }
 
   bool IsFromDirtyLibrary(const Function& func) {
@@ -1079,13 +1034,23 @@
 }
 
 
+RawString* IsolateReloadContext::FindLibraryPrivateKey(
+    const Library& replacement_or_new) {
+  const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new));
+  if (old.IsNull()) {
+    return String::null();
+  }
+  return old.private_key();
+}
+
+
 RawLibrary* IsolateReloadContext::OldLibraryOrNull(
     const Library& replacement_or_new) {
   UnorderedHashSet<LibraryMapTraits>
       old_libraries_set(old_libraries_set_storage_);
   Library& lib = Library::Handle();
   lib ^= old_libraries_set.GetOrNull(replacement_or_new);
-  old_libraries_set_storage_ = old_libraries_set.Release().raw();
+  old_libraries_set.Release();
   return lib.raw();
 }
 
@@ -1103,6 +1068,11 @@
     }
     old ^= OldLibraryOrNull(replacement_or_new);
     if (old.IsNull()) {
+      if (FLAG_identity_reload) {
+        TIR_Print("Could not find original library for %s\n",
+                  replacement_or_new.ToCString());
+        UNREACHABLE();
+      }
       // New library.
       AddLibraryMapping(replacement_or_new, replacement_or_new);
     } else {
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index d439414..de6ff00 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -68,6 +68,10 @@
 
   void RegisterClass(const Class& new_cls);
 
+  // Finds the library private key for |replacement_or_new| or return null
+  // if |replacement_or_new| is new.
+  RawString* FindLibraryPrivateKey(const Library& replacement_or_new);
+
   int64_t start_time_micros() const { return start_time_micros_; }
 
  private:
diff --git a/runtime/vm/jit_optimizer.cc b/runtime/vm/jit_optimizer.cc
index e9085b6..dd23e57 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -217,7 +217,8 @@
         String::Handle(Z, ic_data.target_name()),
         Object::empty_array(),  // Dummy argument descriptor.
         ic_data.deopt_id(),
-        ic_data.NumArgsTested()));
+        ic_data.NumArgsTested(),
+        false));
     new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
     new_ic_data.AddReceiverCheck(cid, function);
     return new_ic_data;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 003f1b3..c367f2e 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -46,6 +46,8 @@
       id_zone_(&default_id_zone_),
       reply_port_(ILLEGAL_PORT),
       seq_(NULL),
+      parameter_keys_(NULL),
+      parameter_values_(NULL),
       method_(""),
       param_keys_(NULL),
       param_values_(NULL),
@@ -70,13 +72,18 @@
                        const Instance& seq,
                        const String& method,
                        const Array& param_keys,
-                       const Array& param_values) {
+                       const Array& param_values,
+                       bool parameters_are_dart_objects) {
   set_reply_port(reply_port);
   seq_ = &Instance::ZoneHandle(seq.raw());
   method_ = method.ToCString();
 
-  String& string_iterator = String::Handle();
-  if (param_keys.Length() > 0) {
+  if (parameters_are_dart_objects) {
+    parameter_keys_ = &Array::ZoneHandle(param_keys.raw());
+    parameter_values_ = &Array::ZoneHandle(param_values.raw());
+    ASSERT(parameter_keys_->Length() == parameter_values_->Length());
+  } else if (param_keys.Length() > 0) {
+    String& string_iterator = String::Handle();
     ASSERT(param_keys.Length() == param_values.Length());
     const char** param_keys_native =
         zone->Alloc<const char*>(param_keys.Length());
@@ -92,6 +99,7 @@
     }
     SetParams(param_keys_native, param_values_native, param_keys.Length());
   }
+
   if (FLAG_trace_service) {
     Isolate* isolate = Isolate::Current();
     ASSERT(isolate != NULL);
@@ -130,6 +138,14 @@
       return "Isolate must be runnable";
     case kIsolateMustBePaused:
       return "Isolate must be paused";
+    case kIsolateIsReloading:
+      return "Isolate is reloading";
+    case kFileSystemAlreadyExists:
+      return "File system already exists";
+    case kFileSystemDoesNotExist:
+      return "File system does not exist";
+    case kFileDoesNotExist:
+      return "File does not exist";
     default:
       return "Extension error";
   }
@@ -667,6 +683,42 @@
 }
 
 
+intptr_t JSONStream::NumObjectParameters() const {
+  if (parameter_keys_ == NULL) {
+    return 0;
+  }
+  ASSERT(parameter_keys_ != NULL);
+  ASSERT(parameter_values_ != NULL);
+  return parameter_keys_->Length();
+}
+
+
+RawObject* JSONStream::GetObjectParameterKey(intptr_t i) const {
+  ASSERT((i >= 0) && (i < NumObjectParameters()));
+  return parameter_keys_->At(i);
+}
+
+
+RawObject* JSONStream::GetObjectParameterValue(intptr_t i) const {
+  ASSERT((i >= 0) && (i < NumObjectParameters()));
+  return parameter_values_->At(i);
+}
+
+
+RawObject* JSONStream::LookupObjectParam(const char* c_key) const {
+  const String& key = String::Handle(String::New(c_key));
+  Object& test = Object::Handle();
+  const intptr_t num_object_parameters = NumObjectParameters();
+  for (intptr_t i = 0; i < num_object_parameters; i++) {
+    test = GetObjectParameterKey(i);
+    if (test.IsString() && String::Cast(test).Equals(key)) {
+      return GetObjectParameterValue(i);
+    }
+  }
+  return Object::null();
+}
+
+
 void JSONStream::SetParams(const char** param_keys,
                            const char** param_values,
                            intptr_t num_params) {
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 3c77d4b..1dec0db 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -53,7 +53,12 @@
   kStreamNotSubscribed       = 104,
   kIsolateMustBeRunnable     = 105,
   kIsolateMustBePaused       = 106,
-  kIsolateIsReloading        = 107,
+
+  // Experimental (used in private rpcs).
+  kIsolateIsReloading        = 1000,
+  kFileSystemAlreadyExists   = 1001,
+  kFileSystemDoesNotExist    = 1002,
+  kFileDoesNotExist          = 1003,
 };
 
 // Expected that user_data is a JSONStream*.
@@ -73,7 +78,8 @@
              const Instance& seq,
              const String& method,
              const Array& param_keys,
-             const Array& param_values);
+             const Array& param_values,
+             bool parameters_are_dart_objects = false);
   void SetupError();
 
   void PrintError(intptr_t code, const char* details_format, ...);
@@ -99,6 +105,11 @@
 
   Dart_Port reply_port() const { return reply_port_; }
 
+  intptr_t NumObjectParameters() const;
+  RawObject* GetObjectParameterKey(intptr_t i) const;
+  RawObject* GetObjectParameterValue(intptr_t i) const;
+  RawObject* LookupObjectParam(const char* key) const;
+
   intptr_t num_params() const { return num_params_; }
   const char* GetParamKey(intptr_t i) const {
     return param_keys_[i];
@@ -227,6 +238,8 @@
   ServiceIdZone* id_zone_;
   Dart_Port reply_port_;
   Instance* seq_;
+  Array* parameter_keys_;
+  Array* parameter_values_;
   const char* method_;
   const char** param_keys_;
   const char** param_values_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 13b84c6..be99b1d 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -10364,6 +10364,8 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   ASSERT(thread->IsMutatorThread());
+  // Force the url to have a hash code.
+  url.Hash();
   const Library& result = Library::Handle(zone, Library::New());
   result.StorePointer(&result.raw_ptr()->name_, Symbols::Empty().raw());
   result.StorePointer(&result.raw_ptr()->url_, url.raw());
@@ -10551,6 +10553,18 @@
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
 
+  if (FLAG_support_reload && isolate->IsReloading()) {
+    // When reloading, we need to make sure we use the original private key
+    // if this library previously existed.
+    IsolateReloadContext* reload_context = isolate->reload_context();
+    const String& original_key =
+        String::Handle(reload_context->FindLibraryPrivateKey(*this));
+    if (!original_key.IsNull()) {
+      StorePointer(&raw_ptr()->private_key_, original_key.raw());
+      return;
+    }
+  }
+
   // Format of the private key is: "@<sequence number><6 digits of hash>
   const intptr_t hash_mask = 0x7FFFF;
 
@@ -10936,12 +10950,17 @@
     pending_deferred_loads.Add(deferred_lib);
     const String& lib_url = String::Handle(zone, deferred_lib.url());
     Dart_LibraryTagHandler handler = isolate->library_tag_handler();
+    Object& obj = Object::Handle(zone);
     {
       TransitionVMToNative transition(thread);
       Api::Scope api_scope(thread);
-      handler(Dart_kImportTag,
-              Api::NewHandle(thread, importer()),
-              Api::NewHandle(thread, lib_url.raw()));
+      obj = Api::UnwrapHandle(
+              handler(Dart_kImportTag,
+                      Api::NewHandle(thread, importer()),
+                      Api::NewHandle(thread, lib_url.raw())));
+    }
+    if (obj.IsError()) {
+      Exceptions::PropagateError(Error::Cast(obj));
     }
   } else {
     // Another load request is in flight.
@@ -12553,6 +12572,17 @@
 }
 
 
+void ICData::SetIsStaticCall(bool static_call) const {
+  StoreNonPointer(&raw_ptr()->state_bits_,
+                  StaticCallBit::update(static_call, raw_ptr()->state_bits_));
+}
+
+
+bool ICData::is_static_call() const {
+  return StaticCallBit::decode(raw_ptr()->state_bits_);
+}
+
+
 void ICData::set_state_bits(uint32_t bits) const {
   StoreNonPointer(&raw_ptr()->state_bits_, bits);
 }
@@ -13365,7 +13395,8 @@
                                  const String& target_name,
                                  const Array& arguments_descriptor,
                                  intptr_t deopt_id,
-                                 intptr_t num_args_tested) {
+                                 intptr_t num_args_tested,
+                                 bool is_static_call) {
   ASSERT(!owner.IsNull());
   ASSERT(!target_name.IsNull());
   ASSERT(!arguments_descriptor.IsNull());
@@ -13388,6 +13419,7 @@
 #if defined(TAG_IC_DATA)
   result.set_tag(-1);
 #endif
+  result.SetIsStaticCall(is_static_call);
   result.SetNumArgsTested(num_args_tested);
   return result.raw();
 }
@@ -13432,7 +13464,8 @@
                        const String& target_name,
                        const Array& arguments_descriptor,
                        intptr_t deopt_id,
-                       intptr_t num_args_tested) {
+                       intptr_t num_args_tested,
+                       bool is_static_call) {
   Zone* zone = Thread::Current()->zone();
   const ICData& result = ICData::Handle(zone,
                                         NewDescriptor(zone,
@@ -13440,7 +13473,8 @@
                                                       target_name,
                                                       arguments_descriptor,
                                                       deopt_id,
-                                                      num_args_tested));
+                                                      num_args_tested,
+                                                      is_static_call));
   result.set_ic_data_array(
       Array::Handle(zone, NewEmptyICDataArray(num_args_tested)));
   return result.raw();
@@ -13453,7 +13487,8 @@
       String::Handle(from.target_name()),
       Array::Handle(from.arguments_descriptor()),
       from.deopt_id(),
-      num_args_tested));
+      num_args_tested,
+      from.is_static_call()));
   // Copy deoptimization reasons.
   result.SetDeoptReasons(from.DeoptReasons());
   return result.raw();
@@ -13468,7 +13503,8 @@
       String::Handle(zone, from.target_name()),
       Array::Handle(zone, from.arguments_descriptor()),
       from.deopt_id(),
-      from.NumArgsTested()));
+      from.NumArgsTested(),
+      from.is_static_call()));
   // Clone entry array.
   const Array& from_array = Array::Handle(zone, from.ic_data());
   const intptr_t len = from_array.Length();
@@ -18039,7 +18075,7 @@
   // on new heap.
   RawObject* raw = Object::Allocate(MixinAppType::kClassId,
                                     MixinAppType::InstanceSize(),
-                                    Heap::kNew);
+                                    Heap::kOld);
   return reinterpret_cast<RawMixinAppType*>(raw);
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 984a718..cd014a3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1842,7 +1842,7 @@
 
   bool IsImmutable() const;
 
-  void Reset(bool is_static_call) const;
+  void Reset() const;
   void ResetData() const;
 
   // Note: only deopts with reasons before Unknown in this list are recorded in
@@ -2028,7 +2028,8 @@
                         const String& target_name,
                         const Array& arguments_descriptor,
                         intptr_t deopt_id,
-                        intptr_t num_args_tested);
+                        intptr_t num_args_tested,
+                        bool is_static_call);
   static RawICData* NewFrom(const ICData& from, intptr_t num_args_tested);
 
   // Generates a new ICData with descriptor and data array copied (deep clone).
@@ -2146,6 +2147,9 @@
   intptr_t tag() const { return raw_ptr()->tag_; }
 #endif
 
+  void SetIsStaticCall(bool static_call) const;
+  bool is_static_call() const;
+
  private:
   static RawICData* New();
 
@@ -2167,7 +2171,9 @@
     kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
     kDeoptReasonSize = kLastRecordedDeoptReason + 1,
     kRangeFeedbackPos = kDeoptReasonPos + kDeoptReasonSize,
-    kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots
+    kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots,
+    kStaticCallPos = kRangeFeedbackPos + kRangeFeedbackSize,
+    kStaticCallSize = 1,
   };
 
   class NumArgsTestedBits : public BitField<uint32_t,
@@ -2183,6 +2189,10 @@
                                             ICData::kRangeFeedbackPos,
                                             ICData::kRangeFeedbackSize> {};
 
+  class StaticCallBit : public BitField<uint32_t,
+                                        bool,
+                                        ICData::kStaticCallPos,
+                                        ICData::kStaticCallSize> {};
 #if defined(DEBUG)
   // Used in asserts to verify that a check is not added twice.
   bool HasCheck(const GrowableArray<intptr_t>& cids) const;
@@ -2196,7 +2206,8 @@
                                   const String& target_name,
                                   const Array& arguments_descriptor,
                                   intptr_t deopt_id,
-                                  intptr_t num_args_tested);
+                                  intptr_t num_args_tested,
+                                  bool is_static_call);
 
   static void WriteSentinel(const Array& data, intptr_t test_entry_length);
 
@@ -2275,7 +2286,6 @@
   // Reloading support:
   void Reparent(const Class& new_cls) const;
   void ZeroEdgeCounters() const;
-  void FillICDataWithSentinels(const Code& code) const;
 
   RawClass* Owner() const;
   RawClass* origin() const;
@@ -4539,6 +4549,10 @@
     StorePointer(&raw_ptr()->code_source_map_, code_source_map.raw());
   }
 
+  // Used during reloading (see object_reload.cc). Calls Reset on all ICDatas
+  // that are embedded inside the Code object.
+  void ResetICDatas() const;
+
   TokenPosition GetTokenPositionAt(intptr_t offset) const;
 
   // Array of DeoptInfo objects.
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 405854d..ba5098a 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -56,38 +56,48 @@
 }
 
 
-static void ClearICs(const Function& function, const Code& code) {
-  if (function.ic_data_array() == Array::null()) {
-    return;  // Already reset in an earlier round.
-  }
-
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-
-  ZoneGrowableArray<const ICData*>* ic_data_array =
-      new(zone) ZoneGrowableArray<const ICData*>();
-  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
-  if (ic_data_array->length() == 0) {
+void Code::ResetICDatas() const {
+  // Iterate over the Code's object pool and reset all ICDatas.
+#ifdef TARGET_ARCH_IA32
+  // IA32 does not have an object pool, but, we can iterate over all
+  // embedded objects by using the variable length data section.
+  if (!is_alive()) {
     return;
   }
-  const PcDescriptors& descriptors =
-      PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kIcCall |
-                                            RawPcDescriptors::kUnoptStaticCall);
-  while (iter.MoveNext()) {
-    const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
-    if (ic_data == NULL) {
+  const Instructions& instrs = Instructions::Handle(instructions());
+  ASSERT(!instrs.IsNull());
+  uword base_address = instrs.EntryPoint();
+  Object& object = Object::Handle();
+  intptr_t offsets_length = pointer_offsets_length();
+  const int32_t* offsets = raw_ptr()->data();
+  for (intptr_t i = 0; i < offsets_length; i++) {
+    int32_t offset = offsets[i];
+    RawObject** object_ptr =
+        reinterpret_cast<RawObject**>(base_address + offset);
+    RawObject* raw_object = *object_ptr;
+    if (!raw_object->IsHeapObject()) {
       continue;
     }
-    bool is_static_call = iter.Kind() == RawPcDescriptors::kUnoptStaticCall;
-    ic_data->Reset(is_static_call);
+    object = raw_object;
+    if (object.IsICData()) {
+      ICData::Cast(object).Reset();
+    }
   }
-}
-
-
-void Function::FillICDataWithSentinels(const Code& code) const {
-  ASSERT(code.raw() == CurrentCode());
-  ClearICs(*this, code);
+#else
+  const ObjectPool& pool = ObjectPool::Handle(object_pool());
+  Object& object = Object::Handle();
+  ASSERT(!pool.IsNull());
+  for (intptr_t i = 0; i < pool.Length(); i++) {
+    ObjectPool::EntryType entry_type = pool.InfoAt(i);
+    if (entry_type != ObjectPool::kTaggedObject) {
+      continue;
+    }
+    object = pool.ObjectAt(i);
+    if (object.IsICData()) {
+      ICData::Cast(object).Reset();
+    }
+  }
+#endif
 }
 
 
@@ -423,6 +433,9 @@
     TIR_Print("Finalized replacement class for %s\n", ToCString());
   }
 
+  // At this point the original and replacement must be in the same state.
+  ASSERT(is_finalized() == replacement.is_finalized());
+
   if (is_finalized()) {
     // Get the field maps for both classes. These field maps walk the class
     // hierarchy.
@@ -510,10 +523,8 @@
 
 static const Function* static_call_target = NULL;
 
-void ICData::Reset(bool is_static_call) const {
-  // TODO(johnmccutchan): ICData should know whether or not it's for a
-  // static call.
-  if (is_static_call) {
+void ICData::Reset() const {
+  if (is_static_call()) {
     const Function& old_target = Function::Handle(GetTargetAt(0));
     if (old_target.IsNull()) {
       FATAL("old_target is NULL.\n");
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 7d70f20..05ddd32 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3038,7 +3038,8 @@
   const Array& args_descriptor =
       Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
   ICData& o1 = ICData::Handle();
-  o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested);
+  o1 = ICData::New(function, target_name, args_descriptor, id,
+                   num_args_tested, false);
   EXPECT_EQ(1, o1.NumArgsTested());
   EXPECT_EQ(id, o1.deopt_id());
   EXPECT_EQ(function.raw(), o1.Owner());
@@ -3077,7 +3078,7 @@
   EXPECT_EQ(2, o1.NumberOfUsedChecks());
 
   ICData& o2 = ICData::Handle();
-  o2 = ICData::New(function, target_name, args_descriptor, 57, 2);
+  o2 = ICData::New(function, target_name, args_descriptor, 57, 2, false);
   EXPECT_EQ(2, o2.NumArgsTested());
   EXPECT_EQ(57, o2.deopt_id());
   EXPECT_EQ(function.raw(), o2.Owner());
@@ -3096,7 +3097,8 @@
   // Check ICData for unoptimized static calls.
   const intptr_t kNumArgsChecked = 0;
   const ICData& scall_icdata = ICData::Handle(
-      ICData::New(function, target_name, args_descriptor, 57, kNumArgsChecked));
+      ICData::New(function, target_name, args_descriptor, 57,
+                  kNumArgsChecked, false));
   scall_icdata.AddTarget(target1);
   EXPECT_EQ(target1.raw(), scall_icdata.GetTargetAt(0));
 }
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index ff61aaa..a86889b4 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -25,8 +25,9 @@
   // Returns the current process id.
   static intptr_t ProcessId();
 
-  // Returns the abbreviated time-zone name for the given instant.
-  // For example "CET" or "CEST".
+  // Returns a time-zone name for the given instant.
+  // The name is provided by the underlying platform.
+  // The returned string may be Zone allocated.
   static const char* GetTimeZoneName(int64_t seconds_since_epoch);
 
   // Returns the difference in seconds between local time and UTC for the given
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 2ea8c1d..7236a91 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -34,7 +34,9 @@
 // As a side-effect sets the globals _timezone, _daylight and _tzname.
 static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) {
   time_t seconds = static_cast<time_t>(seconds_since_epoch);
-  if (seconds != seconds_since_epoch) return false;
+  if (seconds != seconds_since_epoch) {
+    return false;
+  }
   // localtime_s implicitly sets _timezone, _daylight and _tzname.
   errno_t error_code = localtime_s(tm_result, &seconds);
   return error_code == 0;
@@ -54,17 +56,38 @@
 
 
 const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) {
-  tm decomposed;
-  // LocalTime will set _tzname.
-  bool succeeded = LocalTime(seconds_since_epoch, &decomposed);
-  if (succeeded) {
-    int inDaylightSavingsTime = decomposed.tm_isdst;
-    ASSERT(inDaylightSavingsTime == 0 || inDaylightSavingsTime == 1);
-    return _tzname[inDaylightSavingsTime];
-  } else {
-    // Return an empty string like V8 does.
+  TIME_ZONE_INFORMATION zone_information;
+  memset(&zone_information, 0, sizeof(zone_information));
+
+  // Initialize and grab the time zone data.
+  _tzset();
+  DWORD status = GetTimeZoneInformation(&zone_information);
+  if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) {
+    // If we can't get the time zone data, the Windows docs indicate that we
+    // are probably out of memory. Return an empty string.
     return "";
   }
+
+  // Figure out whether we're in standard or daylight.
+  bool daylight_savings = (status == TIME_ZONE_ID_DAYLIGHT);
+  if (status == TIME_ZONE_ID_UNKNOWN) {
+    tm local_time;
+    if (LocalTime(seconds_since_epoch, &local_time)) {
+      daylight_savings = (local_time.tm_isdst == 1);
+    }
+  }
+
+  // Convert the wchar string to a null-terminated utf8 string.
+  wchar_t* wchar_name = daylight_savings
+                      ? zone_information.DaylightName
+                      : zone_information.StandardName;
+  intptr_t utf8_len = WideCharToMultiByte(
+      CP_UTF8, 0, wchar_name, -1, NULL, 0, NULL, NULL);
+  char* name = Thread::Current()->zone()->Alloc<char>(utf8_len + 1);
+  WideCharToMultiByte(
+      CP_UTF8, 0, wchar_name, -1, name, utf8_len, NULL, NULL);
+  name[utf8_len] = '\0';
+  return name;
 }
 
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index f2a6422..b8fa54b 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -981,7 +981,7 @@
     const int param_cnt = params.num_fixed_parameters +
                           params.num_optional_parameters;
     const Array& param_descriptor =
-        Array::Handle(Array::New(param_cnt * kParameterEntrySize));
+        Array::Handle(Array::New(param_cnt * kParameterEntrySize, Heap::kOld));
     for (int i = 0, j = 0; i < param_cnt; i++, j += kParameterEntrySize) {
       param_descriptor.SetAt(j + kParameterIsFinalOffset,
                              param[i].is_final ? Bool::True() : Bool::False());
@@ -1518,7 +1518,7 @@
 
   if (func.HasOptionalNamedParameters()) {
     const Array& arg_names =
-        Array::ZoneHandle(Array::New(func.NumOptionalParameters()));
+        Array::ZoneHandle(Array::New(func.NumOptionalParameters(), Heap::kOld));
     for (intptr_t i = 0; i < arg_names.Length(); i++) {
       intptr_t index = func.num_fixed_parameters() + i;
       arg_names.SetAt(i, String::Handle(func.ParameterNameAt(index)));
@@ -4677,6 +4677,11 @@
   }
   ExpectToken(Token::kRBRACE);
 
+  if (cls.LookupTypeParameter(class_name) != TypeParameter::null()) {
+    ReportError(class_pos,
+                "class name conflicts with type parameter '%s'",
+                class_name.ToCString());
+  }
   CheckConstructors(&members);
 
   // Need to compute this here since MakeArray() will clear the
@@ -5340,7 +5345,7 @@
   TRACE_PARSER("ParseInterfaceList");
   ASSERT(CurrentToken() == Token::kIMPLEMENTS);
   const GrowableObjectArray& all_interfaces =
-      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+      GrowableObjectArray::Handle(Z, GrowableObjectArray::New(Heap::kOld));
   AbstractType& interface = AbstractType::Handle(Z);
   // First get all the interfaces already implemented by class.
   Array& cls_interfaces = Array::Handle(Z, cls.interfaces());
@@ -5369,7 +5374,7 @@
   TRACE_PARSER("ParseMixins");
   ASSERT(CurrentToken() == Token::kWITH);
   const GrowableObjectArray& mixin_types =
-      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+      GrowableObjectArray::Handle(Z, GrowableObjectArray::New(Heap::kOld));
   AbstractType& mixin_type = AbstractType::Handle(Z);
   do {
     ConsumeToken();
@@ -5874,6 +5879,7 @@
 
 void Parser::ParseLibraryImportExport(const Object& tl_owner,
                                       TokenPosition metadata_pos) {
+  ASSERT(Thread::Current()->IsMutatorThread());
   bool is_import = (CurrentToken() == Token::kIMPORT);
   bool is_export = (CurrentToken() == Token::kEXPORT);
   ASSERT(is_import || is_export);
@@ -6820,6 +6826,13 @@
   OpenFunctionBlock(closure);
   AddFormalParamsToScope(&closure_params, current_block_->scope);
   async_temp_scope_ = current_block_->scope;
+
+  // Capture instantiator in case it may be needed to generate the type
+  // check of the return value. (C.f. handling of Token::kRETURN.)
+  ASSERT(FunctionLevel() > 0);
+  if (I->type_checks() && IsInstantiatorRequired()) {
+    CaptureInstantiator();
+  }
   return closure.raw();
 }
 
@@ -8385,7 +8398,8 @@
         ArgumentListNode* arguments = new(Z) ArgumentListNode(TokenPos());
         arguments->Add(new(Z) LiteralNode(
             TokenPos(),
-            Integer::ZoneHandle(Z, Integer::New(TokenPos().value()))));
+            Integer::ZoneHandle(Z, Integer::New(TokenPos().value(),
+                                                Heap::kOld))));
         current_block_->statements->Add(
             MakeStaticCall(Symbols::FallThroughError(),
                            Library::PrivateCoreLibName(Symbols::ThrowNew()),
@@ -9164,30 +9178,22 @@
 AstNode* Parser::MakeAssertCall(TokenPosition begin, TokenPosition end) {
   ArgumentListNode* arguments = new(Z) ArgumentListNode(begin);
   arguments->Add(new(Z) LiteralNode(begin,
-      Integer::ZoneHandle(Z, Integer::New(begin.value()))));
+      Integer::ZoneHandle(Z, Integer::New(begin.value(), Heap::kOld))));
   arguments->Add(new(Z) LiteralNode(end,
-      Integer::ZoneHandle(Z, Integer::New(end.value()))));
+      Integer::ZoneHandle(Z, Integer::New(end.value(), Heap::kOld))));
   return MakeStaticCall(Symbols::AssertionError(),
                         Library::PrivateCoreLibName(Symbols::ThrowNew()),
                         arguments);
 }
 
 
-AstNode* Parser::InsertClosureCallNodes(AstNode* condition) {
-  if (condition->IsClosureNode() ||
-      (condition->IsStoreLocalNode() &&
-       condition->AsStoreLocalNode()->value()->IsClosureNode())) {
-    // Function literal in assert implies a call.
-    const TokenPosition pos = condition->token_pos();
-    condition = BuildClosureCall(pos,
-                                 condition,
-                                 new(Z) ArgumentListNode(pos));
-  } else if (condition->IsConditionalExprNode()) {
-    ConditionalExprNode* cond_expr = condition->AsConditionalExprNode();
-    cond_expr->set_true_expr(InsertClosureCallNodes(cond_expr->true_expr()));
-    cond_expr->set_false_expr(InsertClosureCallNodes(cond_expr->false_expr()));
-  }
-  return condition;
+AstNode* Parser::HandleAssertCondition(AstNode* condition) {
+  const TokenPosition pos = condition->token_pos();
+  ArgumentListNode* arguments = new(Z) ArgumentListNode(pos);
+  arguments->Add(condition);
+  return MakeStaticCall(Symbols::AssertionError(),
+                        Library::PrivateCoreLibName(Symbols::HandleCondition()),
+                        arguments);
 }
 
 
@@ -9204,7 +9210,7 @@
   AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
   const TokenPosition condition_end = TokenPos();
   ExpectToken(Token::kRPAREN);
-  condition = InsertClosureCallNodes(condition);
+  condition = HandleAssertCondition(condition);
   condition = new(Z) UnaryOpNode(condition_pos, Token::kNOT, condition);
   AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end);
   return new(Z) IfNode(
@@ -10132,23 +10138,24 @@
     ConsumeToken();
     if (CurrentToken() != Token::kSEMICOLON) {
       const TokenPosition expr_pos = TokenPos();
+      const int function_level = FunctionLevel();
       if (current_function().IsGenerativeConstructor() &&
-          (FunctionLevel() == 0)) {
+          (function_level == 0)) {
         ReportError(expr_pos,
                     "return of a value is not allowed in constructors");
       } else if (current_function().IsGeneratorClosure() &&
-          (FunctionLevel() == 0)) {
+          (function_level == 0)) {
         ReportError(expr_pos, "generator functions may not return a value");
       }
       AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
       if (I->type_checks() &&
-          current_function().IsAsyncClosure() && (FunctionLevel() == 0)) {
+          (((function_level == 0) && current_function().IsAsyncClosure()))) {
         // In checked mode, when the declared result type is Future<T>, verify
         // that the returned expression is of type T or Future<T> as follows:
         // return temp = expr, temp is Future ? temp as Future<T> : temp as T;
         // In case of a mismatch, we need a TypeError and not a CastError, so
         // we do not actually implement an "as" test, but an "assignable" test.
-        const Function& async_func =
+        Function& async_func =
             Function::Handle(Z, current_function().parent_function());
         const AbstractType& result_type =
             AbstractType::ZoneHandle(Z, async_func.result_type());
@@ -10469,7 +10476,8 @@
   }
   // Location argument.
   arguments->Add(new(Z) LiteralNode(
-      type_pos, Integer::ZoneHandle(Z, Integer::New(type_pos.value()))));
+      type_pos, Integer::ZoneHandle(Z, Integer::New(type_pos.value(),
+                                                    Heap::kOld))));
   // Src value argument.
   arguments->Add(new(Z) LiteralNode(type_pos, Object::null_instance()));
   // Dst type argument.
@@ -11697,7 +11705,7 @@
         } else if (primary_node->primary().IsClass()) {
           const Class& type_class = Class::Cast(primary_node->primary());
           AbstractType& type = Type::ZoneHandle(Z, Type::New(
-              type_class, TypeArguments::Handle(Z), primary_pos));
+              type_class, TypeArguments::Handle(Z), primary_pos, Heap::kOld));
           type ^= ClassFinalizer::FinalizeType(
               current_class(), type, ClassFinalizer::kCanonicalize);
           // Type may be malbounded, but not malformed.
@@ -11723,7 +11731,7 @@
         } else if (primary_node->primary().IsClass()) {
           const Class& type_class = Class::Cast(primary_node->primary());
           AbstractType& type = Type::ZoneHandle(Z, Type::New(
-              type_class, TypeArguments::Handle(Z), primary_pos));
+              type_class, TypeArguments::Handle(Z), primary_pos, Heap::kOld));
           type = ClassFinalizer::FinalizeType(
               current_class(), type, ClassFinalizer::kCanonicalize);
           // Type may be malbounded, but not malformed.
@@ -12096,8 +12104,8 @@
   if (!type.IsNull()) {
     return &type;
   }
-  type = Type::New(cls,
-      TypeArguments::Handle(Z, cls.type_parameters()), cls.token_pos());
+  type = Type::New(cls, TypeArguments::Handle(Z, cls.type_parameters()),
+                   cls.token_pos(), Heap::kOld);
   if (cls.is_type_finalized()) {
     type ^= ClassFinalizer::FinalizeType(
         cls, type, ClassFinalizer::kCanonicalizeWellFormed);
@@ -12121,6 +12129,7 @@
 void Parser::InsertCachedConstantValue(const String& url,
                                        TokenPosition token_pos,
                                        const Instance& value) {
+  ASSERT(Thread::Current()->IsMutatorThread());
   Isolate* isolate = Isolate::Current();
   ConstantPosKey key(url, token_pos);
   if (isolate->object_store()->compile_time_constants() == Array::null()) {
@@ -12617,7 +12626,8 @@
     } else if (primary->primary().IsClass()) {
       const Class& type_class = Class::Cast(primary->primary());
       AbstractType& type = Type::ZoneHandle(Z,
-          Type::New(type_class, TypeArguments::Handle(Z), primary_pos));
+          Type::New(type_class, TypeArguments::Handle(Z), primary_pos,
+                    Heap::kOld));
       type ^= ClassFinalizer::FinalizeType(
           current_class(), type, ClassFinalizer::kCanonicalize);
       // Type may be malbounded, but not malformed.
@@ -12748,7 +12758,7 @@
     return Type::DynamicType();
   }
   AbstractType& type = AbstractType::Handle(
-      Z, Type::New(type_class, type_arguments, ident_pos));
+      Z, Type::New(type_class, type_arguments, ident_pos, Heap::kOld));
   if (finalization >= ClassFinalizer::kResolveTypeParameters) {
     ResolveTypeFromClass(current_class(), finalization, &type);
     if (finalization >= ClassFinalizer::kCanonicalize) {
@@ -12831,7 +12841,7 @@
   ASSERT(list_type_arguments.IsNull() || (list_type_arguments.Length() == 1));
   const Class& array_class = Class::Handle(Z, I->object_store()->array_class());
   Type& type = Type::ZoneHandle(Z,
-      Type::New(array_class, list_type_arguments, type_pos));
+      Type::New(array_class, list_type_arguments, type_pos, Heap::kOld));
   type ^= ClassFinalizer::FinalizeType(
       current_class(), type, ClassFinalizer::kCanonicalize);
   GrowableArray<AstNode*> element_list;
@@ -12923,7 +12933,7 @@
     if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 1)) {
       ASSERT(factory_type_args.Length() == 1);
       Type& factory_type = Type::Handle(Z, Type::New(
-          factory_class, factory_type_args, type_pos, Heap::kNew));
+          factory_class, factory_type_args, type_pos, Heap::kOld));
       factory_type ^= ClassFinalizer::FinalizeType(
           current_class(), factory_type, ClassFinalizer::kFinalize);
       factory_type_args = factory_type.arguments();
@@ -13185,7 +13195,7 @@
     if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 2)) {
       ASSERT(factory_type_args.Length() == 2);
       Type& factory_type = Type::Handle(Z, Type::New(
-          factory_class, factory_type_args, type_pos, Heap::kNew));
+          factory_class, factory_type_args, type_pos, Heap::kOld));
       factory_type ^= ClassFinalizer::FinalizeType(
           current_class(), factory_type, ClassFinalizer::kFinalize);
       factory_type_args = factory_type.arguments();
@@ -13639,7 +13649,8 @@
     }
     ArgumentListNode* error_arguments = new(Z) ArgumentListNode(type_pos);
     error_arguments->Add(new(Z) LiteralNode(
-        TokenPos(), Integer::ZoneHandle(Z, Integer::New(type_pos.value()))));
+        TokenPos(), Integer::ZoneHandle(Z, Integer::New(type_pos.value(),
+                                                        Heap::kOld))));
     error_arguments->Add(new(Z) LiteralNode(
         TokenPos(), String::ZoneHandle(Z, type_class_name.raw())));
     result->AddNode(
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 3bcb688..31c6ec0 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -898,7 +898,7 @@
                                 const String* left_ident,
                                 TokenPosition left_pos,
                                 bool is_compound = false);
-  AstNode* InsertClosureCallNodes(AstNode* condition);
+  AstNode* HandleAssertCondition(AstNode* condition);
 
   ConstructorCallNode* CreateConstructorCallNode(
       TokenPosition token_pos,
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 518b027..8f6f624 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1996,7 +1996,7 @@
 class RawFloat32x4 : public RawInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4);
 
-  float value_[4];
+  ALIGN8 float value_[4];
 
   friend class SnapshotReader;
  public:
@@ -2005,12 +2005,13 @@
   float z() const { return value_[2]; }
   float w() const { return value_[3]; }
 };
+COMPILE_ASSERT(sizeof(RawFloat32x4) == 24);
 
 
 class RawInt32x4 : public RawInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Int32x4);
 
-  int32_t value_[4];
+  ALIGN8 int32_t value_[4];
 
   friend class SnapshotReader;
  public:
@@ -2019,18 +2020,20 @@
   int32_t z() const { return value_[2]; }
   int32_t w() const { return value_[3]; }
 };
+COMPILE_ASSERT(sizeof(RawInt32x4) == 24);
 
 
 class RawFloat64x2 : public RawInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Float64x2);
 
-  double value_[2];
+  ALIGN8 double value_[2];
 
   friend class SnapshotReader;
  public:
   double x() const { return value_[0]; }
   double y() const { return value_[1]; }
 };
+COMPILE_ASSERT(sizeof(RawFloat64x2) == 24);
 
 
 // Define an aliases for intptr_t.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 80607bb..087e47e 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -14,6 +14,7 @@
 #include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
+#include "vm/dev_fs.h"
 #include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/message.h"
@@ -413,6 +414,10 @@
     return true;
   }
 
+  virtual bool ValidateObject(const Object& value) const {
+    return true;
+  }
+
   const char* name() const {
     return name_;
   }
@@ -427,12 +432,42 @@
     PrintInvalidParamError(js, name);
   }
 
+  virtual void PrintErrorObject(const char* name,
+                                const Object& value,
+                                JSONStream* js) const {
+    PrintInvalidParamError(js, name);
+  }
+
  private:
   const char* name_;
   bool required_;
 };
 
 
+class DartStringParameter : public MethodParameter {
+ public:
+  DartStringParameter(const char* name, bool required)
+      : MethodParameter(name, required) {
+  }
+
+  virtual bool ValidateObject(const Object& value) const {
+    return value.IsString();
+  }
+};
+
+
+class DartListParameter : public MethodParameter {
+ public:
+  DartListParameter(const char* name, bool required)
+      : MethodParameter(name, required) {
+  }
+
+  virtual bool ValidateObject(const Object& value) const {
+    return value.IsArray() || value.IsGrowableObjectArray();
+  }
+};
+
+
 class NoSuchParameter : public MethodParameter {
  public:
   explicit NoSuchParameter(const char* name)
@@ -442,6 +477,10 @@
   virtual bool Validate(const char* value) const {
     return (value == NULL);
   }
+
+  virtual bool ValidateObject(const Object& value) const {
+    return value.IsNull();
+  }
 };
 
 
@@ -737,19 +776,38 @@
   if (parameters == NULL) {
     return true;
   }
-  for (intptr_t i = 0; parameters[i] != NULL; i++) {
-    const MethodParameter* parameter = parameters[i];
-    const char* name = parameter->name();
-    const bool required = parameter->required();
-    const char* value = js->LookupParam(name);
-    const bool has_parameter = (value != NULL);
-    if (required && !has_parameter) {
-      PrintMissingParamError(js, name);
-      return false;
+  if (js->NumObjectParameters() > 0) {
+    Object& value = Object::Handle();
+    for (intptr_t i = 0; parameters[i] != NULL; i++) {
+      const MethodParameter* parameter = parameters[i];
+      const char* name = parameter->name();
+      const bool required = parameter->required();
+      value = js->LookupObjectParam(name);
+      const bool has_parameter = !value.IsNull();
+      if (required && !has_parameter) {
+        PrintMissingParamError(js, name);
+        return false;
+      }
+      if (has_parameter && !parameter->ValidateObject(value)) {
+        parameter->PrintErrorObject(name, value, js);
+        return false;
+      }
     }
-    if (has_parameter && !parameter->Validate(value)) {
-      parameter->PrintError(name, value, js);
-      return false;
+  } else {
+    for (intptr_t i = 0; parameters[i] != NULL; i++) {
+      const MethodParameter* parameter = parameters[i];
+      const char* name = parameter->name();
+      const bool required = parameter->required();
+      const char* value = js->LookupParam(name);
+      const bool has_parameter = (value != NULL);
+      if (required && !has_parameter) {
+        PrintMissingParamError(js, name);
+        return false;
+      }
+      if (has_parameter && !parameter->Validate(value)) {
+        parameter->PrintError(name, value, js);
+        return false;
+      }
     }
   }
   return true;
@@ -775,7 +833,9 @@
 }
 
 
-void Service::InvokeMethod(Isolate* I, const Array& msg) {
+void Service::InvokeMethod(Isolate* I,
+                           const Array& msg,
+                           bool parameters_are_dart_objects) {
   Thread* T = Thread::Current();
   ASSERT(I == T->isolate());
   ASSERT(I != NULL);
@@ -809,7 +869,11 @@
 
     JSONStream js;
     js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
-             seq, method_name, param_keys, param_values);
+             seq,
+             method_name,
+             param_keys,
+             param_values,
+             parameters_are_dart_objects);
 
     // RPC came in with a custom service id zone.
     const char* id_zone_param = js.LookupParam("_idZone");
@@ -889,6 +953,12 @@
 }
 
 
+void Service::HandleObjectRootMessage(const Array& msg_instance) {
+  Isolate* isolate = Isolate::Current();
+  InvokeMethod(isolate, msg_instance, true);
+}
+
+
 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
   ASSERT(isolate != NULL);
   InvokeMethod(isolate, msg);
@@ -3883,6 +3953,7 @@
 
 
 static const MethodParameter* set_vm_name_params[] = {
+  NO_ISOLATE_PARAMETER,
   new MethodParameter("name", true),
   NULL,
 };
@@ -3932,6 +4003,127 @@
 }
 
 
+static const MethodParameter* create_dev_fs_params[] = {
+  NO_ISOLATE_PARAMETER,
+  new DartStringParameter("fsName", true),
+  NULL,
+};
+
+
+static bool CreateDevFS(Thread* thread, JSONStream* js) {
+  const String& fs_name =
+      String::Handle(String::RawCast(js->LookupObjectParam("fsName")));
+  DevFS::CreateFileSystem(js, fs_name);
+  return true;
+}
+
+
+static const MethodParameter* delete_dev_fs_params[] = {
+  NO_ISOLATE_PARAMETER,
+  new DartStringParameter("fsName", true),
+  NULL,
+};
+
+
+static bool DeleteDevFS(Thread* thread, JSONStream* js) {
+  const String& fs_name =
+      String::Handle(String::RawCast(js->LookupObjectParam("fsName")));
+  DevFS::DeleteFileSystem(js, fs_name);
+  return true;
+}
+
+
+static const MethodParameter* list_dev_fs_params[] = {
+  NO_ISOLATE_PARAMETER,
+  NULL,
+};
+
+
+static bool ListDevFS(Thread* thread, JSONStream* js) {
+  DevFS::ListFileSystems(js);
+  return true;
+}
+
+
+static const MethodParameter* write_dev_fs_file_params[] = {
+  NO_ISOLATE_PARAMETER,
+  new DartStringParameter("fsName", true),
+  new DartStringParameter("path", true),
+  new DartStringParameter("fileContents", true),
+  NULL,
+};
+
+
+static bool WriteDevFSFile(Thread* thread, JSONStream* js) {
+  const String& fs_name =
+      String::Handle(String::RawCast(js->LookupObjectParam("fsName")));
+  const String& path =
+      String::Handle(String::RawCast(js->LookupObjectParam("path")));
+  const String& file_contents =
+      String::Handle(String::RawCast(js->LookupObjectParam("fileContents")));
+  DevFS::WriteFile(js, fs_name, path, file_contents);
+  return true;
+}
+
+
+static const MethodParameter* write_dev_fs_files_params[] = {
+  NO_ISOLATE_PARAMETER,
+  new DartStringParameter("fsName", true),
+  new DartListParameter("files", true),
+  NULL,
+};
+
+
+static bool WriteDevFSFiles(Thread* thread, JSONStream* js) {
+  const String& fs_name =
+      String::Handle(String::RawCast(js->LookupObjectParam("fsName")));
+  Array& files = Array::Handle();
+  const Object& files_param = Object::Handle(js->LookupObjectParam("files"));
+  if (files_param.IsArray()) {
+    files ^= files_param.raw();
+  } else {
+    ASSERT(files_param.IsGrowableObjectArray());
+    files ^= GrowableObjectArray::Cast(files_param).data();
+  }
+  ASSERT(!files.IsNull());
+  DevFS::WriteFiles(js, fs_name, files);
+  return true;
+}
+
+
+static const MethodParameter* read_dev_fs_file_params[] = {
+  NO_ISOLATE_PARAMETER,
+  new DartStringParameter("fsName", true),
+  new DartStringParameter("path", true),
+  NULL,
+};
+
+
+static bool ReadDevFSFile(Thread* thread, JSONStream* js) {
+  const String& fs_name =
+      String::Handle(String::RawCast(js->LookupObjectParam("fsName")));
+  const String& path =
+      String::Handle(String::RawCast(js->LookupObjectParam("path")));
+  DevFS::ReadFile(js, fs_name, path);
+  return true;
+}
+
+
+static const MethodParameter* list_dev_fs_files_params[] = {
+  NO_ISOLATE_PARAMETER,
+  new DartStringParameter("fsName", true),
+  NULL,
+};
+
+
+static bool ListDevFSFiles(Thread* thread, JSONStream* js) {
+  const String& fs_name =
+      String::Handle(String::RawCast(js->LookupObjectParam("fsName")));
+  DevFS::ListFiles(js, fs_name);
+  return true;
+}
+
+
 static const ServiceMethodDescriptor service_methods_[] = {
   { "_dumpIdZone", DumpIdZone, NULL },
   { "_echo", Echo,
@@ -4044,6 +4236,20 @@
     set_vm_name_params },
   { "_setVMTimelineFlags", SetVMTimelineFlags,
     set_vm_timeline_flags_params },
+  { "_createDevFS", CreateDevFS,
+    create_dev_fs_params },
+  { "_deleteDevFS", DeleteDevFS,
+    delete_dev_fs_params },
+  { "_listDevFS", ListDevFS,
+    list_dev_fs_params },
+  { "_writeDevFSFile", WriteDevFSFile,
+    write_dev_fs_file_params },
+  { "_writeDevFSFiles", WriteDevFSFiles,
+    write_dev_fs_files_params },
+  { "_readDevFSFile", ReadDevFSFile,
+    read_dev_fs_file_params },
+  { "_listDevFSFiles", ListDevFSFiles,
+    list_dev_fs_files_params },
 };
 
 
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 084b218..420ff62 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -82,6 +82,10 @@
   // Handles a message which is not directed to an isolate.
   static void HandleRootMessage(const Array& message);
 
+  // Handles a message which is not directed to an isolate and also
+  // expects the parameter keys and values to be actual dart objects.
+  static void HandleObjectRootMessage(const Array& message);
+
   // Handles a message which is directed to a particular isolate.
   static void HandleIsolateMessage(Isolate* isolate, const Array& message);
 
@@ -161,7 +165,9 @@
   static void PrintJSONForVM(JSONStream* js, bool ref);
 
  private:
-  static void InvokeMethod(Isolate* isolate, const Array& message);
+  static void InvokeMethod(Isolate* isolate,
+                           const Array& message,
+                           bool parameters_are_dart_objects = false);
 
   static void EmbedderHandleMessage(EmbedderServiceHandler* handler,
                                     JSONStream* js);
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index d4d02d7..c73c176 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -7,6 +7,7 @@
 #include "vm/compiler.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
+#include "vm/dev_fs.h"
 #include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/message.h"
@@ -457,6 +458,9 @@
   // Grab the isolate create callback here to avoid race conditions with tests
   // that change this after Dart_Initialize returns.
   create_callback_ = Isolate::CreateCallback();
+  if (FLAG_support_service) {
+    DevFS::Init();
+  }
   Dart::thread_pool()->Run(new RunServiceTask());
 }
 
@@ -505,6 +509,9 @@
     free(server_address_);
     server_address_ = NULL;
   }
+  if (FLAG_support_service) {
+    DevFS::Cleanup();
+  }
 }
 
 
@@ -530,4 +537,8 @@
   ServiceIsolate::SetServicePort(port);
 }
 
+
+void ServiceIsolate::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+}
+
 }  // namespace dart
diff --git a/runtime/vm/service_isolate.h b/runtime/vm/service_isolate.h
index dc2e4be..9def85c 100644
--- a/runtime/vm/service_isolate.h
+++ b/runtime/vm/service_isolate.h
@@ -12,6 +12,8 @@
 
 namespace dart {
 
+class ObjectPointerVisitor;
+
 class ServiceIsolate : public AllStatic {
  public:
   static const char* kName;
@@ -41,6 +43,8 @@
     return server_address_;
   }
 
+  static void VisitObjectPointers(ObjectPointerVisitor* visitor);
+
  private:
   static void KillServiceIsolate();
 
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index baafca84..499f604 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -1829,6 +1829,15 @@
   }
 
   {
+    BYTECODE(CheckSmi, 0);
+    intptr_t obj = reinterpret_cast<intptr_t>(FP[rA]);
+    if ((obj & kSmiTagMask) == kSmiTag) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
     BYTECODE(IfEqStrictTOS, 0);
     SP -= 2;
     if (SP[1] != SP[2]) {
@@ -1965,55 +1974,69 @@
 
   {
     BYTECODE(Deopt, A_D);
-    const uint16_t deopt_id = rD;
-    if (deopt_id == 0) {  // Lazy deoptimization.
-      // Preserve result of the previous call.
-      // TODO(vegorov) we could have actually included result into the
-      // deoptimization environment because it is passed through the stack.
-      // If we do then we could remove special result handling from this code.
-      RawObject* result = SP[0];
+    const bool is_lazy = rD == 0;
 
-      // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
-      // The code in this frame may not cause GC.
-      // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls.
-      EnterSyntheticFrame(&FP, &SP, pc - 1);
-      const intptr_t frame_size_in_bytes =
-          DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(FP),
-                                   /*is_lazy_deopt=*/1);
-      LeaveSyntheticFrame(&FP, &SP);
+    // Preserve result of the previous call.
+    // TODO(vegorov) we could have actually included result into the
+    // deoptimization environment because it is passed through the stack.
+    // If we do then we could remove special result handling from this code.
+    RawObject* result = SP[0];
 
-      SP = FP + (frame_size_in_bytes / kWordSize);
-      EnterSyntheticFrame(&FP, &SP, pc - 1);
-      DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(FP));
+    // When not preserving the result, we still need to preserve SP[0] as it
+    // contains some temporary expression.
+    if (!is_lazy) {
+      SP++;
+    }
 
-      // We are now inside a valid frame.
-      {
+    // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
+    // The code in this frame may not cause GC.
+    // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls.
+    EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0));
+    const intptr_t frame_size_in_bytes =
+        DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(FP), is_lazy ? 1 : 0);
+    LeaveSyntheticFrame(&FP, &SP);
+
+    SP = FP + (frame_size_in_bytes / kWordSize);
+    EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0));
+    DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(FP));
+
+    // We are now inside a valid frame.
+    {
+      if (is_lazy) {
         *++SP = result;  // Preserve result (call below can cause GC).
-        *++SP = 0;  // Space for the result: number of materialization args.
-        Exit(thread, FP, SP + 1, /*pc=*/0);
-        NativeArguments native_args(thread, 0, SP, SP);
-        INVOKE_RUNTIME(DRT_DeoptimizeMaterialize, native_args);
       }
-      const intptr_t materialization_arg_count =
-          Smi::Value(RAW_CAST(Smi, *SP--));
-      result = *SP--;  // Reload the result. It might have been relocated by GC.
+      *++SP = 0;  // Space for the result: number of materialization args.
+      Exit(thread, FP, SP + 1, /*pc=*/0);
+      NativeArguments native_args(thread, 0, SP, SP);
+      INVOKE_RUNTIME(DRT_DeoptimizeMaterialize, native_args);
+    }
+    const intptr_t materialization_arg_count =
+        Smi::Value(RAW_CAST(Smi, *SP--));
+    if (is_lazy) {
+      // Reload the result. It might have been relocated by GC.
+      result = *SP--;
+    }
 
-      // Restore caller PC.
-      pc = SavedCallerPC(FP);
+    // Restore caller PC.
+    pc = SavedCallerPC(FP);
 
-      // Check if it is a fake PC marking the entry frame.
-      ASSERT((reinterpret_cast<uword>(pc) & 2) == 0);
+    // Check if it is a fake PC marking the entry frame.
+    ASSERT((reinterpret_cast<uword>(pc) & 2) == 0);
 
-      // Restore SP, FP and PP. Push result and dispatch.
-      // Note: unlike in a normal return sequence we don't need to drop
-      // arguments - those are not part of the innermost deoptimization
-      // environment they were dropped by FlowGraphCompiler::RecordAfterCall.
-      SP = FrameArguments(FP, materialization_arg_count);
-      FP = SavedCallerFP(FP);
-      pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr();
-      *SP = result;
+    // Restore SP, FP and PP. Push result and dispatch.
+    // Note: unlike in a normal return sequence we don't need to drop
+    // arguments - those are not part of the innermost deoptimization
+    // environment they were dropped by FlowGraphCompiler::RecordAfterCall.
+
+    // If the result is not preserved, the unoptimized frame ends at the
+    // next slot.
+    SP = FrameArguments(FP, materialization_arg_count);
+    FP = SavedCallerFP(FP);
+    pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr();
+    if (is_lazy) {
+      SP[0] = result;  // Put the result on the stack.
     } else {
-      UNIMPLEMENTED();
+      SP--;  // No result to push.
     }
     DISPATCH();
   }
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 8b85956..96b4eba 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -71,6 +71,7 @@
   V(CyclicInitializationError, "CyclicInitializationError")                    \
   V(ThrowNew, "_throwNew")                                                     \
   V(ThrowNewIfNotLoaded, "_throwNewIfNotLoaded")                               \
+  V(HandleCondition, "_handleCondition")                                       \
   V(Symbol, "Symbol")                                                          \
   V(SymbolCtor, "Symbol.")                                                     \
   V(List, "List")                                                              \
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 2059b7107..b0c773e 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -140,7 +140,11 @@
                                      Dart_Handle library,
                                      Dart_Handle url) {
   if (tag == Dart_kCanonicalizeUrl) {
-    return Dart_DefaultCanonicalizeUrl(library, url);
+    Dart_Handle library_url = Dart_LibraryUrl(library);
+    if (Dart_IsError(library_url)) {
+      return library_url;
+    }
+    return Dart_DefaultCanonicalizeUrl(library_url, url);
   }
   if (tag == Dart_kScriptTag) {
     // Reload request.
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 3c11343..902eae7 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -155,6 +155,8 @@
     'deferred_objects.h',
     'deopt_instructions.cc',
     'deopt_instructions.h',
+    'dev_fs.cc',
+    'dev_fs.h',
     'disassembler.cc',
     'disassembler.h',
     'disassembler_arm.cc',
diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
index 35e93e0..b5e9c3c 100644
--- a/sdk/lib/core/date_time.dart
+++ b/sdk/lib/core/date_time.dart
@@ -664,8 +664,10 @@
   external int get microsecondsSinceEpoch;
 
   /**
-   * The abbreviated time zone name&mdash;for example,
-   * [:"CET":] or [:"CEST":].
+   * The time zone name provided by the platform.
+   *
+   * On Unix-like systems this will probably be an abbreviation. On Windows
+   * this will probably be the full-name, e.g. "Pacific Standard Time".
    */
   external String get timeZoneName;
 
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 4ac4486..92d144f 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -52,7 +52,11 @@
   /// Shared file lock.
   SHARED,
   /// Exclusive file lock.
-  EXCLUSIVE
+  EXCLUSIVE,
+  /// Blocking shared file lock.
+  BLOCKING_SHARED,
+  /// Blocking exclusive file lock.
+  BLOCKING_EXCLUSIVE,
 }
 
 /**
@@ -735,6 +739,11 @@
    *
    * To obtain an exclusive lock on a file it must be opened for writing.
    *
+   * If [mode] is [FileLock.EXCLUSIVE] or [FileLock.SHARED], an error is
+   * signaled if the lock cannot be obtained. If [mode] is
+   * [FileLock.BLOCKING_EXCLUSIVE] or [FileLock.BLOCKING_SHARED], the
+   * returned [Future] is resolved only when the lock has been obtained.
+   *
    * *NOTE* file locking does have slight differences in behavior across
    * platforms:
    *
@@ -768,6 +777,11 @@
    *
    * To obtain an exclusive lock on a file it must be opened for writing.
    *
+   * If [mode] is [FileLock.EXCLUSIVE] or [FileLock.SHARED], an exception is
+   * thrown if the lock cannot be obtained. If [mode] is
+   * [FileLock.BLOCKING_EXCLUSIVE] or [FileLock.BLOCKING_SHARED], the
+   * call returns only after the lock has been obtained.
+   *
    * *NOTE* file locking does have slight differences in behavior across
    * platforms:
    *
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index bb00477..5b61fb3 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -919,6 +919,18 @@
   static final int LOCK_UNLOCK = 0;
   static final int LOCK_SHARED = 1;
   static final int LOCK_EXCLUSIVE = 2;
+  static final int LOCK_BLOCKING_SHARED = 3;
+  static final int LOCK_BLOCKING_EXCLUSIVE = 4;
+
+  int _fileLockValue(FileLock fl) {
+    switch (fl) {
+      case FileLock.SHARED: return LOCK_SHARED;
+      case FileLock.EXCLUSIVE: return LOCK_EXCLUSIVE;
+      case FileLock.BLOCKING_SHARED: return LOCK_BLOCKING_SHARED;
+      case FileLock.BLOCKING_EXCLUSIVE: return LOCK_BLOCKING_EXCLUSIVE;
+      default: return -1;
+    }
+  }
 
   Future<RandomAccessFile> lock(
       [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]) {
@@ -928,7 +940,7 @@
     if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
       throw new ArgumentError();
     }
-    int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED;
+    int lock = _fileLockValue(mode);
     return _dispatch(_FILE_LOCK, [null, lock, start, end])
         .then((response) {
           if (_isErrorResponse(response)) {
@@ -963,7 +975,7 @@
     if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
       throw new ArgumentError();
     }
-    int lock = (mode == FileLock.EXCLUSIVE) ? LOCK_EXCLUSIVE : LOCK_SHARED;
+    int lock = _fileLockValue(mode);
     var result = _ops.lock(lock, start, end);
     if (result is OSError) {
       throw new FileSystemException('lock failed', path, result);
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index 481206e..08bb5b1 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -116,23 +116,58 @@
     return _completer.future;
   }
 
+  // We currently support two ways of passing parameters from Dart code to C
+  // code. The original way always converts the parameters to strings before
+  // passing them over. Our goal is to convert all C handlers to take the
+  // parameters as Dart objects but until the conversion is complete, we
+  // maintain the list of supported methods below.
+  bool _methodNeedsObjectParameters(String method) {
+    switch (method) {
+      case '_listDevFS':
+      case '_listDevFSFiles':
+      case '_createDevFS':
+      case '_deleteDevFS':
+      case '_writeDevFSFile':
+      case '_writeDevFSFiles':
+      case '_readDevFSFile':
+        return true;
+      default:
+        return false;
+    }
+  }
+
   Future<String> sendToVM() {
     final receivePort = new RawReceivePort();
     receivePort.handler = (value) {
       receivePort.close();
       _completer.complete(value);
     };
-    var keys = _makeAllString(params.keys.toList(growable:false));
-    var values = _makeAllString(params.values.toList(growable:false));
-    var request = new List(6)
-        ..[0] = 0  // Make room for OOB message type.
-        ..[1] = receivePort.sendPort
-        ..[2] = serial
-        ..[3] = method
-        ..[4] = keys
-        ..[5] = values;
-    sendRootServiceMessage(request);
-    return _completer.future;
+    if (_methodNeedsObjectParameters(method)) {
+      // We use a different method invocation path here.
+      var keys = params.keys.toList(growable:false);
+      var values = params.values.toList(growable:false);
+      var request = new List(6)
+          ..[0] = 0  // Make room for OOB message type.
+          ..[1] = receivePort.sendPort
+          ..[2] = serial
+          ..[3] = method
+          ..[4] = keys
+          ..[5] = values;
+      sendObjectRootServiceMessage(request);
+      return _completer.future;
+    } else {
+      var keys = _makeAllString(params.keys.toList(growable:false));
+      var values = _makeAllString(params.values.toList(growable:false));
+      var request = new List(6)
+          ..[0] = 0  // Make room for OOB message type.
+          ..[1] = receivePort.sendPort
+          ..[2] = serial
+          ..[3] = method
+          ..[4] = keys
+          ..[5] = values;
+      sendRootServiceMessage(request);
+      return _completer.future;
+    }
   }
 
   void setResponse(String response) {
@@ -147,3 +182,4 @@
 
 external bool sendIsolateServiceMessage(SendPort sp, List m);
 external void sendRootServiceMessage(List m);
+external void sendObjectRootServiceMessage(List m);
\ No newline at end of file
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index bcdc45e..1845277 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -448,3 +448,5 @@
 Language/Expressions/Property_Extraction/General_Closurization/static_type_t07: CompileTimeError # Issue 23777
 Language/Libraries_and_Scripts/Scripts/syntax_t11: Pass, CompileTimeError # Issue 26592
 Language/Libraries_and_Scripts/Parts/compilation_t04: Pass, CompileTimeError # Issue 26592
+Language/Libraries_and_Scripts/Parts/compilation_t02: Pass, MissingCompileTimeError # Issue 26692
+Language/Libraries_and_Scripts/Parts/compilation_t01: Pass, MissingCompileTimeError # Issue 26692
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 4d8a0e7..948470b 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -25,16 +25,15 @@
 
 LibTest/core/Symbol/Symbol_A01_t04: RuntimeError # Issue 25804
 
-Language/Classes/same_name_type_variable_t01: Pass, MissingCompileTimeError, Fail # Issue 14513
-Language/Classes/same_name_type_variable_t04: Pass, MissingCompileTimeError, Fail # Issue 14513
-Language/Classes/same_name_type_variable_t07: Pass, MissingCompileTimeError, Fail # Issue 14513
+Language/Classes/same_name_type_variable_t04: Pass, MissingCompileTimeError, Fail # Issue 14513,25525
+Language/Classes/same_name_type_variable_t07: Pass, MissingCompileTimeError, Fail # Issue 14513,25525
 
-LibTest/math/acos_A01_t01: PASS, FAIL, OK  # Issue 26261 
-LibTest/math/asin_A01_t01: PASS, FAIL, OK  # Issue 26261 
-LibTest/math/atan_A01_t01: PASS, FAIL, OK  # Issue 26261 
+LibTest/math/acos_A01_t01: PASS, FAIL, OK  # Issue 26261
+LibTest/math/asin_A01_t01: PASS, FAIL, OK  # Issue 26261
+LibTest/math/atan_A01_t01: PASS, FAIL, OK  # Issue 26261
 
-LibTest/math/cos_A01_t01: PASS, FAIL, OK  # Issue 26261 
-LibTest/math/tan_A01_t01: PASS, FAIL, OK  # Issue 26261 
+LibTest/math/cos_A01_t01: PASS, FAIL, OK  # Issue 26261
+LibTest/math/tan_A01_t01: PASS, FAIL, OK  # Issue 26261
 
 LibTest/core/Expando/Expando_A03_t01: RuntimeError # Issue 17735
 LibTest/core/Expando/Expando_A03_t03: RuntimeError # Issue 17735
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index b13b657..c4c30e7 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -30,6 +30,7 @@
 Language/Classes/Static_Methods/type_object_t01: RuntimeError # Please triage this failure
 Language/Classes/Static_Methods/type_object_t02: RuntimeError # Please triage this failure
 Language/Classes/definition_t23: CompileTimeError # Please triage this failure
+Language/Classes/same_name_type_variable_t01: Fail # Missing CT error on class with same name a type parameter
 Language/Classes/same_name_type_variable_t02: Fail # Missing CT error on member with same name a type parameter
 Language/Classes/same_name_type_variable_t03: Fail # Missing CT error on member with same name a type parameter
 Language/Classes/same_name_type_variable_t05: Fail # Missing CT error on member with same name a type parameter
@@ -1549,7 +1550,7 @@
 WebPlatformTest/shadow-dom/events/event-retargeting/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/event-retargeting/test-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/event-retargeting/test-004_t01: RuntimeError # Please triage this failure
-WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-001_t01: Pass, RuntimeError # Issue 52 
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-001_t01: Pass, RuntimeError # Issue 52
 WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-002_t01: Pass, RuntimeError # Issue 52
 WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-003_t01: Pass, RuntimeError # Issue 52
 WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-004_t01: Pass, RuntimeError # Issue 52
@@ -3296,7 +3297,6 @@
 LayoutTests/fast/backgrounds/background-repeat-computed-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/backgrounds/repeat/parsing-background-repeat_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/borders/border-image-width-numbers-computed-style_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/borders/border-radius-child_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/2d.fillText.gradient_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/2d.text.draw.fill.maxWidth.gradient_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/2d.text.draw.fill.maxWidth.negative_t01: RuntimeError # Please triage this failure
@@ -3420,7 +3420,6 @@
 LayoutTests/fast/css/background-serialize_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/border-image-style-length_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/checked-pseudo-selector_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/collapsed-whitespace-reattach-in-style-recalc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/computed-offset-with-zoom_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-none_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-normal_t01: RuntimeError # Please triage this failure
@@ -3548,7 +3547,6 @@
 LayoutTests/fast/dom/HTMLDialogElement/top-layer-position-relative_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLDialogElement/top-layer-position-static_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLDocument/active-element-gets-unforcusable_t01: Skip # Times out. Please triage this failure
-LayoutTests/fast/dom/HTMLDocument/set-focus-on-valid-element_t01: RuntimeError, Timeout # Please triage this failure
 LayoutTests/fast/dom/HTMLElement/insertAdjacentHTML-errors_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLElement/set-inner-outer-optimization_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLElement/spellcheck_t01: RuntimeError # Please triage this failure
@@ -3910,7 +3908,6 @@
 LayoutTests/fast/multicol/hit-test-end-of-column-with-line-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/hit-test-end-of-column_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/hit-test-float_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/multicol/hit-test-gap-between-pages-flipped_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance-images_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/orphans-relayout_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/vertical-lr/float-truncation_t01: RuntimeError # Please triage this failure
@@ -3957,7 +3954,6 @@
 LayoutTests/fast/sub-pixel/cssom-subpixel-precision_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/sub-pixel/float-containing-block-with-margin_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/sub-pixel/shadows-computed-style_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/sub-pixel/table-rows-have-stable-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/svg/tabindex-focus_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/svg/whitespace-angle_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/svg/whitespace-integer_t01: RuntimeError # Please triage this failure
@@ -4427,8 +4423,43 @@
 WebPlatformTest/webstorage/event_session_key_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_storagearea_t01: Pass, RuntimeError # Fails on 7.1. Please triage this failure
 WebPlatformTest/webstorage/event_session_url_t01: Skip # Times out. Please triage this failure
+WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Makes the following test time out.
 WebPlatformTest/webstorage/storage_session_setitem_quotaexceedederr_t01: Skip # Times out. Please triage this failure
 
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: Skip
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: Skip
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: Skip
+LayoutTests/fast/dom/HTMLDocument/set-focus-on-valid-element_t01: Skip
+
+LayoutTests/fast/canvas/webgl/context-lost_t01: Skip
+
+LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/css-selector-text_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/font-property-priority_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/invalid-not-with-simple-selector-sequence_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/parsing-font-variant-ligatures_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/css/pseudo-valid-unapplied_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/dom/HTMLLinkElement/resolve-url-on-insertion_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/forms/datalist/datalist-child-validation_t01: RuntimeError # Fails 10 out of 10.
+LayoutTests/fast/overflow/scrollbar-restored_t01: RuntimeError # Fails 10 out of 10.
+LibTest/html/Element/isContentEditable_A01_t01: RuntimeError # Fails 10 out of 10.
+LibTest/html/Element/isContentEditable_A02_t01: RuntimeError # Fails 10 out of 10.
+LibTest/html/IFrameElement/isContentEditable_A01_t01: RuntimeError, Pass # Fails 19 out of 20.
+
+LayoutTests/fast/flexbox/repaint-scrollbar_t01: Pass, RuntimeError # Fails 2 out of 10.
+LibTest/html/Element/getBoundingClientRect_A01_t02: Pass, RuntimeError # Fails 3 out of 10.
+LayoutTests/fast/css/focus-display-block-inline_t01: Pass, RuntimeError # Fails 5 out of 10.
+LayoutTests/fast/css/pseudo-any_t01: Pass, RuntimeError # Fails 4 out of 10.
+LayoutTests/fast/dom/partial-layout-overlay-scrollbars_t01: Pass, RuntimeError # Fails 8 out of 10.
+LayoutTests/fast/forms/autofocus-input-css-style-change_t01: Pass, RuntimeError # Fails 7 out of 10.
+LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-onblur-setvalue-onfocusremoved_t01: Pass, RuntimeError # Fails 6 out of 10.
+
+LayoutTests/fast/canvas/webgl/glsl-conformance_t01: Skip # Times out 1 out of 20.
+
 [ $compiler == dart2js && $runtime == safarimobilesim ]
 LayoutTests/fast/alignment/parse-align-items_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/alignment/parse-align-self_t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index a73769a..10bd582 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -14,8 +14,9 @@
 
 [ $compiler == none && $runtime == dartium && $system == windows ]
 LayoutTests/fast/writing-mode/vertical-inline-block-hittest_t01: Pass, RuntimeError # Issue 21605
-WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-002_t01: RuntimeError # Please triage this failure.
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t01: Skip # Timesout Issue 26134
+WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-002_t01: Skip # Timesout sporadically
+WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-003_t01: Skip # Timesout sporadically
 LayoutTests/fast/css/MarqueeLayoutTest_t01: Pass, RuntimeError # Please triage this failure
 
 [ $compiler == none && $runtime == dartium && $system != windows ]
@@ -116,6 +117,7 @@
 LayoutTests/fast/shapes/parsing/parsing-shape-margin_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/table/absolute-table-percent-lengths_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/css-table-width_t01: RuntimeError # co19-roll r786: Please triage this failure.
+LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/table/fixed-table-layout-width-change_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/html-table-width-max-width-constrained_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/margins-flipped-text-direction_t01: RuntimeError # co19-roll r786: Please triage this failure.
@@ -130,6 +132,7 @@
 LayoutTests/fast/text/line-break-after-inline-latin1_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/url/trivial-segments_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/url/trivial_t01: RuntimeError # co19-roll r786: Please triage this failure.
+LayoutTests/fast/writing-mode/auto-sizing-orthogonal-flows_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/xpath/xpath-result-eventlistener-crash_t01: RuntimeError # co19-roll r761: Please triage this failure.
 LibTest/html/Node/ownerDocument_A01_t01: RuntimeError # co19-roll r722: Issue 18251
 WebPlatformTest/DOMEvents/approved/Propagation.path.target.removed_t01: RuntimeError # co19-roll r738: Please triage this failure.
@@ -657,7 +660,6 @@
 LayoutTests/fast/forms/formmethod-attribute-input-2_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/formmethod-attribute-input-html_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/formmethod-attribute-input-html_t01: Skip # Test reloads itself. Issue 18558.
-LayoutTests/fast/forms/input-appearance-elementFromPoint_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/input-hit-test-border_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/input-inputmode_t01: RuntimeError # Experimental feature not exposed in Chrome yet
 LayoutTests/fast/forms/input-width-height-attributes-without-renderer-loaded-image_t01: RuntimeError # co19-roll r801: Please triage this failure.
@@ -697,8 +699,6 @@
 LayoutTests/fast/inline/out-of-flow-objects-and-whitespace-after-empty-inline_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/inline/parent-inline-element-padding-contributes-width_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/inline/positioned-element-padding-contributes-width_t01: RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/layers/normal-flow-hit-test_t01: RuntimeError # co19 issue 11.
-LayoutTests/fast/layers/normal-flow-hit-test_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/layers/zindex-hit-test_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/layers/zindex-hit-test_t01: RuntimeError # co19 issue 11.
 LayoutTests/fast/lists/list-style-position-inside_t01: Pass, RuntimeError # co19 issue 11.
@@ -730,7 +730,6 @@
 LayoutTests/fast/multicol/hit-test-end-of-column-with-line-height_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/hit-test-end-of-column_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/hit-test-float_t01: RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/multicol/hit-test-gap-between-pages-flipped_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/hit-test-gap-between-pages_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/newmulticol/balance-images_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/multicol/newmulticol/balance-maxheight_t01: RuntimeError # co19-roll r801: Please triage this failure.
@@ -812,7 +811,6 @@
 LayoutTests/fast/table/computeLogicalWidth-table-needsSectionRecalc_t01: Pass, RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/css-table-max-height_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/css-table-max-width_t01: RuntimeError # co19-roll r786: Please triage this failure.
-LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/fixed-table-layout-width-change_t01: Pass, RuntimeError # False passes on Firefox # co19 issue 11.
 LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: Skip # co19 issue 11.
@@ -893,7 +891,6 @@
 LayoutTests/fast/url/segments-from-data-url_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/url/segments_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/url/standard-url_t01: RuntimeError # co19-roll r786: Please triage this failure.
-LayoutTests/fast/writing-mode/auto-sizing-orthogonal-flows_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/writing-mode/percentage-margins-absolute-replaced_t01: Pass, RuntimeError # co19 issue 11.
 LayoutTests/fast/writing-mode/positionForPoint_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/writing-mode/positionForPoint_t01: Skip # co19 issue 732.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index ed82429..5a12788 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -84,9 +84,6 @@
 [ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && $mode == debug && $builder_tag == asan ]
 Language/Types/Interface_Types/subtype_t27: Skip  # Issue 21174.
 
-[ ($runtime == vm || $runtime == dart_app) && $arch == arm ]
-LibTest/typed_data/Float32x4/operator_multiplication_A01_t01: Fail # Dart issue 24416
-
 [ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) ]
 # co19 update Sep 29, 2015 (3ed795ea02e022ef19c77cf1b6095b7c8f5584d0)
 Language/Classes/Getters/type_object_t01: RuntimeError # Issue 23721
@@ -190,3 +187,6 @@
 
 LibTest/math/log_A01_t01: RuntimeError # Precision of Math.log (Issue #18998)
 Language/Expressions/Object_Identity/double_t02: RuntimeError # Issue #26374
+
+[ $compiler == precompiler && $runtime == dart_precompiled && $arch == simarm ]
+LibTest/typed_data/Float32x4/operator_division_A01_t02: RuntimeError # Issue #26675
diff --git a/tests/compiler/dart2js/serialization/compilation_test.dart b/tests/compiler/dart2js/serialization/compilation_test.dart
index 9889bf4..b770f51 100644
--- a/tests/compiler/dart2js/serialization/compilation_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation_test.dart
@@ -38,6 +38,10 @@
      int index,
      Test test,
      bool verbose: false}) async {
+  if (test != null && test.name == 'Disable tree shaking through reflection') {
+    // TODO(johnniwinther): Support serialization of native element data.
+    return;
+  }
   String testDescription = test != null ? test.name : '${entryPoint}';
   String id = index != null ? '$index: ' : '';
   print('------------------------------------------------------------------');
diff --git a/tests/corelib/date_time_test.dart b/tests/corelib/date_time_test.dart
index efb2206..27758f8 100644
--- a/tests/corelib/date_time_test.dart
+++ b/tests/corelib/date_time_test.dart
@@ -1234,7 +1234,7 @@
       String source1 = "$date ${time}Z";
       String source2 = "${date}T${time}Z";
       var utcTime1 = DateTime.parse(source1);
-      var utcTime2 = DateTime.parse(source1);
+      var utcTime2 = DateTime.parse(source2);
       Expect.isTrue(utcTime1.isUtc);
       Expect.equals(utcTime1, utcTime2);
       Expect.equals(source1, utcTime1.toString());
@@ -1244,7 +1244,7 @@
       String source1 = "$date $time";
       String source2 = "${date}T$time";
       var utcTime1 = DateTime.parse(source1);
-      var utcTime2 = DateTime.parse(source1);
+      var utcTime2 = DateTime.parse(source2);
       Expect.isFalse(utcTime1.isUtc);
       Expect.equals(utcTime1, utcTime2);
       Expect.equals(source1, utcTime1.toString());
diff --git a/tests/html/html.status b/tests/html/html.status
index 57c3849..c36e35a 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -292,13 +292,15 @@
 input_element_test/supported_datetime-local: Fail
 touchevent_test/supported: Fail # Safari does not support TouchEvents
 notification_test/constructors: Fail # Safari doesn't let us access the fields of the Notification to verify them.
-
-[ $runtime == safari ]
 indexeddb_1_test/functional: Skip # Times out. Issue 21433
 indexeddb_2_test: RuntimeError # Issue 21433
 indexeddb_4_test: RuntimeError # Issue 21433
 indexeddb_5_test: RuntimeError # Issue 21433
 
+
+js_test/JsArray: RuntimeError # Fails 10 out of 10.
+indexeddb_3_test: Skip # Times out 1 out of 10.
+
 [ $runtime == opera ]
 blob_constructor_test: Fail
 canvas_test: Fail
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index d9976d3..67d2941 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -132,6 +132,9 @@
 browser/typed_data_message_test: StaticWarning
 mint_maker_test: StaticWarning
 
+[ $compiler == none && $runtime == vm ]
+scenarios/short_package/short_package_test: Fail, OK  # We do not plan to support the tested behavior anyway.
+
 [ $compiler != none || $runtime != vm ]
 package_root_test: SkipByDesign  # Uses Isolate.packageRoot
 package_config_test: SkipByDesign  # Uses Isolate.packageConfig
diff --git a/tests/language/initializing_formal_capture_test.dart b/tests/language/initializing_formal_capture_test.dart
new file mode 100644
index 0000000..7ad3f08
--- /dev/null
+++ b/tests/language/initializing_formal_capture_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// DartOptions=--initializing-formal-access
+
+import "package:expect/expect.dart";
+
+class A {
+  var x, y;
+  A(this.x) : y = (() => x);
+}
+
+main() {
+  A a = new A(2);
+  a.x = 3;
+  Expect.equals(a.x, 3);
+  Expect.equals(a.y(), 2);
+}
diff --git a/tests/language/initializing_formal_final_test.dart b/tests/language/initializing_formal_final_test.dart
new file mode 100644
index 0000000..0832ce0
--- /dev/null
+++ b/tests/language/initializing_formal_final_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// DartOptions=--initializing-formal-access
+
+import "package:expect/expect.dart";
+
+class A {
+  var x, y;
+  // This should cause a warning because `x` is final when
+  // accessed as an initializing formal.
+  A(this.x) : y = (() { x = 3; });
+}
+
+main() {
+  A a = new A(2);
+  Expect.equals(a.x, 2);
+  Expect.throws(() => a.y(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/initializing_formal_promotion_test.dart b/tests/language/initializing_formal_promotion_test.dart
new file mode 100644
index 0000000..b0314e8
--- /dev/null
+++ b/tests/language/initializing_formal_promotion_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// DartOptions=--initializing-formal-access
+
+import "package:expect/expect.dart";
+
+class B {}
+
+class A {
+  B x, y;
+  A(this.x) {
+    // Promote to subtype.
+    if (x is C) y = x.x;
+    // Promotion fails, not a subtype.
+    if (x is A) y = x;
+  }
+}
+
+class C extends A implements B {
+  C(B x) : super(x);
+}
+
+main() {
+  C c2 = new C(null);
+  C cc = new C(c2);
+  Expect.equals(c2.y, null);
+  Expect.equals(cc.y, c2);
+}
diff --git a/tests/language/initializing_formal_type_test.dart b/tests/language/initializing_formal_type_test.dart
new file mode 100644
index 0000000..352eecf
--- /dev/null
+++ b/tests/language/initializing_formal_type_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// DartOptions=--initializing-formal-access
+
+import "package:expect/expect.dart";
+
+class A {
+  int x;
+  String y;
+  A(this.x) : y = x { y = x; }
+}
+
+main() {
+  A a = new A(null);
+  Expect.equals(a.x, null);
+  Expect.equals(a.y, null);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 9657b54..77da565 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -55,6 +55,9 @@
 
 # Experimental feature: Use initializing formals in initializers and constructor body.
 initializing_formal_access_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_capture_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_final_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_type_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
 
 [ ($compiler == none || $compiler == precompiler || $compiler == dart2app || $compiler == dart2appjit) && ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) ]
 
@@ -107,6 +110,9 @@
 
 # Experimental feature: Use initializing formals in initializers and constructor body.
 initializing_formal_access_test: RuntimeError # TODO(eernst): create a suitable sdk issue.
+initializing_formal_capture_test: RuntimeError # TODO(eernst): create a suitable sdk issue.
+initializing_formal_final_test: RuntimeError # TODO(eernst): create a suitable sdk issue.
+initializing_formal_type_test: RuntimeError # TODO(eernst): create a suitable sdk issue.
 
 config_import_test: Skip  # Issue 26250
 
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 8525e33..85801af 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -4,6 +4,8 @@
 
 [ $compiler == dart2analyzer ]
 
+regress_26668_test: Fail # Issue 26678
+
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
 
@@ -512,3 +514,7 @@
 
 # Experimental feature: Use initializing formals in initializers and constructor body.
 initializing_formal_access_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_capture_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_final_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_promotion_test: StaticWarning # TODO(eernst): Create a suitable sdk issue.
+initializing_formal_type_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index bb54e5c..d80aae4 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -56,6 +56,9 @@
 
 # Experimental feature: Use initializing formals in initializers and constructor body.
 initializing_formal_access_test: CompiletimeError # DartOptions not passed to compiler.
+initializing_formal_capture_test: CompiletimeError # DartOptions not passed to compiler.
+initializing_formal_final_test: CompiletimeError # DartOptions not passed to compiler.
+initializing_formal_type_test: CompiletimeError # DartOptions not passed to compiler.
 
 [ $compiler == dart2js ]
 invocation_mirror_empty_arguments_test: Fail # Issue 24331
diff --git a/tests/language/regress_26668_test.dart b/tests/language/regress_26668_test.dart
new file mode 100644
index 0000000..1b329aa
--- /dev/null
+++ b/tests/language/regress_26668_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+main() async {
+  var myClass = new CustomClass<int>();
+  await myClass.processData();
+}
+
+class CustomClass<T> {
+  Future<T> processData() async {
+    return 0;
+  }
+}
+
diff --git a/tests/language/vm/deopt_smi_check_vm_test.dart b/tests/language/vm/deopt_smi_check_vm_test.dart
new file mode 100644
index 0000000..3c61430
--- /dev/null
+++ b/tests/language/vm/deopt_smi_check_vm_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test deoptimization on a smi check.
+// VMOptions=--optimization-counter-threshold=10  --no-background-compilation
+
+import 'package:expect/expect.dart';
+
+hc(a) {
+  var r = a.hashCode;
+  return r;
+}
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    Expect.equals((1).hashCode, hc(1));
+  }
+  // Passing double causes deoptimization.
+  Expect.equals((1.0).hashCode, hc(1.0));
+}
diff --git a/tests/language/vm/string_polymorphic_test.dart b/tests/language/vm/string_polymorphic_test.dart
index 72eac28..8e0dc22 100644
--- a/tests/language/vm/string_polymorphic_test.dart
+++ b/tests/language/vm/string_polymorphic_test.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// Tests that the VM does not crash on weird corner cases of class Math.
 // VMOptions=--optimization_counter_threshold=10 --no-background_compilation
 
 import 'package:expect/expect.dart';
diff --git a/tests/language/vm/typed_data_polymorphic_view_test.dart b/tests/language/vm/typed_data_polymorphic_view_test.dart
index 694c899..fbbaa7f 100644
--- a/tests/language/vm/typed_data_polymorphic_view_test.dart
+++ b/tests/language/vm/typed_data_polymorphic_view_test.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// Tests that the VM does not crash on weird corner cases of class Math.
 // VMOptions=--optimization_counter_threshold=10 --no-background_compilation
 
 import 'dart:typed_data';
diff --git a/tests/standalone/deferred/alpha.dart b/tests/standalone/deferred/alpha.dart
new file mode 100644
index 0000000..20aac88
--- /dev/null
+++ b/tests/standalone/deferred/alpha.dart
@@ -0,0 +1,2 @@
+// beta.dart does not exist!
+import 'beta.dart';
diff --git a/tests/standalone/deferred/exists.dart b/tests/standalone/deferred/exists.dart
new file mode 100644
index 0000000..26cc193
--- /dev/null
+++ b/tests/standalone/deferred/exists.dart
@@ -0,0 +1 @@
+var x = 99;
diff --git a/tests/standalone/deferred/transitive_error.dart b/tests/standalone/deferred/transitive_error.dart
new file mode 100644
index 0000000..e5a9af7
--- /dev/null
+++ b/tests/standalone/deferred/transitive_error.dart
@@ -0,0 +1 @@
+import 'alpha.dart';
diff --git a/tests/standalone/deferred_transitive_import_error_test.dart b/tests/standalone/deferred_transitive_import_error_test.dart
new file mode 100644
index 0000000..585c9cd
--- /dev/null
+++ b/tests/standalone/deferred_transitive_import_error_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+// A deferred library that doesn't exist.
+import 'package:foo/foo.dart' deferred as foo;
+// A deferred library that does exist.
+import 'deferred/exists.dart' deferred as exists;
+// A deferred library that transitively will fail due to a file not found.
+import 'deferred/transitive_error.dart' deferred as te;
+
+main() async {
+  // Attempt to load foo which will fail.
+  var fooError;
+  await foo.loadLibrary().catchError((e) {
+    fooError = e;
+  });
+  Expect.isNotNull(fooError);
+  await exists.loadLibrary();
+  Expect.equals(99, exists.x);
+  /* TODO(johnmccutchan): Implement transitive error reporting.
+  var teError;
+  await te.loadLibrary().catchError((e) {
+    teError = e;
+  });
+  Expect.isNotNull(teError);
+  */
+}
diff --git a/tests/standalone/io/file_blocking_lock_script.dart b/tests/standalone/io/file_blocking_lock_script.dart
new file mode 100644
index 0000000..5c955c4
--- /dev/null
+++ b/tests/standalone/io/file_blocking_lock_script.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Script used by the file_lock_test.dart test.
+
+import "dart:async";
+import "dart:io";
+
+Future<int> testLockWholeFile(File file, int len) async {
+  var raf = await file.open(mode: APPEND);
+  await raf.setPosition(0);
+  int nextToWrite = 1;
+  while (nextToWrite <= len) {
+    await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, len);
+
+    int at;
+    int p;
+    while (true) {
+      p = await raf.position();
+      at = await raf.readByte();
+      if (at == 0 || at == -1) break;
+      nextToWrite++;
+    }
+    await raf.setPosition(p);
+    await raf.writeByte(nextToWrite);
+    await raf.flush();
+    nextToWrite++;
+    await raf.unlock(0, len);
+  }
+
+  await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, len);
+  await raf.setPosition(0);
+  for (int i = 1; i <= len; i++) {
+    if ((await raf.readByte()) != i) {
+      await raf.unlock(0, len);
+      await raf.close();
+      return 1;
+    }
+  }
+  await raf.unlock(0, len);
+  await raf.close();
+  return 0;
+}
+
+main(List<String> args) async {
+  File file = new File(args[0]);
+  int len = int.parse(args[1]);
+  exit(await testLockWholeFile(file, len));
+}
diff --git a/tests/standalone/io/file_blocking_lock_test.dart b/tests/standalone/io/file_blocking_lock_test.dart
new file mode 100644
index 0000000..9cd6689
--- /dev/null
+++ b/tests/standalone/io/file_blocking_lock_test.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test works by spawning a new process running
+// file_blocking_lock_script.dart, trading the file lock back and forth,
+// writing bytes 1 ... 25 in order to the file. There are checks to ensure
+// that the bytes are written in order, that one process doesn't write all the
+// bytes and that a non-blocking lock fails such that a blocking lock must
+// be taken, which succeeds.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+// Check whether the file is locked or not.
+runPeer(String path, int len, FileLock mode) {
+  var script = Platform.script.resolve(
+      'file_blocking_lock_script.dart').toFilePath();
+  var arguments = []
+      ..addAll(Platform.executableArguments)
+      ..add(script)
+      ..add(path)
+      ..add(len.toString());
+  return Process.start(Platform.executable, arguments).then((process) {
+    process.stdout
+        .transform(UTF8.decoder)
+        .listen((data) { print(data); });
+    process.stderr
+        .transform(UTF8.decoder)
+        .listen((data) { print(data); });
+    return process;
+  });
+}
+
+testLockWholeFile() async {
+  const int length = 25;
+  Directory directory = await Directory.systemTemp.createTemp('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  await file.writeAsBytes(new List.filled(length, 0));
+  var raf = await file.open(mode: APPEND);
+  await raf.setPosition(0);
+  await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, length);
+  Process peer = await runPeer(file.path, length, FileLock.BLOCKING_EXCLUSIVE);
+
+  int nextToWrite = 1;
+  int at = 0;
+  List iWrote = new List.filled(length, 0);
+  bool nonBlockingFailed = false;
+  while (nextToWrite <= length) {
+    int p = await raf.position();
+    await raf.writeByte(nextToWrite);
+    await raf.flush();
+    // Record which bytes this process wrote so that we can check that the
+    // other process was able to take the lock and write some bytes.
+    iWrote[nextToWrite-1] = nextToWrite;
+    nextToWrite++;
+    // Let the other process get the lock at least once by spinning until the
+    // non-blocking lock fails.
+    while (!nonBlockingFailed) {
+      await raf.unlock(0, length);
+      try {
+        await raf.lock(FileLock.EXCLUSIVE, 0, length);
+      } catch(e) {
+        // Check that at some point the non-blocking lock fails.
+        nonBlockingFailed = true;
+        await raf.lock(FileLock.BLOCKING_EXCLUSIVE, 0, length);
+      }
+    }
+    while (true) {
+      p = await raf.position();
+      at = await raf.readByte();
+      if (at == 0 || at == -1) break;
+      nextToWrite++;
+    }
+    await raf.setPosition(p);
+  }
+
+  await raf.setPosition(0);
+  for (int i = 1; i <= length; i++) {
+    Expect.equals(i, await raf.readByte());
+  }
+  await raf.unlock(0, length);
+
+  bool wroteAll = true;
+  for (int i = 0; i < length; i++) {
+    // If there's a 0 entry, this process didn't write all bytes.
+    wroteAll = wroteAll && (iWrote[i] == 0);
+  }
+  Expect.equals(false, wroteAll);
+
+  Expect.equals(true, nonBlockingFailed);
+
+  await peer.exitCode.then((v) async {
+    Expect.equals(0, v);
+    await raf.close();
+    await directory.delete(recursive: true);
+  });
+}
+
+main() async {
+  asyncStart();
+  await testLockWholeFile();
+  asyncEnd();
+}
diff --git a/tests/standalone/packages_file_test.dart b/tests/standalone/packages_file_test.dart
index 719d3d7..9902d69 100644
--- a/tests/standalone/packages_file_test.dart
+++ b/tests/standalone/packages_file_test.dart
@@ -220,7 +220,7 @@
 // * `Process.packageConfig`
 // * `Isolate.packageRoot`
 // * `Isolate.packageRoot`
-// * `Isolate.resolvePacakgeUri` of various inputs.
+// * `Isolate.resolvePackageUri` of various inputs.
 // * A variable defined in a library loaded using a `package:` URI.
 //
 // The configurations all have URIs as `root`, `config` and `mainFile` strings,
@@ -292,14 +292,17 @@
     fixPaths(expect);
 
     expect = {
-      "pconf":   null,
-      "proot":   null,
-      "iconf":   null,
-      "iroot":   null,
-      // "foo":   null,
-      "foo/":    null,
-      "foo/bar": null,
-      "foo.x":  "qux",
+      "pconf":    null,
+      "proot":    null,
+      "iconf":    null,
+      "iroot":    null,
+      "foo":      null,
+      "foo/":     null,
+      "foo/bar":  null,
+      "foo.x":    "qux",
+      "bar/bar":  null,
+      "relative": "relative/path",
+      "nonpkg":   "http://example.org/file"
     }..addAll(expect ?? const {});
 
     // Add http files to the http server.
@@ -350,9 +353,11 @@
           "foo.x": null
         } : {
           "iroot": "%http/packages/",
+          "foo": "%http/packages/foo",
           "foo/": "%http/packages/foo/",
           "foo/bar": "%http/packages/foo/bar",
           "foo.x": null,
+          "bar/bar": "%http/packages/bar/bar",
         });
     }
 
@@ -364,8 +369,10 @@
         files: files,
         expect: {
           "iroot": "%$scheme/packages/",
+          "foo": "%$scheme/packages/foo",
           "foo/": "%$scheme/packages/foo/",
           "foo/bar": "%$scheme/packages/foo/bar",
+          "bar/bar": "%$scheme/packages/bar/bar",
         });
     }
 
@@ -382,9 +389,11 @@
         files: files,
         expect: {
           "iroot": "%$scheme/sub/packages/",
+          "foo": "%$scheme/sub/packages/foo",
           "foo/": "%$scheme/sub/packages/foo/",
           "foo/bar": "%$scheme/sub/packages/foo/bar",
           // "foo.x": "qux",  // Blocked by issue http://dartbug.com/26482
+          "bar/bar": "%$scheme/sub/packages/bar/bar",
         });
     }
 
@@ -418,9 +427,11 @@
           "foo/bar": "%file/pkgs/foo/bar",
         } : {
           "iroot": "%http/sub/packages/",
+          "foo": "%http/sub/packages/foo",
           "foo/": "%http/sub/packages/foo/",
           "foo/bar": "%http/sub/packages/foo/bar",
           "foo.x": null,
+          "bar/bar": "%http/sub/packages/bar/bar",
         });
     }
 
@@ -435,9 +446,11 @@
         expect: {
           "proot": "%$scheme/notthere/",
           "iroot": "%$scheme/notthere/",
+          "foo": "%$scheme/notthere/foo",
           "foo/": "%$scheme/notthere/foo/",
           "foo/bar": "%$scheme/notthere/foo/bar",
           "foo.x": null,
+          "bar/bar": "%$scheme/notthere/bar/bar",
         });
     }
 
@@ -470,8 +483,10 @@
         expect: {
           "proot": "%$scheme/pkgs/",
           "iroot": "%$scheme/pkgs/",
+          "foo": "%$scheme/pkgs/foo",
           "foo/": "%$scheme/pkgs/foo/",
           "foo/bar": "%$scheme/pkgs/foo/bar",
+          "bar/bar": "%$scheme/pkgs/bar/bar",
         });
     }
 
@@ -486,8 +501,10 @@
         expect: {
           "proot": "%$scheme/pkgs/",
           "iroot": "%$scheme/pkgs/",
+          "foo": "%$scheme/pkgs/foo",
           "foo/": "%$scheme/pkgs/foo/",
           "foo/bar": "%$scheme/pkgs/foo/bar",
+          "bar/bar": "%$scheme/pkgs/bar/bar",
         });
     }
 
@@ -545,8 +562,10 @@
           expect: {
             "proot": "%$pkgScheme/pkgs/",
             "iroot": "%$pkgScheme/pkgs/",
+            "foo": "%$pkgScheme/pkgs/foo",
             "foo/": "%$pkgScheme/pkgs/foo/",
             "foo/bar": "%$pkgScheme/pkgs/foo/bar",
+            "bar/bar": "%$pkgScheme/pkgs/bar/bar",
             "foo.x": "qux",
           });
       }
@@ -650,6 +669,10 @@
   Uri res1 = await Isolate.resolvePackageUri(Uri.parse("package:foo"));
   Uri res2 = await Isolate.resolvePackageUri(Uri.parse("package:foo/"));
   Uri res3 = await Isolate.resolvePackageUri(Uri.parse("package:foo/bar"));
+  Uri res4 = await Isolate.resolvePackageUri(Uri.parse("package:bar/bar"));
+  Uri res5 = await Isolate.resolvePackageUri(Uri.parse("relative/path"));
+  Uri res6 = await Isolate.resolvePackageUri(
+      Uri.parse("http://example.org/file"));
   String fooX = await foo
     .loadLibrary()
     .timeout(const Duration(seconds: 1))
@@ -666,6 +689,9 @@
     "foo/": res2?.toString(),
     "foo/bar": res3?.toString(),
     "foo.x": fooX?.toString(),
+    "bar/bar": res4?.toString(),
+    "relative": res5?.toString(),
+    "nonpkg": res6?.toString(),
   }));
 }
 """;
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index d0cad39..c039aad 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -114,6 +114,7 @@
 unboxed_int_converter_test: Skip
 pair_location_remapping_test: Skip
 regress_25335_test: Skip # Int64List not supported.
+deferred_transitive_import_error_test: Skip # Contains intentional errors.
 
 [ $compiler == dart2js && $cps_ir && $checked ]
 *: Skip # `assert` not implemented
@@ -170,6 +171,7 @@
 package/scenarios/packages_file_in_parent/sub/packages_file_in_parent_test: StaticWarning
 typed_data_test: StaticWarning
 typed_data_view_test: StaticWarning
+deferred_transitive_import_error_test: Skip # Contains intentional errors.
 
 [ $compiler == dart2analyzer ]
 package/package1_test: CompileTimeError
@@ -260,7 +262,7 @@
 io/test_runner_test: Skip # Platform.executable
 io/file_lock_test: Skip # Platform.executable
 io/code_collection_test: Skip # Platform.executable
-io/file_lock_test: Skip # Platform.executable
+io/file_blocking_lock_test: Skip # Platform.executable
 io/raw_socket_cross_process_test: Skip # Platform.executable
 io/test_extension_test: Skip # Platform.executable
 io/named_pipe_script_test: Skip # Platform.executable
@@ -317,3 +319,6 @@
 
 oom_error_stacktrace_test: Skip # Issue #26377
 out_of_memory_test: Skip # Issue #26377
+
+[ $runtime == dart_precompiled ]
+deferred_transitive_import_error_test: Skip # Contains intentional errors.
diff --git a/tools/VERSION b/tools/VERSION
index a19c07d..4fd0654 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 18
 PATCH 0
-PRERELEASE 0
+PRERELEASE 1
 PRERELEASE_PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 581d762..1127f27 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -202,7 +202,7 @@
     else:
       cmd.extend(['--progress=buildbot', '-v'])
 
-    cmd.append('--clear_browser_cache')
+    cmd.append('--reset-browser-configuration')
 
     global IsFirstTestStepCall
     if IsFirstTestStepCall:
diff --git a/tools/dartium/buildbot_annotated_steps.py b/tools/dartium/buildbot_annotated_steps.py
index 61faf75..c568b8e 100755
--- a/tools/dartium/buildbot_annotated_steps.py
+++ b/tools/dartium/buildbot_annotated_steps.py
@@ -34,7 +34,7 @@
   """
   cmd = []
   if sys.platform.startswith('linux'):
-    cmd = ['xvfb-run', '-a']
+    cmd = ['xvfb-run', '--server-args=-screen 0 1024x768x24','-a']
   cmd.append(sys.executable)
   script = os.path.join(DART_PATH, 'tools', 'dartium', 'test.py')
   cmd.append(script)
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 015ae81..fb3247f 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
 
 vars.update({
   "dartium_chromium_commit": "ef7d4ae18c646aea34c07a7ef62de7342c3b8c12",
-  "dartium_webkit_commit": "b7c1bc7268a2b3bdd0cbf59998d99624b3e1a4e9",
+  "dartium_webkit_commit": "bf1214d91e35290e9da29c9972640fc8c6825c81",
   "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/safari_factory_reset.py b/tools/safari_factory_reset.py
new file mode 100755
index 0000000..9276fa5
--- /dev/null
+++ b/tools/safari_factory_reset.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import os
+import string
+import subprocess
+import sys
+
+import utils
+
+
+def Main():
+  args = sys.argv[1:]
+  tools_dir = os.path.dirname(os.path.realpath(__file__))
+  dart_script_name = os.path.join(
+    tools_dir, 'testing', 'dart', 'reset_safari.dart');
+  command = [utils.CheckedInSdkExecutable(),
+             '--checked', dart_script_name] + args
+  exit_code = subprocess.call(command)
+  utils.DiagnoseExitCode(exit_code, command)
+  return exit_code
+
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 2776569..76124f2 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -14,6 +14,9 @@
 import 'path.dart';
 import 'utils.dart';
 
+import 'reset_safari.dart' show
+    killAndResetSafari;
+
 class BrowserOutput {
   final StringBuffer stdout = new StringBuffer();
   final StringBuffer stderr = new StringBuffer();
@@ -53,10 +56,10 @@
   String id;
 
   /**
-   * Delete the browser specific caches on startup.
+   * Reset the browser to a known configuration on start-up.
    * Browser specific implementations are free to ignore this.
    */
-  static bool deleteCache = false;
+  static bool resetBrowserConfiguration = false;
 
   /** Print everything (stdout, stderr, usageLog) whenever we add to it */
   bool debugPrint = false;
@@ -105,6 +108,15 @@
     'ie10'
   ];
 
+  /// If [browserName] doesn't support Window.open, we use iframes instead.
+  static bool requiresIframe(String browserName) {
+    return !BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
+  }
+
+  static bool requiresFocus(String browserName) {
+    return browserName == "safari";
+  }
+
   // TODO(kustermann): add standard support for chrome on android
   static bool supportedBrowser(String name) {
     return SUPPORTED_BROWSERS.contains(name);
@@ -269,6 +281,13 @@
 
   /** Starts the browser loading the given url */
   Future<bool> start(String url);
+
+  /// Called when the driver page is requested, that is, when the browser first
+  /// contacts the test server. At this time, it's safe to assume that the
+  /// browser process has started and opened its first window.
+  ///
+  /// This is used by [Safari] to ensure the browser window has focus.
+  Future<Null> onDriverPageRequested() => new Future<Null>.value();
 }
 
 class Safari extends Browser {
@@ -278,62 +297,48 @@
   static const String versionFile =
       "/Applications/Safari.app/Contents/version.plist";
 
-  /**
-   * Directories where safari stores state. We delete these if the deleteCache
-   * is set
-   */
-  static const List<String> CACHE_DIRECTORIES = const [
-    "Library/Caches/com.apple.Safari",
-    "Library/Safari",
-    "Library/Saved Application State/com.apple.Safari.savedState",
-    "Library/Caches/Metadata/Safari"
-  ];
+  static const String safariBundleLocation = "/Applications/Safari.app/";
 
-  Future<bool> allowPopUps() {
-    var command = "defaults";
-    var args = [
-      "write",
-      "com.apple.safari",
-      "com.apple.Safari.ContentPageGroupIdentifier."
-          "WebKit2JavaScriptCanOpenWindowsAutomatically",
-      "1"
-    ];
-    return Process.run(command, args).then((result) {
-      if (result.exitCode != 0) {
-        _logEvent("Could not disable pop-up blocking for safari");
-        return false;
-      }
-      return true;
-    });
-  }
-
-  Future<bool> deleteIfExists(Iterator<String> paths) {
-    if (!paths.moveNext()) return new Future.value(true);
-    Directory directory = new Directory(paths.current);
-    return directory.exists().then((exists) {
-      if (exists) {
-        _logEvent("Deleting ${paths.current}");
-        return directory
-            .delete(recursive: true)
-            .then((_) => deleteIfExists(paths))
-            .catchError((error) {
-          _logEvent("Failure trying to delete ${paths.current}: $error");
-          return false;
-        });
-      } else {
-        _logEvent("${paths.current} is not present");
-        return deleteIfExists(paths);
-      }
-    });
-  }
-
-  // Clears the cache if the static deleteCache flag is set.
+  // Clears the cache if the static resetBrowserConfiguration flag is set.
   // Returns false if the command to actually clear the cache did not complete.
-  Future<bool> clearCache() {
-    if (!Browser.deleteCache) return new Future.value(true);
-    var home = Platform.environment['HOME'];
-    Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
-    return deleteIfExists(iterator);
+  Future<bool> resetConfiguration() async {
+    if (!Browser.resetBrowserConfiguration) return true;
+
+    Completer completer = new Completer();
+    handleUncaughtError(error, StackTrace stackTrace) {
+      if (!completer.isCompleted) {
+        completer.completeError(error, stackTrace);
+      } else {
+        throw new AsyncError(error, stackTrace);
+      }
+    }
+    Zone parent = Zone.current;
+    ZoneSpecification specification = new ZoneSpecification(
+        print: (Zone self, ZoneDelegate delegate, Zone zone, String line) {
+          delegate.run(parent, () {
+            _logEvent(line);
+          });
+        });
+    Future zoneWrapper() {
+      Uri safariUri = Uri.base.resolve(safariBundleLocation);
+      return new Future(() => killAndResetSafari(bundle: safariUri))
+          .then(completer.complete);
+    }
+
+    // We run killAndResetSafari in a Zone as opposed to running an external
+    // process. The Zone allows us to collect its output, and protect the rest
+    // of the test infrastructure against errors in it.
+    runZoned(
+        zoneWrapper, zoneSpecification: specification,
+        onError: handleUncaughtError);
+
+    try {
+      await completer.future;
+      return true;
+    } catch (error, st) {
+      _logEvent("Unable to reset Safari: $error$st");
+      return false;
+    }
   }
 
   Future<String> getVersion() {
@@ -369,42 +374,58 @@
     });
   }
 
-  void _createLaunchHTML(var path, var url) {
+  Future<Null> _createLaunchHTML(var path, var url) async {
     var file = new File("${path}/launch.html");
-    var randomFile = file.openSync(mode: FileMode.WRITE);
+    var randomFile = await file.open(mode: FileMode.WRITE);
     var content = '<script language="JavaScript">location = "$url"</script>';
-    randomFile.writeStringSync(content);
-    randomFile.close();
+    await randomFile.writeString(content);
+    await randomFile.close();
   }
 
-  Future<bool> start(String url) {
+  Future<bool> start(String url) async {
     _logEvent("Starting Safari browser on: $url");
-    return allowPopUps().then((success) {
-      if (!success) {
-        return false;
-      }
-      return clearCache().then((cleared) {
-        if (!cleared) {
-          _logEvent("Could not clear cache");
-          return false;
-        }
-        // Get the version and log that.
-        return getVersion().then((version) {
-          _logEvent("Got version: $version");
-          return Directory.systemTemp.createTemp().then((userDir) {
-            _cleanup = () {
-              userDir.deleteSync(recursive: true);
-            };
-            _createLaunchHTML(userDir.path, url);
-            var args = ["${userDir.path}/launch.html"];
-            return startBrowserProcess(_binary, args);
-          });
-        }).catchError((error) {
-          _logEvent("Running $_binary --version failed with $error");
-          return false;
-        });
-      });
-    });
+    if (!await resetConfiguration()) {
+      _logEvent("Could not clear cache");
+      return false;
+    }
+    String version;
+    try {
+      version = await getVersion();
+    } catch (error) {
+      _logEvent("Running $_binary --version failed with $error");
+      return false;
+    }
+    _logEvent("Got version: $version");
+    Directory userDir;
+    try {
+      userDir = await Directory.systemTemp.createTemp();
+    } catch (error) {
+      _logEvent("Error creating temporary directory: $error");
+      return false;
+    }
+    _cleanup = () {
+      userDir.deleteSync(recursive: true);
+    };
+    try {
+      await _createLaunchHTML(userDir.path, url);
+    } catch (error) {
+      _logEvent("Error creating launch HTML: $error");
+      return false;
+    }
+    var args = [
+        "-d", "-i", "-m", "-s", "-u", _binary,
+        "${userDir.path}/launch.html"];
+    try {
+      return startBrowserProcess("/usr/bin/caffeinate", args);
+    } catch (error) {
+      _logEvent("Error starting browser process: $error");
+      return false;
+    }
+  }
+
+  Future<Null> onDriverPageRequested() async {
+    await Process.run("/usr/bin/osascript",
+        ['-e', 'tell application "Safari" to activate']);
   }
 
   String toString() => "Safari";
@@ -477,24 +498,43 @@
 class SafariMobileSimulator extends Safari {
   /**
    * Directories where safari simulator stores state. We delete these if the
-   * deleteCache is set
+   * resetBrowserConfiguration is set
    */
   static const List<String> CACHE_DIRECTORIES = const [
     "Library/Application Support/iPhone Simulator/7.1/Applications"
   ];
 
-  // Clears the cache if the static deleteCache flag is set.
+  // Helper function to delete many directories recursively.
+  Future<bool> deleteIfExists(Iterable<String> paths) async {
+    for (var path in paths) {
+      Directory directory = new Directory(path);
+      if (await directory.exists()) {
+        _logEvent("Deleting $path");
+        try {
+          await directory.delete(recursive: true);
+        } catch (error) {
+          _logEvent("Failure trying to delete $path: $error");
+          return false;
+        }
+      } else {
+        _logEvent("$path is not present");
+      }
+    }
+    return true;
+  }
+
+  // Clears the cache if the static resetBrowserConfiguration flag is set.
   // Returns false if the command to actually clear the cache did not complete.
-  Future<bool> clearCache() {
-    if (!Browser.deleteCache) return new Future.value(true);
+  Future<bool> resetConfiguration() {
+    if (!Browser.resetBrowserConfiguration) return new Future.value(true);
     var home = Platform.environment['HOME'];
-    Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
-    return deleteIfExists(iterator);
+    var paths = CACHE_DIRECTORIES.map((s) => "$home/$s");
+    return deleteIfExists(paths);
   }
 
   Future<bool> start(String url) {
     _logEvent("Starting safari mobile simulator browser on: $url");
-    return clearCache().then((success) {
+    return resetConfiguration().then((success) {
       if (!success) {
         _logEvent("Could not clear cache, exiting");
         return false;
@@ -561,9 +601,10 @@
     });
   }
 
-  // Clears the recovery cache if the static deleteCache flag is set.
-  Future<bool> clearCache() {
-    if (!Browser.deleteCache) return new Future.value(true);
+  // Clears the recovery cache if the static resetBrowserConfiguration flag is
+  // set.
+  Future<bool> resetConfiguration() {
+    if (!Browser.resetBrowserConfiguration) return new Future.value(true);
     var localAppData = Platform.environment['LOCALAPPDATA'];
 
     Directory dir = new Directory("$localAppData\\Microsoft\\"
@@ -578,7 +619,7 @@
 
   Future<bool> start(String url) {
     _logEvent("Starting ie browser on: $url");
-    return clearCache().then((_) => getVersion()).then((version) {
+    return resetConfiguration().then((_) => getVersion()).then((version) {
       _logEvent("Got version: $version");
       return startBrowserProcess(_binary, [url]);
     });
@@ -876,12 +917,12 @@
   static const Duration MIN_NONEMPTY_QUEUE_TIME = const Duration(seconds: 1);
 
   final Map configuration;
-  BrowserTestingServer testingServer;
+  final BrowserTestingServer testingServer;
 
   final String localIp;
-  String browserName;
+  final String browserName;
   int maxNumBrowsers;
-  bool checkedMode;
+  final bool checkedMode;
   int numBrowsers = 0;
   // Used to send back logs from the browser (start, stop etc)
   Function logger;
@@ -928,27 +969,23 @@
     if (_currentStartingBrowserId == id) _currentStartingBrowserId = null;
   }
 
-  // If [browserName] doesn't support opening new windows, we use new iframes
-  // instead.
-  bool get useIframe =>
-      !Browser.BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
-
-  /// The optional testingServer parameter allows callers to pass in
-  /// a testing server with different behavior than the  default
-  /// BrowserTestServer. The url handlers of the testingServer are
-  /// overwritten, so an existing handler can't be shared between instances.
   BrowserTestRunner(
-      this.configuration, this.localIp, this.browserName, this.maxNumBrowsers,
-      {BrowserTestingServer this.testingServer}) {
-    checkedMode = configuration['checked'];
-    if (browserName == 'ff') browserName = 'firefox';
+      Map configuration,
+      String localIp,
+      String browserName,
+      this.maxNumBrowsers)
+      : configuration = configuration,
+        localIp = localIp,
+        browserName = (browserName == 'ff') ? 'firefox' : browserName,
+        checkedMode = configuration['checked'],
+        testingServer = new BrowserTestingServer(
+            configuration, localIp,
+            Browser.requiresIframe(browserName),
+            Browser.requiresFocus(browserName)) {
+    testingServer.testRunner = this;
   }
 
   Future start() async {
-    if (testingServer == null) {
-      testingServer =
-          new BrowserTestingServer(configuration, localIp, useIframe);
-    }
     await testingServer.start();
     testingServer
       ..testDoneCallBack = handleResults
@@ -1285,6 +1322,9 @@
   ///                                   test
 
   final String localIp;
+  final bool useIframe;
+  final bool requiresFocus;
+  BrowserTestRunner testRunner;
 
   static const String driverPath = "/driver";
   static const String nextTestPath = "/next_test";
@@ -1297,14 +1337,14 @@
   var testCount = 0;
   var errorReportingServer;
   bool underTermination = false;
-  bool useIframe = false;
 
   Function testDoneCallBack;
   Function testStatusUpdateCallBack;
   Function testStartedCallBack;
   Function nextTestCallBack;
 
-  BrowserTestingServer(this.configuration, this.localIp, this.useIframe);
+  BrowserTestingServer(
+      this.configuration, this.localIp, this.useIframe, this.requiresFocus);
 
   Future start() {
     var test_driver_error_port = configuration['test_driver_error_port'];
@@ -1366,29 +1406,41 @@
       handleStarted(request, browserId(request, startedPath), testId(request));
     });
 
-    makeSendPageHandler(String prefix) => (HttpRequest request) {
-          noCache(request);
-          var textResponse = "";
-          if (prefix == driverPath) {
-            textResponse = getDriverPage(browserId(request, prefix));
-            request.response.headers.set('Content-Type', 'text/html');
-          }
-          if (prefix == nextTestPath) {
-            textResponse = getNextTest(browserId(request, prefix));
-            request.response.headers.set('Content-Type', 'text/plain');
-          }
-          request.response.write(textResponse);
-          request.listen((_) {}, onDone: request.response.close);
-          request.response.done.catchError((error) {
-            if (!underTermination) {
-              print("URI ${request.uri}");
-              print("Textresponse $textResponse");
-              throw "Error returning content to browser: $error";
-            }
+    void sendPageHandler(HttpRequest request) {
+      // Do NOT make this method async. We need to call catchError below
+      // synchronously to avoid unhandled asynchronous errors.
+      noCache(request);
+      Future<String> textResponse;
+      if (request.uri.path.startsWith(driverPath)) {
+        textResponse = getDriverPage(browserId(request, driverPath));
+        request.response.headers.set('Content-Type', 'text/html');
+      } else if (request.uri.path.startsWith(nextTestPath)) {
+        textResponse = new Future<String>.value(
+            getNextTest(browserId(request, nextTestPath)));
+        request.response.headers.set('Content-Type', 'text/plain');
+      } else {
+        textResponse = new Future<String>.value("");
+      }
+      request.response.done.catchError((error) {
+        if (!underTermination) {
+          return textResponse.then((String text) {
+            print("URI ${request.uri}");
+            print("textResponse $textResponse");
+            throw "Error returning content to browser: $error";
           });
-        };
-    server.addHandler(driverPath, makeSendPageHandler(driverPath));
-    server.addHandler(nextTestPath, makeSendPageHandler(nextTestPath));
+        }
+      });
+      textResponse.then((String text) async {
+        request.response.write(text);
+        await request.listen(null).asFuture();
+        // Ignoring the returned closure as it returns the 'done' future
+        // which alread has catchError installed above.
+        request.response.close();
+      });
+    }
+
+    server.addHandler(driverPath, sendPageHandler);
+    server.addHandler(nextTestPath, sendPageHandler);
   }
 
   void handleReport(HttpRequest request, String browserId, var testId,
@@ -1447,33 +1499,34 @@
     return "http://$localIp:$port/driver/$browserId";
   }
 
-  String getDriverPage(String browserId) {
+  Future<String> getDriverPage(String browserId) async {
+    await testRunner.browserStatus[browserId].browser.onDriverPageRequested();
     var errorReportingUrl =
         "http://$localIp:${errorReportingServer.port}/$browserId";
     String driverContent = """
 <!DOCTYPE html><html>
 <head>
-  <style>
-    body {
-      margin: 0;
-    }
-    .box {
-      overflow: hidden;
-      overflow-y: auto;
-      position: absolute;
-      left: 0;
-      right: 0;
-    }
-    .controller.box {
-      height: 75px;
-      top: 0;
-    }
-    .test.box {
-      top: 75px;
-      bottom: 0;
-    }
-  </style>
   <title>Driving page</title>
+  <style>
+.big-notice {
+  background-color: red;
+  color: white;
+  font-weight: bold;
+  font-size: xx-large;
+  text-align: center;
+}
+.controller.box {
+  white-space: nowrap;
+  overflow: scroll;
+  height: 6em;
+}
+body {
+  font-family: sans-serif;
+}
+body div {
+  padding-top: 10px;
+}
+  </style>
   <script type='text/javascript'>
     var STATUS_UPDATE_INTERVAL = 10000;
 
@@ -1603,7 +1656,8 @@
           embedded_iframe_div.removeChild(embedded_iframe);
           embedded_iframe = document.createElement('iframe');
           embedded_iframe.id = "embedded_iframe";
-          embedded_iframe.style="width:100%;height:100%";
+          embedded_iframe.width='800px';
+          embedded_iframe.height='600px';
           embedded_iframe_div.appendChild(embedded_iframe);
           embedded_iframe.src = url;
         } else {
@@ -1775,13 +1829,26 @@
   </script>
 </head>
   <body onload="startTesting()">
+
+    <div class='big-notice'>
+      Please keep this window in focus at all times.
+    </div>
+
+    <div>
+      Some browsers, Safari, in particular, may pause JavaScript when not
+      visible to conserve power consumption and CPU resources. In addition,
+      some tests of focus events will not work correctly if this window doesn't
+      have focus. It's also advisable to close any other programs that may open
+      modal dialogs, for example, Chrome with Calendar open.
+    </div>
+
     <div class="controller box">
     Dart test driver, number of tests: <span id="number"></span><br>
     Currently executing: <span id="currently_executing"></span><br>
     Unhandled error: <span id="unhandled_error"></span>
     </div>
     <div id="embedded_iframe_div" class="test box">
-      <iframe style="width:100%;height:100%;" id="embedded_iframe"></iframe>
+      <iframe id="embedded_iframe"></iframe>
     </div>
   </body>
 </html>
diff --git a/tools/testing/dart/reset_safari.dart b/tools/testing/dart/reset_safari.dart
new file mode 100644
index 0000000..e1886a5
--- /dev/null
+++ b/tools/testing/dart/reset_safari.dart
@@ -0,0 +1,227 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+/// Helper program for killing and resetting all Safari settings to a known
+/// state that works well for testing dart2js output in Safari.
+///
+/// Warning: this will delete all your Safari settings and bookmarks.
+library testing.reset_safari;
+
+import 'dart:async' show
+    Future,
+    Timer;
+
+import 'dart:io' show
+    Directory,
+    File,
+    Platform,
+    Process,
+    ProcessResult;
+
+const String defaultSafariBundleLocation = "/Applications/Safari.app/";
+
+const String relativeSafariLocation = "Contents/MacOS/Safari";
+
+const String lsofLocation = "/usr/sbin/lsof";
+
+const String killLocation = "/bin/kill";
+
+const String pkillLocation = "/usr/bin/pkill";
+
+const String safari = "com.apple.Safari";
+
+const String defaultsLocation = "/usr/bin/defaults";
+
+final List<String> safariSettings = <String>[
+    "Library/Caches/$safari",
+    "Library/Safari",
+    "Library/Saved Application State/$safari.savedState",
+    "Library/Caches/Metadata/Safari",
+    "Library/Preferences/$safari.plist",
+];
+
+const Duration defaultPollDelay = const Duration(milliseconds: 1);
+
+final String cpgi = "$safari.ContentPageGroupIdentifier";
+
+final String knownSafariPreference = '''
+{
+    DefaultBrowserPromptingState2 = 2;
+    StartPageViewControllerMode = 0;
+    TestDriveOriginBrowser = 1;
+    TestDriveUserDecision = 2;
+    TestDriveState = 3;
+    AlwaysRestoreSessionAtLaunch = 0;
+    NewTabBehavior = 1;
+    NewWindowBehavior = 1;
+    LastSafariVersionWithWelcomePage = "9.0";
+    OpenNewTabsInFront = 0;
+    TabCreationPolicy = 0;
+
+    IncludeDevelopMenu = 1;
+    WebKitDeveloperExtrasEnabledPreferenceKey = 1;
+    "$cpgi.WebKit2DeveloperExtrasEnabled" = 1;
+
+    AutoFillCreditCardData = 0;
+    AutoFillMiscellaneousForms = 0;
+    AutoFillPasswords = 0;
+
+    SuppressSearchSuggestions = 1;
+
+    PreloadTopHit = 0;
+    ShowFavoritesUnderSmartSearchField = 0;
+    WebsiteSpecificSearchEnabled = 0;
+
+    WarnAboutFraudulentWebsites = 0;
+
+
+    WebKitJavaScriptEnabled = 1;
+    "$cpgi.WebKit2JavaScriptEnabled" = 1;
+
+    WebKitJavaScriptCanOpenWindowsAutomatically = 1;
+    "$cpgi.WebKit2JavaScriptCanOpenWindowsAutomatically" = 1;
+
+    "$cpgi.WebKit2WebGLEnabled" = 1;
+    WebGLDefaultLoadPolicy = WebGLPolicyAllowNoSecurityRestrictions;
+
+    "$cpgi.WebKit2PluginsEnabled" = 0;
+
+    BlockStoragePolicy = 1;
+    WebKitStorageBlockingPolicy = 0;
+    "$cpgi.WebKit2StorageBlockingPolicy" = 0;
+
+
+    SafariGeolocationPermissionPolicy = 0;
+
+    CanPromptForPushNotifications = 0;
+
+    InstallExtensionUpdatesAutomatically = 0;
+
+    ShowFullURLInSmartSearchField = 1;
+
+    "$cpgi.WebKit2PlugInSnapshottingEnabled" = 0;
+}
+''';
+
+Future<Null> get pollDelay => new Future.delayed(defaultPollDelay);
+
+String signalArgument(
+    String defaultSignal,
+    {bool force: false,
+     bool testOnly: false}) {
+  if (force && testOnly) {
+    throw new ArgumentError("[force] and [testOnly] can't both be true.");
+  }
+  if (force) return "-KILL";
+  if (testOnly) return "-0";
+  return defaultSignal;
+}
+
+Future<int> kill(
+    List<String> pids,
+    {bool force: false,
+     bool testOnly: false}) async {
+  List<String> arguments =
+      <String>[signalArgument("-TERM", force: force, testOnly: testOnly)]
+      ..addAll(pids);
+  ProcessResult result = await Process.run(killLocation, arguments);
+  return result.exitCode;
+}
+
+Future<int> pkill(
+    String pattern,
+    {bool force: false,
+     bool testOnly: false}) async {
+  List<String> arguments = <String>[
+      signalArgument("-HUP", force: force, testOnly: testOnly),
+      pattern];
+  ProcessResult result = await Process.run(pkillLocation, arguments);
+  return result.exitCode;
+}
+
+Uri validatedBundleName(Uri bundle) {
+  if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation);
+  if (!bundle.path.endsWith("/")) {
+    throw new ArgumentError(
+        "Bundle ('$bundle') must end with a slash ('/').");
+  }
+  return bundle;
+}
+
+Future<Null> killSafari({Uri bundle}) async {
+  bundle = validatedBundleName(bundle);
+  Uri safariBinary = bundle.resolve(relativeSafariLocation);
+  ProcessResult result = await Process.run(
+      lsofLocation, ["-t", safariBinary.toFilePath()]);
+  if (result.exitCode == 0) {
+    String stdout = result.stdout;
+    List<String> pids = new List<String>.from(
+        stdout.split("\n").where((String line) => !line.isEmpty));
+    Timer timer = new Timer(const Duration(seconds: 10), () {
+      print("Kill -9 Safari $pids");
+      kill(pids, force: true);
+    });
+    int exitCode = await kill(pids);
+    while (exitCode == 0) {
+      await pollDelay;
+      print("Polling Safari $pids");
+      exitCode = await kill(pids, testOnly: true);
+    }
+    timer.cancel();
+  }
+  Timer timer = new Timer(const Duration(seconds: 10), () {
+    print("Kill -9 $safari");
+    pkill(safari, force: true);
+  });
+  int exitCode = await pkill(safari);
+  while (exitCode == 0) {
+    await pollDelay;
+    print("Polling $safari");
+    exitCode = await pkill(safari, testOnly: true);
+  }
+  timer.cancel();
+}
+
+Future<Null> deleteIfExists(Uri uri) async {
+  Directory directory = new Directory.fromUri(uri);
+  if (await directory.exists()) {
+    print("Deleting directory '$uri'.");
+    await directory.delete(recursive: true);
+  } else {
+    File file = new File.fromUri(uri);
+    if (await file.exists()) {
+      print("Deleting file '$uri'.");
+      await file.delete();
+    } else {
+      print("File '$uri' not found.");
+    }
+  }
+}
+
+Future<Null> resetSafariSettings() async {
+  String home = Platform.environment["HOME"];
+  if (!home.endsWith("/")) {
+    home = "$home/";
+  }
+  Uri homeDirectory = Uri.base.resolve(home);
+  for (String setting in safariSettings) {
+    await deleteIfExists(homeDirectory.resolve(setting));
+  }
+  ProcessResult result = await Process.run(
+      defaultsLocation, <String>["write", safari, knownSafariPreference]);
+  if (result.exitCode != 0) {
+    throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}";
+  }
+}
+
+Future<Null> killAndResetSafari({Uri bundle}) async {
+  bundle = validatedBundleName(bundle);
+  await killSafari(bundle: bundle);
+  await resetSafariSettings();
+}
+
+Future<Null> main() async {
+  await killAndResetSafari();
+}
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index f8cd209..b0e044c 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -69,7 +69,7 @@
   var recordingPath = firstConf['record_to_file'];
   var recordingOutputPath = firstConf['replay_from_file'];
 
-  Browser.deleteCache = firstConf['clear_browser_cache'];
+  Browser.resetBrowserConfiguration = firstConf['reset_browser_configuration'];
 
   if (recordingPath != null && recordingOutputPath != null) {
     print("Fatal: Can't have the '--record_to_file' and '--replay_from_file'"
@@ -183,6 +183,13 @@
       var suite_path = new Path(conf['suite_dir']);
       testSuites.add(new PKGTestSuite(conf, suite_path));
     } else {
+      for (final testSuiteDir in TEST_SUITE_DIRECTORIES) {
+        final name = testSuiteDir.filename;
+        if (selectors.containsKey(name)) {
+          testSuites
+              .add(new StandardTestSuite.forDirectory(conf, testSuiteDir));
+        }
+      }
       for (String key in selectors.keys) {
         if (key == 'co19') {
           testSuites.add(new Co19TestSuite(conf));
@@ -214,14 +221,6 @@
               new PkgBuildTestSuite(conf, 'pkgbuild', 'pkg/pkgbuild.status'));
         }
       }
-
-      for (final testSuiteDir in TEST_SUITE_DIRECTORIES) {
-        final name = testSuiteDir.filename;
-        if (selectors.containsKey(name)) {
-          testSuites
-              .add(new StandardTestSuite.forDirectory(conf, testSuiteDir));
-        }
-      }
     }
   }
 
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index c5c6e34..912ef75 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -338,9 +338,11 @@
           false,
           type: 'bool'),
       new _TestOptionSpecification(
-          'clear_browser_cache',
-          'Browser specific clearing of caches(i.e., delete it).',
-          ['--clear_browser_cache'],
+          'reset_browser_configuration',
+          'Browser specific reset of configuration. '
+          'WARNING: Using this option may remove your bookmarks and '
+          'other settings.',
+          ['--reset-browser-configuration'],
           [],
           false,
           type: 'bool'),
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 5fe73cc..ce30a73 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -1338,6 +1338,14 @@
         contentShellOptions.add('--no-timeout');
         contentShellOptions.add('--dump-render-tree');
 
+        // Disable the GPU under Linux and Dartium. If the GPU is enabled,
+        // Chrome may send a termination signal to a test.  The test will be
+        // terminated if a machine (bot) doesn't have a GPU or if a test is
+        // still running after a certain period of time.
+        if (configuration['system'] == 'linux' &&
+            configuration['runtime'] == 'drt') {
+          contentShellOptions.add('--disable-gpu');
+        }
         if (compiler == 'none') {
           dartFlags.add('--ignore-unrecognized-flags');
           if (configuration["checked"]) {