Skip to content

Commit daeb019

Browse files
committed
WIP
1 parent 189c1d3 commit daeb019

File tree

7 files changed

+41
-49
lines changed

7 files changed

+41
-49
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6778,7 +6778,7 @@ WARNING(availability_enum_element_no_potential_warn,
67786778

67796779
ERROR(availability_protocol_requires_version,
67806780
none, "protocol %0 requires %1 to be available in %2 %3 and newer",
6781-
(Identifier, DeclName, StringRef, llvm::VersionTuple))
6781+
(const ProtocolDecl *, const ValueDecl *, StringRef, llvm::VersionTuple))
67826782

67836783
NOTE(availability_protocol_requirement_here, none,
67846784
"protocol requirement here", ())
@@ -6858,12 +6858,6 @@ NOTE(type_witness_availability_obsoleted, none,
68586858
(const ValueDecl *, const AssociatedTypeDecl *, const ProtocolDecl *,
68596859
StringRef, llvm::VersionTuple))
68606860

6861-
ERROR(type_witness_availability_only_version_newer, none,
6862-
"%kindonly0 witnessing requirement %1 of %2 is "
6863-
"only available in %3 %4 or newer",
6864-
(const ValueDecl *, const AssociatedTypeDecl *, const ProtocolDecl *,
6865-
StringRef, llvm::VersionTuple))
6866-
68676861
//------------------------------------------------------------------------------
68686862
// MARK: @discardableResult
68696863
//------------------------------------------------------------------------------

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4591,7 +4591,7 @@ swift::diagnoseSubstitutionMapAvailability(SourceLoc loc,
45914591
}
45924592

45934593
static bool diagnoseExplicitUnavailabilityForTypeWitness(
4594-
const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4594+
SourceLoc loc, const TypeDecl *witness, const AssociatedTypeDecl *assocType,
45954595
const ExportContext &where) {
45964596
auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo(witness, where);
45974597
if (!diagnosticInfo)
@@ -4633,55 +4633,49 @@ static bool diagnoseExplicitUnavailabilityForTypeWitness(
46334633
}
46344634

46354635
static void diagnosePotentialUnavailabilityForTypeWitness(
4636-
const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4637-
const DeclContext *dc, const UnavailabilityReason &reason) {
4636+
SourceLoc loc, const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4637+
const DeclContext *dc, const AvailabilityContext &requiredAvailability) {
46384638
auto &ctx = dc->getASTContext();
46394639
auto proto = assocType->getProtocol();
4640-
auto requiredRange = reason.getRequiredOSVersionRange();
4641-
auto loc = witness->getLoc();
4640+
auto requiredRange = requiredAvailability.getOSVersion();
46424641

46434642
{
46444643
auto err = ctx.Diags.diagnose(
4645-
loc, diag::type_witness_availability_only_version_newer, witness,
4646-
assocType, proto, prettyPlatformString(targetPlatform(ctx.LangOpts)),
4644+
loc, diag::availability_protocol_requires_version, proto,
4645+
assocType, witness, prettyPlatformString(targetPlatform(ctx.LangOpts)),
46474646
requiredRange.getLowerEndpoint());
46484647
err.warnUntilSwiftVersion(7);
46494648

46504649
// Direct a fixit to the error if an existing guard is nearly-correct
4651-
if (fixAvailabilityByNarrowingNearbyVersionCheck(loc, dc, requiredRange,
4652-
ctx, err))
4650+
if (fixAvailabilityByNarrowingNearbyVersionCheck(witness->getLoc(), dc,
4651+
requiredRange, ctx, err))
46534652
return;
46544653
}
46554654

4656-
fixAvailability(loc, dc, requiredRange, ctx);
4655+
fixAvailability(witness->getLoc(), dc, requiredRange, ctx);
4656+
4657+
if (loc != witness->getLoc())
4658+
ctx.Diags.diagnose(witness, diag::decl_declared_here, witness);
46574659
}
46584660

46594661
bool swift::diagnoseTypeWitnessAvailability(
4660-
const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4662+
SourceLoc loc, const TypeDecl *witness, const AssociatedTypeDecl *assocType,
46614663
const NormalProtocolConformance *conformance, const ExportContext &where) {
46624664
if (where.isImplicit() || witness->isImplicit())
46634665
return false;
46644666

46654667
if (witness->isInvalid())
46664668
return false;
46674669

4668-
if (diagnoseExplicitUnavailabilityForTypeWitness(witness, assocType, where))
4670+
if (diagnoseExplicitUnavailabilityForTypeWitness(loc, witness, assocType,
4671+
where))
46694672
return true;
46704673

46714674
auto dc = conformance->getDeclContext();
4672-
auto &ctx = dc->getASTContext();
4673-
4674-
// The witness must be as available as the associated type and the conformance
4675-
// itself.
4676-
auto availability = AvailabilityInference::availableRange(assocType, ctx);
4677-
availability.intersectWith(
4678-
AvailabilityInference::availableRange(dc->getAsDecl(), ctx));
4679-
4680-
auto maybeUnavail = TypeChecker::checkDeclarationAvailability(
4681-
witness, where.withRefinedAvailability(availability));
4682-
if (maybeUnavail.has_value()) {
4683-
diagnosePotentialUnavailabilityForTypeWitness(witness, assocType, dc,
4684-
*maybeUnavail);
4675+
auto requiredAvailability = AvailabilityContext::alwaysAvailable();
4676+
if (!TypeChecker::isAvailabilitySafeForConformance(conformance->getProtocol(), assocType, witness, dc, requiredAvailability)) {
4677+
diagnosePotentialUnavailabilityForTypeWitness(loc, witness, assocType, dc,
4678+
requiredAvailability);
46854679
return true;
46864680
}
46874681

lib/Sema/TypeCheckAvailability.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ bool diagnoseSubstitutionMapAvailability(
247247
/// Diagnoses use of unavailable types as witnesses for associated type
248248
/// requirements. Returns true if a diagnostic was emitted.
249249
bool diagnoseTypeWitnessAvailability(
250-
const TypeDecl *witness, const AssociatedTypeDecl *assocType,
250+
SourceLoc loc, const TypeDecl *witness, const AssociatedTypeDecl *assocType,
251251
const NormalProtocolConformance *conformance, const ExportContext &context);
252252

253253
/// Diagnose uses of unavailable declarations. Returns true if a diagnostic

lib/Sema/TypeCheckDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,8 +1689,8 @@ SelfAccessKindRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const {
16891689
}
16901690

16911691
bool TypeChecker::isAvailabilitySafeForConformance(
1692-
ProtocolDecl *proto, ValueDecl *requirement, ValueDecl *witness,
1693-
DeclContext *dc, AvailabilityContext &requirementInfo) {
1692+
const ProtocolDecl *proto, const ValueDecl *requirement, const ValueDecl *witness,
1693+
const DeclContext *dc, AvailabilityContext &requirementInfo) {
16941694

16951695
// We assume conformances in
16961696
// non-SourceFiles have already been checked for availability.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4313,8 +4313,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
43134313
SourceLoc diagLoc = getLocForDiagnosingWitness(conformance, witness);
43144314
diags.diagnose(
43154315
diagLoc, diag::availability_protocol_requires_version,
4316-
conformance->getProtocol()->getName(),
4317-
witness->getName(),
4316+
conformance->getProtocol(),
4317+
witness,
43184318
prettyPlatformString(targetPlatform(ctx.LangOpts)),
43194319
check.RequiredAvailability.getOSVersion().getLowerEndpoint());
43204320
emitDeclaredHereIfNeeded(diags, diagLoc, witness);
@@ -4909,9 +4909,10 @@ static void ensureRequirementsAreSatisfied(ASTContext &ctx,
49094909
}
49104910

49114911
// The type witness must be as available as the associated type.
4912-
if (auto witnessTypeDecl = type->getAnyNominal()) {
4913-
diagnoseTypeWitnessAvailability(witnessTypeDecl, assocType, conformance,
4914-
where);
4912+
if (auto witness = type->getAnyNominal()) {
4913+
SourceLoc diagLoc = getLocForDiagnosingWitness(conformance, witness);
4914+
diagnoseTypeWitnessAvailability(diagLoc, witness, assocType,
4915+
conformance, where);
49154916
}
49164917

49174918
// Make sure any associated type witnesses don't make reference to a

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -991,8 +991,8 @@ bool diagnoseConformanceExportability(SourceLoc loc,
991991
/// the provided conformance. On return, requiredAvailability holds th
992992
/// availability levels required for conformance.
993993
bool
994-
isAvailabilitySafeForConformance(ProtocolDecl *proto, ValueDecl *requirement,
995-
ValueDecl *witness, DeclContext *dc,
994+
isAvailabilitySafeForConformance(const ProtocolDecl *proto, const ValueDecl *requirement,
995+
const ValueDecl *witness, const DeclContext *dc,
996996
AvailabilityContext &requiredAvailability);
997997

998998
/// Returns an over-approximation of the range of operating system versions

test/decl/protocol/associated_type_witness_availability.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,23 +116,26 @@ protocol ProtoWithAssocTypeAndReq {
116116
func req(_ a: A)
117117
}
118118

119+
@available(macOS 11, *)
120+
struct InferredOld {} // Ok, InferredOld is less available than its parent but more available than the deployment target
121+
119122
struct ConformsToProtoWithAssocTypeAndReq_InferredWitnessOld: ProtoWithAssocTypeAndReq {
120-
@available(macOS 11, *)
121-
struct InferredOld {} // Ok, InferredOld is less available than its parent but more available than the deployment target
122123

123124
func req(_ a: InferredOld) {}
124125
}
125126

126-
struct ConformsToProtoWithAssocTypeAndReq_InferredWitnessSame: ProtoWithAssocTypeAndReq {
127-
@available(macOS 12, *)
128-
struct InferredSame {} // Ok, InferredSame is less available than its parent but available at the deployment target
127+
@available(macOS 12, *)
128+
struct InferredSame {} // Ok, InferredSame is less available than its parent but available at the deployment target
129129

130+
struct ConformsToProtoWithAssocTypeAndReq_InferredWitnessSame: ProtoWithAssocTypeAndReq {
130131
func req(_ a: InferredSame) {}
131132
}
132133

134+
@available(macOS 13, *)
135+
struct InferredTooNew {} // expected-note {{'InferredTooNew' declared here}}
136+
133137
struct ConformsToProtoWithAssocTypeAndReq_InferredWitnessTooNew: ProtoWithAssocTypeAndReq {
134-
@available(macOS 13, *)
135-
struct InferredTooNew {} // expected-warning {{struct witnessing requirement 'A' of 'ProtoWithAssocTypeAndReq' is only available in macOS 13 or newer; this will be an error in a future Swift language mode}}
138+
// expected-warning@-1 {{struct witnessing requirement 'A' of 'ProtoWithAssocTypeAndReq' is only available in macOS 13 or newer; this will be an error in a future Swift language mode}}
136139

137140
@available(macOS 13, *)
138141
func req(_ a: InferredTooNew) {}

0 commit comments

Comments
 (0)