Skip to content

Commit 359ea9e

Browse files
committed
Sema: don't consider opaque types distinct for overloading purposes.
This is necessary because: ``` func foo() -> some P func foo() -> some P ``` theoretically defines two distinct return types, but there'd be no way to disambiguate them. Disallow overloading only by opaque return type.
1 parent 26e763a commit 359ea9e

File tree

5 files changed

+71
-2
lines changed

5 files changed

+71
-2
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,14 @@ struct OverloadSignature {
223223
/// Whether this signature is of a member defined in an extension of a generic
224224
/// type.
225225
unsigned InExtensionOfGenericType : 1;
226+
227+
/// Whether this declaration has an opaque return type.
228+
unsigned HasOpaqueReturnType : 1;
226229

227230
OverloadSignature()
228231
: UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false),
229232
IsVariable(false), IsFunction(false), InProtocolExtension(false),
230-
InExtensionOfGenericType(false) {}
233+
InExtensionOfGenericType(false), HasOpaqueReturnType(false) {}
231234
};
232235

233236
/// Determine whether two overload signatures conflict.

include/swift/AST/Types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4692,6 +4692,14 @@ class ArchetypeType : public SubstitutableType,
46924692

46934693
/// Get the generic environment this archetype lives in.
46944694
GenericEnvironment *getGenericEnvironment() const;
4695+
4696+
/// Get the protocol/class existential type that most closely represents the
4697+
/// set of constraints on this archetype.
4698+
///
4699+
/// Right now, this only considers constraints on the archetype itself, not
4700+
/// any of its associated types, since those are the only kind of existential
4701+
/// type we can represent.
4702+
Type getExistentialType() const;
46954703

46964704
// Implement isa/cast/dyncast/etc.
46974705
static bool classof(const TypeBase *T) {

lib/AST/Decl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,10 @@ bool swift::conflicting(const OverloadSignature& sig1,
20822082
(sig2.IsVariable && !sig1.Name.getArgumentNames().empty()));
20832083
}
20842084

2085+
// Note that we intentionally ignore the HasOpaqueReturnType bit here.
2086+
// For declarations that can't be overloaded by type, we want them to be
2087+
// considered conflicting independent of their type.
2088+
20852089
return sig1.Name == sig2.Name;
20862090
}
20872091

@@ -2120,6 +2124,9 @@ bool swift::conflicting(ASTContext &ctx,
21202124
}
21212125

21222126
// Otherwise, the declarations conflict if the overload types are the same.
2127+
if (sig1.HasOpaqueReturnType != sig2.HasOpaqueReturnType)
2128+
return false;
2129+
21232130
if (sig1Type != sig2Type)
21242131
return false;
21252132

@@ -2206,6 +2213,12 @@ static Type mapSignatureFunctionType(ASTContext &ctx, Type type,
22062213
type = objectType;
22072214
}
22082215
}
2216+
2217+
// Functions and subscripts cannot overload differing only in opaque return
2218+
// types. Replace the opaque type with `Any`.
2219+
if (auto opaque = type->getAs<OpaqueTypeArchetypeType>()) {
2220+
type = opaque->getExistentialType();
2221+
}
22092222

22102223
return mapSignatureParamType(ctx, type);
22112224
}
@@ -2252,6 +2265,8 @@ OverloadSignature ValueDecl::getOverloadSignature() const {
22522265
signature.IsInstanceMember = isInstanceMember();
22532266
signature.IsVariable = isa<VarDecl>(this);
22542267
signature.IsFunction = isa<AbstractFunctionDecl>(this);
2268+
signature.HasOpaqueReturnType =
2269+
!signature.IsVariable && (bool)getOpaqueResultTypeDecl();
22552270

22562271
// Unary operators also include prefix/postfix.
22572272
if (auto func = dyn_cast<FuncDecl>(this)) {

lib/AST/Type.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,6 +2391,24 @@ ArchetypeType *ArchetypeType::getRoot() const {
23912391
return const_cast<ArchetypeType*>(parent);
23922392
}
23932393

2394+
Type ArchetypeType::getExistentialType() const {
2395+
// Opened types hold this directly.
2396+
if (auto opened = dyn_cast<OpenedArchetypeType>(this))
2397+
return opened->getOpenedExistentialType();
2398+
2399+
// Otherwise, compute it from scratch.
2400+
SmallVector<Type, 4> constraintTypes;
2401+
2402+
if (auto super = getSuperclass()) {
2403+
constraintTypes.push_back(super);
2404+
}
2405+
for (auto proto : getConformsTo()) {
2406+
constraintTypes.push_back(proto->getDeclaredType());
2407+
}
2408+
return ProtocolCompositionType::get(
2409+
const_cast<ArchetypeType*>(this)->getASTContext(), constraintTypes, false);
2410+
}
2411+
23942412
PrimaryArchetypeType::PrimaryArchetypeType(const ASTContext &Ctx,
23952413
GenericEnvironment *GenericEnv,
23962414
Type InterfaceType,

test/type/opaque.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,29 @@ var DoesNotConformComputedProp: some P {
287287
}
288288
*/
289289

290-
290+
func redeclaration() -> some P { return 0 } // expected-note{{previously declared}}
291+
func redeclaration() -> some P { return 0 } // expected-error{{redeclaration}}
292+
func redeclaration() -> some Q { return 0 }
293+
func redeclaration() -> P { return 0 }
294+
295+
var redeclaredProp: some P { return 0 } // expected-note 3{{previously declared}}
296+
var redeclaredProp: some P { return 0 } // expected-error{{redeclaration}}
297+
var redeclaredProp: some Q { return 0 } // expected-error{{redeclaration}}
298+
var redeclaredProp: P { return 0 } // expected-error{{redeclaration}}
299+
300+
struct RedeclarationTest {
301+
func redeclaration() -> some P { return 0 } // expected-note{{previously declared}}
302+
func redeclaration() -> some P { return 0 } // expected-error{{redeclaration}}
303+
func redeclaration() -> some Q { return 0 }
304+
func redeclaration() -> P { return 0 }
305+
306+
var redeclaredProp: some P { return 0 } // expected-note 3{{previously declared}}
307+
var redeclaredProp: some P { return 0 } // expected-error{{redeclaration}}
308+
var redeclaredProp: some Q { return 0 } // expected-error{{redeclaration}}
309+
var redeclaredProp: P { return 0 } // expected-error{{redeclaration}}
310+
311+
subscript(redeclared _: Int) -> some P { return 0 } // expected-note{{previously declared}}
312+
subscript(redeclared _: Int) -> some P { return 0 } // expected-error{{redeclaration}}
313+
subscript(redeclared _: Int) -> some Q { return 0 }
314+
subscript(redeclared _: Int) -> P { return 0 }
315+
}

0 commit comments

Comments
 (0)