Implement downward inference for set literals

Change-Id: I21458e79a2c7127675c7d50ba0726c7b0bd29493
Reviewed-on: https://dart-review.googlesource.com/c/86980
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index b46d408..b7853c6 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -5306,6 +5306,33 @@
   }
 
   @override
+  void visitSetLiteral(SetLiteral node) {
+    InterfaceType setT;
+
+    TypeArgumentList typeArguments = node.typeArguments;
+    if (typeArguments != null) {
+      if (typeArguments.length == 1) {
+        DartType elementType = typeArguments.arguments[0].type;
+        if (!elementType.isDynamic) {
+          setT = typeProvider.setType.instantiate([elementType]);
+        }
+      }
+    } else {
+      setT = typeAnalyzer.inferSetType(node, downwards: true);
+    }
+    if (setT != null) {
+      DartType eType = setT.typeArguments[0];
+      for (Expression child in node.elements) {
+        InferenceContext.setType(child, eType);
+      }
+      InferenceContext.setType(node, setT);
+    } else {
+      InferenceContext.clearType(node);
+    }
+    super.visitSetLiteral(node);
+  }
+
+  @override
   void visitShowCombinator(ShowCombinator node) {}
 
   @override
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 6657e81..fe1a85f 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -187,7 +187,7 @@
 class StaticTypeAnalyzer3Test extends StaticTypeAnalyzer2TestShared {
   bool get enableNewAnalysisDriver => true;
 
-  test_emptyMapLiteral_inContext() async {
+  test_emptyMapLiteral_parameter_typed() async {
     String code = r'''
 main() {
   useMap({});
@@ -199,7 +199,7 @@
     expectExpressionType('{}', 'Map<int, int>');
   }
 
-  test_emptyMapLiteral_notInContext() async {
+  test_emptyMapLiteral_initializer_var() async {
     String code = r'''
 main() {
   var v = {};
@@ -209,7 +209,7 @@
     expectExpressionType('{}', 'Map<dynamic, dynamic>');
   }
 
-  test_emptySetLiteral_inContext() async {
+  test_emptySetLiteral_parameter_typed() async {
     String code = r'''
 main() {
   useSet({});
@@ -220,6 +220,15 @@
     await resolveTestUnit(code);
     expectExpressionType('{}', 'Set<int>');
   }
+
+  test_emptySetLiteral_initializer_typed_nested() async {
+    String code = r'''
+Set<Set<int>> ints = {{}};
+''';
+    await resolveTestUnit(code);
+    expectExpressionType('{}', 'Set<int>');
+    expectExpressionType('{{}}', 'Set<Set<int>>');
+  }
 }
 
 @reflectiveTest