Merge pull request #7844 from slavapestov/one-last-cleanup

SILOptimizer: Use the SubstitutionMap form of substGenericArgs()
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 626e2e6..42e442f 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -164,6 +164,9 @@
 ERROR(cannot_match_expr_pattern_with_value,none,
       "expression pattern of type %0 cannot match values of type %1",
       (Type, Type))
+ERROR(cannot_match_unresolved_expr_pattern_with_value,none,
+      "pattern cannot match values of type %0",
+      (Type))
 
 ERROR(cannot_reference_compare_types,none,
       "cannot check reference equality of functions; operands here have types "
diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h
index 3c561ce..5100365 100644
--- a/include/swift/AST/Pattern.h
+++ b/include/swift/AST/Pattern.h
@@ -492,7 +492,7 @@
   SourceLoc DotLoc;
   SourceLoc NameLoc;
   Identifier Name;
-  EnumElementDecl *ElementDecl;
+  PointerUnion<EnumElementDecl *, Expr*> ElementDeclOrUnresolvedOriginalExpr;
   Pattern /*nullable*/ *SubPattern;
   
 public:
@@ -501,10 +501,25 @@
                      Pattern *SubPattern, Optional<bool> Implicit = None)
     : Pattern(PatternKind::EnumElement),
       ParentType(ParentType), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
-      ElementDecl(Element), SubPattern(SubPattern) {
+      ElementDeclOrUnresolvedOriginalExpr(Element),
+      SubPattern(SubPattern) {
     if (Implicit.hasValue() && *Implicit)
       setImplicit();
   }
+  
+  /// Create an unresolved EnumElementPattern for a `.foo` pattern relying on
+  /// contextual type.
+  EnumElementPattern(SourceLoc DotLoc,
+                     SourceLoc NameLoc,
+                     Identifier Name,
+                     Pattern *SubPattern,
+                     Expr *UnresolvedOriginalExpr)
+    : Pattern(PatternKind::EnumElement),
+      ParentType(), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
+      ElementDeclOrUnresolvedOriginalExpr(UnresolvedOriginalExpr),
+      SubPattern(SubPattern) {
+    
+  }
 
   bool hasSubPattern() const { return SubPattern; }
   
@@ -524,8 +539,19 @@
   
   Identifier getName() const { return Name; }
   
-  EnumElementDecl *getElementDecl() const { return ElementDecl; }
-  void setElementDecl(EnumElementDecl *d) { ElementDecl = d; }
+  EnumElementDecl *getElementDecl() const {
+    return ElementDeclOrUnresolvedOriginalExpr.dyn_cast<EnumElementDecl*>();
+  }
+  void setElementDecl(EnumElementDecl *d) {
+    ElementDeclOrUnresolvedOriginalExpr = d;
+  }
+  
+  Expr *getUnresolvedOriginalExpr() const {
+    return ElementDeclOrUnresolvedOriginalExpr.get<Expr*>();
+  }
+  bool hasUnresolvedOriginalExpr() const {
+    return ElementDeclOrUnresolvedOriginalExpr.is<Expr*>();
+  }
   
   SourceLoc getNameLoc() const { return NameLoc; }
   SourceLoc getLoc() const { return NameLoc; }
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 9e6b638..82a1cee 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -29,6 +29,20 @@
 #include <vector>
 
 namespace swift {
+
+  /// Kind of implicit platform conditions.
+  enum class PlatformConditionKind {
+    /// The active os target (OSX, iOS, Linux, etc.)
+    OS,
+    /// The active arch target (x86_64, i386, arm, arm64, etc.)
+    Arch,
+    /// The active endianness target (big or little)
+    Endianness,
+    /// Runtime support (_ObjC or _Native)
+    Runtime,
+  };
+  enum { NumPlatformConditionKind = 4 };
+
   /// \brief A collection of options that affect the language dialect and
   /// provide compiler debugging facilities.
   class LangOptions {
@@ -202,14 +216,9 @@
     }
 
     /// Sets an implicit platform condition.
-    ///
-    /// There are currently three supported platform conditions:
-    /// - os: The active os target (OSX or iOS)
-    /// - arch: The active arch target (x86_64, i386, arm, arm64)
-    /// - _runtime: Runtime support (_ObjC or _Native)
-    void addPlatformConditionValue(StringRef Name, StringRef Value) {
-      assert(!Name.empty() && !Value.empty());
-      PlatformConditionValues.emplace_back(Name, Value);
+    void addPlatformConditionValue(PlatformConditionKind Kind, StringRef Value) {
+      assert(!Value.empty());
+      PlatformConditionValues.emplace_back(Kind, Value);
     }
 
     /// Removes all values added with addPlatformConditionValue.
@@ -218,7 +227,7 @@
     }
     
     /// Returns the value for the given platform condition or an empty string.
-    StringRef getPlatformConditionValue(StringRef Name) const;
+    StringRef getPlatformConditionValue(PlatformConditionKind Kind) const;
 
     /// Explicit conditional compilation flags, initialized via the '-D'
     /// compiler flag.
@@ -230,7 +239,7 @@
     /// Determines if a given conditional compilation flag has been set.
     bool isCustomConditionalCompilationFlagSet(StringRef Name) const;
 
-    ArrayRef<std::pair<std::string, std::string>>
+    ArrayRef<std::pair<PlatformConditionKind, std::string>>
     getPlatformConditionValues() const {
       return PlatformConditionValues;
     }
@@ -244,35 +253,18 @@
       return EffectiveLanguageVersion.isVersion3();
     }
 
-    /// Returns true if the 'os' platform condition argument represents
+    /// Returns true if the given platform condition argument represents
     /// a supported target operating system.
     ///
-    /// Note that this also canonicalizes the OS name if the check returns
-    /// true.
-    ///
     /// \param suggestions Populated with suggested replacements
     /// if a match is not found.
-    static bool checkPlatformConditionOS(
-      StringRef &OSName, std::vector<StringRef> &suggestions);
-
-    /// Returns true if the 'arch' platform condition argument represents
-    /// a supported target architecture.
-    ///
-    /// \param suggestions Populated with suggested replacements
-    /// if a match is not found.
-    static bool isPlatformConditionArchSupported(
-      StringRef ArchName, std::vector<StringRef> &suggestions);
-
-    /// Returns true if the 'endian' platform condition argument represents
-    /// a supported target endianness.
-    ///
-    /// \param suggestions Populated with suggested replacements
-    /// if a match is not found.
-    static bool isPlatformConditionEndiannessSupported(
-      StringRef endianness, std::vector<StringRef> &suggestions);
+    static bool checkPlatformConditionSupported(
+      PlatformConditionKind Kind, StringRef Value,
+      std::vector<StringRef> &suggestions);
 
   private:
-    llvm::SmallVector<std::pair<std::string, std::string>, 3>
+    llvm::SmallVector<std::pair<PlatformConditionKind, std::string>,
+                      NumPlatformConditionKind>
         PlatformConditionValues;
     llvm::SmallVector<std::string, 2> CustomConditionalCompilationFlags;
   };
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index 19efc63..93ec8a9 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -52,6 +52,11 @@
   "big"
 };
 
+static const StringRef SupportedConditionalCompilationRuntimes[] = {
+  "_ObjC",
+  "_Native",
+};
+
 template <size_t N>
 bool contains(const StringRef (&Array)[N], const StringRef &V,
               std::vector<StringRef> &suggestions) {
@@ -75,36 +80,31 @@
   return false;
 }
 
-bool LangOptions::checkPlatformConditionOS(
-  StringRef &OSName, std::vector<StringRef> &suggestions) {
-  if (OSName == "macOS")
-    OSName = "OSX";
-  return contains(SupportedConditionalCompilationOSs,
-                  OSName,
-                  suggestions);
-}
-
-bool
-LangOptions::isPlatformConditionArchSupported(
-  StringRef ArchName, std::vector<StringRef> &suggestions) {
-  return contains(SupportedConditionalCompilationArches,
-                  ArchName,
-                  suggestions);
-}
-
-bool
-LangOptions::isPlatformConditionEndiannessSupported(
-  StringRef Endianness, std::vector<StringRef> &suggestions) {
-  return contains(SupportedConditionalCompilationEndianness,
-                  Endianness,
-                  suggestions);
+bool LangOptions::
+checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value,
+                                std::vector<StringRef> &suggestions) {
+  switch (Kind) {
+  case PlatformConditionKind::OS:
+    return contains(SupportedConditionalCompilationOSs, Value,
+                    suggestions);
+  case PlatformConditionKind::Arch:
+    return contains(SupportedConditionalCompilationArches, Value,
+                    suggestions);
+  case PlatformConditionKind::Endianness:
+    return contains(SupportedConditionalCompilationEndianness, Value,
+                    suggestions);
+  case PlatformConditionKind::Runtime:
+    return contains(SupportedConditionalCompilationRuntimes, Value,
+                    suggestions);
+  }
+  llvm_unreachable("Unhandled enum value");
 }
 
 StringRef
-LangOptions::getPlatformConditionValue(StringRef Name) const {
+LangOptions::getPlatformConditionValue(PlatformConditionKind Kind) const {
   // Last one wins.
   for (auto &Opt : reversed(PlatformConditionValues)) {
-    if (Opt.first == Name)
+    if (Opt.first == Kind)
       return Opt.second;
   }
   return StringRef();
@@ -141,23 +141,23 @@
 
   // Set the "os" platform condition.
   if (Target.isMacOSX())
-    addPlatformConditionValue("os", "OSX");
+    addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
   else if (triple.isTvOS())
-    addPlatformConditionValue("os", "tvOS");
+    addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
   else if (triple.isWatchOS())
-    addPlatformConditionValue("os", "watchOS");
+    addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
   else if (triple.isiOS())
-    addPlatformConditionValue("os", "iOS");
+    addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
   else if (triple.isAndroid())
-    addPlatformConditionValue("os", "Android");
+    addPlatformConditionValue(PlatformConditionKind::OS, "Android");
   else if (triple.isOSLinux())
-    addPlatformConditionValue("os", "Linux");
+    addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
   else if (triple.isOSFreeBSD())
-    addPlatformConditionValue("os", "FreeBSD");
+    addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
   else if (triple.isOSWindows())
-    addPlatformConditionValue("os", "Windows");
+    addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
   else if (triple.isPS4())
-    addPlatformConditionValue("os", "PS4");
+    addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
   else
     UnsupportedOS = true;
 
@@ -167,25 +167,25 @@
   switch (Target.getArch()) {
   case llvm::Triple::ArchType::arm:
   case llvm::Triple::ArchType::thumb:
-    addPlatformConditionValue("arch", "arm");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "arm");
     break;
   case llvm::Triple::ArchType::aarch64:
-    addPlatformConditionValue("arch", "arm64");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "arm64");
     break;
   case llvm::Triple::ArchType::ppc64:
-    addPlatformConditionValue("arch", "powerpc64");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64");
     break;
   case llvm::Triple::ArchType::ppc64le:
-    addPlatformConditionValue("arch", "powerpc64le");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le");
     break;
   case llvm::Triple::ArchType::x86:
-    addPlatformConditionValue("arch", "i386");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "i386");
     break;
   case llvm::Triple::ArchType::x86_64:
-    addPlatformConditionValue("arch", "x86_64");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64");
     break;
   case llvm::Triple::ArchType::systemz:
-    addPlatformConditionValue("arch", "s390x");
+    addPlatformConditionValue(PlatformConditionKind::Arch, "s390x");
     break;
   default:
     UnsupportedArch = true;
@@ -198,25 +198,25 @@
   switch (Target.getArch()) {
   case llvm::Triple::ArchType::arm:
   case llvm::Triple::ArchType::thumb:
-    addPlatformConditionValue("_endian", "little");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
     break;
   case llvm::Triple::ArchType::aarch64:
-    addPlatformConditionValue("_endian", "little");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
     break;
   case llvm::Triple::ArchType::ppc64:
-    addPlatformConditionValue("_endian", "big");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
     break;
   case llvm::Triple::ArchType::ppc64le:
-    addPlatformConditionValue("_endian", "little");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
     break;
   case llvm::Triple::ArchType::x86:
-    addPlatformConditionValue("_endian", "little");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
     break;
   case llvm::Triple::ArchType::x86_64:
-    addPlatformConditionValue("_endian", "little");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
     break;
   case llvm::Triple::ArchType::systemz:
-    addPlatformConditionValue("_endian", "big");
+    addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
     break;
   default:
     llvm_unreachable("undefined architecture endianness");
@@ -224,9 +224,9 @@
 
   // Set the "runtime" platform condition.
   if (EnableObjCInterop)
-    addPlatformConditionValue("_runtime", "_ObjC");
+    addPlatformConditionValue(PlatformConditionKind::Runtime, "_ObjC");
   else
-    addPlatformConditionValue("_runtime", "_Native");
+    addPlatformConditionValue(PlatformConditionKind::Runtime, "_Native");
 
   // If you add anything to this list, change the default size of
   // PlatformConditionValues to not require an extra allocation
diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp
index a106f48..f6c064d 100644
--- a/lib/Parse/ParseIfConfig.cpp
+++ b/lib/Parse/ParseIfConfig.cpp
@@ -16,8 +16,10 @@
 
 #include "swift/Parse/Parser.h"
 #include "swift/Basic/Defer.h"
+#include "swift/Basic/LangOptions.h"
 #include "swift/Basic/Version.h"
 #include "swift/Parse/Lexer.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/SaveAndRestore.h"
 
@@ -356,51 +358,46 @@
         // tolerate extra parens).
         auto argumentIdent = UDRE->getName().getBaseName();
         auto argument = argumentIdent.str();
-
-        // Error for values that don't make sense if there's a clear definition
-        // of the possible values (as there is for _runtime).
-        if (fnName.equals("_runtime") &&
-            !argument.equals("_ObjC") && !argument.equals("_Native")) {
-          D.diagnose(CE->getLoc(),
-                     diag::unsupported_platform_runtime_condition_argument);
-          return ConditionalCompilationExprState::error();
-        }
-
-        std::vector<StringRef> suggestions;
-        SWIFT_DEFER {
-          for (const StringRef& suggestion : suggestions) {
-            D.diagnose(UDRE->getLoc(), diag::note_typo_candidate,
-                       suggestion)
-            .fixItReplace(UDRE->getSourceRange(), suggestion);
-          }
-        };
-        if (fnName == "os") {
-          if (!LangOptions::checkPlatformConditionOS(argument,
-                                                     suggestions)) {
-            D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
-                       "operating system", fnName);
-            return ConditionalCompilationExprState::error();
-          }
-        } else if (fnName == "arch") {
-          if (!LangOptions::isPlatformConditionArchSupported(argument,
-                                                             suggestions)) {
-            D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
-                       "architecture", fnName);
-            return ConditionalCompilationExprState::error();
-          }
-        } else if (fnName == "_endian") {
-          if (!LangOptions::isPlatformConditionEndiannessSupported(argument,
-                                                                   suggestions)) {
-            D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
-                       "endianness", fnName);
-          }
-        }
+        PlatformConditionKind Kind =
+          llvm::StringSwitch<PlatformConditionKind>(fnName)
+          .Case("os", PlatformConditionKind::OS)
+          .Case("arch", PlatformConditionKind::Arch)
+          .Case("_endian", PlatformConditionKind::Endianness)
+          .Case("_runtime", PlatformConditionKind::Runtime);
 
         // FIXME: Perform the replacement macOS -> OSX elsewhere.
-        if (fnName == "os" && argument == "macOS")
+        if (Kind == PlatformConditionKind::OS && argument == "macOS")
           argument = "OSX";
 
-        auto target = Context.LangOpts.getPlatformConditionValue(fnName);
+        std::vector<StringRef> suggestions;
+        if (!LangOptions::checkPlatformConditionSupported(Kind, argument,
+                                                          suggestions)) {
+          if (Kind == PlatformConditionKind::Runtime) {
+            // Error for _runtime()
+            D.diagnose(UDRE->getLoc(),
+                       diag::unsupported_platform_runtime_condition_argument);
+            return ConditionalCompilationExprState::error();
+          }
+          StringRef DiagName;
+          switch (Kind) {
+          case PlatformConditionKind::OS:
+            DiagName = "operating system"; break;
+          case PlatformConditionKind::Arch:
+            DiagName = "architecture"; break;
+          case PlatformConditionKind::Endianness:
+            DiagName = "endianness"; break;
+          case PlatformConditionKind::Runtime:
+            llvm_unreachable("handled above");
+          }
+          D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
+                     DiagName, fnName);
+          for (const StringRef &suggestion : suggestions) {
+            D.diagnose(UDRE->getLoc(), diag::note_typo_candidate, suggestion)
+              .fixItReplace(UDRE->getSourceRange(), suggestion);
+          }
+        }
+
+        auto target = Context.LangOpts.getPlatformConditionValue(Kind);
         return {target == argument, ConditionalCompilationExprKind::DeclRef};
       } else {
         D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_argument,
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index de33fab..4f27b76 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -3495,11 +3495,13 @@
     Expr *visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
       // If we end up here, we should have diagnosed somewhere else
       // already.
-      if (!SuppressDiagnostics) {
-        cs.TC.diagnose(expr->getLoc(), diag::pattern_in_expr,
+      Expr *simplified = simplifyExprType(expr);
+      if (!SuppressDiagnostics
+          && !simplified->getType()->is<UnresolvedType>()) {
+        cs.TC.diagnose(simplified->getLoc(), diag::pattern_in_expr,
                        expr->getSubPattern()->getKind());
       }
-      return expr;
+      return simplified;
     }
     
     Expr *visitBindOptionalExpr(BindOptionalExpr *expr) {
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index ba8e396..1730ae3 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -6077,9 +6077,13 @@
 
     if (callExpr->isImplicit() && overloadName == "~=") {
       // This binop was synthesized when typechecking an expression pattern.
-      auto diag = diagnose(lhsExpr->getLoc(),
-                    diag::cannot_match_expr_pattern_with_value,
-                           lhsType, rhsType);
+      auto diag = lhsType->is<UnresolvedType>()
+        ? diagnose(lhsExpr->getLoc(),
+                   diag::cannot_match_unresolved_expr_pattern_with_value,
+                   rhsType)
+        : diagnose(lhsExpr->getLoc(),
+                   diag::cannot_match_expr_pattern_with_value,
+                   lhsType, rhsType);
       diag.highlight(lhsExpr->getSourceRange());
       diag.highlight(rhsExpr->getSourceRange());
       if (auto optUnwrappedType = rhsType->getOptionalObjectType()) {
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index f50c194..f84b7dd 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2670,8 +2670,13 @@
     
     Type visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
       // If there are UnresolvedPatterns floating around after name binding,
-      // they are pattern productions in invalid positions.
-      return ErrorType::get(CS.getASTContext());
+      // they are pattern productions in invalid positions. However, we will
+      // diagnose that condition elsewhere; to avoid unnecessary noise errors,
+      // just plop an open type variable here.
+      
+      auto locator = CS.getConstraintLocator(expr);
+      auto typeVar = CS.createTypeVariable(locator, TVO_CanBindToLValue);
+      return typeVar;
     }
 
     /// Get the type T?
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 0a3131e..b2fa7ec 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -394,7 +394,7 @@
   // Unresolved member syntax '.Element' forms an EnumElement pattern. The
   // element will be resolved when we type-check the pattern.
   Pattern *visitUnresolvedMemberExpr(UnresolvedMemberExpr *ume) {
-    // We the unresolved member has an argument, turn it into a subpattern.
+    // If the unresolved member has an argument, turn it into a subpattern.
     Pattern *subPattern = nullptr;
     if (auto arg = ume->getArgument()) {
       subPattern = getSubExprPattern(arg);
@@ -402,11 +402,11 @@
     
     // FIXME: Compound names.
     return new (TC.Context) EnumElementPattern(
-                              TypeLoc(), ume->getDotLoc(),
+                              ume->getDotLoc(),
                               ume->getNameLoc().getBaseNameLoc(),
                               ume->getName().getBaseName(),
-                              nullptr,
-                              subPattern);
+                              subPattern,
+                              ume);
   }
   
   // Member syntax 'T.Element' forms a pattern if 'T' is an enum and the
@@ -1004,6 +1004,7 @@
                                       TypeResolutionOptions options,
                                       GenericTypeResolver *resolver,
                                       TypeLoc tyLoc) {
+recur:
   if (tyLoc.isNull()) {
     tyLoc = TypeLoc::withoutLoc(type);
   }
@@ -1377,6 +1378,14 @@
 
               return true;
             }
+          
+          // If we have the original expression parse tree, try reinterpreting
+          // it as an expr-pattern if enum element lookup failed, since `.foo`
+          // could also refer to a static member of the context type.
+          } else if (EEP->hasUnresolvedOriginalExpr()) {
+            P = new (Context) ExprPattern(EEP->getUnresolvedOriginalExpr(),
+                                          nullptr, nullptr);
+            goto recur;
           }
 
           diagnose(EEP->getLoc(), diag::enum_element_pattern_member_not_found,
diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp
index dc0d4ac..f193f73 100644
--- a/lib/Serialization/SerializedModuleLoader.cpp
+++ b/lib/Serialization/SerializedModuleLoader.cpp
@@ -96,7 +96,7 @@
   // FIXME: Which name should we be using here? Do we care about CPU subtypes?
   // FIXME: At the very least, don't hardcode "arch".
   llvm::SmallString<16> archFile{
-      ctx.LangOpts.getPlatformConditionValue("arch")};
+      ctx.LangOpts.getPlatformConditionValue(PlatformConditionKind::Arch)};
   llvm::SmallString<16> archDocFile{archFile};
   if (!archFile.empty()) {
     archFile += '.';
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index 3b07ff8..1183a45 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -114,7 +114,8 @@
   ()
 case Watch.Edition: // TODO: should warn that cast can't succeed with currently known conformances
   ()
-case .HairForceOne: // expected-error{{enum case 'HairForceOne' not found in type 'HairType'}}
+// TODO: Bad error message
+case .HairForceOne: // expected-error{{cannot convert}}
   ()
 default:
   break
@@ -254,3 +255,53 @@
 if case let doesNotExist as SomeClass:AlsoDoesNotExist {}
 // expected-error@-1 {{use of undeclared type 'AlsoDoesNotExist'}}
 // expected-error@-2 {{variable binding in a condition requires an initializer}}
+
+// `.foo` and `.bar(...)` pattern syntax should also be able to match
+// static members as expr patterns
+
+struct StaticMembers: Equatable {
+  init() {}
+  init(_: Int) {}
+  init?(opt: Int) {}
+  static var prop = StaticMembers()
+  static var optProp: Optional = StaticMembers()
+
+  static func method(_: Int) -> StaticMembers { return prop }
+  static func method(withLabel: Int) -> StaticMembers { return prop }
+  static func optMethod(_: Int) -> StaticMembers? { return optProp }
+
+  static func ==(x: StaticMembers, y: StaticMembers) -> Bool { return true }
+}
+
+let staticMembers = StaticMembers()
+let optStaticMembers: Optional = StaticMembers()
+
+switch staticMembers {
+  case .init: break // expected-error{{cannot match values of type 'StaticMembers'}}
+  case .init(opt:): break // expected-error{{cannot match values of type 'StaticMembers'}}
+  case .init(): break
+
+  case .init(0): break
+  case .init(_): break // expected-error{{'_' can only appear in a pattern}}
+  case .init(let x): break // expected-error{{cannot appear in an expression}}
+  case .init(opt: 0): break // expected-error{{not unwrapped}}
+
+  case .prop: break
+  // TODO: repeated error message
+  case .optProp: break // expected-error* {{not unwrapped}}
+
+  case .method: break // expected-error{{cannot match}}
+  case .method(0): break
+  case .method(_): break // expected-error{{'_' can only appear in a pattern}}
+  case .method(let x): break // expected-error{{cannot appear in an expression}}
+
+  case .method(withLabel:): break // expected-error{{cannot match}}
+  case .method(withLabel: 0): break
+  case .method(withLabel: _): break // expected-error{{'_' can only appear in a pattern}}
+  case .method(withLabel: let x): break // expected-error{{cannot appear in an expression}}
+
+  case .optMethod: break // expected-error{{cannot match}}
+  case .optMethod(0): break // expected-error{{not unwrapped}}
+}
+
+_ = 0
diff --git a/test/Parse/matching_patterns.swift b/test/Parse/matching_patterns.swift
index d7766ec..57dd399 100644
--- a/test/Parse/matching_patterns.swift
+++ b/test/Parse/matching_patterns.swift
@@ -100,7 +100,7 @@
     }
 
     switch foo {
-    case .Naught: // expected-error{{enum case 'Naught' not found in type 'Foo'}}
+    case .Naught: // expected-error{{pattern cannot match values of type 'Foo'}}
       ()
     case .A, .B, .C:
       ()
@@ -137,7 +137,7 @@
 var notAnEnum = 0
 
 switch notAnEnum {
-case .Foo: // expected-error{{enum case 'Foo' not found in type 'Int'}}
+case .Foo: // expected-error{{pattern cannot match values of type 'Int'}}
   ()
 }
 
@@ -264,10 +264,8 @@
 // expected-error@-1{{'+++' is not a prefix unary operator}}
   ()
 case (_, var e, 3) +++ (1, 2, 3):
-// expected-error@-1{{binary operator '+++' cannot be applied to operands of type '(_, <<error type>>, Int)' and '(Int, Int, Int)'}}
-// expected-note@-2{{expected an argument list of type '((Int, Int, Int), (Int, Int, Int))'}}
-// expected-error@-3{{'var' binding pattern cannot appear in an expression}}
-// expected-error@-4{{'var' binding pattern cannot appear in an expression}}
+// expected-error@-1{{'_' can only appear in a pattern}}
+// expected-error@-2{{'var' binding pattern cannot appear in an expression}}
   ()
 }
 
diff --git a/test/Parse/switch.swift b/test/Parse/switch.swift
index 6741c3b..7e2b81ae 100644
--- a/test/Parse/switch.swift
+++ b/test/Parse/switch.swift
@@ -264,7 +264,7 @@
 
 func enumElementSyntaxOnTuple() {
   switch (1, 1) {
-  case .Bar: // expected-error {{enum case 'Bar' not found in type '(Int, Int)'}}
+  case .Bar: // expected-error {{pattern cannot match values of type '(Int, Int)'}}
     break
   default:
     break
diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift
index b33944c..f927ee7 100644
--- a/test/stmt/statements.swift
+++ b/test/stmt/statements.swift
@@ -247,7 +247,7 @@
 
 func brokenSwitch(_ x: Int) -> Int {
   switch x {
-  case .Blah(var rep): // expected-error{{enum case 'Blah' not found in type 'Int'}}
+  case .Blah(var rep): // expected-error{{pattern cannot match values of type 'Int'}}
     return rep
   }
 }
diff --git a/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift b/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift
index 8b4bedd..18fddac 100644
--- a/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift
+++ b/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift
@@ -8,6 +8,7 @@
 // RUN: not %target-swift-frontend %s -emit-ir
 // FIXME(huonw): where clauses on associatedtypes broke this
 // XFAIL: *
+// REQUIRES: asserts
 class A{let f= <c
 protocol A{
 typealias e:A{}
diff --git a/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift b/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift
index 999e950..d8533f9 100644
--- a/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift
+++ b/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift
@@ -8,5 +8,6 @@
 // RUN: not %target-swift-frontend %s -emit-ir
 // FIXME(huonw): where clauses on associatedtypes broke this
 // XFAIL: *
+// REQUIRES: asserts
 class A:a
 protocol a{typealias B:A.B