Merge pull request #12941 from rjmccall/block-to-func-formal-bridging

Bridge the formal block type in a block-to-func thunk
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index a832224..5c2db0f 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -81,7 +81,9 @@
   # HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM
   # into swift.  The use of this flag pollutes all targets, and we are not able
   # to remove it on a per-target basis which breaks cross-compilation.
-  string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+  if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+    string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+  endif()
 
   set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
   string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" PACKAGE_VERSION_MAJOR
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index ab1b13a..5be9bbc 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2225,6 +2225,10 @@
   getFormalAccessScope(const DeclContext *useDC = nullptr,
                        bool respectVersionedAttr = false) const;
 
+
+  /// Copy the formal access level and @_versioned attribute from source.
+  void copyFormalAccessAndVersionedAttrFrom(ValueDecl *source);
+
   /// Returns the access level that actually controls how a declaration should
   /// be emitted and may be used.
   ///
@@ -3402,7 +3406,7 @@
 
   /// Synthesize implicit, trivial destructor, add it to this ClassDecl
   /// and return it.
-  DestructorDecl *addImplicitDestructor();
+  void addImplicitDestructor();
 
   /// Determine whether this class inherits the convenience initializers
   /// from its superclass.
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 483107a..4233676 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2184,6 +2184,19 @@
   llvm_unreachable("unknown access level");
 }
 
+void ValueDecl::copyFormalAccessAndVersionedAttrFrom(ValueDecl *source) {
+  if (!hasAccess()) {
+    setAccess(source->getFormalAccess());
+  }
+
+  // Inherit the @_versioned attribute.
+  if (source->getAttrs().hasAttribute<VersionedAttr>()) {
+    auto &ctx = getASTContext();
+    auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
+    getAttrs().add(clonedAttr);
+  }
+}
+
 Type TypeDecl::getDeclaredInterfaceType() const {
   if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
     return NTD->getDeclaredInterfaceType();
@@ -2689,9 +2702,9 @@
   return cast<DestructorDecl>(results.front());
 }
 
-DestructorDecl *ClassDecl::addImplicitDestructor() {
+void ClassDecl::addImplicitDestructor() {
   if (hasDestructor() || isInvalid())
-    return nullptr;
+    return;
 
   auto *selfDecl = ParamDecl::createSelf(getLoc(), this);
 
@@ -2699,12 +2712,36 @@
   auto *DD = new (ctx) DestructorDecl(getLoc(), selfDecl, this);
 
   DD->setImplicit();
+  DD->setValidationStarted();
 
   // Create an empty body for the destructor.
   DD->setBody(BraceStmt::create(ctx, getLoc(), { }, getLoc(), true));
   addMember(DD);
   setHasDestructor();
-  return DD;
+
+  // Propagate access control and versioned-ness.
+  DD->copyFormalAccessAndVersionedAttrFrom(this);
+
+  // Wire up generic environment of DD.
+  DD->setGenericEnvironment(getGenericEnvironmentOfContext());
+
+  // Mark DD as ObjC, as all dtors are.
+  DD->setIsObjC(true);
+  recordObjCMethod(DD);
+
+  // Assign DD the interface type (Self) -> () -> ()
+  ArrayRef<AnyFunctionType::Param> noParams;
+  AnyFunctionType::ExtInfo info;
+  Type selfTy = selfDecl->getInterfaceType();
+  Type voidTy = TupleType::getEmpty(ctx);
+  Type funcTy = FunctionType::get(noParams, voidTy, info);
+  if (auto *sig = DD->getGenericSignature()) {
+    DD->setInterfaceType(
+      GenericFunctionType::get(sig, {selfTy}, funcTy, info));
+  } else {
+    DD->setInterfaceType(
+      FunctionType::get({selfTy}, funcTy, info));
+  }
 }
 
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 40c58a4..3982bd6 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4254,7 +4254,7 @@
         result->setCheckedInheritanceClause();
         result->setAddedImplicitInitializers(); // suppress all initializers
         addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
-        Impl.registerExternalDecl(result);
+        result->addImplicitDestructor();
         return result;
       };
 
@@ -4274,7 +4274,6 @@
         auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
                                       nsObjectDecl->getDeclContext());
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
-        result->addImplicitDestructor();
         return result;
       }
 
@@ -4359,7 +4358,6 @@
         markMissingSwiftDecl(result);
       if (decl->getAttr<clang::ObjCRuntimeVisibleAttr>()) {
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
-        result->addImplicitDestructor();
       }
 
       // If this Objective-C class has a supertype, import it.
@@ -4392,7 +4390,6 @@
       if (decl->getName() == "OS_object" ||
           decl->getName() == "OS_os_log") {
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
-        result->addImplicitDestructor();
       }
 
       // If the superclass is runtime-only, our class is also. This only
@@ -4420,9 +4417,7 @@
 #include "InferredAttributes.def"
 
       result->setMemberLoader(&Impl, 0);
-
-      // Pass the class to the type checker to create an implicit destructor.
-      Impl.registerExternalDecl(result);
+      result->addImplicitDestructor();
 
       return result;
     }
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 38d6a0d..882d537 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2205,9 +2205,3 @@
 
   return ctor;
 }
-
-void TypeChecker::addImplicitDestructor(ClassDecl *CD) {
-  auto *DD = CD->addImplicitDestructor();
-  if (DD)
-    typeCheckDecl(DD, /*isFirstPass=*/true);
-}
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 72124cc..fa3707a 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -671,7 +671,7 @@
                                     FunctionType::ExtInfo());
   }
   eqDecl->setInterfaceType(interfaceTy);
-  copyFormalAccess(eqDecl, typeDecl);
+  eqDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -1090,7 +1090,7 @@
                                       AnyFunctionType::ExtInfo());
 
   getterDecl->setInterfaceType(interfaceType);
-  copyFormalAccess(getterDecl, typeDecl);
+  getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -1106,7 +1106,7 @@
   hashValueDecl->setInterfaceType(intType);
   hashValueDecl->makeComputed(SourceLoc(), getterDecl,
                               nullptr, nullptr, SourceLoc());
-  copyFormalAccess(hashValueDecl, typeDecl);
+  hashValueDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
   hashValuePat->setType(intType);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index c3fb22a..853e9ed 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -349,7 +349,7 @@
   }
   initDecl->setInterfaceType(allocIfaceType);
   initDecl->setInitializerInterfaceType(initIfaceType);
-  copyFormalAccess(initDecl, enumDecl);
+  initDecl->copyFormalAccessAndVersionedAttrFrom(enumDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 0beaf5f..f2e6d36 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -251,7 +251,7 @@
     interfaceType = FunctionType::get({selfParam}, interfaceType,
                                       FunctionType::ExtInfo());
   getterDecl->setInterfaceType(interfaceType);
-  copyFormalAccess(getterDecl, typeDecl);
+  getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -281,7 +281,7 @@
   propDecl->setImplicit();
   propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
                          SourceLoc());
-  copyFormalAccess(propDecl, typeDecl);
+  propDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
   propDecl->setInterfaceType(propertyInterfaceType);
 
   // If this is supposed to be a final property, mark it as such.
@@ -304,14 +304,3 @@
 
   return {propDecl, pbDecl};
 }
-
-void DerivedConformance::copyFormalAccess(ValueDecl *dest, ValueDecl *source) {
-  dest->setAccess(source->getFormalAccess());
-
-  // Inherit the @_versioned attribute.
-  if (source->getAttrs().hasAttribute<VersionedAttr>()) {
-    auto &ctx = source->getASTContext();
-    auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
-    dest->getAttrs().add(clonedAttr);
-  }
-}
diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h
index 0e6ab8b..2457971 100644
--- a/lib/Sema/DerivedConformances.h
+++ b/lib/Sema/DerivedConformances.h
@@ -185,9 +185,6 @@
 /// Build a reference to the 'self' decl of a derived function.
 DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
 
-/// Copy access from the source decl to the destination decl.
-void copyFormalAccess(ValueDecl *dest, ValueDecl *source);
-
 }
   
 }
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 9070037..62f9cb5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -4638,7 +4638,7 @@
     if (!IsFirstPass)
       TC.addImplicitConstructors(CD);
 
-    TC.addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
 
     if (!IsFirstPass && !CD->isInvalid())
       TC.checkConformancesInContext(CD, CD);
@@ -7213,13 +7213,7 @@
            && "Decl parsing must prevent destructors outside of types!");
 
     TC.checkDeclAttributesEarly(DD);
-    if (!DD->hasAccess()) {
-      DD->setAccess(enclosingClass->getFormalAccess());
-    }
-
-    if (enclosingClass->getAttrs().hasAttribute<VersionedAttr>()) {
-      DD->getAttrs().add(new (TC.Context) VersionedAttr(/*implicit=*/true));
-    }
+    DD->copyFormalAccessAndVersionedAttrFrom(enclosingClass);
 
     configureImplicitSelf(TC, DD);
 
@@ -7963,7 +7957,7 @@
   // class, you shouldn't have to know what the vtable layout is.
   if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
     TC.addImplicitConstructors(CD);
-    TC.addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
   }
 
   // validateDeclForNameLookup will not trigger an immediate full
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index b5d3c2f..b75df46 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -69,7 +69,7 @@
     addImplicitStructConformances(SD);
   }
   if (auto CD = dyn_cast<ClassDecl>(decl)) {
-    addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
   }
   if (auto ED = dyn_cast<EnumDecl>(decl)) {
     addImplicitEnumConformances(ED);
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 1a22724..fa1ecae 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1511,10 +1511,6 @@
   /// struct or class.
   void addImplicitConstructors(NominalTypeDecl *typeDecl);
 
-  /// \brief Add an implicitly-defined destructor, if there is no
-  /// user-provided destructor.
-  void addImplicitDestructor(ClassDecl *CD);
-
   /// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an
   /// imported NS_OPTIONS struct.
   void addImplicitStructConformances(StructDecl *ED);
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 5ca4aa6..0918a5b 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -1277,9 +1277,18 @@
     DeclBaseName name = getDeclBaseName(IID);
     pathTrace.addValue(name);
 
-    Type filterTy = getType(TID);
-    if (!isType)
+    Type filterTy;
+    if (!isType) {
+      auto maybeType = getTypeChecked(TID);
+      if (!maybeType) {
+        // FIXME: Don't throw away the inner error's information.
+        llvm::consumeError(maybeType.takeError());
+        return llvm::make_error<XRefError>("couldn't decode type",
+                                           pathTrace, name);
+      }
+      filterTy = maybeType.get();
       pathTrace.addType(filterTy);
+    }
 
     baseModule->lookupQualified(ModuleType::get(baseModule), name,
                                 NL_QualifiedDefault | NL_KnownNoDependency,
@@ -1482,9 +1491,18 @@
 
       pathTrace.addValue(memberName);
 
-      Type filterTy = getType(TID);
-      if (!isType)
+      Type filterTy;
+      if (!isType) {
+        auto maybeType = getTypeChecked(TID);
+        if (!maybeType) {
+          // FIXME: Don't throw away the inner error's information.
+          llvm::consumeError(maybeType.takeError());
+          return llvm::make_error<XRefError>("couldn't decode type",
+                                             pathTrace, memberName);
+        }
+        filterTy = maybeType.get();
         pathTrace.addType(filterTy);
+      }
 
       if (values.size() != 1) {
         return llvm::make_error<XRefError>("multiple matching base values",
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index 260d04e..6aa7709 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -1,3 +1,6 @@
+# HACK: Force this library to build with undefined symbols.
+string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+
 # libswiftRemoteMirror.dylib should not have runtime dependencies; it's
 # always built as a shared library.
 if(SWIFT_BUILD_DYNAMIC_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 3861ca5..79c021f 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -559,11 +559,11 @@
     // in angles in the wrong quadrant if users aren't careful.  This is
     // not a problem for Double or Float80, as pi rounds down in both of
     // those formats.
-    return Float(0x1.921fb4p1)
+    return 0x1.921fb4p1
 %elif bits == 64:
-    return Double(0x1.921fb54442d18p1)
+    return 0x1.921fb54442d18p1
 %elif bits == 80:
-    return Float80(0x1.921fb54442d1846ap1)
+    return 0x1.921fb54442d1846ap1
 %end
   }
 
diff --git a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
index 7bf9c7a..6eaf68c 100644
--- a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
+++ b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
@@ -115,3 +115,22 @@
 //- (nonnull instancetype)initWithValue:(long)value;
 #endif
 @end
+
+
+#if !BAD
+struct BoxedInt {
+  int value;
+};
+#endif
+
+@interface MethodWithDisappearingType : Object
+#if !BAD
+- (struct BoxedInt)boxItUp;
+#endif
+@end
+
+@interface InitializerWithDisappearingType : Object
+#if !BAD
+- (nonnull instancetype)initWithBoxedInt:(struct BoxedInt)box;
+#endif
+@end
diff --git a/test/Serialization/Recovery/overrides.swift b/test/Serialization/Recovery/overrides.swift
index c0b7b25..486f6c0 100644
--- a/test/Serialization/Recovery/overrides.swift
+++ b/test/Serialization/Recovery/overrides.swift
@@ -311,4 +311,33 @@
 // CHECK-RECOVERY-NEXT: /* placeholder for init(value:) */
 // CHECK-RECOVERY-NEXT: {{^}$}}
 
+public class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+  public override func boxItUp() -> BoxedInt { fatalError() }
+}
+
+// CHECK-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-NEXT: override func boxItUp() -> BoxedInt
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
+public class E2_InitializerStub : InitializerWithDisappearingType {
+  public init(unrelatedValue: Int) { fatalError() }
+}
+
+// CHECK-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-NEXT: init(unrelatedValue: Int)
+// CHECK-NEXT: init(boxedInt box: BoxedInt)
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init(unrelatedValue: Int)
+// CHECK-RECOVERY-NEXT: /* placeholder for init(boxedInt:) */
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
 #endif // TEST