Skip to content

Commit 07b7e38

Browse files
committed
Merge #2457 "Fix @objc checking for optional value types"
We previously treated 'NSFoo?' as ObjC-compatible simply because 'NSFoo' was an imported type or was marked '@objc'.
2 parents 6bfb6e0 + 54f07d3 commit 07b7e38

File tree

8 files changed

+33
-36
lines changed

8 files changed

+33
-36
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ class ASTContext {
522522
ForeignRepresentationInfo
523523
getForeignRepresentationInfo(NominalTypeDecl *nominal,
524524
ForeignLanguage language,
525-
DeclContext *dc);
525+
const DeclContext *dc);
526526

527527
/// Add a declaration to a list of declarations that need to be emitted
528528
/// as part of the current module or source file, but are otherwise not

include/swift/AST/ProtocolConformance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
254254

255255
/// Determine whether this protocol conformance is visible from the
256256
/// given declaration context.
257-
bool isVisibleFrom(DeclContext *dc) const;
257+
bool isVisibleFrom(const DeclContext *dc) const;
258258

259259
/// Determine whether the witness for the given requirement
260260
/// is either the default definition or was otherwise deduced.

include/swift/AST/Types.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -712,22 +712,22 @@ class alignas(1 << TypeAlignInBits) TypeBase {
712712
/// Determine whether the given type is representable in the given
713713
/// foreign language.
714714
std::pair<ForeignRepresentableKind, ProtocolConformance *>
715-
getForeignRepresentableIn(ForeignLanguage language, DeclContext *dc);
715+
getForeignRepresentableIn(ForeignLanguage language, const DeclContext *dc);
716716

717717
/// Determines whether the given Swift type is representable within
718718
/// the given foreign language.
719719
///
720720
/// A given Swift type is representable in the given foreign
721721
/// language if the Swift type can be used from source code written
722722
/// in that language.
723-
bool isRepresentableIn(ForeignLanguage language, DeclContext *dc);
723+
bool isRepresentableIn(ForeignLanguage language, const DeclContext *dc);
724724

725725
/// Determines whether the type is trivially representable within
726726
/// the foreign language, meaning that it is both representable in
727727
/// that language and that the runtime representations are
728728
/// equivalent.
729729
bool isTriviallyRepresentableIn(ForeignLanguage language,
730-
DeclContext *dc);
730+
const DeclContext *dc);
731731

732732
/// \brief Given that this is a nominal type or bound generic nominal
733733
/// type, return its parent type; this will be a null type if the type

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3795,7 +3795,7 @@ static NominalTypeDecl *findUnderlyingTypeInModule(ASTContext &ctx,
37953795
ForeignRepresentationInfo
37963796
ASTContext::getForeignRepresentationInfo(NominalTypeDecl *nominal,
37973797
ForeignLanguage language,
3798-
DeclContext *dc) {
3798+
const DeclContext *dc) {
37993799
if (Impl.ForeignRepresentableCache.empty()) {
38003800
// Local function to add a type with the given name and module as
38013801
// trivially-representable.

lib/AST/ProtocolConformance.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ ProtocolConformance::getRootNormalConformance() const {
404404
return cast<NormalProtocolConformance>(C);
405405
}
406406

407-
bool ProtocolConformance::isVisibleFrom(DeclContext *dc) const {
407+
bool ProtocolConformance::isVisibleFrom(const DeclContext *dc) const {
408408
// FIXME: Implement me!
409409
return true;
410410
}

lib/AST/Type.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,8 +1930,8 @@ bool TypeBase::isPotentiallyBridgedValueType() {
19301930
}
19311931

19321932
/// Determine whether this is a representable Objective-C object type.
1933-
static ForeignRepresentableKind getObjCObjectRepresentable(Type type,
1934-
DeclContext *dc) {
1933+
static ForeignRepresentableKind
1934+
getObjCObjectRepresentable(Type type, const DeclContext *dc) {
19351935
// @objc metatypes are representable when their instance type is.
19361936
if (auto metatype = type->getAs<AnyMetatypeType>()) {
19371937
// If the instance type is not representable, the metatype is not
@@ -1986,7 +1986,8 @@ static ForeignRepresentableKind getObjCObjectRepresentable(Type type,
19861986
/// to be reflected in PrintAsObjC, so that the Swift type will be
19871987
/// properly printed for (Objective-)C and in SIL's bridging logic.
19881988
static std::pair<ForeignRepresentableKind, ProtocolConformance *>
1989-
getForeignRepresentable(Type type, ForeignLanguage language, DeclContext *dc) {
1989+
getForeignRepresentable(Type type, ForeignLanguage language,
1990+
const DeclContext *dc) {
19901991
// Look through one level of optional type, but remember that we did.
19911992
bool wasOptional = false;
19921993
if (auto valueType = type->getAnyOptionalObjectType()) {
@@ -2089,10 +2090,6 @@ getForeignRepresentable(Type type, ForeignLanguage language, DeclContext *dc) {
20892090

20902091
ASTContext &ctx = nominal->getASTContext();
20912092

2092-
// If the type is @objc, it is trivially representable in Objective-C.
2093-
if (nominal->isObjC() && language == ForeignLanguage::ObjectiveC)
2094-
return { ForeignRepresentableKind::Trivial, nullptr };
2095-
20962093
// Unmanaged<T> can be trivially represented in Objective-C if T
20972094
// is trivially represented in Objective-C.
20982095
if (language == ForeignLanguage::ObjectiveC &&
@@ -2112,14 +2109,17 @@ getForeignRepresentable(Type type, ForeignLanguage language, DeclContext *dc) {
21122109

21132110
// If the type was imported from Clang, check whether it is
21142111
// representable in the requested language.
2115-
if (nominal->hasClangNode()) {
2112+
if (nominal->hasClangNode() || nominal->isObjC()) {
21162113
switch (language) {
21172114
case ForeignLanguage::C:
21182115
// Imported structs and enums are trivially representable in C.
21192116
// FIXME: This is not entirely true; we need to check that
21202117
// all of the exposed parts are representable in C.
2121-
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal))
2118+
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal)) {
2119+
if (wasOptional)
2120+
break;
21222121
return { ForeignRepresentableKind::Trivial, nullptr };
2122+
}
21232123

21242124
// Imported classes and protocols are not.
21252125
if (isa<ClassDecl>(nominal) || isa<ProtocolDecl>(nominal))
@@ -2128,7 +2128,10 @@ getForeignRepresentable(Type type, ForeignLanguage language, DeclContext *dc) {
21282128
llvm_unreachable("Unhandled nominal type declaration");
21292129

21302130
case ForeignLanguage::ObjectiveC:
2131-
// Anything Clang imported is trivially representable in Objective-C.
2131+
if (isa<StructDecl>(nominal) || isa<EnumDecl>(nominal))
2132+
if (wasOptional)
2133+
break;
2134+
21322135
return { ForeignRepresentableKind::Trivial, nullptr };
21332136
}
21342137
}
@@ -2218,11 +2221,13 @@ getForeignRepresentable(Type type, ForeignLanguage language, DeclContext *dc) {
22182221
}
22192222

22202223
std::pair<ForeignRepresentableKind, ProtocolConformance *>
2221-
TypeBase::getForeignRepresentableIn(ForeignLanguage language, DeclContext *dc) {
2224+
TypeBase::getForeignRepresentableIn(ForeignLanguage language,
2225+
const DeclContext *dc) {
22222226
return getForeignRepresentable(Type(this), language, dc);
22232227
}
22242228

2225-
bool TypeBase::isRepresentableIn(ForeignLanguage language, DeclContext *dc) {
2229+
bool TypeBase::isRepresentableIn(ForeignLanguage language,
2230+
const DeclContext *dc) {
22262231
switch (getForeignRepresentableIn(language, dc).first) {
22272232
case ForeignRepresentableKind::None:
22282233
return false;
@@ -2236,7 +2241,7 @@ bool TypeBase::isRepresentableIn(ForeignLanguage language, DeclContext *dc) {
22362241
}
22372242

22382243
bool TypeBase::isTriviallyRepresentableIn(ForeignLanguage language,
2239-
DeclContext *dc) {
2244+
const DeclContext *dc) {
22402245
switch (getForeignRepresentableIn(language, dc).first) {
22412246
case ForeignRepresentableKind::None:
22422247
case ForeignRepresentableKind::Bridged:

lib/SILGen/SILGenExpr.cpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,25 +2292,14 @@ RValue RValueEmitter::visitRebindSelfInConstructorExpr(
22922292
static bool isNullableTypeInC(SILModule &M, Type ty) {
22932293
ty = ty->getLValueOrInOutObjectType()->getReferenceStorageReferent();
22942294

2295+
// Functions, class instances, and @objc existentials are all nullable.
22952296
if (ty->hasReferenceSemantics())
22962297
return true;
2297-
2298-
auto &C = ty->getASTContext();
2299-
auto nom = ty->getAnyNominal();
2300-
if (!nom)
2301-
return false;
23022298

2303-
if (nom == C.getUnsafePointerDecl()
2304-
|| nom == C.getUnsafeMutablePointerDecl()
2305-
|| nom == C.getAutoreleasingUnsafeMutablePointerDecl()
2306-
|| nom == C.getOpaquePointerDecl())
2307-
return true;
2308-
2309-
auto selectorTy = M.Types.getSelectorType();
2310-
if (selectorTy && ty->isEqual(selectorTy))
2311-
return true;
2312-
2313-
return false;
2299+
// Other types like UnsafePointer can also be nullable.
2300+
ty = OptionalType::get(ty);
2301+
return ty->isTriviallyRepresentableIn(ForeignLanguage::C,
2302+
M.getAssociatedContext());
23142303
}
23152304

23162305
/// Determine whether the given declaration returns a non-optional object that

test/attr/attr_objc.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,7 @@ class infer_instanceVar1 {
11061106
var var_Optional12: OpaquePointer?
11071107
var var_Optional13: UnsafeMutablePointer<Int>?
11081108
var var_Optional14: UnsafeMutablePointer<Class_ObjC1>?
1109+
var var_Optional15: NSRange? // another bridged struct
11091110

11101111
// CHECK-LABEL: @objc var var_Optional1: Class_ObjC1?
11111112
// CHECK-LABEL: @objc var var_Optional2: Protocol_ObjC1?
@@ -1121,6 +1122,7 @@ class infer_instanceVar1 {
11211122
// CHECK-LABEL: @objc var var_Optional12: OpaquePointer?
11221123
// CHECK-LABEL: @objc var var_Optional13: UnsafeMutablePointer<Int>?
11231124
// CHECK-LABEL: @objc var var_Optional14: UnsafeMutablePointer<Class_ObjC1>?
1125+
// CHECK-LABEL: @objc var var_Optional15: NSRange?
11241126

11251127

11261128
var var_ImplicitlyUnwrappedOptional1: Class_ObjC1!
@@ -1159,6 +1161,7 @@ class infer_instanceVar1 {
11591161
var var_Optional_fail14: CBool?
11601162
var var_Optional_fail20: AnyObject??
11611163
var var_Optional_fail21: AnyObject.Type??
1164+
var var_Optional_fail22: NSComparisonResult? // a non-bridged imported value type
11621165
// CHECK-NOT: @objc{{.*}}Optional_fail
11631166

11641167
// CHECK-LABEL: @objc var var_CFunctionPointer_1: @convention(c) () -> ()

0 commit comments

Comments
 (0)