Skip to content

Commit 765ce78

Browse files
committed
Sema: Downgrade potentially unavailable enum cases to a warning in module interfaces
There are two pieces here: - A -warn-on-potentially-unavailable-enum-case flag is passed down by the driver when *producing* a swiftinterface - When *consuming* a swiftinterface, also enable this behavior Part of rdar://problem/78306593.
1 parent 85891fd commit 765ce78

File tree

8 files changed

+54
-3
lines changed

8 files changed

+54
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5354,6 +5354,10 @@ ERROR(availability_enum_element_no_potential,
53545354
none, "enum cases with associated values cannot be marked potentially unavailable with "
53555355
"'@available'", ())
53565356

5357+
WARNING(availability_enum_element_no_potential_warn,
5358+
none, "enum cases with associated values cannot be marked potentially unavailable with "
5359+
"'@available'", ())
5360+
53575361
ERROR(availability_protocol_requires_version,
53585362
none, "protocol %0 requires %1 to be available in %2 %3 and newer",
53595363
(Identifier, DeclName, StringRef, llvm::VersionTuple))

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ namespace swift {
134134
/// Should conformance availability violations be diagnosed as errors?
135135
bool EnableConformanceAvailabilityErrors = false;
136136

137+
/// Should potential unavailability on enum cases be downgraded to a warning?
138+
bool WarnOnPotentiallyUnavailableEnumCase = false;
139+
137140
/// Maximum number of typo corrections we are allowed to perform.
138141
/// This is disabled by default until we can get typo-correction working within acceptable performance bounds.
139142
unsigned TypoCorrectionLimit = 0;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,10 @@ def disable_conformance_availability_errors : Flag<["-"],
453453
"disable-conformance-availability-errors">,
454454
HelpText<"Diagnose conformance availability violations as warnings">;
455455

456+
def warn_on_potentially_unavailable_enum_case : Flag<["-"],
457+
"warn-on-potentially-unavailable-enum-case">,
458+
HelpText<"Downgrade potential unavailability of enum case to a warning">;
459+
456460
def report_errors_to_debugger : Flag<["-"], "report-errors-to-debugger">,
457461
HelpText<"Deprecated, will be removed in future versions.">;
458462

lib/Driver/ToolChains.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
175175
arguments.push_back("-aarch64-use-tbi");
176176
}
177177

178+
if (output.getPrimaryOutputType() == file_types::TY_SwiftModuleFile) {
179+
arguments.push_back("-warn-on-potentially-unavailable-enum-case");
180+
}
181+
178182
// Enable or disable ObjC interop appropriately for the platform
179183
if (Triple.isOSDarwin()) {
180184
arguments.push_back("-enable-objc-interop");

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
457457
= A->getOption().matches(OPT_enable_conformance_availability_errors);
458458
}
459459

460+
Opts.WarnOnPotentiallyUnavailableEnumCase |=
461+
Args.hasArg(OPT_warn_on_potentially_unavailable_enum_case);
460462
if (auto A = Args.getLastArg(OPT_enable_access_control,
461463
OPT_disable_access_control)) {
462464
Opts.EnableAccessControl

lib/Sema/TypeCheckAttr.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,6 +3365,8 @@ Type TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, Type type,
33653365

33663366
Optional<Diag<>>
33673367
TypeChecker::diagnosticIfDeclCannotBePotentiallyUnavailable(const Decl *D) {
3368+
auto *DC = D->getDeclContext();
3369+
33683370
if (auto *VD = dyn_cast<VarDecl>(D)) {
33693371
if (!VD->hasStorage())
33703372
return None;
@@ -3377,14 +3379,23 @@ TypeChecker::diagnosticIfDeclCannotBePotentiallyUnavailable(const Decl *D) {
33773379

33783380
// Globals and statics are lazily initialized, so they are safe
33793381
// for potential unavailability.
3380-
if (!VD->isStatic() && !VD->getDeclContext()->isModuleScopeContext())
3382+
if (!VD->isStatic() && !DC->isModuleScopeContext())
33813383
return diag::availability_stored_property_no_potential;
33823384

33833385
} else if (auto *EED = dyn_cast<EnumElementDecl>(D)) {
33843386
// An enum element with an associated value cannot be potentially
33853387
// unavailable.
3386-
if (EED->hasAssociatedValues())
3387-
return diag::availability_enum_element_no_potential;
3388+
if (EED->hasAssociatedValues()) {
3389+
auto &ctx = DC->getASTContext();
3390+
auto *SF = DC->getParentSourceFile();
3391+
3392+
if (SF->Kind == SourceFileKind::Interface ||
3393+
ctx.LangOpts.WarnOnPotentiallyUnavailableEnumCase) {
3394+
return diag::availability_enum_element_no_potential_warn;
3395+
} else {
3396+
return diag::availability_enum_element_no_potential;
3397+
}
3398+
}
33883399
}
33893400

33903401
return None;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public enum Horse {
2+
@available(macOS 100, *)
3+
case kevin(Int)
4+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-build-swift -emit-module %S/Inputs/availability_enum_case_other.swift -emit-module-interface-path %t/availability_enum_case_other.swiftinterface -swift-version 5 -enable-library-evolution
4+
// RUN: %target-typecheck-verify-swift -I %t
5+
6+
// RUN: %target-build-swift -emit-module %S/Inputs/availability_enum_case_other.swift -emit-module-interface-path %t/availability_enum_case_other.swiftinterface -swift-version 5 -enable-library-evolution -whole-module-optimization
7+
// RUN: %target-typecheck-verify-swift -I %t
8+
9+
// REQUIRES: OS=macosx
10+
11+
import availability_enum_case_other
12+
13+
func ride(horse: Horse) {
14+
// expected-note@-1 {{add @available attribute to enclosing global function}}
15+
16+
_ = Horse.kevin
17+
// expected-error@-1 {{'kevin' is only available in macOS 100 or newer}}
18+
// expected-note@-2 {{add 'if #available' version check}}
19+
}

0 commit comments

Comments
 (0)