Skip to content

Commit 9a9ea69

Browse files
committed
[PrintAsObjC] Downgrade +new unavailability to deprecation in Swift 4
The general policy has been that even if something crashes at run time, we don't make it a hard error in Swift 4 mode (or Swift 3 mode!) if it wasn't a hard error in Swift 4.0 (3.0). In this case, we thought we could get away with it, and then it turns out it actually caused some problems. (And as 2bc0106 shows, we can still make mistakes.) This change isn't perfect because the diagnostic appears in /clients/ rather than in the module that's being compiled as Swift 4 (instead of Swift 5). But it still means that someone who hasn't changed /anything/ from a valid Swift 4.0 project will be able to compile without any changes, even if they were relying on being able to call +new when -init was unavailable for some reason. More rdar://problem/35942058
1 parent 7493ecc commit 9a9ea69

File tree

6 files changed

+21
-10
lines changed

6 files changed

+21
-10
lines changed

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,14 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
679679

680680
if (makeNewUnavailable) {
681681
assert(!makeNewExplicitlyAvailable);
682-
os << "+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("
683-
"\"-init is unavailable\");\n";
682+
// Downgrade this to a warning in pre-Swift-5 mode. This isn't perfect
683+
// because it's a diagnostic inflicted on /clients/, but it's close
684+
// enough. It really is invalid to call +new when -init is unavailable.
685+
StringRef annotationName = "SWIFT_UNAVAILABLE_MSG";
686+
if (!M.getASTContext().isSwiftVersionAtLeast(5))
687+
annotationName = "SWIFT_DEPRECATED_MSG";
688+
os << "+ (nonnull instancetype)new " << annotationName
689+
<< "(\"-init is unavailable\");\n";
684690
} else if (makeNewExplicitlyAvailable) {
685691
os << "+ (nonnull instancetype)new;\n";
686692
}

test/PrintAsObjC/availability.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757

5858
// CHECK-LABEL: @interface AvailabilitySub
5959
// CHECK-NEXT: - (nonnull instancetype)init SWIFT_UNAVAILABLE;
60-
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
60+
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_DEPRECATED_MSG("-init is unavailable");
6161
// CHECK-NEXT: - (nonnull instancetype)initWithX:(NSInteger)_ SWIFT_UNAVAILABLE;
6262
// CHECK-NEXT: @end
6363

test/PrintAsObjC/classes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class DiscardableResult : NSObject {
178178
// CHECK-LABEL: @interface InheritedInitializersRequired
179179
// CHECK-NEXT: - (nonnull instancetype)initWithEvenMoreFun OBJC_DESIGNATED_INITIALIZER;
180180
// CHECK-NEXT: - (nonnull instancetype)init SWIFT_UNAVAILABLE;
181-
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
181+
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_DEPRECATED_MSG("-init is unavailable");
182182
// CHECK-NEXT: @end
183183
@objc class InheritedInitializersRequired : InheritedInitializers {
184184
@objc required init(evenMoreFun: ()) { super.init() }
@@ -436,7 +436,7 @@ class MyObject : NSObject {}
436436
// CHECK-LABEL: @interface NewBanned
437437
// CHECK-NEXT: - (nonnull instancetype)initWithArbitraryArgument:(NSInteger)arbitraryArgument OBJC_DESIGNATED_INITIALIZER;
438438
// CHECK-NEXT: - (nonnull instancetype)init SWIFT_UNAVAILABLE;
439-
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
439+
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_DEPRECATED_MSG("-init is unavailable");
440440
// CHECK-NEXT: @end
441441
@objc class NewBanned : NSObject {
442442
init(arbitraryArgument: Int) { super.init() }

test/PrintAsObjC/protocols.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protocol CustomNameType2 {}
5555
// CHECK-LABEL: @interface MyObject : NSObject <NSCoding, Fungible>
5656
// CHECK-NEXT: initWithCoder
5757
// CHECK-NEXT: init SWIFT_UNAVAILABLE
58-
// CHECK-NEXT: new SWIFT_UNAVAILABLE
58+
// CHECK-NEXT: new SWIFT_DEPRECATED
5959
// CHECK-NEXT: @end
6060
// NEGATIVE-NOT: @protocol NSCoding
6161
class MyObject : NSObject, NSCoding, Fungible {

validation-test/PrintAsObjC/reintroduced-new.m renamed to test/PrintAsObjC/reintroduced-new.m

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../../test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
77
// FIXME: END -enable-source-import hackaround
88

9-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/Inputs/reintroduced-new.swift -disable-objc-attr-requires-foundation-module -module-name main
10-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -parse-as-library %t/main.swiftmodule -typecheck -emit-objc-header-path %t/generated.h -disable-objc-attr-requires-foundation-module
11-
// RUN: not %clang -fsyntax-only -x objective-c %s -include %t/generated.h -fobjc-arc -fmodules -Werror -isysroot %S/../../test/Inputs/clang-importer-sdk 2>&1 | %FileCheck %s
9+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/Inputs/reintroduced-new.swift -swift-version 4 -disable-objc-attr-requires-foundation-module -module-name main
10+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -parse-as-library %t/main.swiftmodule -typecheck -emit-objc-header-path %t/generated.h -disable-objc-attr-requires-foundation-module -swift-version 4
11+
// RUN: not %clang -fsyntax-only -x objective-c %s -include %t/generated.h -fobjc-arc -fmodules -Werror -isysroot %S/../../test/Inputs/clang-importer-sdk 2>&1 | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-4 %s
12+
13+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/Inputs/reintroduced-new.swift -disable-objc-attr-requires-foundation-module -module-name main -swift-version 5
14+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -parse-as-library %t/main.swiftmodule -typecheck -emit-objc-header-path %t/generated.h -disable-objc-attr-requires-foundation-module -swift-version 5
15+
// RUN: not %clang -fsyntax-only -x objective-c %s -include %t/generated.h -fobjc-arc -fmodules -Werror -isysroot %S/../../test/Inputs/clang-importer-sdk 2>&1 | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-5 %s
1216

1317
// CHECK-NOT: error:
1418

@@ -17,7 +21,8 @@ void test() {
1721
(void)[[Base alloc] init];
1822
// CHECK-NOT: error:
1923
(void)[[Sub alloc] init];
20-
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'new' is unavailable: -init is unavailable
24+
// CHECK-4: :[[@LINE+2]]:{{[0-9]+}}: error: 'new' is deprecated: -init is unavailable
25+
// CHECK-5: :[[@LINE+1]]:{{[0-9]+}}: error: 'new' is unavailable: -init is unavailable
2126
(void)[Base new];
2227
// CHECK-NOT: error:
2328
(void)[Sub new];

0 commit comments

Comments
 (0)