Skip to content

Sema: (Mostly) check conformance availability #34565

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
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
33 changes: 3 additions & 30 deletions include/swift/AST/Availability.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,46 +182,19 @@ class VersionRange {

/// Records the reason a declaration is potentially unavailable.
class UnavailabilityReason {
public:
enum class Kind {
/// The declaration is potentially unavailable because it requires an OS
/// version range that is not guaranteed by the minimum deployment
/// target.
RequiresOSVersionRange,

/// The declaration is potentially unavailable because it is explicitly
/// weakly linked.
ExplicitlyWeakLinked
};

private:
// A value of None indicates the declaration is potentially unavailable
// because it is explicitly weak linked.
Optional<VersionRange> RequiredDeploymentRange;
VersionRange RequiredDeploymentRange;

UnavailabilityReason(const Optional<VersionRange> &RequiredDeploymentRange)
explicit UnavailabilityReason(const VersionRange RequiredDeploymentRange)
: RequiredDeploymentRange(RequiredDeploymentRange) {}

public:
static UnavailabilityReason explicitlyWeaklyLinked() {
return UnavailabilityReason(None);
}

static UnavailabilityReason requiresVersionRange(const VersionRange Range) {
return UnavailabilityReason(Range);
}

Kind getReasonKind() const {
if (RequiredDeploymentRange.hasValue()) {
return Kind::RequiresOSVersionRange;
} else {
return Kind::ExplicitlyWeakLinked;
}
}

const VersionRange &getRequiredOSVersionRange() const {
assert(getReasonKind() == Kind::RequiresOSVersionRange);
return RequiredDeploymentRange.getValue();
return RequiredDeploymentRange;
}
};

Expand Down
33 changes: 33 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5040,6 +5040,39 @@ ERROR(availabilty_string_subscript_migration, none,
"subscripts returning String were obsoleted in Swift 4; explicitly "
"construct a String from subscripted result", ())

// Conformance availability checking diagnostics

ERROR(conformance_availability_unavailable, none,
"conformance of %0 to %1 is unavailable"
"%select{ in %3|}2%select{|: %4}4",
(Type, Type, bool, StringRef, StringRef))

NOTE(conformance_availability_marked_unavailable, none,
"conformance of %0 to %1 has been explicitly marked "
"unavailable here", (Type, Type))

NOTE(conformance_availability_introduced_in_version, none,
"conformance of %0 to %1 was introduced in %2 %3",
(Type, Type, StringRef, llvm::VersionTuple))

NOTE(conformance_availability_obsoleted, none,
"conformance of %0 to %1 was obsoleted in %2 %3",
(Type, Type, StringRef, llvm::VersionTuple))

WARNING(conformance_availability_deprecated, none,
"conformance of %0 to %1 %select{is|%select{is|was}4}2 "
"deprecated%select{| in %3%select{| %5}4}2%select{|: %6}6",
(Type, Type, bool, StringRef, bool, llvm::VersionTuple,
StringRef))

ERROR(conformance_availability_only_version_newer, none,
"conformance of %0 to %1 is only available in %2 %3 or newer",
(Type, Type, StringRef, llvm::VersionTuple))

WARNING(conformance_availability_only_version_newer_warn, none,
"conformance of %0 to %1 is only available in %2 %3 or newer",
(Type, Type, StringRef, llvm::VersionTuple))

//------------------------------------------------------------------------------
// MARK: @discardableResult
//------------------------------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ namespace swift {
/// Disable API availability checking.
bool DisableAvailabilityChecking = false;

/// Should conformance availability violations be diagnosed as errors?
bool EnableConformanceAvailabilityErrors = false;

/// Maximum number of typo corrections we are allowed to perform.
/// This is disabled by default until we can get typo-correction working within acceptable performance bounds.
unsigned TypoCorrectionLimit = 0;
Expand Down
8 changes: 8 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,14 @@ def disable_availability_checking : Flag<["-"],
"disable-availability-checking">,
HelpText<"Disable checking for potentially unavailable APIs">;

def enable_conformance_availability_errors : Flag<["-"],
"enable-conformance-availability-errors">,
HelpText<"Diagnose conformance availability violations as errors">;

def disable_conformance_availability_errors : Flag<["-"],
"disable-conformance-availability-errors">,
HelpText<"Diagnose conformance availability violations as warnings">;

def report_errors_to_debugger : Flag<["-"], "report-errors-to-debugger">,
HelpText<"Deprecated, will be removed in future versions.">;

Expand Down
6 changes: 6 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,12 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.DisableAvailabilityChecking |=
Args.hasArg(OPT_disable_availability_checking);

if (auto A = Args.getLastArg(OPT_enable_conformance_availability_errors,
OPT_disable_conformance_availability_errors)) {
Opts.EnableConformanceAvailabilityErrors
= A->getOption().matches(OPT_enable_conformance_availability_errors);
}

if (auto A = Args.getLastArg(OPT_enable_access_control,
OPT_disable_access_control)) {
Opts.EnableAccessControl
Expand Down
7 changes: 3 additions & 4 deletions lib/Sema/ResilienceDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,16 @@ TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
bool
TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
const RootProtocolConformance *rootConf,
const ExtensionDecl *ext,
const ExportContext &where) {
if (!where.mustOnlyReferenceExportedDecls())
return false;

auto originKind = getDisallowedOriginKind(
rootConf->getDeclContext()->getAsDecl(),
where);
auto originKind = getDisallowedOriginKind(ext, where);
if (originKind == DisallowedOriginKind::None)
return false;

ModuleDecl *M = rootConf->getDeclContext()->getParentModule();
ModuleDecl *M = ext->getParentModule();
ASTContext &ctx = M->getASTContext();

auto reason = where.getExportabilityReason();
Expand Down
Loading