Skip to content

[4.0] [SE-0160] Make deprecated @objc inference warnings opt-in. #9183

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
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 cmake/modules/SwiftSource.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ function(_compile_swift_files
endif()

if (SWIFTFILE_IS_STDLIB_CORE OR SWIFTFILE_IS_SDK_OVERLAY)
list(APPEND swift_flags "-warn-swift3-objc-inference")
list(APPEND swift_flags "-warn-swift3-objc-inference-complete")
endif()

list(APPEND swift_flags ${SWIFT_EXPERIMENTAL_EXTRA_FLAGS})
Expand Down
16 changes: 15 additions & 1 deletion include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ namespace swift {
};
enum { NumPlatformConditionKind = 4 };

/// Describes which Swift 3 Objective-C inference warnings should be
/// emitted.
enum class Swift3ObjCInferenceWarnings {
/// No warnings; this is the default.
None,
/// "Minimal" warnings driven by uses of declarations that make use of
/// the Objective-C entry point directly.
Minimal,
/// "Complete" warnings that add "@objc" for every entry point that
/// Swift 3 would have inferred as "@objc" but Swift 4 will not.
Complete,
};

/// \brief A collection of options that affect the language dialect and
/// provide compiler debugging facilities.
class LangOptions {
Expand Down Expand Up @@ -212,7 +225,8 @@ namespace swift {

/// Warn about cases where Swift 3 would infer @objc but later versions
/// of Swift do not.
bool WarnSwift3ObjCInference = false;
Swift3ObjCInferenceWarnings WarnSwift3ObjCInference =
Swift3ObjCInferenceWarnings::None;

/// Enable keypaths.
bool EnableExperimentalKeyPaths = false;
Expand Down
14 changes: 12 additions & 2 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,19 @@ def continue_building_after_errors : Flag<["-"], "continue-building-after-errors
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
HelpText<"Continue building, even after errors are encountered">;

def warn_swift3_objc_inference : Flag<["-"], "warn-swift3-objc-inference">,
def warn_swift3_objc_inference_complete :
Flag<["-"], "warn-swift3-objc-inference-complete">,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
HelpText<"Warn about deprecated @objc inference in Swift 3 for every declaration that will no longer be inferred as @objc in Swift 4">;

def warn_swift3_objc_inference_minimal :
Flag<["-"], "warn-swift3-objc-inference-minimal">,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
HelpText<"Warn about deprecated @objc inference in Swift 3">;
HelpText<"Warn about deprecated @objc inference in Swift 3 based on direct uses of the Objective-C entrypoint">;

def warn_swift3_objc_inference : Flag<["-"], "warn-swift3-objc-inference">,
Alias<warn_swift3_objc_inference_complete>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, HelpHidden]>;

// Platform options.
def enable_app_extension : Flag<["-"], "application-extension">,
Expand Down
12 changes: 11 additions & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,13 +1011,23 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
}

Opts.EnableAppExtensionRestrictions |= Args.hasArg(OPT_enable_app_extension);
Opts.WarnSwift3ObjCInference |= Args.hasArg(OPT_warn_swift3_objc_inference);

Opts.EnableSwift3ObjCInference =
Args.hasFlag(OPT_enable_swift3_objc_inference,
OPT_disable_swift3_objc_inference,
Opts.isSwiftVersion3());

if (Opts.EnableSwift3ObjCInference) {
if (const Arg *A = Args.getLastArg(
OPT_warn_swift3_objc_inference_minimal,
OPT_warn_swift3_objc_inference_complete)) {
if (A->getOption().getID() == OPT_warn_swift3_objc_inference_minimal)
Opts.WarnSwift3ObjCInference = Swift3ObjCInferenceWarnings::Minimal;
else
Opts.WarnSwift3ObjCInference = Swift3ObjCInferenceWarnings::Complete;
}
}

llvm::Triple Target = Opts.Target;
StringRef TargetArg;
if (const Arg *A = Args.getLastArg(OPT_target)) {
Expand Down
27 changes: 14 additions & 13 deletions lib/Migrator/Migrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,20 @@ Migrator::performAFixItMigration() {
Invocation.clearInputs();
Invocation.getLangOptions().EffectiveLanguageVersion = { 4, 0, 0 };

// The default subset of @objc fix-its, referred to as "minimal" migration
// in SE-0160, adds @objc to things that clearly must be visible to the
// Objective-C runtime. These are compiler error fix-its.
Invocation.getLangOptions().WarnSwift3ObjCInference = true;
Invocation.getLangOptions().EnableSwift3ObjCInference = false;

// However, if the user selects the workflow to keep the behavior of Swift 3's
// implicit Objective-C visibility, force Swift 3 @objc inference to be on.
// Coupled with the -warn-swift3-objc-inference flag above, we'll get warning
// fix-its from the compiler.
if (getMigratorOptions().KeepObjcVisibility) {
Invocation.getLangOptions().EnableSwift3ObjCInference = true;
}
// SE-0160: When migrating, always use the Swift 3 @objc inference rules,
// which drives warnings with the "@objc" Fix-Its.
Invocation.getLangOptions().EnableSwift3ObjCInference = true;

// The default behavior of the migrator, referred to as "minimal" migration
// in SE-0160, only adds @objc Fix-Its to those cases where the Objective-C
// entry point is explicitly used somewhere in the source code. The user
// may also select a workflow that adds @objc for every declaration that
// would infer @objc under the Swift 3 rules but would no longer infer
// @objc in Swift 4.
Invocation.getLangOptions().WarnSwift3ObjCInference =
getMigratorOptions().KeepObjcVisibility
? Swift3ObjCInferenceWarnings::Complete
: Swift3ObjCInferenceWarnings::Minimal;

const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();

Expand Down
6 changes: 4 additions & 2 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,8 @@ namespace {
// complain.
if (auto attr = member->getAttrs().getAttribute<ObjCAttr>()) {
if (attr->isSwift3Inferred() &&
!tc.Context.LangOpts.WarnSwift3ObjCInference) {
tc.Context.LangOpts.WarnSwift3ObjCInference
== Swift3ObjCInferenceWarnings::Minimal) {
tc.diagnose(memberLoc,
diag::expr_dynamic_lookup_swift3_objc_inference,
member->getDescriptiveKind(),
Expand Down Expand Up @@ -3954,7 +3955,8 @@ namespace {
// If this attribute was inferred based on deprecated Swift 3 rules,
// complain.
if (attr->isSwift3Inferred() &&
!tc.Context.LangOpts.WarnSwift3ObjCInference) {
tc.Context.LangOpts.WarnSwift3ObjCInference
== Swift3ObjCInferenceWarnings::Minimal) {
tc.diagnose(E->getLoc(), diag::expr_selector_swift3_objc_inference,
foundDecl->getDescriptiveKind(), foundDecl->getFullName(),
foundDecl->getDeclContext()
Expand Down
10 changes: 7 additions & 3 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2416,7 +2416,9 @@ static Optional<ObjCReason> shouldMarkAsObjC(TypeChecker &TC,
if (TC.Context.LangOpts.EnableSwift3ObjCInference) {
// If we've been asked to warn about deprecated @objc inference, do so
// now.
if (TC.Context.LangOpts.WarnSwift3ObjCInference && !isAccessor) {
if (TC.Context.LangOpts.WarnSwift3ObjCInference !=
Swift3ObjCInferenceWarnings::None &&
!isAccessor) {
TC.diagnose(VD, diag::objc_inference_swift3_dynamic)
.highlight(attr->getLocation())
.fixItInsert(VD->getAttributeInsertionLoc(/*forModifier=*/false),
Expand Down Expand Up @@ -2845,7 +2847,8 @@ void swift::markAsObjC(TypeChecker &TC, ValueDecl *D,
// If we've been asked to unconditionally warn about these deprecated
// @objc inference rules, do so now. However, we don't warn about
// accessors---just the main storage declarations.
if (TC.Context.LangOpts.WarnSwift3ObjCInference &&
if (TC.Context.LangOpts.WarnSwift3ObjCInference ==
Swift3ObjCInferenceWarnings::Complete &&
!(isa<FuncDecl>(D) && cast<FuncDecl>(D)->isGetterOrSetter())) {
TC.diagnose(D, diag::objc_inference_swift3_objc_derived);
TC.diagnose(D, diag::objc_inference_swift3_addobjc)
Expand Down Expand Up @@ -6136,7 +6139,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {

// When warning about all deprecated @objc inference rules,
// we only need to do this check if we have implicit 'dynamic'.
if (TC.Context.LangOpts.WarnSwift3ObjCInference) {
if (TC.Context.LangOpts.WarnSwift3ObjCInference !=
Swift3ObjCInferenceWarnings::None) {
if (auto dynamicAttr = Base->getAttrs().getAttribute<DynamicAttr>())
if (!dynamicAttr->isImplicit()) return;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/Sema/TypeCheckExprObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ Optional<Type> TypeChecker::checkObjCKeyPathExpr(DeclContext *dc,
// If this attribute was inferred based on deprecated Swift 3 rules,
// complain.
if (attr->isSwift3Inferred() &&
!Context.LangOpts.WarnSwift3ObjCInference) {
Context.LangOpts.WarnSwift3ObjCInference ==
Swift3ObjCInferenceWarnings::Minimal) {
diagnose(componentNameLoc, diag::expr_keypath_swift3_objc_inference,
var->getFullName(),
var->getDeclContext()
Expand Down
2 changes: 1 addition & 1 deletion test/attr/attr_objc_swift3_deprecated.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify %s -swift-version 3 -warn-swift3-objc-inference
// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify %s -swift-version 3 -warn-swift3-objc-inference-complete
// REQUIRES: objc_interop

import Foundation
Expand Down
6 changes: 3 additions & 3 deletions test/attr/attr_objc_swift3_deprecated_uses.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify %s -swift-version 3
// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify %s -swift-version 3 -warn-swift3-objc-inference-minimal
// REQUIRES: objc_interop

import Foundation
Expand Down Expand Up @@ -30,9 +30,9 @@ class ObjCSubclass : NSObject {
}

class DynamicMembers {
dynamic func foo() { }
dynamic func foo() { } // expected-warning{{inference of '@objc' for 'dynamic' members is deprecated}}{{3-3=@objc }}

dynamic var bar: NSObject? = nil
dynamic var bar: NSObject? = nil // expected-warning{{inference of '@objc' for 'dynamic' members is deprecated}}{{3-3=@objc }}

func overridableFunc() { }
var overridableVar: NSObject? = nil
Expand Down