[AST] Remove stored TypeLoc from TypedPattern (#19175)

* [AST] Remove stored TypeLoc from TypedPattern

TypedPattern was only using this TypeLoc as a means to a TypeRepr, which
caused it to store the pattern type twice (through the superclass and through
the TypeLoc itself.)

This also fixes a bug where deserializing a TypedPattern doesn't store
the type correctly and generally cleans up TypedPattern initialization.

Resolves rdar://44144435

* Address review comments
diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h
index 2210c0c..5579d8a 100644
--- a/include/swift/AST/Pattern.h
+++ b/include/swift/AST/Pattern.h
@@ -383,14 +383,25 @@
 /// dynamic type match.
 class TypedPattern : public Pattern {
   Pattern *SubPattern;
-  mutable TypeLoc PatType;
+  TypeRepr *PatTypeRepr;
 
 public:
-  TypedPattern(Pattern *pattern, TypeLoc tl, Optional<bool> implicit = None)
-    : Pattern(PatternKind::Typed), SubPattern(pattern), PatType(tl) {
-    if (implicit.hasValue() ? *implicit : !tl.hasLocation())
-      setImplicit();
-    Bits.TypedPattern.IsPropagatedType = false;
+  /// Creates a new TypedPattern which annotates the provided sub-pattern with
+  /// the provided TypeRepr. If 'implicit' is true, the pattern will be
+  /// set to implicit. If false, it will not. If 'implicit' is not provided,
+  /// then the pattern will be set to 'implicit' if there is a provided TypeRepr
+  /// which has a valid SourceRange.
+  TypedPattern(Pattern *pattern, TypeRepr *tr, Optional<bool> implicit = None);
+
+  /// Creates an implicit typed pattern annotating the provided sub-pattern
+  /// with a given type.
+  static TypedPattern *
+  createImplicit(ASTContext &ctx, Pattern *pattern, Type type) {
+    auto tp = new (ctx) TypedPattern(pattern, /*typeRepr*/nullptr,
+                                     /*implicit*/true);
+    if (!type.isNull())
+      tp->setType(type);
+    return tp;
   }
 
   /// True if the type in this \c TypedPattern was propagated from a different
@@ -412,27 +423,10 @@
   const Pattern *getSubPattern() const { return SubPattern; }
   void setSubPattern(Pattern *p) { SubPattern = p; }
 
-  TypeLoc &getTypeLoc() {
-    // If we have a delayed interface type, set our type from that.
-    if (getDelayedInterfaceType())
-      PatType.setType(getType());
+  TypeRepr *getTypeRepr() const { return PatTypeRepr; }
 
-    return PatType;
-  }
-  TypeLoc getTypeLoc() const {
-    // If we have a delayed interface type, set our type from that.
-    if (getDelayedInterfaceType())
-      PatType.setType(getType());
-
-    return PatType;
-  }
-
-  SourceLoc getLoc() const {
-    if (SubPattern->isImplicit())
-      return PatType.getSourceRange().Start;
-
-    return SubPattern->getLoc();
-  }
+  TypeLoc getTypeLoc() const;
+  SourceLoc getLoc() const;
   SourceRange getSourceRange() const;
 
   static bool classof(const Pattern *P) {
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index e390cd2..062eef5 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -1571,8 +1571,9 @@
   else
     return nullptr;
   if (!P->isImplicit())
-    if (doIt(P->getTypeLoc()))
-      return nullptr;
+    if (auto *TR = P->getTypeRepr())
+      if (doIt(TR))
+        return nullptr;
   return P;
 }
 
diff --git a/lib/AST/Pattern.cpp b/lib/AST/Pattern.cpp
index 587ed12..0d4cf765 100644
--- a/lib/AST/Pattern.cpp
+++ b/lib/AST/Pattern.cpp
@@ -400,6 +400,30 @@
            Fields.back().getPattern()->getEndLoc() };
 }
 
+TypedPattern::TypedPattern(Pattern *pattern, TypeRepr *tr,
+                           Optional<bool> implicit)
+  : Pattern(PatternKind::Typed), SubPattern(pattern), PatTypeRepr(tr) {
+  if (implicit ? *implicit : tr && !tr->getSourceRange().isValid())
+    setImplicit();
+  Bits.TypedPattern.IsPropagatedType = false;
+}
+
+TypeLoc TypedPattern::getTypeLoc() const {
+  TypeLoc loc = TypeLoc(PatTypeRepr);
+
+  if (hasType())
+    loc.setType(getType());
+
+  return loc;
+}
+
+SourceLoc TypedPattern::getLoc() const {
+  if (SubPattern->isImplicit() && PatTypeRepr)
+    return PatTypeRepr->getSourceRange().Start;
+
+  return SubPattern->getLoc();
+}
+
 SourceRange TypedPattern::getSourceRange() const {
   if (isImplicit() || isPropagatedType()) {
     // If a TypedPattern is implicit, then its type is definitely implicit, so
@@ -408,10 +432,14 @@
     return SubPattern->getSourceRange();
   }
 
-  if (SubPattern->isImplicit())
-    return PatType.getSourceRange();
+  if (!PatTypeRepr)
+    return SourceRange();
 
-  return { SubPattern->getSourceRange().Start, PatType.getSourceRange().End };
+  if (SubPattern->isImplicit())
+    return PatTypeRepr->getSourceRange();
+
+  return { SubPattern->getSourceRange().Start,
+           PatTypeRepr->getSourceRange().End };
 }
 
 /// Construct an ExprPattern.
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 666d925..fceaf9f 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -117,10 +117,7 @@
   Pattern *P = new (Ctx) NamedPattern(decl);
   P->setType(ty);
   P->setImplicit();
-  P = new (Ctx) TypedPattern(P, TypeLoc::withoutLoc(ty));
-  P->setType(ty);
-  P->setImplicit();
-  return P;
+  return TypedPattern::createImplicit(Ctx, P, ty);
 }
 
 /// Create a var member for this struct, along with its pattern binding, and add
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 50aa2ee..6a05539 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4502,8 +4502,8 @@
     storage->setInvalid(true);
 
     Pattern *pattern =
-      new (Context) TypedPattern(new (Context) NamedPattern(storage),
-                                 TypeLoc::withoutLoc(ErrorType::get(Context)));
+      TypedPattern::createImplicit(Context, new (Context) NamedPattern(storage),
+                                   ErrorType::get(Context));
     PatternBindingEntry entry(pattern, /*EqualLoc*/ SourceLoc(),
                               /*Init*/ nullptr, /*InitContext*/ nullptr);
     auto binding = PatternBindingDecl::create(Context, StaticLoc,
@@ -5135,7 +5135,7 @@
           }
 
           TypedPattern *NewTP = new (Context) TypedPattern(PrevPat,
-                                                           TP->getTypeLoc());
+                                                           TP->getTypeRepr());
           NewTP->setPropagatedType();
           PBDEntries[i-1].setPattern(NewTP);
         }
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 4030b09..fa4a348 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -1271,6 +1271,7 @@
                                    Ctx.getIdentifier("tmp2"),
                                    Get);
   Tmp2VD->setType(VD->getType());
+  Tmp2VD->setInterfaceType(VD->getInterfaceType());
   Tmp2VD->setImplicit();
 
 
@@ -1297,9 +1298,8 @@
   }
 
   Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true);
-  Tmp2PBDPattern = new (Ctx) TypedPattern(Tmp2PBDPattern,
-                                          TypeLoc::withoutLoc(VD->getType()),
-                                          /*implicit*/true);
+  Tmp2PBDPattern =
+    TypedPattern::createImplicit(Ctx, Tmp2PBDPattern, VD->getType());
 
   auto *Tmp2PBD = PatternBindingDecl::createImplicit(
       Ctx, StaticSpellingKind::None, Tmp2PBDPattern, InitValue, Get,
@@ -1447,9 +1447,8 @@
   // Create the pattern binding decl for the storage decl.  This will get
   // default initialized using the protocol's initStorage() method.
   Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true);
-  PBDPattern = new (Context) TypedPattern(PBDPattern,
-                                  TypeLoc::withoutLoc(SubstStorageContextTy),
-                                  /*implicit*/true);
+  PBDPattern = TypedPattern::createImplicit(Context, PBDPattern,
+                                            SubstStorageContextTy);
   auto *PBD = PatternBindingDecl::createImplicit(
       Context, VD->getParentPatternBinding()->getStaticSpelling(), PBDPattern,
       InitStorageExpr, VD->getDeclContext(), /*VarLoc*/ VD->getLoc());
@@ -1740,9 +1739,7 @@
   // Create the pattern binding decl for the storage decl.  This will get
   // default initialized to nil.
   Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true);
-  PBDPattern = new (Context) TypedPattern(PBDPattern,
-                                          TypeLoc::withoutLoc(StorageTy),
-                                          /*implicit*/true);
+  PBDPattern = TypedPattern::createImplicit(Context, PBDPattern, StorageTy);
   auto *PBD = PatternBindingDecl::createImplicit(
       Context, StaticSpellingKind::None, PBDPattern, /*init*/ nullptr,
       VD->getDeclContext(), /*VarLoc*/ VD->getLoc());
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 09e635f..1ab14a8 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -221,7 +221,7 @@
   // generate: var indexVar
   Pattern *indexPat = new (C) NamedPattern(indexVar, /*implicit*/ true);
   indexPat->setType(intType);
-  indexPat = new (C) TypedPattern(indexPat, TypeLoc::withoutLoc(intType));
+  indexPat = TypedPattern::createImplicit(C, indexPat, intType);
   indexPat->setType(intType);
   auto *indexBind = PatternBindingDecl::createImplicit(
       C, StaticSpellingKind::None, indexPat, /*InitExpr*/ nullptr, funcDecl);
@@ -1105,9 +1105,7 @@
 
   Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
   hashValuePat->setType(intType);
-  hashValuePat
-    = new (C) TypedPattern(hashValuePat, TypeLoc::withoutLoc(intType),
-                           /*implicit*/ true);
+  hashValuePat = TypedPattern::createImplicit(C, hashValuePat, intType);
   hashValuePat->setType(intType);
 
   auto *patDecl = PatternBindingDecl::createImplicit(
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 8ff09fd..af92c8c 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -340,9 +340,7 @@
   Pattern *propPat = new (C) NamedPattern(propDecl, /*implicit*/ true);
   propPat->setType(propertyContextType);
 
-  propPat = new (C) TypedPattern(propPat,
-                                 TypeLoc::withoutLoc(propertyContextType),
-                                 /*implicit*/ true);
+  propPat = TypedPattern::createImplicit(C, propPat, propertyContextType);
   propPat->setType(propertyContextType);
 
   auto *pbDecl = PatternBindingDecl::createImplicit(
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index f4abb52..d83e1eb 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -699,7 +699,7 @@
   if (TP->hasType())
     return TP->getType()->hasError();
 
-  TypeLoc &TL = TP->getTypeLoc();
+  TypeLoc TL = TP->getTypeLoc();
   bool hadError = TC.validateType(TL, resolution, options);
 
   if (hadError) {
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 129b385..c887a7d 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -381,9 +381,11 @@
       return subPattern;
     }
 
-    auto result = new (getContext()) TypedPattern(subPattern.get(), TypeLoc(),
+    auto type = getType(typeID);
+    auto result = new (getContext()) TypedPattern(subPattern.get(),
+                                                  /*typeRepr*/nullptr,
                                                   isImplicit);
-    recordPatternType(result, getType(typeID));
+    recordPatternType(result, type);
     restoreOffset.reset();
     return result;
   }
diff --git a/test/ModuleInterface/private-stored-members.swift b/test/ModuleInterface/private-stored-members.swift
index 0512a42..c2f4936 100644
--- a/test/ModuleInterface/private-stored-members.swift
+++ b/test/ModuleInterface/private-stored-members.swift
@@ -1,43 +1,40 @@
 // RUN: %empty-directory(%t)
 
 // RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
-// RUN: %FileCheck %s < %t.swiftinterface
+// RUN: %FileCheck %s < %t.swiftinterface --check-prefix CHECK --check-prefix COMMON
 
 // RUN: %target-swift-frontend -emit-interface-path %t-resilient.swiftinterface -enable-resilience -emit-module -o /dev/null %s
-// RUN: %FileCheck %s --check-prefix RESILIENT < %t-resilient.swiftinterface
+// RUN: %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON < %t-resilient.swiftinterface
 
 // RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module
-// FIXME(rdar44144435): %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -emit-interface-path - | %FileCheck %s
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-interface-path - | %FileCheck %s --check-prefix CHECK --check-prefix COMMON
 
 // RUN: %target-swift-frontend -emit-module -o %t/TestResilient.swiftmodule -enable-resilience %t.swiftinterface -disable-objc-attr-requires-foundation-module
-// FIXME(rdar44144435): %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -enable-resilience -emit-interface-path - | %FileCheck %s
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-interface-path - | %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON
 
 
-// CHECK: struct MyStruct {{{$}}
-// RESILIENT: struct MyStruct {{{$}}
+// COMMON: struct MyStruct {{{$}}
 public struct MyStruct {
-// CHECK-NEXT: var publicVar: Int64{{$}}
-// RESILIENT-NEXT: var publicVar: Int64{{$}}
+// COMMON-NEXT: var publicVar: [[INT64:(Swift\.)?Int64]]{{$}}
   public var publicVar: Int64
 
-// CHECK-NEXT: let publicLet: Bool{{$}}
-// RESILIENT-NEXT: let publicLet: Bool{{$}}
+// COMMON-NEXT: let publicLet: [[BOOL:(Swift\.)?Bool]]{{$}}
   public let publicLet: Bool
 
-// CHECK-NEXT: internal var _: Int64{{$}}
-// RESILIENT-NOT: internal var _: Int64{{$}}
+// CHECK-NEXT: internal var _: [[INT64]]{{$}}
+// RESILIENT-NOT: internal var _: [[INT64]]{{$}}
   var internalVar: Int64
 
-// CHECK-NEXT: internal let _: Bool{{$}}
-// RESILIENT-NOT: internal let _: Bool{{$}}
+// CHECK-NEXT: internal let _: [[BOOL]]{{$}}
+// RESILIENT-NOT: internal let _: [[BOOL]]{{$}}
   let internalLet: Bool
 
-// CHECK-NEXT: private var _: Int64{{$}}
-// RESILIENT-NOT: private var _: Int64{{$}}
+// CHECK-NEXT: private var _: [[INT64]]{{$}}
+// RESILIENT-NOT: private var _: [[INT64]]{{$}}
   private var privateVar: Int64
 
-// CHECK-NEXT: private let _: Bool{{$}}
-// RESILIENT-NOT: private let _: Bool{{$}}
+// CHECK-NEXT: private let _: [[BOOL]]{{$}}
+// RESILIENT-NOT: private let _: [[BOOL]]{{$}}
   private let privateLet: Bool
 
 // CHECK-NOT: private var
@@ -50,39 +47,34 @@
 // RESILIENT-NOT: private static var
   private static var staticPrivateVar: Int64 = 0
 
-// CHECK-NEXT: var publicEndVar: Int64{{$}}
-// RESILIENT-NEXT: var publicEndVar: Int64{{$}}
+// COMMON: var publicEndVar: [[INT64]]{{$}}
   public var publicEndVar: Int64 = 0
 
-// CHECK: }{{$}}
-// RESILIENT: }{{$}}
+// COMMON: }{{$}}
 }
 
-// CHECK: class MyClass {{{$}}
-// RESILIENT: class MyClass {{{$}}
+// COMMON: class MyClass {{{$}}
 public class MyClass {
-// CHECK-NEXT: var publicVar: Int64{{$}}
-// RESILIENT-NEXT: var publicVar: Int64{{$}}
+// COMMON-NEXT: var publicVar: [[INT64]]{{$}}
   public var publicVar: Int64 = 0
 
-// CHECK-NEXT: let publicLet: Bool{{$}}
-// RESILIENT-NEXT: let publicLet: Bool{{$}}
+// COMMON-NEXT: let publicLet: [[BOOL]]{{$}}
   public let publicLet: Bool = true
 
-// CHECK-NEXT: internal var _: Int64{{$}}
-// RESILIENT-NOT: internal var _: Int64{{$}}
+// CHECK-NEXT: internal var _: [[INT64]]{{$}}
+// RESILIENT-NOT: internal var _: [[INT64]]{{$}}
   var internalVar: Int64 = 0
 
-// CHECK-NEXT: internal let _: Bool{{$}}
-// RESILIENT-NOT: internal let _: Bool{{$}}
+// CHECK-NEXT: internal let _: [[BOOL]]{{$}}
+// RESILIENT-NOT: internal let _: [[BOOL]]{{$}}
   let internalLet: Bool = true
 
-// CHECK-NEXT: private var _: Int64{{$}}
-// RESILIENT-NOT: private var _: Int64{{$}}
+// CHECK-NEXT: private var _: [[INT64]]{{$}}
+// RESILIENT-NOT: private var _: [[INT64]]{{$}}
   private var privateVar: Int64 = 0
 
-// CHECK-NEXT: private let _: Bool{{$}}
-// RESILIENT-NOT: private let _: Bool{{$}}
+// CHECK-NEXT: private let _: [[BOOL]]{{$}}
+// RESILIENT-NOT: private let _: [[BOOL]]{{$}}
   private let privateLet: Bool = true
 
 // CHECK-NOT: private var
@@ -95,12 +87,10 @@
 // RESILIENT-NOT: private static var
   private static var staticPrivateVar: Int64 = 0
 
-// CHECK-NEXT: var publicEndVar: Int64{{$}}
-// RESILIENT-NEXT: var publicEndVar: Int64{{$}}
+// COMMON: var publicEndVar: [[INT64]]{{$}}
   public var publicEndVar: Int64 = 0
 
   public init() {}
 
-// CHECK: }{{$}}
-// RESILIENT: }{{$}}
+// COMMON: }{{$}}
 }