Skip to content

Commit 904a2ff

Browse files
committed
Allow unavailable conformances to non-Sendaable protocols during contraction
Refusing to acknowledge unavailable conformances at this point in the requirement machine doesn't allow us to make use of unavailable conformances from unavailable contexts, something which code currently depends on. Limit the new filtering behavior to `Sendable` conformances where we need them, as a narrow fix for this regression. We'll revisit the approach here later. Fixes rdar://94154905.
1 parent 6267513 commit 904a2ff

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

lib/AST/RequirementMachine/ConcreteContraction.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,16 @@ Optional<Type> ConcreteContraction::substTypeParameterRec(
271271
auto *proto = assocType->getProtocol();
272272
auto *module = proto->getParentModule();
273273

274+
bool allowUnavailable =
275+
!proto->isSpecificProtocol(KnownProtocolKind::Sendable);
274276
// The 'Sendable' protocol does not declare any associated types, so the
275277
// 'allowMissing' value here is actually irrelevant.
276278
auto conformance = ((*substBaseType)->isTypeParameter()
277279
? ProtocolConformanceRef(proto)
278280
: module->lookupConformance(
279281
*substBaseType, proto,
280282
/*allowMissing=*/false,
281-
/*allowUnavailable=*/false));
283+
allowUnavailable));
282284

283285
// The base type doesn't conform, in which case the requirement remains
284286
// unsubstituted.
@@ -391,9 +393,11 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
391393
if (ConcreteTypes.count(stripBoundDependentMemberTypes(firstType)) > 0)
392394
allowMissing = true;
393395

396+
bool allowUnavailable =
397+
!proto->isSpecificProtocol(KnownProtocolKind::Sendable);
394398
if (!substFirstType->isTypeParameter() &&
395399
!module->lookupConformance(substFirstType, proto,
396-
allowMissing, /*allowUnavailable=*/false)) {
400+
allowMissing, allowUnavailable)) {
397401
// Handle the case of <T where T : P, T : C> where C is a class and
398402
// C does not conform to P by leaving the conformance requirement
399403
// unsubstituted.

test/Generics/superclass_constraint.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,7 @@ extension Animal: Pony { }
230230

231231
public struct AnimalWrapper<Friend: Animal> { }
232232

233-
// CHECK: Generic signature: <Friend where Friend : Animal, Friend : Pony>
233+
// FIXME: Generic signature: <Friend where Friend : Animal, Friend : Pony>
234+
// Generic signature: <Friend where Friend : Animal>
234235
extension AnimalWrapper: Pony where Friend: Pony { }
236+
// expected-warning@-1{{redundant conformance constraint 'Animal' : 'Pony'}}

test/decl/protocol/unavailable.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P { }
4+
5+
struct X { }
6+
7+
@available(*, unavailable)
8+
extension X: P { }
9+
10+
struct Y<T: P> { }
11+
12+
@available(*, unavailable)
13+
extension Y {
14+
// Okay, because the unavailable conformance is used within an
15+
// unavailable context.
16+
init() where T == X { }
17+
}

0 commit comments

Comments
 (0)