Skip to content

Commit a6ae2d7

Browse files
authored
Hack: Force UIEdgeInsets.zero to always come from the SDK (#17122)
...instead of relying on the one in the overlay in pre-4.2 versions of Swift. This caused crashes in deserialization, which (deliberately) doesn't respect availability. There are three changes here: - Remove UIEdgeInsets.zero and UIOffset.zero from the UIKit overlay. - Always use the 4.2 name for UIEdgeInsetsZero and UIOffsetZero from the underlying UIKit framework. (This is the nested name.) - Ignore the unavailability messages for those two constants in pre-4.2 Swift, since we're now relying on them being present. The latter two, the compiler changes, can go away once UIKit's API notes no longer specify different pre-4.2 behavior, but meanwhile we need to keep compatibility with the SDKs released in Xcode 10b1. https://bugs.swift.org/browse/SR-7879
1 parent 25249e6 commit a6ae2d7

File tree

5 files changed

+40
-16
lines changed

5 files changed

+40
-16
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7341,6 +7341,21 @@ getSwiftNameFromClangName(StringRef replacement) {
73417341
return SwiftContext.AllocateCopy(StringRef(renamed));
73427342
}
73437343

7344+
bool importer::isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl) {
7345+
// FIXME: Once UIKit removes the "nonswift" availability in their versioned
7346+
// API notes, this workaround can go away.
7347+
auto *constant = dyn_cast<clang::VarDecl>(decl);
7348+
if (!constant)
7349+
return false;
7350+
7351+
clang::DeclarationName name = constant->getDeclName();
7352+
const clang::IdentifierInfo *ident = name.getAsIdentifierInfo();
7353+
if (!ident)
7354+
return false;
7355+
7356+
return ident->isStr("UIEdgeInsetsZero") || ident->isStr("UIOffsetZero");
7357+
}
7358+
73447359
/// Import Clang attributes as Swift attributes.
73457360
void ClangImporter::Implementation::importAttributes(
73467361
const clang::NamedDecl *ClangDecl,
@@ -7405,6 +7420,11 @@ void ClangImporter::Implementation::importAttributes(
74057420

74067421
// Is this our special "availability(swift, unavailable)" attribute?
74077422
if (Platform == "swift") {
7423+
// FIXME: Until Apple gets a chance to update UIKit's API notes, ignore
7424+
// the Swift-unavailability for certain properties.
7425+
if (isSpecialUIKitStructZeroProperty(ClangDecl))
7426+
continue;
7427+
74087428
auto replacement = avail->getReplacement();
74097429
StringRef swiftReplacement = "";
74107430
if (!replacement.empty())

lib/ClangImporter/ImportName.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,12 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
616616

617617
// Handle versioned API notes for Swift 3 and later. This is the common case.
618618
if (version > ImportNameVersion::swift2()) {
619+
// FIXME: Until Apple gets a chance to update UIKit's API notes, always use
620+
// the new name for certain properties.
621+
if (auto *namedDecl = dyn_cast<clang::NamedDecl>(decl))
622+
if (importer::isSpecialUIKitStructZeroProperty(namedDecl))
623+
version = ImportNameVersion::swift4_2();
624+
619625
const auto *activeAttr = decl->getAttr<clang::SwiftNameAttr>();
620626
const clang::SwiftNameAttr *result = activeAttr;
621627
clang::VersionTuple bestSoFar;

lib/ClangImporter/ImporterImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,10 @@ namespace importer {
13831383
/// Whether we should suppress the import of the given Clang declaration.
13841384
bool shouldSuppressDeclImport(const clang::Decl *decl);
13851385

1386+
/// Identifies certain UIKit constants that used to have overlay equivalents,
1387+
/// but are now renamed using the swift_name attribute.
1388+
bool isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl);
1389+
13861390
/// Finds a particular kind of nominal by looking through typealiases.
13871391
template <typename T>
13881392
static T *dynCastIgnoringCompatibilityAlias(Decl *D) {

stdlib/public/SDK/UIKit/UIKit.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,6 @@ import _SwiftUIKitOverlayShims
2121
// UIGeometry
2222
//===----------------------------------------------------------------------===//
2323

24-
extension UIEdgeInsets {
25-
@available(swift, obsoleted: 4.2) // in 4.2 it is provided by the apinotes
26-
public static var zero: UIEdgeInsets {
27-
@_transparent // @fragile
28-
get { return UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) }
29-
}
30-
}
31-
32-
extension UIOffset {
33-
@available(swift, obsoleted: 4.2) // in 4.2 it is provided by the apinotes
34-
public static var zero: UIOffset {
35-
@_transparent // @fragile
36-
get { return UIOffset(horizontal: 0.0, vertical: 0.0) }
37-
}
38-
}
39-
4024
extension UIEdgeInsets : Equatable {
4125
@_transparent // @fragile
4226
public static func == (lhs: UIEdgeInsets, rhs: UIEdgeInsets) -> Bool {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -emit-module-path %t/main4.swiftmodule -swift-version 4 %s
3+
// RUN: %target-build-swift -emit-module-path %t/main4_2.swiftmodule -swift-version 4.2 %s
4+
5+
// REQUIRES: OS=ios
6+
7+
import UIKit
8+
9+
public func testInsets(_: UIEdgeInsets = .zero) {}
10+
public func testOffsets(_: UIOffset = .zero) {}

0 commit comments

Comments
 (0)