Skip to content

Commit 629ba5b

Browse files
authored
Merge pull request #76053 from tshortli/associated-conformance-availability
Sema: Relax associated conformance availability checking
2 parents 5d3192a + 359de85 commit 629ba5b

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ ExportContext ExportContext::withExported(bool exported) const {
295295
return copy;
296296
}
297297

298+
ExportContext ExportContext::withRefinedAvailability(
299+
const AvailabilityContext &availability) const {
300+
auto copy = *this;
301+
copy.RunningOSVersion.intersectWith(availability);
302+
return copy;
303+
}
304+
298305
std::optional<PlatformKind> ExportContext::getUnavailablePlatformKind() const {
299306
if (Unavailable)
300307
return PlatformKind(Platform);

lib/Sema/TypeCheckAvailability.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class ExportContext {
153153
/// That is, this will perform a 'bitwise and' on the 'exported' bit.
154154
ExportContext withExported(bool exported) const;
155155

156+
/// Produce a new context with the same properties as this one, except the
157+
/// availability context is constrained by \p availability if necessary.
158+
ExportContext
159+
withRefinedAvailability(const AvailabilityContext &availability) const;
160+
156161
DeclContext *getDeclContext() const { return DC; }
157162

158163
AvailabilityContext getAvailabilityContext() const {

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4987,9 +4987,21 @@ static void ensureRequirementsAreSatisfied(ASTContext &ctx,
49874987
if (assocConf.isConcrete()) {
49884988
auto *concrete = assocConf.getConcrete();
49894989
auto replacementTy = dc->mapTypeIntoContext(concrete->getType());
4990-
diagnoseConformanceAvailability(conformance->getLoc(),
4991-
assocConf, where,
4992-
depTy, replacementTy);
4990+
4991+
// If this requirement has a dependent member type, only require the
4992+
// associated conformance to be as available as the requirement's
4993+
// associated type.
4994+
auto availability = AvailabilityContext::alwaysAvailable();
4995+
if (auto depMemberType = depTy->getAs<DependentMemberType>()) {
4996+
auto assocType = depMemberType->getAssocType();
4997+
availability.intersectWith(
4998+
TypeChecker::overApproximateAvailabilityAtLocation(
4999+
assocType->getLoc(), assocType->getDeclContext()));
5000+
}
5001+
5002+
diagnoseConformanceAvailability(
5003+
conformance->getLoc(), assocConf,
5004+
where.withRefinedAvailability(availability), depTy, replacementTy);
49935005
}
49945006

49955007
return false;

test/Sema/conformance_availability.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ func passAvailableConformance1a(x: HasAvailableConformance1) {
279279
_ = UsesHorse<HasAvailableConformance1>.self
280280
}
281281

282+
// Always available conformance
283+
struct HasAvailableConformance2: Horse {}
284+
285+
// Conformance available in macOS 200
286+
struct HasAvailableConformance3 {}
287+
288+
@available(macOS 200, *)
289+
extension HasAvailableConformance3: Horse {}
290+
282291
// Associated conformance with unavailability
283292
protocol Rider {
284293
associatedtype H : Horse
@@ -326,6 +335,58 @@ extension AssocConformanceAvailable4 : Rider {
326335
typealias H = HasAvailableConformance1
327336
}
328337

338+
@available(macOS 100, *)
339+
protocol Saddle {
340+
associatedtype H : Horse = HasAvailableConformance1
341+
}
342+
343+
struct ConformsToSaddle1 : Saddle {}
344+
345+
struct ConformsToSaddle2 : Saddle {
346+
typealias H = HasAvailableConformance2
347+
}
348+
349+
struct ConformsToSaddle3 : Saddle {
350+
// expected-error@-1 {{conformance of 'HasAvailableConformance3' to 'Horse' is only available in macOS 200 or newer}}
351+
// expected-note@-2 {{add @available attribute to enclosing struct}}
352+
// expected-note@-3 {{in associated type 'Self.H' (inferred as 'HasAvailableConformance3'}}
353+
typealias H = HasAvailableConformance3
354+
}
355+
356+
struct ConformsToSaddle4 : Saddle {
357+
// expected-error@-1 {{conformance of 'HasAvailableConformance3' to 'Horse' is only available in macOS 200 or newer}}
358+
// expected-note@-2 {{add @available attribute to enclosing struct}}
359+
// expected-note@-3 {{in associated type 'Self.H' (inferred as 'HasAvailableConformance3'}}
360+
@available(macOS 200, *)
361+
typealias H = HasAvailableConformance3
362+
}
363+
364+
protocol Barn {
365+
@available(macOS 100, *)
366+
associatedtype H : Horse = HasAvailableConformance1
367+
}
368+
369+
struct ConformsToBarn1 : Barn {}
370+
371+
struct ConformsToBarn2 : Barn {
372+
typealias H = HasAvailableConformance2
373+
}
374+
375+
struct ConformsToBarn3 : Barn {
376+
// expected-error@-1 {{conformance of 'HasAvailableConformance3' to 'Horse' is only available in macOS 200 or newer}}
377+
// expected-note@-2 {{add @available attribute to enclosing struct}}
378+
// expected-note@-3 {{in associated type 'Self.H' (inferred as 'HasAvailableConformance3'}}
379+
typealias H = HasAvailableConformance3
380+
}
381+
382+
struct ConformsToBarn4 : Barn {
383+
// expected-error@-1 {{conformance of 'HasAvailableConformance3' to 'Horse' is only available in macOS 200 or newer}}
384+
// expected-note@-2 {{add @available attribute to enclosing struct}}
385+
// expected-note@-3 {{in associated type 'Self.H' (inferred as 'HasAvailableConformance3'}}
386+
@available(macOS 200, *)
387+
typealias H = HasAvailableConformance3
388+
}
389+
329390
// Solution ranking should down-rank solutions involving unavailable conformances
330391
protocol First {}
331392
extension First {

0 commit comments

Comments
 (0)