Skip to content

Commit 25e0a9f

Browse files
theblixguyslavapestov
authored andcommitted
[Typechecker] Fix an issue with redeclaration checking (swiftlang#23227)
* [typechecker] fix an issue with redeclaration checking * [typechecker] use mapSignatureFunctionType in getOverloadSignatureType() to compute the type for the enum element decl, etc * [typechecker] allow matching enums to functions as well, not just functions to enums * [typechecker] fix the check for two enums * [typechecker] check for nominal types as well when comparing enum elements * [test] add more tests * [typechecker] check for typealias as well
1 parent 0c923e0 commit 25e0a9f

File tree

3 files changed

+162
-0
lines changed

3 files changed

+162
-0
lines changed

include/swift/AST/Decl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ struct OverloadSignature {
213213
/// Whether this is a function.
214214
unsigned IsFunction : 1;
215215

216+
/// Whether this is a enum element.
217+
unsigned IsEnumElement : 1;
218+
219+
/// Whether this is a nominal type.
220+
unsigned IsNominal : 1;
221+
222+
/// Whether this is a type alias.
223+
unsigned IsTypeAlias : 1;
224+
216225
/// Whether this signature is part of a protocol extension.
217226
unsigned InProtocolExtension : 1;
218227

lib/AST/Decl.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,32 @@ bool swift::conflicting(ASTContext &ctx,
20902090
if (!conflicting(sig1, sig2, skipProtocolExtensionCheck))
20912091
return false;
20922092

2093+
// Functions and enum elements do not conflict with each other if their types
2094+
// are different.
2095+
if (((sig1.IsFunction && sig2.IsEnumElement) ||
2096+
(sig1.IsEnumElement && sig2.IsFunction)) &&
2097+
sig1Type != sig2Type) {
2098+
return false;
2099+
}
2100+
2101+
// Nominal types and enum elements always conflict with each other.
2102+
if ((sig1.IsNominal && sig2.IsEnumElement) ||
2103+
(sig1.IsEnumElement && sig2.IsNominal)) {
2104+
return true;
2105+
}
2106+
2107+
// Typealiases and enum elements always conflict with each other.
2108+
if ((sig1.IsTypeAlias && sig2.IsEnumElement) ||
2109+
(sig1.IsEnumElement && sig2.IsTypeAlias)) {
2110+
return true;
2111+
}
2112+
2113+
// Enum elements always conflict with each other. At this point, they
2114+
// have the same base name but different types.
2115+
if (sig1.IsEnumElement && sig2.IsEnumElement) {
2116+
return true;
2117+
}
2118+
20932119
// Functions always conflict with non-functions with the same signature.
20942120
// In practice, this only applies for zero argument functions.
20952121
if (sig1.IsFunction != sig2.IsFunction)
@@ -2248,6 +2274,9 @@ OverloadSignature ValueDecl::getOverloadSignature() const {
22482274
signature.IsInstanceMember = isInstanceMember();
22492275
signature.IsVariable = isa<VarDecl>(this);
22502276
signature.IsFunction = isa<AbstractFunctionDecl>(this);
2277+
signature.IsEnumElement = isa<EnumElementDecl>(this);
2278+
signature.IsNominal = isa<NominalTypeDecl>(this);
2279+
signature.IsTypeAlias = isa<TypeAliasDecl>(this);
22512280

22522281
// Unary operators also include prefix/postfix.
22532282
if (auto func = dyn_cast<FuncDecl>(this)) {
@@ -2293,6 +2322,13 @@ CanType ValueDecl::getOverloadSignatureType() const {
22932322
->getCanonicalType();
22942323
}
22952324

2325+
if (isa<EnumElementDecl>(this)) {
2326+
auto mappedType = mapSignatureFunctionType(
2327+
getASTContext(), getInterfaceType(), /*topLevelFunction=*/false,
2328+
/*isMethod=*/false, /*isInitializer=*/false, /*curryLevels=*/0);
2329+
return mappedType->getCanonicalType();
2330+
}
2331+
22962332
// Note: If you add more cases to this function, you should update the
22972333
// implementation of the swift::conflicting overload that deals with
22982334
// overload types, in order to account for cases where the overload types

test/decl/overload.swift

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,5 +476,122 @@ extension SR7250 where T : P3 {
476476
subscript(i: Int) -> String { return "" }
477477
}
478478

479+
// SR-10084
479480

481+
struct SR_10084_S {
482+
let name: String
483+
}
484+
485+
enum SR_10084_E {
486+
case foo(SR_10084_S) // expected-note {{'foo' previously declared here}}
487+
488+
static func foo(_ name: String) -> SR_10084_E { // Okay
489+
return .foo(SR_10084_S(name: name))
490+
}
491+
492+
func foo(_ name: Bool) -> SR_10084_E { // Okay
493+
return .foo(SR_10084_S(name: "Test"))
494+
}
495+
496+
static func foo(_ value: SR_10084_S) -> SR_10084_E { // expected-error {{invalid redeclaration of 'foo'}}
497+
return .foo(value)
498+
}
499+
}
500+
501+
enum SR_10084_E_1 {
502+
static func foo(_ name: String) -> SR_10084_E_1 { // Okay
503+
return .foo(SR_10084_S(name: name))
504+
}
505+
506+
static func foo(_ value: SR_10084_S) -> SR_10084_E_1 { // expected-note {{'foo' previously declared here}}
507+
return .foo(value)
508+
}
509+
510+
case foo(SR_10084_S) // expected-error {{invalid redeclaration of 'foo'}}
511+
}
512+
513+
enum SR_10084_E_2 {
514+
case fn(() -> Void) // expected-note {{'fn' previously declared here}}
515+
516+
static func fn(_ x: @escaping () -> Void) -> SR_10084_E_2 { // expected-error {{invalid redeclaration of 'fn'}}
517+
fatalError()
518+
}
519+
520+
static func fn(_ x: @escaping () -> Int) -> SR_10084_E_2 { // Okay
521+
fatalError()
522+
}
523+
524+
static func fn(_ x: @escaping () -> Bool) -> SR_10084_E_2 { // Okay
525+
fatalError()
526+
}
527+
}
528+
529+
enum SR_10084_E_3 {
530+
protocol A {} //expected-error {{protocol 'A' cannot be nested inside another declaration}} // expected-note {{'A' previously declared here}}
531+
case A // expected-error {{invalid redeclaration of 'A'}}
532+
}
533+
534+
enum SR_10084_E_4 {
535+
class B {} // expected-note {{'B' previously declared here}}
536+
case B // expected-error {{invalid redeclaration of 'B'}}
537+
}
538+
539+
enum SR_10084_E_5 {
540+
struct C {} // expected-note {{'C' previously declared here}}
541+
case C // expected-error {{invalid redeclaration of 'C'}}
542+
}
543+
544+
enum SR_10084_E_6 {
545+
case D // expected-note {{'D' previously declared here}}
546+
protocol D {} //expected-error {{protocol 'D' cannot be nested inside another declaration}} // expected-error {{invalid redeclaration of 'D'}}
547+
}
548+
549+
enum SR_10084_E_7 {
550+
case E // expected-note {{'E' previously declared here}}
551+
class E {} // expected-error {{invalid redeclaration of 'E'}}
552+
}
553+
554+
enum SR_10084_E_8 {
555+
case F // expected-note {{'F' previously declared here}}
556+
struct F {} // expected-error {{invalid redeclaration of 'F'}}
557+
}
558+
559+
enum SR_10084_E_9 {
560+
case A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}}
561+
static let A: SR_10084_E_9 = .A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}} // expected-error {{ambiguous use of 'A'}}
562+
}
563+
564+
enum SR_10084_E_10 {
565+
static let A: SR_10084_E_10 = .A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}} // expected-error {{ambiguous use of 'A'}}
566+
case A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}}
567+
}
568+
569+
enum SR_10084_E_11 {
570+
case A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}}
571+
static var A: SR_10084_E_11 = .A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}} // expected-error {{ambiguous use of 'A'}}
572+
}
573+
574+
enum SR_10084_E_12 {
575+
static var A: SR_10084_E_12 = .A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}} // expected-error {{ambiguous use of 'A'}}
576+
case A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}}
577+
}
578+
579+
enum SR_10084_E_13 {
580+
case X // expected-note {{'X' previously declared here}}
581+
struct X<T> {} // expected-error {{invalid redeclaration of 'X'}}
582+
}
583+
584+
enum SR_10084_E_14 {
585+
struct X<T> {} // expected-note {{'X' previously declared here}}
586+
case X // expected-error {{invalid redeclaration of 'X'}}
587+
}
588+
589+
enum SR_10084_E_15 {
590+
case Y // expected-note {{'Y' previously declared here}}
591+
typealias Y = Int // expected-error {{invalid redeclaration of 'Y'}}
592+
}
480593

594+
enum SR_10084_E_16 {
595+
typealias Z = Int // expected-note {{'Z' previously declared here}}
596+
case Z // expected-error {{invalid redeclaration of 'Z'}}
597+
}

0 commit comments

Comments
 (0)