Skip to content

Commit 4035b99

Browse files
authored
Merge pull request #72316 from DougGregor/noncopyable-mangle-enum-cases
2 parents e156289 + 3446fc7 commit 4035b99

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,12 +461,24 @@ class ASTMangler : public Mangler {
461461
bool innermostTypeDecl;
462462
bool extension;
463463
std::optional<unsigned> mangledDepth; // for inverses
464+
std::optional<unsigned> suppressedInnermostDepth;
464465
public:
465466
bool reachedInnermostTypeDecl() {
466467
bool answer = innermostTypeDecl;
467468
innermostTypeDecl = false;
468469
return answer;
469470
}
471+
472+
/// Whether inverses of the innermost declaration's generic parameters
473+
/// should be suppressed.
474+
///
475+
/// This makes sense only for entities that can only ever be defined
476+
/// within the primary type, such as enum cases and the stored properties
477+
/// of struct and class types.
478+
std::optional<unsigned> getSuppressedInnermostInversesDepth() const {
479+
return suppressedInnermostDepth;
480+
}
481+
470482
bool reachedExtension() const { return extension; }
471483
void setReachedExtension() { assert(!extension); extension = true; }
472484
GenericSignature getSignature() const { return sig; }

lib/AST/ASTMangler.cpp

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,12 +2610,13 @@ void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
26102610
static void reconcileInverses(
26112611
SmallVector<InverseRequirement, 2> &inverses,
26122612
GenericSignature sig,
2613-
std::optional<unsigned> inversesAlreadyMangledDepth) {
2613+
std::optional<unsigned> inversesAlreadyMangledDepth,
2614+
std::optional<unsigned> suppressedInnermostDepth) {
26142615
CanGenericSignature baseSig;
26152616
if (sig)
26162617
baseSig = sig.getCanonicalSignature();
26172618

2618-
if (baseSig || inversesAlreadyMangledDepth)
2619+
if (baseSig || inversesAlreadyMangledDepth || suppressedInnermostDepth)
26192620
llvm::erase_if(inverses, [&](InverseRequirement const& inv) -> bool {
26202621
// Drop inverses that aren't applicable in the nested / child signature,
26212622
// because of an added requirement.
@@ -2630,6 +2631,10 @@ static void reconcileInverses(
26302631
if (gp->getDepth() <= limit)
26312632
return true;
26322633

2634+
if (suppressedInnermostDepth &&
2635+
gp->getDepth() == *suppressedInnermostDepth)
2636+
return true;
2637+
26332638
return false;
26342639
});
26352640

@@ -3353,7 +3358,8 @@ void ASTMangler::gatherGenericSignatureParts(GenericSignature sig,
33533358
// Process inverses relative to the base entity's signature.
33543359
if (AllowInverses) {
33553360
// Simplify and canonicalize inverses.
3356-
reconcileInverses(inverseReqs, base.getSignature(), base.getDepth());
3361+
reconcileInverses(inverseReqs, base.getSignature(), base.getDepth(),
3362+
base.getSuppressedInnermostInversesDepth());
33573363
} else {
33583364
inverseReqs.clear();
33593365
}
@@ -4654,6 +4660,31 @@ void ASTMangler::appendConstrainedExistential(Type base, GenericSignature sig,
46544660
return appendOperator("XP");
46554661
}
46564662

4663+
/// Determine whether this declaration can only occur within the primary
4664+
/// type definition.
4665+
static bool canOnlyOccurInPrimaryTypeDefinition(const Decl *decl) {
4666+
// Enum elements always occur within the primary definition.
4667+
if (isa<EnumElementDecl>(decl))
4668+
return true;
4669+
4670+
return false;
4671+
}
4672+
4673+
/// When the immediate enclosing context of this declaration is
4674+
/// a generic type (with its own generic parameters), return the depth of
4675+
/// the innermost generic parameters.
4676+
static std::optional<unsigned> getEnclosingTypeGenericDepth(const Decl *decl) {
4677+
auto typeDecl = dyn_cast<GenericTypeDecl>(decl->getDeclContext());
4678+
if (!typeDecl)
4679+
return std::nullopt;
4680+
4681+
auto genericParams = typeDecl->getGenericParams();
4682+
if (!genericParams)
4683+
return std::nullopt;
4684+
4685+
return genericParams->getParams().back()->getDepth();
4686+
}
4687+
46574688
ASTMangler::BaseEntitySignature::BaseEntitySignature(const Decl *decl)
46584689
: sig(nullptr), innermostTypeDecl(true), extension(false),
46594690
mangledDepth(std::nullopt) {
@@ -4668,12 +4699,22 @@ ASTMangler::BaseEntitySignature::BaseEntitySignature(const Decl *decl)
46684699
case DeclKind::Enum:
46694700
case DeclKind::Struct:
46704701
case DeclKind::Class:
4702+
case DeclKind::EnumElement:
46714703
sig = decl->getInnermostDeclContext()->getGenericSignatureOfContext();
46724704

46734705
// Protocol members never mangle inverse constraints on `Self`.
46744706
if (isa<ProtocolDecl>(decl->getDeclContext()))
46754707
setDepth(0);
46764708

4709+
// Declarations that can only occur in the primary type definition should
4710+
// not mangle inverses for the generic parameters of that type definition.
4711+
// This allows types to introduce conditional conformances to invertible
4712+
// protocols without breaking ABI.
4713+
if (canOnlyOccurInPrimaryTypeDefinition(decl)) {
4714+
if (auto depth = getEnclosingTypeGenericDepth(decl))
4715+
suppressedInnermostDepth = depth;
4716+
}
4717+
46774718
break;
46784719

46794720
case DeclKind::TypeAlias: // FIXME: is this right? typealiases have a generic signature!
@@ -4686,7 +4727,6 @@ ASTMangler::BaseEntitySignature::BaseEntitySignature(const Decl *decl)
46864727
case DeclKind::Module:
46874728
case DeclKind::Param:
46884729
case DeclKind::Macro:
4689-
case DeclKind::EnumElement:
46904730
case DeclKind::Extension:
46914731
case DeclKind::TopLevelCode:
46924732
case DeclKind::Import:

lib/IRGen/IRGenMangler.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,6 @@ class IRGenMangler : public Mangle::ASTMangler {
401401
}
402402

403403
std::string mangleEnumCase(const ValueDecl *Decl) {
404-
// No mangling of inverse conformances.
405-
llvm::SaveAndRestore X(AllowInverses, false);
406-
407404
beginMangling();
408405
appendEntity(Decl);
409406
appendOperator("WC");

test/IRGen/mangling_inverse_generics_evolution.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ public protocol P: ~Copyable { }
1212

1313
public struct CallMe<U: ~Copyable> {
1414
public enum Maybe<T: ~Copyable>: ~Copyable {
15-
// CHECK-LABEL: @"$s4test6CallMeV5MaybeO4someyAEyx_qd__Gqd__cAGmr__lFWC"
16-
// CHECK: @"$s4test6CallMeV5MaybeO4noneyAEyx_qd__GAGmr__lFWC"
15+
// CHECK-LABEL: @"$s4test6CallMeV5MaybeOAARiczrlE4someyAEyx_qd__Gqd__cAGmr__lFWC"
16+
// CHECK: @"$s4test6CallMeV5MaybeOAARiczrlE4noneyAEyx_qd__GAGmr__lFWC"
1717
case none
1818
case some(T)
1919
}

0 commit comments

Comments
 (0)