Merge pull request #9931 from CodaFi/what-does-brian-eno

diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index 252891e..122164b 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -950,30 +950,43 @@
       // missing case '(.some(_), .none)'
       if (InEditor) {
         Buffer.clear();
+        SmallVector<Space, 8> emittedSpaces;
         for (auto &uncoveredSpace : uncovered.getSpaces()) {
           SmallVector<Space, 4> flats;
           flatten(uncoveredSpace, flats);
           for (auto &flat : flats) {
+            if (flat.isSubspace(Space(emittedSpaces), TC)) {
+              continue;
+            }
+            
             OS << tok::kw_case << " ";
             flat.show(OS);
             OS << ":\n" << Placeholder << "\n";
+            
+            emittedSpaces.push_back(flat);
           }
         }
 
-        TC.Context.Diags.diagnose(StartLoc, diag::non_exhaustive_switch);
-        TC.Context.Diags.diagnose(StartLoc, diag::missing_several_cases, false)
+        TC.diagnose(StartLoc, diag::non_exhaustive_switch);
+        TC.diagnose(StartLoc, diag::missing_several_cases, false)
           .fixItInsert(EndLoc, Buffer.str());
       } else {
         TC.Context.Diags.diagnose(StartLoc, diag::non_exhaustive_switch);
 
+        SmallVector<Space, 8> emittedSpaces;
         for (auto &uncoveredSpace : uncovered.getSpaces()) {
           SmallVector<Space, 4> flats;
           flatten(uncoveredSpace, flats);
           for (auto &flat : flats) {
+            if (flat.isSubspace(Space(emittedSpaces), TC)) {
+              continue;
+            }
+            
             Buffer.clear();
             flat.show(OS);
-            TC.Context.Diags.diagnose(StartLoc, diag::missing_particular_case,
-                               Buffer.str());
+            TC.diagnose(StartLoc, diag::missing_particular_case, Buffer.str());
+            
+            emittedSpaces.push_back(flat);
           }
         }
       }
diff --git a/test/Sema/exhaustive_switch.swift b/test/Sema/exhaustive_switch.swift
index 944db82..0ea73f2 100644
--- a/test/Sema/exhaustive_switch.swift
+++ b/test/Sema/exhaustive_switch.swift
@@ -309,3 +309,37 @@
   case .two: break
   }
 }
+
+enum Runcible {
+  case spoon
+  case hat
+  case fork
+}
+
+func checkDiagnosticMinimality(x: Runcible?) {
+  switch (x!, x!) { // expected-error {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.fork, _)'}}
+  // expected-note@-2 {{add missing case: '(.hat, .hat)'}}
+  // expected-note@-3 {{add missing case: '(.hat, .fork)'}}
+  // expected-note@-4 {{add missing case: '(_, .fork)'}}
+  case (.spoon, .spoon):
+    break
+  case (.spoon, .hat):
+    break
+  case (.hat, .spoon):
+    break
+  }
+  
+  switch (x!, x!) { // expected-error {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.fork, _)'}}
+  // expected-note@-2 {{add missing case: '(.hat, .spoon)'}}
+  // expected-note@-3 {{add missing case: '(.hat, .fork)'}}
+  // expected-note@-4 {{add missing case: '(.spoon, .hat)'}}
+  // expected-note@-5 {{add missing case: '(.spoon, .fork)'}}
+  // expected-note@-6 {{add missing case: '(_, .fork)'}}
+  case (.spoon, .spoon):
+    break
+  case (.hat, .hat):
+    break
+  }
+}