Skip to content

Commit 14df2a5

Browse files
authored
Merge pull request #4659 from DougGregor/objc-throwing-inference
[3.0] Throwing methods must return an object type in the @objc thunk to be @objc
2 parents 893ee41 + 6a51859 commit 14df2a5

File tree

3 files changed

+33
-28
lines changed

3 files changed

+33
-28
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4853,6 +4853,7 @@ TypeChecker::findWitnessedObjCRequirements(const ValueDecl *witness,
48534853
// We only care about Objective-C protocols.
48544854
if (!proto->isObjC()) continue;
48554855

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

48634864
// Dig out the conformance.
4864-
Optional<ProtocolConformance *> conformance;
48654865
if (!conformance.hasValue()) {
48664866
SmallVector<ProtocolConformance *, 2> conformances;
48674867
nominal->lookupConformance(dc->getParentModule(), proto,

lib/Sema/TypeCheckType.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,31 +2903,18 @@ bool TypeChecker::isCIntegerType(const DeclContext *DC, Type T) {
29032903

29042904
/// Determines whether the given type is bridged to an Objective-C class type.
29052905
static bool isBridgedToObjectiveCClass(DeclContext *dc, Type type) {
2906-
// Simple case: bridgeable object types.
2907-
if (type->isBridgeableObjectType())
2908-
return true;
2909-
2910-
// Any bridges to AnyObject.
2911-
if (type->isAny())
2912-
return true;
2913-
2914-
// Determine whether this type is bridged to Objective-C.
2915-
ASTContext &ctx = type->getASTContext();
2916-
Optional<Type> bridged = ctx.getBridgedToObjC(dc, type,
2917-
ctx.getLazyResolver());
2918-
if (!bridged)
2906+
switch (type->getForeignRepresentableIn(ForeignLanguage::ObjectiveC, dc)
2907+
.first) {
2908+
case ForeignRepresentableKind::Trivial:
2909+
case ForeignRepresentableKind::None:
29192910
return false;
29202911

2921-
// Check whether we're bridging to a class.
2922-
auto classDecl = (*bridged)->getClassOrBoundGenericClass();
2923-
if (!classDecl)
2924-
return false;
2925-
2926-
// Allow anything that isn't bridged to NSNumber.
2927-
// FIXME: This feels like a hack, but we don't have the right predicate
2928-
// anywhere.
2929-
return classDecl->getName().str()
2930-
!= ctx.getSwiftName(KnownFoundationEntity::NSNumber);
2912+
case ForeignRepresentableKind::Object:
2913+
case ForeignRepresentableKind::Bridged:
2914+
case ForeignRepresentableKind::BridgedError:
2915+
case ForeignRepresentableKind::StaticBridged:
2916+
return true;
2917+
}
29312918
}
29322919

29332920
bool TypeChecker::isRepresentableInObjC(

test/attr/attr_objc.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ struct PlainStruct {}
1111
enum PlainEnum {}
1212
protocol PlainProtocol {} // expected-note {{protocol 'PlainProtocol' declared here}}
1313

14-
enum ErrorEnum : Error { }
14+
enum ErrorEnum : Error {
15+
case failed
16+
}
1517

1618
@objc class Class_ObjC1 {}
1719

@@ -1978,6 +1980,24 @@ class ClassThrows1 {
19781980
// CHECK: @objc init(degrees: Double) throws
19791981
// CHECK-DUMP: constructor_decl "init(degrees:)"{{.*}}foreign_error=NilResult,unowned,param=1,paramtype=Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>
19801982
init(degrees: Double) throws { }
1983+
1984+
// CHECK: {{^}} func methodReturnsBridgedValueType() throws -> NSRange
1985+
func methodReturnsBridgedValueType() throws -> NSRange { return NSRange() }
1986+
1987+
@objc func methodReturnsBridgedValueType2() throws -> NSRange {
1988+
return NSRange()
1989+
}
1990+
// 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}}
1991+
1992+
// CHECK: {{^}} @objc func methodReturnsError() throws -> Error
1993+
func methodReturnsError() throws -> Error { return ErrorEnum.failed }
1994+
1995+
// CHECK: @objc func methodReturnStaticBridged() throws -> ((Int) -> (Int) -> Int)
1996+
func methodReturnStaticBridged() throws -> ((Int) -> (Int) -> Int) {
1997+
func add(x: Int) -> (Int) -> Int {
1998+
return { x + $0 }
1999+
}
2000+
}
19812001
}
19822002

19832003
// CHECK-DUMP-LABEL: class_decl "SubclassImplicitClassThrows1"
@@ -2127,20 +2147,18 @@ extension ClassInfersFromProtocol3 {
21272147
func method1(value: String) { }
21282148
}
21292149

2150+
// Inference for subclasses.
21302151
class SuperclassImplementsProtocol : InferFromProtocol { }
21312152

2132-
// Note: no inference for subclasses
21332153
class SubclassInfersFromProtocol1 : SuperclassImplementsProtocol {
21342154
// CHECK: {{^}} @objc func method1(value: Int)
21352155
func method1(value: Int) { }
21362156
}
21372157

2138-
// Note: no inference for subclasses
21392158
class SubclassInfersFromProtocol2 : SuperclassImplementsProtocol {
21402159
}
21412160

21422161
extension SubclassInfersFromProtocol2 {
21432162
// CHECK: {{^}} @objc dynamic func method1(value: Int)
21442163
func method1(value: Int) { }
21452164
}
2146-

0 commit comments

Comments
 (0)