Skip to content

[TypeChecker] Rephrase platforms in availability diagnostics #24334

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 2 commits into from
May 6, 2019
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
32 changes: 13 additions & 19 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3971,8 +3971,9 @@ ERROR(dynamic_replacement_replaced_constructor_is_not_convenience, none,
//------------------------------------------------------------------------------

ERROR(availability_decl_unavailable, none,
"%select{getter for |setter for |}0%1 is unavailable",
(unsigned, DeclName))
"%select{getter for |setter for |}0%1 is unavailable"
"%select{ in %3|}2",
(unsigned, DeclName, bool, StringRef))

#define REPLACEMENT_DECL_KIND_SELECT "select{| instance method| property}"
ERROR(availability_decl_unavailable_rename, none,
Expand All @@ -3988,16 +3989,9 @@ ERROR(availability_decl_unavailable_rename_msg, none,
(unsigned, DeclName, bool, unsigned, StringRef, StringRef))

ERROR(availability_decl_unavailable_msg, none,
"%select{getter for |setter for |}0%1 is unavailable: %2",
(unsigned, DeclName, StringRef))

ERROR(availability_decl_unavailable_in_swift, none,
"%select{getter for |setter for |}0%1 is unavailable in Swift",
(unsigned, DeclName))

ERROR(availability_decl_unavailable_in_swift_msg, none,
"%select{getter for |setter for |}0%1 is unavailable in Swift: %2",
(unsigned, DeclName, StringRef))
"%select{getter for |setter for |}0%1 is unavailable"
"%select{ in %3|}2: %4",
(unsigned, DeclName, bool, StringRef, StringRef))

NOTE(availability_marked_unavailable, none,
"%select{getter for |setter for |}0%1 has been explicitly marked "
Expand All @@ -4013,18 +4007,18 @@ NOTE(availability_obsoleted, none,

WARNING(availability_deprecated, none,
"%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 "
"deprecated%select{| %select{on|in}4 %3%select{| %5}4}2",
"deprecated%select{| in %3%select{| %5}4}2",
(unsigned, DeclName, bool, StringRef, bool, llvm::VersionTuple))

WARNING(availability_deprecated_msg, none,
"%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 "
"deprecated%select{| %select{on|in}4 %3%select{| %5}4}2: %6",
"deprecated%select{| in %3%select{| %5}4}2: %6",
(unsigned, DeclName, bool, StringRef, bool, llvm::VersionTuple,
StringRef))

WARNING(availability_deprecated_rename, none,
"%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 "
"deprecated%select{| %select{on|in}4 %3%select{| %5}4}2: "
"deprecated%select{| in %3%select{| %5}4}2: "
"%select{renamed to|replaced by}6%" REPLACEMENT_DECL_KIND_SELECT "7 "
"'%8'",
(unsigned, DeclName, bool, StringRef, bool, llvm::VersionTuple, bool,
Expand All @@ -4041,7 +4035,7 @@ NOTE(availability_decl_more_than_enclosing_enclosing_here, none,
"enclosing scope here", ())

ERROR(availability_decl_only_version_newer, none,
"%0 is only available on %1 %2 or newer",
"%0 is only available in %1 %2 or newer",
(DeclName, StringRef, llvm::VersionTuple))

NOTE(availability_guard_with_version_check, none,
Expand All @@ -4051,13 +4045,13 @@ NOTE(availability_add_attribute, none,
"add @available attribute to enclosing %0", (DescriptiveDeclKind))

ERROR(availability_accessor_only_version_newer, none,
"%select{getter|setter}0 for %1 is only available on %2 %3"
"%select{getter|setter}0 for %1 is only available in %2 %3"
" or newer",
(/*AccessorKind*/unsigned, DeclName, StringRef, llvm::VersionTuple))

ERROR(availability_inout_accessor_only_version_newer, none,
"cannot pass as inout because %select{getter|setter}0 for %1 is only "
"available on %2 %3 or newer",
"available in %2 %3 or newer",
(/*AccessorKind*/unsigned, DeclName, StringRef, llvm::VersionTuple))

ERROR(availability_query_required_for_platform, none,
Expand All @@ -4079,7 +4073,7 @@ ERROR(availability_stored_property_no_potential,
"'@available'", ())

ERROR(availability_protocol_requires_version,
none, "protocol %0 requires %1 to be available on %2 %3 and newer",
none, "protocol %0 requires %1 to be available in %2 %3 and newer",
(DeclName, DeclName, StringRef, llvm::VersionTuple))

NOTE(availability_protocol_requirement_here, none,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/PlatformKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ StringRef platformString(PlatformKind platform);
Optional<PlatformKind> platformFromString(StringRef Name);

/// Returns a human-readable version of the platform name as a string, suitable
/// for emission in diagnostics (e.g., "OS X").
/// for emission in diagnostics (e.g., "macOS").
StringRef prettyPlatformString(PlatformKind platform);

/// Returns whether the passed-in platform is active, given the language
Expand Down
10 changes: 5 additions & 5 deletions include/swift/AST/PlatformKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
AVAILABILITY_PLATFORM(iOS, "iOS")
AVAILABILITY_PLATFORM(tvOS, "tvOS")
AVAILABILITY_PLATFORM(watchOS, "watchOS")
AVAILABILITY_PLATFORM(OSX, "OS X")
AVAILABILITY_PLATFORM(iOSApplicationExtension, "iOS application extension")
AVAILABILITY_PLATFORM(tvOSApplicationExtension, "tvOS application extension")
AVAILABILITY_PLATFORM(watchOSApplicationExtension, "watchOS application extension")
AVAILABILITY_PLATFORM(OSXApplicationExtension, "OS X application extension")
AVAILABILITY_PLATFORM(OSX, "macOS")
AVAILABILITY_PLATFORM(iOSApplicationExtension, "application extensions for iOS")
AVAILABILITY_PLATFORM(tvOSApplicationExtension, "application extensions for tvOS")
AVAILABILITY_PLATFORM(watchOSApplicationExtension, "application extensions for watchOS")
AVAILABILITY_PLATFORM(OSXApplicationExtension, "application extensions for macOS")

#undef AVAILABILITY_PLATFORM
113 changes: 62 additions & 51 deletions lib/Sema/TypeCheckAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2114,64 +2114,74 @@ bool swift::diagnoseExplicitUnavailability(

ASTContext &ctx = D->getASTContext();
auto &diags = ctx.Diags;

StringRef platform;
switch (Attr->getPlatformAgnosticAvailability()) {
case PlatformAgnosticAvailabilityKind::Deprecated:
break;
llvm_unreachable("shouldn't see deprecations in explicit unavailability");

case PlatformAgnosticAvailabilityKind::None:
case PlatformAgnosticAvailabilityKind::Unavailable:
if (Attr->Platform != PlatformKind::none) {
// This was platform-specific; indicate the platform.
platform = Attr->prettyPlatformString();
break;
}
LLVM_FALLTHROUGH;

case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific:
case PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific:
case PlatformAgnosticAvailabilityKind::UnavailableInSwift: {
bool inSwift = (Attr->getPlatformAgnosticAvailability() ==
PlatformAgnosticAvailabilityKind::UnavailableInSwift);

if (!Attr->Rename.empty()) {
SmallString<32> newNameBuf;
Optional<ReplacementDeclKind> replaceKind =
describeRename(ctx, Attr, D, newNameBuf);
unsigned rawReplaceKind = static_cast<unsigned>(
replaceKind.getValueOr(ReplacementDeclKind::None));
StringRef newName = replaceKind ? newNameBuf.str() : Attr->Rename;

if (Attr->Message.empty()) {
auto diag = diags.diagnose(Loc,
diag::availability_decl_unavailable_rename,
RawAccessorKind, Name,
replaceKind.hasValue(),
rawReplaceKind, newName);
attachRenameFixIts(diag);
} else {
EncodedDiagnosticMessage EncodedMessage(Attr->Message);
auto diag =
diags.diagnose(Loc, diag::availability_decl_unavailable_rename_msg,
RawAccessorKind, Name, replaceKind.hasValue(),
rawReplaceKind, newName, EncodedMessage.Message);
attachRenameFixIts(diag);
}
} else if (isSubscriptReturningString(D, ctx)) {
diags.diagnose(Loc, diag::availabilty_string_subscript_migration)
.highlight(R)
.fixItInsert(R.Start, "String(")
.fixItInsertAfter(R.End, ")");
// We don't want to give further detail about these.
platform = "";
break;

// Skip the note emitted below.
return true;
} else if (Attr->Message.empty()) {
diags.diagnose(Loc, inSwift ? diag::availability_decl_unavailable_in_swift
: diag::availability_decl_unavailable,
RawAccessorKind, Name)
.highlight(R);
} else {
EncodedDiagnosticMessage EncodedMessage(Attr->Message);
diags.diagnose(Loc,
inSwift ? diag::availability_decl_unavailable_in_swift_msg
: diag::availability_decl_unavailable_msg,
RawAccessorKind, Name, EncodedMessage.Message)
.highlight(R);
}
case PlatformAgnosticAvailabilityKind::UnavailableInSwift:
// This API is explicitly unavailable in Swift.
platform = "Swift";
break;
}

if (!Attr->Rename.empty()) {
SmallString<32> newNameBuf;
Optional<ReplacementDeclKind> replaceKind =
describeRename(ctx, Attr, D, newNameBuf);
unsigned rawReplaceKind = static_cast<unsigned>(
replaceKind.getValueOr(ReplacementDeclKind::None));
StringRef newName = replaceKind ? newNameBuf.str() : Attr->Rename;

if (Attr->Message.empty()) {
auto diag = diags.diagnose(Loc,
diag::availability_decl_unavailable_rename,
RawAccessorKind, Name,
replaceKind.hasValue(),
rawReplaceKind, newName);
attachRenameFixIts(diag);
} else {
EncodedDiagnosticMessage EncodedMessage(Attr->Message);
auto diag =
diags.diagnose(Loc, diag::availability_decl_unavailable_rename_msg,
RawAccessorKind, Name, replaceKind.hasValue(),
rawReplaceKind, newName, EncodedMessage.Message);
attachRenameFixIts(diag);
}
} else if (isSubscriptReturningString(D, ctx)) {
diags.diagnose(Loc, diag::availabilty_string_subscript_migration)
.highlight(R)
.fixItInsert(R.Start, "String(")
.fixItInsertAfter(R.End, ")");

// Skip the note emitted below.
return true;
} else if (Attr->Message.empty()) {
diags.diagnose(Loc, diag::availability_decl_unavailable,
RawAccessorKind, Name, platform.empty(), platform)
.highlight(R);
} else {
EncodedDiagnosticMessage EncodedMessage(Attr->Message);
diags.diagnose(Loc, diag::availability_decl_unavailable_msg,
RawAccessorKind, Name, platform.empty(), platform,
EncodedMessage.Message)
.highlight(R);
}

switch (Attr->getVersionAvailability(ctx)) {
Expand Down Expand Up @@ -2205,7 +2215,7 @@ bool swift::diagnoseExplicitUnavailability(
} else if (Attr->isPackageDescriptionVersionSpecific()) {
platformDisplayString = "PackageDescription";
} else {
platformDisplayString = Attr->prettyPlatformString();
platformDisplayString = platform;
}

diags.diagnose(D, diag::availability_obsoleted,
Expand Down Expand Up @@ -2642,7 +2652,7 @@ AvailabilityWalker::diagnoseIncDecRemoval(const ValueDecl *D, SourceRange R,

// If we emit a deprecation diagnostic, produce a fixit hint as well.
auto diag = TC.diagnose(R.Start, diag::availability_decl_unavailable_msg,
RawAccessorKind, Name,
RawAccessorKind, Name, true, "",
"it has been removed in Swift 3");
if (isa<PrefixUnaryExpr>(call)) {
// Prefix: remove the ++ or --.
Expand Down Expand Up @@ -2693,7 +2703,8 @@ AvailabilityWalker::diagnoseMemoryLayoutMigration(const ValueDecl *D,

EncodedDiagnosticMessage EncodedMessage(Attr->Message);
auto diag = TC.diagnose(R.Start, diag::availability_decl_unavailable_msg,
RawAccessorKind, Name, EncodedMessage.Message);
RawAccessorKind, Name, true, "",
EncodedMessage.Message);
diag.highlight(R);

auto subject = args->getSubExpr();
Expand Down
6 changes: 5 additions & 1 deletion test/ClangImporter/availability_app_extension.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -application-extension %s

// Check the exact error message, which requires a regex match
// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -application-extension %s 2>&1 | %FileCheck %s

// REQUIRES: objc_interop

import Foundation

func test_unavailable_app_extension() {
_ = SomeCrazyAppExtensionForbiddenAPI() // expected-error {{'SomeCrazyAppExtensionForbiddenAPI()' is unavailable: Not available in App Extensions}}
_ = SomeCrazyAppExtensionForbiddenAPI() // expected-error {{unavailable}}
// CHECK: error: 'SomeCrazyAppExtensionForbiddenAPI()' is unavailable in application extensions for {{[a-z]+}}OS: Not available in App Extensions
}
10 changes: 5 additions & 5 deletions test/ClangImporter/availability_implicit_macosx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ func useClassThatTriggersImportOfPotentiallyUnavailableOptions() {
}

func directUseShouldStillTriggerDeprecationWarning() {
_ = NSDeprecatedOptions.first // expected-warning {{'NSDeprecatedOptions' was deprecated in OS X 10.51: Use a different API}}
_ = NSDeprecatedEnum.first // expected-warning {{'NSDeprecatedEnum' was deprecated in OS X 10.51: Use a different API}}
_ = NSDeprecatedOptions.first // expected-warning {{'NSDeprecatedOptions' was deprecated in macOS 10.51: Use a different API}}
_ = NSDeprecatedEnum.first // expected-warning {{'NSDeprecatedEnum' was deprecated in macOS 10.51: Use a different API}}
}

func useInSignature(_ options: NSDeprecatedOptions) { // expected-warning {{'NSDeprecatedOptions' was deprecated in OS X 10.51: Use a different API}}
func useInSignature(_ options: NSDeprecatedOptions) { // expected-warning {{'NSDeprecatedOptions' was deprecated in macOS 10.51: Use a different API}}
}

class SuperClassWithDeprecatedInitializer {
Expand All @@ -49,15 +49,15 @@ class SubClassWithSynthesizedDesignedInitializerOverride : SuperClassWithDepreca
}

func callImplicitInitializerOnSubClassWithSynthesizedDesignedInitializerOverride() {
_ = SubClassWithSynthesizedDesignedInitializerOverride() // expected-warning {{'init()' was deprecated in OS X 10.51}}
_ = SubClassWithSynthesizedDesignedInitializerOverride() // expected-warning {{'init()' was deprecated in macOS 10.51}}
}

@available(OSX, introduced: 10.9, deprecated: 10.51)
class NSDeprecatedSuperClass {
var i : Int = 7 // Causes initializer to be synthesized
}

class NotDeprecatedSubClassOfDeprecatedSuperClass : NSDeprecatedSuperClass { // expected-warning {{'NSDeprecatedSuperClass' was deprecated in OS X 10.51}}
class NotDeprecatedSubClassOfDeprecatedSuperClass : NSDeprecatedSuperClass { // expected-warning {{'NSDeprecatedSuperClass' was deprecated in macOS 10.51}}
}

func callImplicitInitializerOnNotDeprecatedSubClassOfDeprecatedSuperClass() {
Expand Down
12 changes: 6 additions & 6 deletions test/ClangImporter/objc_factory_method.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,27 @@ func testFactoryWithLaterIntroducedInit() {

// Don't prefer more available convenience factory initializer over less
// available designated initializer
_ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flim:5) // expected-error {{'init(flim:)' is only available on OS X 10.52 or newer}}
_ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flim:5) // expected-error {{'init(flim:)' is only available in macOS 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}}

_ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flam:5) // expected-error {{'init(flam:)' is only available on OS X 10.52 or newer}}
_ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flam:5) // expected-error {{'init(flam:)' is only available in macOS 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}} {{3-63=if #available(OSX 10.52, *) {\n _ = NSHavingConvenienceFactoryAndLaterDesignatedInit(flam:5)\n \} else {\n // Fallback on earlier versions\n \}}}


// Don't prefer more available factory initializer over less
// available designated initializer
_ = NSHavingFactoryAndLaterConvenienceInit(flim:5) // expected-error {{'init(flim:)' is only available on OS X 10.52 or newer}}
_ = NSHavingFactoryAndLaterConvenienceInit(flim:5) // expected-error {{'init(flim:)' is only available in macOS 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}}


_ = NSHavingFactoryAndLaterConvenienceInit(flam:5) // expected-error {{'init(flam:)' is only available on OS X 10.52 or newer}}
_ = NSHavingFactoryAndLaterConvenienceInit(flam:5) // expected-error {{'init(flam:)' is only available in macOS 10.52 or newer}}
// expected-note @-1 {{add 'if #available' version check}}


// When both a convenience factory and a convenience initializer have the
// same availability, choose the convenience initializer.
_ = NSHavingConvenienceFactoryAndSameConvenienceInit(flim:5) // expected-warning {{'init(flim:)' was deprecated in OS X 10.51: ConvenienceInit}}
_ = NSHavingConvenienceFactoryAndSameConvenienceInit(flam:5) // expected-warning {{'init(flam:)' was deprecated in OS X 10.51: ConvenienceInit}}
_ = NSHavingConvenienceFactoryAndSameConvenienceInit(flim:5) // expected-warning {{'init(flim:)' was deprecated in macOS 10.51: ConvenienceInit}}
_ = NSHavingConvenienceFactoryAndSameConvenienceInit(flam:5) // expected-warning {{'init(flam:)' was deprecated in macOS 10.51: ConvenienceInit}}

_ = NSHavingConvenienceFactoryAndSameConvenienceInit(flotsam:5) // expected-warning {{'init(flotsam:)' is deprecated: ConvenienceInit}}
_ = NSHavingConvenienceFactoryAndSameConvenienceInit(jetsam:5) // expected-warning {{'init(jetsam:)' is deprecated: ConvenienceInit}}
Expand Down
2 changes: 1 addition & 1 deletion test/Interpreter/availability_host_os.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ print(mavericks()) // CHECK: {{^9$}}
print(yosemite()) // CHECK-NEXT: {{^10$}}

#if FAIL
print(todosSantos()) // expected-error {{'todosSantos()' is only available on OS X 10.99 or newer}}
print(todosSantos()) // expected-error {{'todosSantos()' is only available in macOS 10.99 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
#endif
4 changes: 2 additions & 2 deletions test/Sema/Inputs/availability_multi_other.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class OtherIntroduced10_51 {

// This method uses a 10_52 only type in its signature, so validating
// the declaration should produce an availability error
func returns10_52() -> OtherIntroduced10_52 { // expected-error {{'OtherIntroduced10_52' is only available on OS X 10.52 or newer}}
func returns10_52() -> OtherIntroduced10_52 { // expected-error {{'OtherIntroduced10_52' is only available in macOS 10.52 or newer}}
// expected-note@-1 {{add @available attribute to enclosing instance method}}

// Body is not type checked (by design) so no error is expected for unavailable type used in return.
Expand Down Expand Up @@ -86,5 +86,5 @@ extension OtherIntroduced10_51 {
class OtherIntroduced10_53 {
}

var globalFromOtherOn10_52 : OtherIntroduced10_52? = nil // expected-error {{'OtherIntroduced10_52' is only available on OS X 10.52 or newer}}
var globalFromOtherOn10_52 : OtherIntroduced10_52? = nil // expected-error {{'OtherIntroduced10_52' is only available in macOS 10.52 or newer}}
// expected-note@-1 {{add @available attribute to enclosing var}}
Loading