Skip to content
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
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4853,6 +4853,7 @@ TypeChecker::findWitnessedObjCRequirements(const ValueDecl *witness,
// We only care about Objective-C protocols.
if (!proto->isObjC()) continue;

Optional<ProtocolConformance *> conformance;
for (auto req : proto->lookupDirect(name, true)) {
// Skip anything in a protocol extension.
if (req->getDeclContext() != proto) continue;
Expand All @@ -4861,7 +4862,6 @@ TypeChecker::findWitnessedObjCRequirements(const ValueDecl *witness,
if (isa<TypeDecl>(req)) continue;

// Dig out the conformance.
Optional<ProtocolConformance *> conformance;
if (!conformance.hasValue()) {
SmallVector<ProtocolConformance *, 2> conformances;
nominal->lookupConformance(dc->getParentModule(), proto,
Expand Down
33 changes: 10 additions & 23 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2903,31 +2903,18 @@ bool TypeChecker::isCIntegerType(const DeclContext *DC, Type T) {

/// Determines whether the given type is bridged to an Objective-C class type.
static bool isBridgedToObjectiveCClass(DeclContext *dc, Type type) {
// Simple case: bridgeable object types.
if (type->isBridgeableObjectType())
return true;

// Any bridges to AnyObject.
if (type->isAny())
return true;

// Determine whether this type is bridged to Objective-C.
ASTContext &ctx = type->getASTContext();
Optional<Type> bridged = ctx.getBridgedToObjC(dc, type,
ctx.getLazyResolver());
if (!bridged)
switch (type->getForeignRepresentableIn(ForeignLanguage::ObjectiveC, dc)
.first) {
case ForeignRepresentableKind::Trivial:
case ForeignRepresentableKind::None:
return false;

// Check whether we're bridging to a class.
auto classDecl = (*bridged)->getClassOrBoundGenericClass();
if (!classDecl)
return false;

// Allow anything that isn't bridged to NSNumber.
// FIXME: This feels like a hack, but we don't have the right predicate
// anywhere.
return classDecl->getName().str()
!= ctx.getSwiftName(KnownFoundationEntity::NSNumber);
case ForeignRepresentableKind::Object:
case ForeignRepresentableKind::Bridged:
case ForeignRepresentableKind::BridgedError:
case ForeignRepresentableKind::StaticBridged:
return true;
}
}

bool TypeChecker::isRepresentableInObjC(
Expand Down
26 changes: 22 additions & 4 deletions test/attr/attr_objc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ struct PlainStruct {}
enum PlainEnum {}
protocol PlainProtocol {} // expected-note {{protocol 'PlainProtocol' declared here}}

enum ErrorEnum : Error { }
enum ErrorEnum : Error {
case failed
}

@objc class Class_ObjC1 {}

Expand Down Expand Up @@ -1978,6 +1980,24 @@ class ClassThrows1 {
// CHECK: @objc init(degrees: Double) throws
// CHECK-DUMP: constructor_decl "init(degrees:)"{{.*}}foreign_error=NilResult,unowned,param=1,paramtype=Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>
init(degrees: Double) throws { }

// CHECK: {{^}} func methodReturnsBridgedValueType() throws -> NSRange
func methodReturnsBridgedValueType() throws -> NSRange { return NSRange() }

@objc func methodReturnsBridgedValueType2() throws -> NSRange {
return NSRange()
}
// expected-error@-3{{throwing method cannot be marked @objc because it returns a value of type 'NSRange' (aka '_NSRange'); return 'Void' or a type that bridges to an Objective-C class}}

// CHECK: {{^}} @objc func methodReturnsError() throws -> Error
func methodReturnsError() throws -> Error { return ErrorEnum.failed }

// CHECK: @objc func methodReturnStaticBridged() throws -> ((Int) -> (Int) -> Int)
func methodReturnStaticBridged() throws -> ((Int) -> (Int) -> Int) {
func add(x: Int) -> (Int) -> Int {
return { x + $0 }
}
}
}

// CHECK-DUMP-LABEL: class_decl "SubclassImplicitClassThrows1"
Expand Down Expand Up @@ -2127,20 +2147,18 @@ extension ClassInfersFromProtocol3 {
func method1(value: String) { }
}

// Inference for subclasses.
class SuperclassImplementsProtocol : InferFromProtocol { }

// Note: no inference for subclasses
class SubclassInfersFromProtocol1 : SuperclassImplementsProtocol {
// CHECK: {{^}} @objc func method1(value: Int)
func method1(value: Int) { }
}

// Note: no inference for subclasses
class SubclassInfersFromProtocol2 : SuperclassImplementsProtocol {
}

extension SubclassInfersFromProtocol2 {
// CHECK: {{^}} @objc dynamic func method1(value: Int)
func method1(value: Int) { }
}