Skip to content

Update the branch to build with Xcode 12.5 #37047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/swift/Runtime/Bincompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,18 @@ namespace bincompat {

/// Whether protocol conformance iteration should be reversed, to prefer
/// conformances from images that are later in the list over earlier ones.
/// Default is false starting with Swift 5.4.
bool workaroundProtocolConformanceReverseIteration();

/// Whether we should crash when we encounter a non-nullable Obj-C
/// reference with a null value as the source of a cast.
/// Default is true starting with Swift 5.4.
bool unexpectedObjCNullWhileCastingIsFatal();

/// Whether we should use the legacy semantics for casting nil optionals
/// to nested optionals
bool useLegacyOptionalNilInjection();

} // namespace bincompat

} // namespace runtime
Expand Down
80 changes: 79 additions & 1 deletion stdlib/public/runtime/Bincompat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,92 @@
//===----------------------------------------------------------------------===//

#include "swift/Runtime/Bincompat.h"
#include <stdint.h>

// If this is an Apple OS, use the Apple binary compatibility rules
#if __has_include(<mach-o/dyld_priv.h>)
#include <mach-o/dyld_priv.h>
#ifndef BINARY_COMPATIBILITY_APPLE
#define BINARY_COMPATIBILITY_APPLE 1
#endif
#else
#undef BINARY_COMPATIBILITY_APPLE
#endif

namespace swift {

namespace runtime {

namespace bincompat {

bool workaroundProtocolConformanceReverseIteration() { return false; }
// Should we mimic the old override behavior when scanning protocol conformance records?

// Old apps expect protocol conformances to override each other in a particular
// order. Starting with Swift 5.4, that order has changed as a result of
// significant performance improvements to protocol conformance scanning. If
// this returns `true`, the protocol conformance scan will do extra work to
// mimic the old override behavior.
bool workaroundProtocolConformanceReverseIteration() {
#if BINARY_COMPATIBILITY_APPLE
// If this is a newer Apple OS ...
if (__builtin_available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *)) {
const dyld_build_version_t spring_2021_os_versions = {0xffffffff, 0x007e50301};
// ... but the app was compiled before Spring 2021, use the legacy behavior.
return !dyld_program_sdk_at_least(spring_2021_os_versions);
} else {
return false; // Use new (non-legacy) behavior on old Apple OSes
}
#else
return false; // Never use the legacy behavior on non-Apple OSes
#endif
}

// Should the dynamic cast operation crash when it sees
// a non-nullable Obj-C pointer with a null value?

// Obj-C does not strictly enforce non-nullability in all cases, so it is
// possible for Obj-C code to pass null pointers into Swift code even when
// declared non-nullable. Such null pointers can lead to undefined behavior
// later on. Starting in Swift 5.4, these unexpected null pointers are fatal
// runtime errors, but this is selectively disabled for old apps.
bool unexpectedObjCNullWhileCastingIsFatal() {
#if BINARY_COMPATIBILITY_APPLE
// If this is a new enough Apple OS ...
if (__builtin_available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *)) {
const dyld_build_version_t spring_2021_os_versions = {0xffffffff, 0x007e50301};
// ... use strict behavior for apps compiled on or after Spring 2021.
return dyld_program_sdk_at_least(spring_2021_os_versions);
} else {
return false; // Use permissive behavior on old Apple OS
}
#else
return true; // Always use the strict behavior on non-Apple OSes
#endif
}

// Should casting a nil optional to another optional
// use the legacy semantics?

// For consistency, starting with Swift 5.4, casting Optional<Int> to
// Optional<Optional<Int>> always wraps the source in another layer
// of Optional.
// Earlier versions of the Swift runtime did not do this if the source
// optional was nil. In that case, the outer target optional would be
// set to nil.
bool useLegacyOptionalNilInjection() {
#if BINARY_COMPATIBILITY_APPLE
// If this is a new enough Apple OS ...
if (__builtin_available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *)) {
const dyld_build_version_t spring_2021_os_versions = {0xffffffff, 0x007e50301};
// It's using Spring 2021 or later SDK, so don't use the legacy behavior.
return !dyld_program_sdk_at_least(spring_2021_os_versions);
} else {
return true; // Use the legacy behavior on old Apple OS
}
#else
return false; // Always use the 5.4 behavior on non-Apple OSes
#endif
}

} // namespace bincompat

Expand Down
19 changes: 10 additions & 9 deletions stdlib/public/runtime/DynamicCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "SwiftHashableSupport.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/Basic/Lazy.h"
#include "swift/Runtime/Bincompat.h"
#include "swift/Runtime/Casting.h"
#include "swift/Runtime/Config.h"
#include "swift/Runtime/ExistentialContainer.h"
Expand Down Expand Up @@ -110,12 +111,6 @@ extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(Sh);
/// Nominal type descriptor for Swift.String.
extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(SS);

// If this returns `true`, then we will call `fatalError` when we encounter a
// null reference in a storage locaation whose type does not allow null.
static bool unexpectedNullIsFatal() {
return true; // Placeholder for an upcoming check.
}

/// This issues a fatal error or warning if the srcValue contains a null object
/// reference. It is used when the srcType is a non-nullable reference type, in
/// which case it is dangerous to continue with a null reference. The null
Expand All @@ -134,7 +129,7 @@ static HeapObject * getNonNullSrcObject(OpaqueValue *srcValue,
const char *msg = "Found unexpected null pointer value"
" while trying to cast value of type '%s' (%p)"
" to '%s' (%p)%s\n";
if (unexpectedNullIsFatal()) {
if (runtime::bincompat::unexpectedObjCNullWhileCastingIsFatal()) {
// By default, Swift 5.4 and later issue a fatal error.
swift::fatalError(/* flags = */ 0, msg,
srcTypeName.c_str(), srcType,
Expand Down Expand Up @@ -1044,7 +1039,7 @@ initializeToNilAtDepth(OpaqueValue *destLocation, const Metadata *destType, int
}

static void
copyNil(OpaqueValue *destLocation, const Metadata *destType, const Metadata *srcType)
copyNilPreservingDepth(OpaqueValue *destLocation, const Metadata *destType, const Metadata *srcType)
{
assert(srcType->getKind() == MetadataKind::Optional);
assert(destType->getKind() == MetadataKind::Optional);
Expand Down Expand Up @@ -1087,7 +1082,13 @@ tryCastUnwrappingOptionalBoth(
srcValue, /*emptyCases=*/1);
auto sourceIsNil = (sourceEnumCase != 0);
if (sourceIsNil) {
copyNil(destLocation, destType, srcType);
if (runtime::bincompat::useLegacyOptionalNilInjection()) {
auto destInnerType = cast<EnumMetadata>(destType)->getGenericArgs()[0];
// Set .none at the outer level
destInnerType->vw_storeEnumTagSinglePayload(destLocation, 1, 1);
} else {
copyNilPreservingDepth(destLocation, destType, srcType);
}
return DynamicCastResult::SuccessViaCopy; // nil was essentially copied to dest
} else {
auto destEnumType = cast<EnumMetadata>(destType);
Expand Down
8 changes: 7 additions & 1 deletion test/Casting/Casts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ CastsTests.test("Dynamic cast to ObjC protocol") {
#endif

// SR-6126
if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) {
if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) {
CastsTests.test("Nil handling for Optionals and Arrays (SR-6126)") {
func check(_ arg: Int??) -> String {
switch arg {
Expand Down Expand Up @@ -621,6 +621,7 @@ CastsTests.test("NSNull?.none -> Any? should set outer nil") {
}
#endif

if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) {
CastsTests.test("Int??.some(nil) => Int??? should inject naturally") {
let a: Int?? = .some(nil)
let b = a as? Int???
Expand All @@ -629,7 +630,9 @@ CastsTests.test("Int??.some(nil) => Int??? should inject naturally") {
let e = d!
expectNil(e)
}
}

if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) {
CastsTests.test("Int??.some(nil) => String??? should inject naturally") {
let a: Int?? = .some(nil)
let b = runtimeCast(a, to: String???.self)
Expand All @@ -638,7 +641,9 @@ CastsTests.test("Int??.some(nil) => String??? should inject naturally") {
let e = d!
expectNil(e)
}
}

if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) {
CastsTests.test("Int??.some(nil) => Any??? should inject naturally") {
let a: Int?? = .some(nil)
let b = a as? Any???
Expand All @@ -647,6 +652,7 @@ CastsTests.test("Int??.some(nil) => Any??? should inject naturally") {
let e = d!
expectNil(e)
}
}

#if _runtime(_ObjC)
CastsTests.test("NSString -> String fast path") {
Expand Down
7 changes: 1 addition & 6 deletions test/Runtime/protocol_conformance_collision.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

// UNSUPPORTED: use_os_stdlib

// REQUIRES: rdar73049300

import Accelerate
import Foundation
import StdlibUnittest
Expand Down Expand Up @@ -48,10 +46,7 @@ func firstHashValue(_ x: P) -> Int {
}

let osHasWorkaround: Bool
// These are deliberately NOT version 9999, as we don't want to hit the special
// case where development runtimes always return true for 9999. This check needs
// to be false until real version numbers are put in.
if #available(macOS 99990, iOS 99990, tvOS 99990, watchOS 99990, *) {
if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) {
osHasWorkaround = true
} else {
osHasWorkaround = false
Expand Down
2 changes: 1 addition & 1 deletion utils/find-overlay-deps-closure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
set -o pipefail
set -e

OVERLAY_NAME_ALTERNATION="AppKit|AssetsLibrary|AVFoundation|CallKit|CloudKit|Compression|Contacts|CoreAudio|CoreData|CoreGraphics|CoreImage|CoreLocation|CoreMedia|CryptoTokenKit|dispatch|Foundation|GameplayKit|GLKit|HomeKit|IOKit|Intents|MapKit|objc|OpenCL|os|Photos|QuartzCore|SafariServices|SceneKit|simd|SpriteKit|UIKit|WatchKit|XCTest|xpc"
OVERLAY_NAME_ALTERNATION="AppKit|AssetsLibrary|AVFoundation|CallKit|CloudKit|Compression|Contacts|CoreAudio|CoreData|CoreGraphics|CoreImage|CoreLocation|CoreMedia|CoreML|CryptoTokenKit|dispatch|Foundation|GameplayKit|GLKit|HomeKit|IOKit|Intents|MapKit|objc|OpenCL|os|Photos|QuartzCore|SafariServices|SceneKit|simd|SpriteKit|UIKit|WatchKit|XCTest|xpc"

function find_deps() {
local OVERLAY_ARG=$1
Expand Down