Skip to content

Commit 50e6f2a

Browse files
committed
[Amendment] SE-0296: Allow overloads that differ only in async
Implement the amendment currently under review that allows overloads that differ only in async vs. non-async. Implements rdar://79788345.
1 parent fd62b9c commit 50e6f2a

File tree

4 files changed

+22
-9
lines changed

4 files changed

+22
-9
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ struct OverloadSignature {
228228
/// Whether this is a function.
229229
unsigned IsFunction : 1;
230230

231+
/// Whether this is an async function.
232+
unsigned IsAsyncFunction : 1;
233+
231234
/// Whether this is a enum element.
232235
unsigned IsEnumElement : 1;
233236

@@ -249,8 +252,9 @@ struct OverloadSignature {
249252

250253
OverloadSignature()
251254
: UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false),
252-
IsVariable(false), IsFunction(false), InProtocolExtension(false),
253-
InExtensionOfGenericType(false), HasOpaqueReturnType(false) { }
255+
IsVariable(false), IsFunction(false), IsAsyncFunction(false),
256+
InProtocolExtension(false), InExtensionOfGenericType(false),
257+
HasOpaqueReturnType(false) { }
254258
};
255259

256260
/// Determine whether two overload signatures conflict.

lib/AST/Decl.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,10 @@ bool swift::conflicting(const OverloadSignature& sig1,
24832483
if (sig1.IsInstanceMember != sig2.IsInstanceMember)
24842484
return false;
24852485

2486+
// If one is an async function and the other is not, they can't conflict.
2487+
if (sig1.IsAsyncFunction != sig2.IsAsyncFunction)
2488+
return false;
2489+
24862490
// If one is a compound name and the other is not, they do not conflict
24872491
// if one is a property and the other is a non-nullary function.
24882492
if (sig1.Name.isCompoundName() != sig2.Name.isCompoundName()) {
@@ -2709,7 +2713,6 @@ OverloadSignature ValueDecl::getOverloadSignature() const {
27092713
= static_cast<bool>(getDeclContext()->getExtendedProtocolDecl());
27102714
signature.IsInstanceMember = isInstanceMember();
27112715
signature.IsVariable = isa<VarDecl>(this);
2712-
signature.IsFunction = isa<AbstractFunctionDecl>(this);
27132716
signature.IsEnumElement = isa<EnumElementDecl>(this);
27142717
signature.IsNominal = isa<NominalTypeDecl>(this);
27152718
signature.IsTypeAlias = isa<TypeAliasDecl>(this);
@@ -2723,6 +2726,13 @@ OverloadSignature ValueDecl::getOverloadSignature() const {
27232726
}
27242727
}
27252728

2729+
// Functions include async/not-async.
2730+
if (auto func = dyn_cast<AbstractFunctionDecl>(this)) {
2731+
signature.IsFunction = true;
2732+
if (func->hasAsync())
2733+
signature.IsAsyncFunction = true;
2734+
}
2735+
27262736
if (auto *extension = dyn_cast<ExtensionDecl>(getDeclContext()))
27272737
if (extension->isGeneric())
27282738
signature.InExtensionOfGenericType = true;

test/ClangImporter/objc_async_conformance.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ extension C2 {
2020
}
2121

2222
// a version of C2 that requires both sync and async methods (differing only by
23-
// completion handler) in ObjC, is not possible to conform to with 'async' in
24-
// a Swift protocol
23+
// completion handler) in ObjC.
2524
class C3 : NSObject, RequiredObserver {}
2625
extension C3 {
27-
func hello() -> Bool { true } // expected-note {{'hello()' previously declared here}}
28-
func hello() async -> Bool { true } // expected-error {{invalid redeclaration of 'hello()'}}
26+
func hello() -> Bool { true }
27+
func hello() async -> Bool { true }
2928
}
3029

3130
// the only way to conform to 'RequiredObserver' in Swift is to not use 'async'

test/decl/func/async.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
func redecl1() async { } // expected-note{{previously declared here}}
77
func redecl1() async throws { } // expected-error{{invalid redeclaration of 'redecl1()'}}
88

9-
func redecl2() -> String { "" } // expected-note{{previously declared here}}
10-
func redecl2() async -> String { "" } // expected-error{{invalid redeclaration of 'redecl2()'}}
9+
func redecl2() -> String { "" } // okay
10+
func redecl2() async -> String { "" } // okay
1111

1212
// Override checking
1313

0 commit comments

Comments
 (0)