Skip to content

Re-apply "Make all CF types Equatable and Hashable." #4568

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
May 8, 2017
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ CHANGELOG
Swift 4.0
---------

* Core Foundation types implicitly conform to Hashable (and Equatable), using
CFHash and CFEqual as the implementation. This change applies even to "Swift
3 mode", so if you were previously adding this conformance yourself, use
`#if swift(>=3.2)` to restrict the extension to Swift 3.1 and below.
([SR-2388](https://bugs.swift.org/browse/SR-2388))

* [SE-0156][]

Protocol composition types can now contain one or more class type terms,
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/KnownIdentifiers.def
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ IDENTIFIER(container)
IDENTIFIER(CoreGraphics)
IDENTIFIER(CoreMedia)
IDENTIFIER(CGFloat)
IDENTIFIER(CoreFoundation)
IDENTIFIER(CVarArg)
IDENTIFIER(Darwin)
IDENTIFIER(dealloc)
Expand Down
4 changes: 3 additions & 1 deletion include/swift/AST/KnownProtocols.def
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,17 @@ PROTOCOL(Comparable)
PROTOCOL(Error)
PROTOCOL_(ErrorCodeProtocol)
PROTOCOL(OptionSet)

PROTOCOL_(BridgedNSError)
PROTOCOL_(BridgedStoredNSError)
PROTOCOL_(CFObject)
PROTOCOL_(SwiftNewtypeWrapper)
PROTOCOL(CodingKey)
PROTOCOL(Encodable)
PROTOCOL(Decodable)

PROTOCOL_(ObjectiveCBridgeable)
PROTOCOL_(DestructorSafeContainer)
PROTOCOL_(SwiftNewtypeWrapper)

EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByArrayLiteral)
EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByBooleanLiteral)
Expand Down
33 changes: 18 additions & 15 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,23 +761,26 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
// Find all of the declarations with this name in the appropriate module.
SmallVector<ValueDecl *, 1> results;

// _BridgedNSError, _BridgedStoredNSError, and _ErrorCodeProtocol
// are in the Foundation module.
if (kind == KnownProtocolKind::BridgedNSError ||
kind == KnownProtocolKind::BridgedStoredNSError ||
kind == KnownProtocolKind::ErrorCodeProtocol) {
ModuleDecl *foundation =
const_cast<ASTContext *>(this)->getLoadedModule(Id_Foundation);
if (!foundation)
return nullptr;

auto identifier = getIdentifier(getProtocolName(kind));
foundation->lookupValue({ }, identifier, NLKind::UnqualifiedLookup,
results);
} else {
lookupInSwiftModule(getProtocolName(kind), results);
const ModuleDecl *M;
switch (kind) {
case KnownProtocolKind::BridgedNSError:
case KnownProtocolKind::BridgedStoredNSError:
case KnownProtocolKind::ErrorCodeProtocol:
M = getLoadedModule(Id_Foundation);
break;
case KnownProtocolKind::CFObject:
M = getLoadedModule(Id_CoreFoundation);
break;
default:
M = getStdlibModule();
break;
}

if (!M)
return nullptr;
M->lookupValue({ }, getIdentifier(getProtocolName(kind)),
NLKind::UnqualifiedLookup, results);

for (auto result : results) {
if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
Impl.KnownProtocols[index] = protocol;
Expand Down
29 changes: 18 additions & 11 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1186,17 +1186,19 @@ createValueConstructor(ClangImporter::Implementation &Impl,
return constructor;
}

static void populateInheritedTypes(ClangImporter::Implementation &Impl,
NominalTypeDecl *nominal,
ArrayRef<ProtocolDecl *> protocols) {
static void populateInheritedTypes(NominalTypeDecl *nominal,
ArrayRef<ProtocolDecl *> protocols,
Type superclass = Type()) {
SmallVector<TypeLoc, 4> inheritedTypes;
inheritedTypes.resize(protocols.size());
for_each(MutableArrayRef<TypeLoc>(inheritedTypes),
ArrayRef<ProtocolDecl *>(protocols),
if (superclass)
inheritedTypes.push_back(TypeLoc::withoutLoc(superclass));
inheritedTypes.resize(protocols.size() + (superclass ? 1 : 0));
for_each(MutableArrayRef<TypeLoc>(inheritedTypes).drop_front(superclass?1:0),
protocols,
[](TypeLoc &tl, ProtocolDecl *proto) {
tl = TypeLoc::withoutLoc(proto->getDeclaredType());
});
nominal->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
nominal->setInherited(nominal->getASTContext().AllocateCopy(inheritedTypes));
nominal->setCheckedInheritanceClause();
}

Expand All @@ -1206,7 +1208,7 @@ addProtocolsToStruct(ClangImporter::Implementation &Impl,
StructDecl *structDecl,
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
ArrayRef<ProtocolDecl *> protocols) {
populateInheritedTypes(Impl, structDecl, protocols);
populateInheritedTypes(structDecl, protocols);

// Note synthesized protocols
for (auto kind : synthesizedProtocolAttrs)
Expand Down Expand Up @@ -4693,9 +4695,14 @@ SwiftDeclConverter::importCFClassType(const clang::TypedefNameDecl *decl,
addObjCAttribute(theClass, None);
Impl.registerExternalDecl(theClass);

SmallVector<ProtocolDecl *, 4> protocols;
theClass->getImplicitProtocols(protocols);
addObjCProtocolConformances(theClass, protocols);
auto *cfObjectProto =
Impl.SwiftContext.getProtocol(KnownProtocolKind::CFObject);
if (cfObjectProto) {
populateInheritedTypes(theClass, cfObjectProto, superclass);
auto *attr = new (Impl.SwiftContext) SynthesizedProtocolAttr(
KnownProtocolKind::CFObject);
theClass->getAttrs().add(attr);
}

// Look for bridging attributes on the clang record. We can
// just check the most recent redeclaration, which will inherit
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5533,6 +5533,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
case KnownProtocolKind::OptionSet:
case KnownProtocolKind::BridgedNSError:
case KnownProtocolKind::BridgedStoredNSError:
case KnownProtocolKind::CFObject:
case KnownProtocolKind::ErrorCodeProtocol:
case KnownProtocolKind::ExpressibleByBuiltinConstStringLiteral:
case KnownProtocolKind::ExpressibleByBuiltinConstUTF16StringLiteral:
Expand Down
95 changes: 69 additions & 26 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1360,39 +1360,82 @@ bool WitnessChecker::findBestWitness(
unsigned &numViable,
unsigned &bestIdx,
bool &doNotDiagnoseMatches) {
auto witnesses = lookupValueWitnesses(requirement, ignoringNames);
enum Attempt {
Regular,
OperatorsFromOverlay,
Done
};

// Match each of the witnesses to the requirement.
bool anyFromUnconstrainedExtension = false;
bool anyFromUnconstrainedExtension;
numViable = 0;
bestIdx = 0;

for (auto witness : witnesses) {
// Don't match anything in a protocol.
// FIXME: When default implementations come along, we can try to match
// these when they're default implementations coming from another
// (unrelated) protocol.
if (isa<ProtocolDecl>(witness->getDeclContext())) {
continue;
}

if (!witness->hasInterfaceType())
TC.validateDecl(witness);
for (Attempt attempt = Regular; numViable == 0 && attempt != Done;
attempt = static_cast<Attempt>(attempt + 1)) {
SmallVector<ValueDecl *, 4> witnesses;
switch (attempt) {
case Regular:
witnesses = lookupValueWitnesses(requirement, ignoringNames);
break;
case OperatorsFromOverlay: {
// If we have a Clang declaration, the matching operator might be in the
// overlay for that module.
if (!requirement->isOperator())
continue;

auto match = matchWitness(TC, Proto, conformance, DC,
requirement, witness, reqEnvironment);
if (match.isViable()) {
++numViable;
bestIdx = matches.size();
} else if (match.Kind == MatchKind::WitnessInvalid) {
doNotDiagnoseMatches = true;
auto *clangModule =
dyn_cast<ClangModuleUnit>(DC->getModuleScopeContext());
if (!clangModule)
continue;

DeclContext *overlay = clangModule->getAdapterModule();
if (!overlay)
continue;

auto lookupOptions = defaultUnqualifiedLookupOptions;
lookupOptions |= NameLookupFlags::KnownPrivate;
auto lookup = TC.lookupUnqualified(overlay, requirement->getName(),
SourceLoc(), lookupOptions);
for (auto candidate : lookup)
witnesses.push_back(candidate.Decl);
break;
}
case Done:
llvm_unreachable("should have exited loop");
}

// Match each of the witnesses to the requirement.
anyFromUnconstrainedExtension = false;
bestIdx = 0;

for (auto witness : witnesses) {
// Don't match anything in a protocol.
// FIXME: When default implementations come along, we can try to match
// these when they're default implementations coming from another
// (unrelated) protocol.
if (isa<ProtocolDecl>(witness->getDeclContext())) {
continue;
}

if (auto *ext = dyn_cast<ExtensionDecl>(match.Witness->getDeclContext()))
if (!ext->isConstrainedExtension() && ext->getAsProtocolExtensionContext())
anyFromUnconstrainedExtension = true;
if (!witness->hasInterfaceType())
TC.validateDecl(witness);

matches.push_back(std::move(match));
auto match = matchWitness(TC, Proto, conformance, DC,
requirement, witness, reqEnvironment);
if (match.isViable()) {
++numViable;
bestIdx = matches.size();
} else if (match.Kind == MatchKind::WitnessInvalid) {
doNotDiagnoseMatches = true;
}

if (auto *ext = dyn_cast<ExtensionDecl>(match.Witness->getDeclContext())){
if (!ext->isConstrainedExtension() &&
ext->getAsProtocolExtensionContext())
anyFromUnconstrainedExtension = true;
}

matches.push_back(std::move(match));
}
}

if (numViable == 0) {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SDK/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if(SWIFT_BUILD_STATIC_SDK_OVERLAY)
list(APPEND SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES STATIC)
endif()

set(all_overlays "AppKit;AssetsLibrary;AVFoundation;CallKit;CloudKit;Contacts;CoreAudio;CoreData;CoreGraphics;CoreImage;CoreLocation;CoreMedia;CryptoTokenKit;Dispatch;Foundation;GameplayKit;GLKit;HomeKit;IOKit;Intents;MapKit;ObjectiveC;OpenCL;os;Photos;QuartzCore;SafariServices;SceneKit;simd;SpriteKit;UIKit;WatchKit;XCTest;XPC")
set(all_overlays "AppKit;AssetsLibrary;AVFoundation;CallKit;CloudKit;Contacts;CoreAudio;CoreData;CoreFoundation;CoreGraphics;CoreImage;CoreLocation;CoreMedia;CryptoTokenKit;Dispatch;Foundation;GameplayKit;GLKit;HomeKit;IOKit;Intents;MapKit;ObjectiveC;OpenCL;os;Photos;QuartzCore;SafariServices;SceneKit;simd;SpriteKit;UIKit;WatchKit;XCTest;XPC")

if(DEFINED SWIFT_OVERLAY_TARGETS)
set(overlays_to_build ${SWIFT_OVERLAY_TARGETS})
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/SDK/CoreAudio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ add_swift_library(swiftCoreAudio ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK
SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR WATCHOS WATCHOS_SIMULATOR
SWIFT_MODULE_DEPENDS_OSX Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_TVOS Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_WATCHOS Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_TVOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_WATCHOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
FRAMEWORK_DEPENDS CoreAudio

DEPLOYMENT_VERSION_OSX ${SWIFTLIB_DEPLOYMENT_VERSION_COREAUDIO_OSX}
Expand Down
10 changes: 10 additions & 0 deletions stdlib/public/SDK/CoreFoundation/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_swift_library(swiftCoreFoundation ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
CoreFoundation.swift

SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
SWIFT_MODULE_DEPENDS_OSX Darwin Dispatch ObjectiveC
SWIFT_MODULE_DEPENDS_IOS Darwin Dispatch ObjectiveC
SWIFT_MODULE_DEPENDS_TVOS Darwin Dispatch ObjectiveC
SWIFT_MODULE_DEPENDS_WATCHOS Darwin Dispatch ObjectiveC
FRAMEWORK_DEPENDS CoreFoundation)
23 changes: 23 additions & 0 deletions stdlib/public/SDK/CoreFoundation/CoreFoundation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

@_exported import CoreFoundation

public protocol _CFObject: class, Hashable {}
extension _CFObject {
public var hashValue: Int {
return Int(bitPattern: CFHash(self))
}
public static func ==(left: Self, right: Self) -> Bool {
return CFEqual(left, right)
}
}
8 changes: 4 additions & 4 deletions stdlib/public/SDK/CoreGraphics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ add_swift_library(swiftCoreGraphics ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_
# SWIFT_COMPILE_FLAGS ${STDLIB_SIL_SERIALIZE_ALL}
SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
SWIFT_MODULE_DEPENDS_OSX Darwin Dispatch IOKit ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_TVOS Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_WATCHOS Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation Dispatch IOKit ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_TVOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_WATCHOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
FRAMEWORK_DEPENDS CoreGraphics

DEPLOYMENT_VERSION_OSX ${SWIFTLIB_DEPLOYMENT_VERSION_COREGRAPHICS_OSX}
Expand Down
10 changes: 0 additions & 10 deletions stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ extension CGColor {
#endif
}

extension CGColor: Equatable {}
public func ==(lhs: CGColor, rhs: CGColor) -> Bool {
return lhs.__equalTo(rhs)
}


//===----------------------------------------------------------------------===//
// CGColorSpace
Expand Down Expand Up @@ -476,11 +471,6 @@ extension CGPath {
}
}

extension CGPath: Equatable {}
public func ==(lhs: CGPath, rhs: CGPath) -> Bool {
return lhs.__equalTo(rhs)
}

extension CGMutablePath {

public func addRoundedRect(in rect: CGRect, cornerWidth: CGFloat,
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/SDK/Foundation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ add_swift_library(swiftFoundation ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SD
SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"

SWIFT_MODULE_DEPENDS_OSX Darwin CoreGraphics Dispatch IOKit ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin CoreGraphics Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_TVOS Darwin CoreGraphics Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_WATCHOS Darwin CoreGraphics Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch IOKit ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation CoreGraphics Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_TVOS Darwin CoreFoundation CoreGraphics Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_WATCHOS Darwin CoreFoundation CoreGraphics Dispatch ObjectiveC # auto-updated
FRAMEWORK_DEPENDS Foundation

DEPLOYMENT_VERSION_OSX ${SWIFTLIB_DEPLOYMENT_VERSION_FOUNDATION_OSX}
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SDK/IOKit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ add_swift_library(swiftIOKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVE
SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS OSX
SWIFT_MODULE_DEPENDS_OSX Darwin Dispatch ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
FRAMEWORK_DEPENDS IOKit

DEPLOYMENT_VERSION_OSX ${SWIFTLIB_DEPLOYMENT_VERSION_IOKIT_OSX}
Expand Down
2 changes: 1 addition & 1 deletion test/ClangImporter/Inputs/SwiftPrivateAttr.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct NSOptions : OptionSet {
}
@available(swift, obsoleted: 3, renamed: "__PrivCFType")
typealias __PrivCFTypeRef = __PrivCFType
class __PrivCFType {
class __PrivCFType : _CFObject {
}
@available(swift, obsoleted: 3, renamed: "__PrivCFSub")
typealias __PrivCFSubRef = __PrivCFSub
Expand Down
1 change: 1 addition & 0 deletions test/IDE/Inputs/print_clang_header/Foo.modulemap
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
framework module Foo {
header "header-to-print.h"
header "other-header.h"
export *
}
Loading