Handle let variable like normal variables in static type computation

Change-Id: Ie6eb1eafd5677207163e22c2f428487b4e55b090
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101522
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 63eefbc..ba35b89 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -940,7 +940,7 @@
 
   @override
   ir.DartType visitLet(ir.Let node) {
-    visitNode(node.variable.initializer);
+    _processLocalVariable(node.variable);
     return super.visitLet(node);
   }
 
@@ -1097,7 +1097,7 @@
     typeMap = typeMap.remove(variableScopeModel.assignedVariables);
     ir.DartType returnType = super.visitFunctionExpression(node);
     Set<ir.VariableDeclaration> _oldVariables = _currentVariables;
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNode(node.function.body);
     handleFunctionExpression(node);
@@ -1342,7 +1342,7 @@
         typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
     typeMap = typeMap.remove(variableScopeModel.assignedVariables);
     Set<ir.VariableDeclaration> _oldVariables = _currentVariables;
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNode(node.function.body);
     handleFunctionDeclaration(node);
@@ -1372,7 +1372,7 @@
   @override
   Null visitProcedure(ir.Procedure node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNode(node.function.body);
     handleProcedure(node);
@@ -1386,7 +1386,7 @@
   @override
   Null visitConstructor(ir.Constructor node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass.thisType);
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitSignature(node.function);
     visitNodes(node.initializers);
     visitNode(node.function.body);
@@ -1401,7 +1401,7 @@
   @override
   Null visitField(ir.Field node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
-    _currentVariables = new Set<ir.VariableDeclaration>();
+    _currentVariables = {};
     visitNode(node.initializer);
     handleField(node);
     _invalidatedVariables.removeAll(_currentVariables);
@@ -1411,8 +1411,7 @@
 
   void handleVariableDeclaration(ir.VariableDeclaration node) {}
 
-  @override
-  Null visitVariableDeclaration(ir.VariableDeclaration node) {
+  void _processLocalVariable(ir.VariableDeclaration node) {
     _currentVariables.add(node);
     ir.DartType type = visitNode(node.initializer);
     if (node.initializer != null &&
@@ -1420,6 +1419,11 @@
         inferEffectivelyFinalVariableTypes) {
       node.type = type;
     }
+  }
+
+  @override
+  Null visitVariableDeclaration(ir.VariableDeclaration node) {
+    _processLocalVariable(node);
     handleVariableDeclaration(node);
   }
 
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index de743f0..0b70e2e 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -143,8 +143,8 @@
     "Dynamic invocation of 'toSet'.": 1
   },
   "pkg/compiler/lib/src/helpers/track_map.dart": {
-    "Dynamic invocation of '+'.": 2,
-    "Dynamic invocation of '-'.": 1
+    "Dynamic invocation of '-'.": 1,
+    "Dynamic invocation of '+'.": 1
   },
   "pkg/compiler/lib/src/constants/constant_system.dart": {
     "Dynamic invocation of '&'.": 1,
@@ -250,6 +250,12 @@
     "Dynamic access of 'named'.": 2,
     "Dynamic invocation of '[]'.": 2
   },
+  "pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
+    "Dynamic access of 'keys'.": 1,
+    "Dynamic invocation of 'toSet'.": 1,
+    "Dynamic invocation of '[]='.": 1,
+    "Dynamic invocation of 'add'.": 1
+  },
   "pkg/compiler/lib/src/universe/function_set.dart": {
     "Dynamic access of 'selector'.": 1,
     "Dynamic access of 'receiver'.": 1
@@ -270,16 +276,6 @@
   "pkg/compiler/lib/src/ssa/value_set.dart": {
     "Dynamic invocation of 'add'.": 2
   },
-  "pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
-    "Dynamic access of 'keys'.": 1,
-    "Dynamic invocation of 'toSet'.": 1,
-    "Dynamic invocation of '[]='.": 1,
-    "Dynamic invocation of 'add'.": 1
-  },
-  "pkg/compiler/lib/src/util/features.dart": {
-    "Dynamic invocation of 'sort'.": 1,
-    "Dynamic invocation of 'join'.": 1
-  },
   "pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart": {
     "Dynamic access of 'superclass'.": 1,
     "Dynamic access of 'needsTearOff'.": 1
diff --git a/tests/compiler/dart2js/static_type/data/cascade.dart b/tests/compiler/dart2js/static_type/data/cascade.dart
new file mode 100644
index 0000000..08c3e25
--- /dev/null
+++ b/tests/compiler/dart2js/static_type/data/cascade.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, 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.
+
+main() {
+  promotedCascade(null);
+}
+
+promotedCascade(dynamic value) {
+  if (/*dynamic*/ value is List<String>) {
+    value =
+        '[${(/*List<String>*/ value.. /*invoke: void*/ sort()). /*invoke: String*/ join(',')}]';
+  }
+  return /*dynamic*/ value;
+}