Skip to content

Commit 72701a1

Browse files
authored
Merge pull request #24166 from jckarter/opaque-overload-checking
Sema: don't consider opaque types distinct for overloading purposes.
2 parents 8f44ca6 + b2d50c8 commit 72701a1

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
@@ -234,11 +234,14 @@ struct OverloadSignature {
234234
/// Whether this signature is of a member defined in an extension of a generic
235235
/// type.
236236
unsigned InExtensionOfGenericType : 1;
237+
238+
/// Whether this declaration has an opaque return type.
239+
unsigned HasOpaqueReturnType : 1;
237240

238241
OverloadSignature()
239242
: UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false),
240243
IsVariable(false), IsFunction(false), InProtocolExtension(false),
241-
InExtensionOfGenericType(false) {}
244+
InExtensionOfGenericType(false), HasOpaqueReturnType(false) {}
242245
};
243246

244247
/// 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
@@ -4689,6 +4689,14 @@ class ArchetypeType : public SubstitutableType,
46894689

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

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

lib/AST/Decl.cpp

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

2153+
// Note that we intentionally ignore the HasOpaqueReturnType bit here.
2154+
// For declarations that can't be overloaded by type, we want them to be
2155+
// considered conflicting independent of their type.
2156+
21532157
return sig1.Name == sig2.Name;
21542158
}
21552159

@@ -2214,6 +2218,9 @@ bool swift::conflicting(ASTContext &ctx,
22142218
}
22152219

22162220
// Otherwise, the declarations conflict if the overload types are the same.
2221+
if (sig1.HasOpaqueReturnType != sig2.HasOpaqueReturnType)
2222+
return false;
2223+
22172224
if (sig1Type != sig2Type)
22182225
return false;
22192226

@@ -2304,6 +2311,12 @@ static Type mapSignatureFunctionType(ASTContext &ctx, Type type,
23042311
type = objectType;
23052312
}
23062313
}
2314+
2315+
// Functions and subscripts cannot overload differing only in opaque return
2316+
// types. Replace the opaque type with `Any`.
2317+
if (auto opaque = type->getAs<OpaqueTypeArchetypeType>()) {
2318+
type = opaque->getExistentialType();
2319+
}
23072320

23082321
return mapSignatureParamType(ctx, type);
23092322
}
@@ -2353,6 +2366,8 @@ OverloadSignature ValueDecl::getOverloadSignature() const {
23532366
signature.IsEnumElement = isa<EnumElementDecl>(this);
23542367
signature.IsNominal = isa<NominalTypeDecl>(this);
23552368
signature.IsTypeAlias = isa<TypeAliasDecl>(this);
2369+
signature.HasOpaqueReturnType =
2370+
!signature.IsVariable && (bool)getOpaqueResultTypeDecl();
23562371

23572372
// Unary operators also include prefix/postfix.
23582373
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
@@ -2385,6 +2385,24 @@ ArchetypeType *ArchetypeType::getRoot() const {
23852385
return const_cast<ArchetypeType*>(parent);
23862386
}
23872387

2388+
Type ArchetypeType::getExistentialType() const {
2389+
// Opened types hold this directly.
2390+
if (auto opened = dyn_cast<OpenedArchetypeType>(this))
2391+
return opened->getOpenedExistentialType();
2392+
2393+
// Otherwise, compute it from scratch.
2394+
SmallVector<Type, 4> constraintTypes;
2395+
2396+
if (auto super = getSuperclass()) {
2397+
constraintTypes.push_back(super);
2398+
}
2399+
for (auto proto : getConformsTo()) {
2400+
constraintTypes.push_back(proto->getDeclaredType());
2401+
}
2402+
return ProtocolCompositionType::get(
2403+
const_cast<ArchetypeType*>(this)->getASTContext(), constraintTypes, false);
2404+
}
2405+
23882406
PrimaryArchetypeType::PrimaryArchetypeType(const ASTContext &Ctx,
23892407
GenericEnvironment *GenericEnv,
23902408
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)