| Index: pkg/compiler/lib/src/closure.dart
 | 
| diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
 | 
| index 44fcc597ac039edf58f5376b60500ac5a9568348..5bdd71b6038b2462da84182c986a4cf119f19a6c 100644
 | 
| --- a/pkg/compiler/lib/src/closure.dart
 | 
| +++ b/pkg/compiler/lib/src/closure.dart
 | 
| @@ -84,13 +84,13 @@ class ScopeInfo {
 | 
|    /// Also parameters to a `sync*` generator must be boxed, because of the way
 | 
|    /// we rewrite sync* functions. See also comments in
 | 
|    /// [ClosureClassMap.useLocal].
 | 
| -  bool variableIsUsedInTryOrSync(Local variable) => false;
 | 
| +  bool localIsUsedInTryOrSync(Local variable) => false;
 | 
|  
 | 
|    /// Loop through each variable that has been defined in this scope, modified
 | 
|    /// anywhere (this scope or another scope) and used in another scope. Because
 | 
|    /// it is used in another scope, these variables need to be "boxed", creating
 | 
|    /// a thin wrapper around accesses to these variables so that accesses get
 | 
| -  /// the correct updated value. The variables in variablesUsedInTryOrSync may
 | 
| +  /// the correct updated value. The variables in localsUsedInTryOrSync may
 | 
|    /// be included in this set.
 | 
|    ///
 | 
|    /// In the case of loops, this is the set of iteration variables (or any
 | 
| @@ -100,9 +100,6 @@ class ScopeInfo {
 | 
|  
 | 
|    /// True if [variable] has been mutated and is also used in another scope.
 | 
|    bool isBoxed(Local variable) => false;
 | 
| -
 | 
| -  /// True if this scope declares any variables that need to be boxed.
 | 
| -  bool get hasBoxedVariables => false;
 | 
|  }
 | 
|  
 | 
|  /// Class representing the usage of a scope that has been captured in the
 | 
| @@ -141,6 +138,27 @@ class ClosureScope extends ScopeInfo {
 | 
|  /// each iteration, by boxing the iteration variable[s].
 | 
|  class LoopClosureScope extends ClosureScope {
 | 
|    const LoopClosureScope();
 | 
| +
 | 
| +  /// True if this loop scope declares in the first part of the loop
 | 
| +  /// `for (<here>;...;...)` any variables that need to be boxed.
 | 
| +  bool get hasBoxedLoopVariables => false;
 | 
| +
 | 
| +  /// The set of iteration variables (or variables declared in the for loop
 | 
| +  /// expression (`for (<here>; ... ; ...)`) that need to be boxed to snapshot
 | 
| +  /// their value. These variables are also included in the set of
 | 
| +  /// `forEachBoxedVariable` method. The distinction between these two sets is
 | 
| +  /// in this example:
 | 
| +  ///
 | 
| +  ///     run(f) => f();
 | 
| +  ///     var a;
 | 
| +  ///     for (int i = 0; i < 3; i++) {
 | 
| +  ///       var b = 3;
 | 
| +  ///       a = () => b = i;
 | 
| +  ///     }
 | 
| +  ///
 | 
| +  /// `i` would be a part of the boxedLoopVariables AND boxedVariables, but b
 | 
| +  /// would only be a part of boxedVariables.
 | 
| +  List<Local> get boxedLoopVariables => const <Local>[];
 | 
|  }
 | 
|  
 | 
|  /// Class that describes the actual mechanics of how the converted, rewritten
 | 
| @@ -647,18 +665,10 @@ class ClosureScopeImpl implements ClosureScope, LoopClosureScope {
 | 
|    bool get requiresContextBox => capturedVariables.keys.isNotEmpty;
 | 
|  
 | 
|    void forEachBoxedVariable(f(Local local, FieldEntity field)) {
 | 
| -    if (capturedVariables.isNotEmpty) {
 | 
| -      capturedVariables.forEach(f);
 | 
| -    } else {
 | 
| -      for (Local l in boxedLoopVariables) {
 | 
| -        // The boxes for loop variables are constructed on-demand per-iteration
 | 
| -        // in the locals handler.
 | 
| -        f(l, null);
 | 
| -      }
 | 
| -    }
 | 
| +    capturedVariables.forEach(f);
 | 
|    }
 | 
|  
 | 
| -  bool get hasBoxedVariables => !capturedVariables.isEmpty;
 | 
| +  bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
 | 
|  
 | 
|    bool isBoxed(Local variable) {
 | 
|      return capturedVariables.containsKey(variable);
 | 
| @@ -670,8 +680,8 @@ class ClosureScopeImpl implements ClosureScope, LoopClosureScope {
 | 
|    }
 | 
|  
 | 
|    // Should not be called. Added to make the new interface happy.
 | 
| -  bool variableIsUsedInTryOrSync(Local variable) =>
 | 
| -      throw new UnsupportedError("ClosureScopeImpl.variableIsUsedInTryOrSync");
 | 
| +  bool localIsUsedInTryOrSync(Local variable) =>
 | 
| +      throw new UnsupportedError("ClosureScopeImpl.localIsUsedInTryOrSync");
 | 
|  
 | 
|    // Should not be called. Added to make the new interface happy.
 | 
|    Local get thisLocal =>
 | 
| @@ -741,14 +751,11 @@ class ClosureClassMap implements ClosureRepresentationInfo {
 | 
|    /// Also parameters to a `sync*` generator must be boxed, because of the way
 | 
|    /// we rewrite sync* functions. See also comments in [useLocal].
 | 
|    // TODO(johnniwinther): Add variables to this only if the variable is mutated.
 | 
| -  final Set<Local> variablesUsedInTryOrSync = new Set<Local>();
 | 
| +  final Set<Local> localsUsedInTryOrSync = new Set<Local>();
 | 
|  
 | 
|    ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod,
 | 
|        this.thisLocal);
 | 
|  
 | 
| -  bool get hasBoxedVariables =>
 | 
| -      throw new UnsupportedError("ClosureClassMap.hasBoxedVariables");
 | 
| -
 | 
|    List<Local> get createdFieldEntities {
 | 
|      List<Local> fields = <Local>[];
 | 
|      if (closureClassEntity == null) return const <Local>[];
 | 
| @@ -775,8 +782,8 @@ class ClosureClassMap implements ClosureRepresentationInfo {
 | 
|  
 | 
|    FieldEntity get thisFieldEntity => freeVariableMap[thisLocal];
 | 
|  
 | 
| -  bool variableIsUsedInTryOrSync(Local variable) =>
 | 
| -      variablesUsedInTryOrSync.contains(variable);
 | 
| +  bool localIsUsedInTryOrSync(Local variable) =>
 | 
| +      localsUsedInTryOrSync.contains(variable);
 | 
|  
 | 
|    Local getLocalVariableForClosureField(ClosureFieldElement field) {
 | 
|      return field.local;
 | 
| @@ -1025,13 +1032,13 @@ class ClosureTranslator extends Visitor {
 | 
|        if (variable != closureData.thisLocal &&
 | 
|            variable != closureData.closureEntity &&
 | 
|            variable is! TypeVariableLocal) {
 | 
| -        closureData.variablesUsedInTryOrSync.add(variable);
 | 
| +        closureData.localsUsedInTryOrSync.add(variable);
 | 
|        }
 | 
|      } else if (variable is LocalParameterElement &&
 | 
|          variable.functionDeclaration.asyncMarker == AsyncMarker.SYNC_STAR) {
 | 
|        // Parameters in a sync* function are shared between each Iterator created
 | 
|        // by the Iterable returned by the function, therefore they must be boxed.
 | 
| -      closureData.variablesUsedInTryOrSync.add(variable);
 | 
| +      closureData.localsUsedInTryOrSync.add(variable);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| 
 |