Skip to content

Commit 64eb9df

Browse files
authored
Merge pull request #67798 from slavapestov/fix-rdar113103854
Sema: Fix a couple of problems in checkContextualRequirements()
2 parents e4310d7 + a7c276b commit 64eb9df

File tree

5 files changed

+55
-13
lines changed

5 files changed

+55
-13
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -603,29 +603,43 @@ bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl,
603603
return true;
604604
}
605605

606+
// Protocols can't appear in constrained extensions, and their where
607+
// clauses pertain to the requirement signature of the protocol and not
608+
// its generic signature.
609+
if (isa<ProtocolDecl>(decl))
610+
return true;
611+
612+
auto *dc = decl->getDeclContext();
613+
614+
const auto genericSig = decl->getGenericSignature();
615+
616+
if (genericSig.getPointer() ==
617+
dc->getSelfNominalTypeDecl()->getGenericSignature().getPointer()) {
618+
return true;
619+
}
620+
621+
// Otherwise, our decl has a where clause of its own, or its inside of a
622+
// constrained extension.
606623
SourceLoc noteLoc;
607624
{
608-
// We are interested in either a contextual where clause or
609-
// a constrained extension context.
610-
const auto ext = dyn_cast<ExtensionDecl>(decl->getDeclContext());
611-
if (decl->getTrailingWhereClause())
612-
noteLoc = decl->getLoc();
613-
else if (ext && ext->isConstrainedExtension())
625+
const auto ext = dyn_cast<ExtensionDecl>(dc);
626+
if (ext && genericSig.getPointer() ==
627+
ext->getGenericSignature().getPointer()) {
614628
noteLoc = ext->getLoc();
615-
else
616-
return true;
629+
} else {
630+
noteLoc = decl->getLoc();
631+
}
617632

618633
if (noteLoc.isInvalid())
619634
noteLoc = loc;
620635
}
621636

622-
const auto subMap = parentTy->getContextSubstitutions(decl->getDeclContext());
623-
const auto genericSig = decl->getGenericSignature();
624-
637+
const auto subMap = parentTy->getContextSubstitutions(dc);
625638
const auto substitutions = [&](SubstitutableType *type) -> Type {
626639
auto result = QueryTypeSubstitutionMap{subMap}(type);
627640
if (result->hasTypeParameter()) {
628641
if (contextSig) {
642+
// Avoid building this generic environment unless we need it.
629643
auto *genericEnv = contextSig.getGenericEnvironment();
630644
return genericEnv->mapTypeIntoContext(result);
631645
}

test/Sema/Inputs/where_clause_across_module_boundaries_module.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,11 @@ public extension DefaultsSerializable where Self: RawRepresentable {
2323

2424
public struct ModuleAFoo: Codable, DefaultsSerializable {
2525
}
26+
27+
public struct AliasTest<T> {
28+
public typealias A = T.Element where T: Collection
29+
}
30+
31+
extension AliasTest where T: Collection {
32+
public typealias B = T.Element
33+
}

test/Sema/where_clause_across_module_boundaries.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ struct ModuleBFoo: Codable, DefaultsSerializable {
1414
enum ModuleBBar: Int, Codable, DefaultsSerializable { // expected-error {{type 'ModuleBBar' does not conform to protocol 'DefaultsSerializable'}}
1515
case foo, bar
1616
}
17+
18+
func foo() {
19+
_ = AliasTest<Int>.A.self // expected-error {{type 'Int' does not conform to protocol 'Collection'}}
20+
_ = AliasTest<Int>.B.self // expected-error {{type 'Int' does not conform to protocol 'Collection'}}
21+
_ = AliasTest<String>.A.self
22+
_ = AliasTest<String>.B.self
23+
}

test/decl/nested/protocol.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,16 @@ func testLookup<T: OuterForUFI.Inner>(_ x: T) {
114114
x.req()
115115
x.extMethod()
116116
}
117+
118+
// rdar://problem/113103854
119+
120+
protocol Q {
121+
associatedtype A
122+
}
123+
124+
struct OuterNonGeneric {
125+
protocol P: Q where Self.A == Int {}
126+
// expected-error@-1 {{protocol 'P' cannot be nested inside another declaration}}
127+
}
128+
129+
func usesProtoWithWhereClause<T: OuterNonGeneric.P>(_: T) {}

validation-test/compiler_crashers_2_fixed/0161-issue-49119.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ protocol P {
88

99
struct Type<Param> {}
1010
extension Type: P where Param: P, Param.A == Type<Param> {
11-
// expected-error@-1 5{{extension of generic struct 'Type' has self-referential generic requirements}}
12-
// expected-note@-2 5{{through reference here}}
11+
// expected-error@-1 6{{extension of generic struct 'Type' has self-referential generic requirements}}
12+
// expected-note@-2 6{{through reference here}}
1313
// expected-error@-3 {{type 'Type<Param>' does not conform to protocol 'P'}}
1414
typealias A = Param
1515
// expected-note@-1 2{{through reference here}}

0 commit comments

Comments
 (0)