Skip to content

Future-proof the mangling of invertible protocols #72692

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1011,9 +1011,6 @@ now codified into the ABI; the index 0 is therefore reserved.

generic-param-pack-marker ::= 'Rv' GENERIC_PARAM-INDEX // generic parameter pack marker

INVERTIBLE-KIND ::= 'c' // Copyable
INVERTIBLE-KIND ::= 'e' // Escapable

GENERIC-PARAM-COUNT ::= 'z' // zero parameters
GENERIC-PARAM-COUNT ::= INDEX // N+1 parameters

Expand All @@ -1022,7 +1019,10 @@ now codified into the ABI; the index 0 is therefore reserved.
requirement ::= protocol assoc-type-list 'RP' GENERIC-PARAM-INDEX // protocol requirement on associated type at depth
requirement ::= protocol substitution 'RQ' // protocol requirement with substitution
#if SWIFT_RUNTIME_VERSION >= 6.0
requirement ::= 'Ri' INVERTIBLE-KIND GENERIC-PARAM-INDEX // inverse requirement
requirement ::= 'Ri' INDEX GENERIC-PARAM-INDEX // inverse requirement on generic parameter where INDEX is the bit number
requirement ::= substitution 'RI' INDEX // inverse requirement with substitution
requirement ::= assoc-type-name 'Rj' INDEX GENERIC-PARAM-INDEX // inverse requirement on associated type
requirement ::= assoc-type-list 'RJ' INDEX GENERIC-PARAM-INDEX // inverse requirement on associated type at depth
#endif
requirement ::= type 'Rb' GENERIC-PARAM-INDEX // base class requirement
requirement ::= type assoc-type-name 'Rc' GENERIC-PARAM-INDEX // base class requirement on associated type
Expand Down
6 changes: 2 additions & 4 deletions include/swift/ABI/SuppressibleProtocols.def
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@
// Name: The name of the protocol, e.g., Copyable
// Bit: The bit in the set bitset of suppressible protocols that is used
// to indicate this.
// MangleChar: The character used for the name mangling to refer to this
// protocol.
//===----------------------------------------------------------------------===//

#ifndef SUPPRESSIBLE_PROTOCOL
# error Must define SUPPRESSIBLE_PROTOCOL macro before including this file
#endif

SUPPRESSIBLE_PROTOCOL(Copyable, 0, 'c')
SUPPRESSIBLE_PROTOCOL(Escapable, 1, 'e')
SUPPRESSIBLE_PROTOCOL(Copyable, 0)
SUPPRESSIBLE_PROTOCOL(Escapable, 1)

#undef SUPPRESSIBLE_PROTOCOL
8 changes: 4 additions & 4 deletions include/swift/ABI/SuppressibleProtocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace swift {
/// Describes a "suppressible" protocol, such as Copyable, which is assumed to
/// hold for all types unless explicitly suppressed.
enum class SuppressibleProtocolKind : uint8_t {
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) Name = Bit,
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) Name = Bit,
#include "swift/ABI/SuppressibleProtocols.def"
};

Expand Down Expand Up @@ -72,7 +72,7 @@ class SuppressibleProtocolSet {
/// Clear out all of the protocols from the set.
void clear() { bits = 0; }

#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
bool contains##Name() const { \
return contains(SuppressibleProtocolKind::Name); \
}
Expand All @@ -82,7 +82,7 @@ class SuppressibleProtocolSet {
/// protocols.
static SuppressibleProtocolSet allKnown() {
SuppressibleProtocolSet result;
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
result.insert(SuppressibleProtocolKind::Name);
#include "swift/ABI/SuppressibleProtocols.def"
return result;
Expand Down Expand Up @@ -213,7 +213,7 @@ class SuppressibleProtocolSet {
static inline const char *
getSuppressibleProtocolKindName(SuppressibleProtocolKind kind) {
switch (kind) {
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
case SuppressibleProtocolKind::Name: return #Name;
#include "swift/ABI/SuppressibleProtocols.def"
}
Expand Down
18 changes: 18 additions & 0 deletions include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,24 @@ class ASTMangler : public Mangler {
GenericSignature contextSig,
BaseEntitySignature &base);

/// Describes how the subject of a requirement was mangled.
struct RequirementSubject {
enum Kind {
GenericParameter,
AssociatedType,
AssociatedTypeAtDepth,
Substitution
} kind;

/// Generic parameter at the base, if there is one. Valid for everything
/// except Substitution subjects.
GenericTypeParamType *gpBase = nullptr;
};

/// Append the subject of a generic requirement and state what kind it is.
RequirementSubject appendRequirementSubject(
CanType subjectType, GenericSignature sig);

/// Append a requirement to the mangling.
///
/// \param reqt The requirement to mangle
Expand Down
7 changes: 2 additions & 5 deletions include/swift/AST/InvertibleProtocolKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@
#define SWIFT_AST_INVERTIBLEPROTOCOLKIND_H

#include <stdint.h>
#include <swift/ABI/SuppressibleProtocols.h>

namespace swift {

enum class InvertibleProtocolKind : uint8_t {
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) Id,
#include "swift/AST/KnownProtocols.def"
};

typedef SuppressibleProtocolKind InvertibleProtocolKind;

} // end namespace swift

Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/KnownProtocols.def
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ PROTOCOL(AsyncIteratorProtocol)

PROTOCOL(FloatingPoint)

#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
INVERTIBLE_PROTOCOL_WITH_NAME(Name, #Name)
#include "swift/ABI/SuppressibleProtocols.def"

Expand Down
3 changes: 0 additions & 3 deletions include/swift/AST/KnownProtocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ KnownProtocolKind getKnownProtocolKind(InvertibleProtocolKind ip);
void simple_display(llvm::raw_ostream &out,
const InvertibleProtocolKind &value);

SuppressibleProtocolKind asSuppressible(InvertibleProtocolKind kind);
InvertibleProtocolKind asInvertible(SuppressibleProtocolKind kind);

} // end namespace swift

#endif
31 changes: 4 additions & 27 deletions include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,38 +456,15 @@ void decodeRequirement(
} else if (child->getKind() ==
Demangle::Node::Kind::DependentGenericInverseConformanceRequirement) {
// Type child
auto constraintNode = child->getChild(1);
auto constraintNode = child->getChild(0);
if (constraintNode->getKind() != Demangle::Node::Kind::Type ||
constraintNode->getNumChildren() != 1)
return;

// Protocol child
auto protocolNode = constraintNode->getChild(0);
if (protocolNode->getKind() != Demangle::Node::Kind::Protocol ||
protocolNode->getNumChildren() != 2)
return;

auto moduleNode = protocolNode->getChild(0);
if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
moduleNode->getText() != "Swift")
return;

auto protocolNameNode = protocolNode->getChild(1);
if (protocolNameNode->getKind() != Demangle::Node::Kind::Identifier)
return;

auto protocolName = protocolNameNode->getText();
using OptInvertibleKind = std::optional<InvertibleProtocolKind>;
auto protocolKind = llvm::StringSwitch<OptInvertibleKind>(protocolName)
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) \
.Case(Name, InvertibleProtocolKind::Id)
#include "swift/AST/KnownProtocols.def"
.Default(std::nullopt);
if (!protocolKind)
return;

auto protocolKind =
static_cast<SuppressibleProtocolKind>(child->getChild(1)->getIndex());
inverseRequirements.push_back(
Builder.createInverseRequirement(subjectType, *protocolKind));
Builder.createInverseRequirement(subjectType, protocolKind));
continue;
}

Expand Down
18 changes: 1 addition & 17 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,26 +132,10 @@ void swift::simple_display(llvm::raw_ostream &out,

// Metadata stores a 16-bit field for suppressible protocols. Trigger a build
// error when we assign the 15th bit so we can think about what to do.
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
static_assert(Bit < 15);
#include "swift/ABI/SuppressibleProtocols.def"

SuppressibleProtocolKind swift::asSuppressible(InvertibleProtocolKind kind) {
switch (kind) {
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
case InvertibleProtocolKind::Name: return SuppressibleProtocolKind::Name;
#include "swift/ABI/SuppressibleProtocols.def"
}
}

InvertibleProtocolKind swift::asInvertible(SuppressibleProtocolKind kind) {
switch (kind) {
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
case SuppressibleProtocolKind::Name: return InvertibleProtocolKind::Name;
#include "swift/ABI/SuppressibleProtocols.def"
}
}

namespace {
enum class SearchPathKind : uint8_t {
Import = 1 << 0,
Expand Down
Loading