Skip to content

Commit 89636fa

Browse files
authored
Merge pull request swiftlang#35420 from slavapestov/relax-typealias-redeclaration-check
Sema: Allow re-declarations of typealiases in constrained extensions with different generic signatures
2 parents 7fada0a + b18c7fb commit 89636fa

File tree

3 files changed

+61
-5
lines changed

3 files changed

+61
-5
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -565,20 +565,22 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const {
565565
if (current == other || (other->hasInterfaceType() && other->isInvalid()))
566566
continue;
567567

568+
auto *otherDC = other->getDeclContext();
569+
568570
// Skip declarations in other modules.
569-
if (currentModule != other->getModuleContext())
571+
if (currentModule != otherDC->getParentModule())
570572
continue;
571573

572574
// If both declarations are in the same file, only diagnose the second one.
573-
if (currentFile == other->getDeclContext()->getParentSourceFile())
575+
if (currentFile == otherDC->getParentSourceFile())
574576
if (current->getLoc().isValid() &&
575577
ctx.SourceMgr.isBeforeInBuffer(
576578
current->getLoc(), other->getLoc()))
577579
continue;
578580

579581
// Don't compare methods vs. non-methods (which only happens with
580582
// operators).
581-
if (currentDC->isTypeContext() != other->getDeclContext()->isTypeContext())
583+
if (currentDC->isTypeContext() != otherDC->isTypeContext())
582584
continue;
583585

584586
// In local context, only consider exact name matches.
@@ -592,7 +594,7 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const {
592594
if (!conflicting(currentSig, otherSig))
593595
continue;
594596

595-
// Skip declarations in other files.
597+
// Skip inaccessible declarations in other files.
596598
// In practice, this means we will warn on a private declaration that
597599
// shadows a non-private one, but only in the file where the shadowing
598600
// happens. We will warn on conflicting non-private declarations in both
@@ -605,6 +607,15 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const {
605607
if (other->isInvalid())
606608
continue;
607609

610+
// Allow redeclarations of typealiases in different constrained
611+
// extensions.
612+
if (isa<TypeAliasDecl>(current) &&
613+
isa<TypeAliasDecl>(other) &&
614+
currentDC != otherDC &&
615+
currentDC->getGenericSignatureOfContext().getCanonicalSignature() !=
616+
otherDC->getGenericSignatureOfContext().getCanonicalSignature())
617+
continue;
618+
608619
// Thwart attempts to override the same declaration more than once.
609620
const auto *currentOverride = current->getOverriddenDecl();
610621
const auto *otherOverride = other->getOverriddenDecl();

test/decl/protocol/req/missing_conformance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ extension CountSteps1 // expected-error {{type 'CountSteps1<T>' does not conform
132132
where T : Equatable
133133
{
134134
typealias Index = Int
135-
// expected-error@-1 {{invalid redeclaration of synthesized implementation for protocol requirement 'Index'}}
135+
136136
func index(_ i: Index, offsetBy d: Int) -> Index {
137137
return i + d
138138
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
struct NonGenericStruct {
4+
typealias Horse = Int // expected-note {{'Horse' previously declared here}}
5+
typealias Horse = String // expected-error {{invalid redeclaration of 'Horse'}}
6+
}
7+
8+
struct NonGenericExtendedStruct {}
9+
10+
extension NonGenericExtendedStruct {
11+
typealias Horse = Int // expected-note {{'Horse' previously declared here}}
12+
}
13+
14+
extension NonGenericExtendedStruct {
15+
typealias Horse = String // expected-error {{invalid redeclaration of 'Horse'}}
16+
}
17+
18+
struct GenericStruct<T> {
19+
typealias Horse = Int // expected-note {{'Horse' previously declared here}}
20+
typealias Horse = String // expected-error {{invalid redeclaration of 'Horse'}}
21+
}
22+
23+
struct GenericExtendedStruct<T> {}
24+
25+
extension GenericExtendedStruct {
26+
typealias Horse = Int // expected-note {{'Horse' previously declared here}}
27+
}
28+
29+
extension GenericExtendedStruct {
30+
typealias Horse = String // expected-error {{invalid redeclaration of 'Horse'}}
31+
}
32+
33+
struct GenericConstrainedExtendedStruct<T> {}
34+
35+
protocol SomeProtocol {}
36+
37+
extension GenericConstrainedExtendedStruct where T : SomeProtocol {
38+
typealias Horse = Int
39+
}
40+
41+
protocol OtherProtocol {}
42+
43+
extension GenericConstrainedExtendedStruct where T : OtherProtocol {
44+
typealias Horse = String // This is OK!
45+
}

0 commit comments

Comments
 (0)