Skip to content
Open
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
38 changes: 19 additions & 19 deletions include/swift/ABI/InvertibleProtocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,67 +40,67 @@ class InvertibleProtocolSet {
StorageType bits;

/// Retrieve the mask for this bit.
static StorageType getMask(InvertibleProtocolKind kind) {
static constexpr StorageType getMask(InvertibleProtocolKind kind) {
return 1 << static_cast<uint8_t>(kind);
}

public:
explicit constexpr InvertibleProtocolSet(StorageType bits) : bits(bits) {}
constexpr InvertibleProtocolSet() : bits(0) {}

InvertibleProtocolSet(
constexpr InvertibleProtocolSet(
std::initializer_list<InvertibleProtocolKind> elements
) : bits(0) {
for (auto element : elements)
insert(element);
}

/// Retrieve the raw bits that describe this set.
StorageType rawBits() const { return bits; }
constexpr StorageType rawBits() const { return bits; }

/// Whether the set contains no protocols.
bool empty() const { return bits == 0; }
constexpr bool empty() const { return bits == 0; }

/// Check whether the set contains the specific invertible protocol.
bool contains(InvertibleProtocolKind kind) const {
constexpr bool contains(InvertibleProtocolKind kind) const {
return bits & getMask(kind);
}

/// Insert the invertible protocol into the set.
void insert(InvertibleProtocolKind kind) {
constexpr void insert(InvertibleProtocolKind kind) {
bits = bits | getMask(kind);
}

/// Insert all of the invertible protocols from the other set into this
/// one.
void insertAll(InvertibleProtocolSet other) {
constexpr void insertAll(InvertibleProtocolSet other) {
bits |= other.bits;
}

/// Remove all of the invertible protocols from this one not present
/// in the other set.
void intersect(InvertibleProtocolSet other) {
constexpr void intersect(InvertibleProtocolSet other) {
bits &= other.bits;
}

/// Remove the given invertible protocol from the set.
void remove(InvertibleProtocolKind kind) {
constexpr void remove(InvertibleProtocolKind kind) {
uint16_t mask = getMask(kind);
bits = bits & ~mask;
}

/// Clear out all of the protocols from the set.
void clear() { bits = 0; }
constexpr void clear() { bits = 0; }

#define INVERTIBLE_PROTOCOL(Name, Bit) \
bool contains##Name() const { \
constexpr bool contains##Name() const { \
return contains(InvertibleProtocolKind::Name); \
}
#include "swift/ABI/InvertibleProtocols.def"

/// Produce a invertible protocol set containing all known invertible
/// protocols.
static InvertibleProtocolSet allKnown() {
static constexpr InvertibleProtocolSet allKnown() {
InvertibleProtocolSet result;
#define INVERTIBLE_PROTOCOL(Name, Bit) \
result.insert(InvertibleProtocolKind::Name);
Expand All @@ -114,7 +114,7 @@ class InvertibleProtocolSet {
/// or mangled names generated by a newer compiler that has introduced
/// another kind of invertible protocol. The Swift runtime will need to
/// step lightly around protocol sets with unknown protocols.
bool hasUnknownProtocols() const {
constexpr bool hasUnknownProtocols() const {
return !(*this - allKnown()).empty();
}

Expand Down Expand Up @@ -198,32 +198,32 @@ class InvertibleProtocolSet {
iterator begin() const { return iterator(rawBits()); }
iterator end() const { return iterator(0); }

friend bool operator==(
friend constexpr bool operator==(
InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) {
return lhs.bits == rhs.bits;
}

friend bool operator!=(
friend constexpr bool operator!=(
InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) {
return lhs.bits != rhs.bits;
}

friend InvertibleProtocolSet operator-(
friend constexpr InvertibleProtocolSet operator-(
InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) {
return InvertibleProtocolSet(lhs.bits & ~rhs.bits);
}

InvertibleProtocolSet &operator-=(InvertibleProtocolSet rhs) {
constexpr InvertibleProtocolSet &operator-=(InvertibleProtocolSet rhs) {
bits = bits & ~rhs.bits;
return *this;
}

friend InvertibleProtocolSet operator|(
friend constexpr InvertibleProtocolSet operator|(
InvertibleProtocolSet lhs, InvertibleProtocolSet rhs) {
return InvertibleProtocolSet(lhs.bits | rhs.bits);
}

InvertibleProtocolSet &operator|=(InvertibleProtocolSet rhs) {
constexpr InvertibleProtocolSet &operator|=(InvertibleProtocolSet rhs) {
bits |= rhs.bits;
return *this;
}
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,12 @@ BridgedAllowFeatureSuppressionAttr_createParsed(BridgedASTContext cContext,
bool inverted,
BridgedArrayRef cFeatures);

SWIFT_NAME("BridgedPreInverseGenericsAttr.createParsed(_:atLoc:range:)")
BridgedPreInverseGenericsAttr
BridgedPreInverseGenericsAttr_createParsed(BridgedASTContext cContext,
swift::SourceLoc atLoc,
swift::SourceRange range);

SWIFT_NAME(
"BridgedBackDeployedAttr.createParsed(_:atLoc:range:platform:version:)")
BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
Expand Down
9 changes: 5 additions & 4 deletions include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/FreestandingMacroExpansion.h"
#include "swift/ABI/InvertibleProtocols.h"
#include "swift/AST/SILThunkKind.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Mangler.h"
Expand Down Expand Up @@ -81,8 +82,8 @@ class ASTMangler : public Mangler {
/// If enabled, marker protocols can be encoded in the mangled name.
bool AllowMarkerProtocols = true;

/// If enabled, inverses will not be mangled into generic signatures.
bool AllowInverses = true;
/// The set of inverses allowed to be mangled into generic signatures.
InvertibleProtocolSet AllowedInverses = InvertibleProtocolSet::allKnown();

/// If enabled, @isolated(any) can be encoded in the mangled name.
/// Suppressing type attributes this way is generally questionable ---
Expand Down Expand Up @@ -560,8 +561,8 @@ class ASTMangler : public Mangler {
BaseEntitySignature(const Decl *decl);
};

static bool inversesAllowed(const Decl *decl);
static bool inversesAllowedIn(const DeclContext *ctx);
static InvertibleProtocolSet inversesAllowed(const Decl *decl);
static InvertibleProtocolSet inversesAllowedIn(const DeclContext *ctx);

void appendContextOf(const ValueDecl *decl, BaseEntitySignature &base);
void appendContextualInverses(const GenericTypeDecl *contextDecl,
Expand Down
51 changes: 51 additions & 0 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#ifndef SWIFT_ATTR_H
#define SWIFT_ATTR_H
#include "swift/ABI/InvertibleProtocols.h"
#include "swift/AST/ASTAllocated.h"
#include "swift/AST/AttrKind.h"
#include "swift/AST/AutoDiff.h"
Expand Down Expand Up @@ -3616,6 +3617,56 @@ class AllowFeatureSuppressionAttr final
Decl *attachedTo) const;
};

/// The @_preInverseGenerics attribute
class PreInverseGenericsAttr : public DeclAttribute {
/// The potentially unresolved 'ExceptType'.
TypeRepr *ExceptTypeRepr;

/// A ProtocolCompositionType whose contained inverses are those that should
/// be KEPT in the mangling of the decl to which this attribute is attached.
///
/// A bare `@_preInverseGenerics` is semantically equivalent to
/// @_preInverseGenerics(except: Any) because `Any` contains no inverses, thus
/// such an attribute will resolve `ExceptType` to `Any`.
Type ExceptType;

friend class ResolvePreInverseGenericsRequest;

public:
PreInverseGenericsAttr(SourceLoc AtLoc, SourceRange Range,
TypeRepr *exceptRepr = nullptr,
Type exceptType = Type());

/// If the 'except:' argument was present, this may still be null in the case
/// of a deserialized attribute. The `hasExcept` query is more reliable.
TypeRepr *getExceptTypeRepr() const { return ExceptTypeRepr; }

/// \returns a ProtocolCompositionType whose inverses represent those that
/// must be kept when mangling.
Type getResolvedExceptType(const Decl *attachedTo) const;

/// True if this attribute was written with an `except:` argument.
bool hasExcept(const Decl *attachedTo) const {
return getExceptTypeRepr() != nullptr ||
!getAllowedInverses(attachedTo).empty();
}

/// \returns the set of inverses allowed to be mangled.
InvertibleProtocolSet getAllowedInverses(const Decl *attachedTo) const;

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DeclAttrKind::PreInverseGenerics;
}

PreInverseGenericsAttr *clone(ASTContext &ctx) const {
return new (ctx)
PreInverseGenericsAttr(AtLoc, Range, ExceptTypeRepr, ExceptType);
}

bool isEquivalent(const PreInverseGenericsAttr *other,
Decl *attachedTo) const;
};

/// Defines the @abi attribute.
class ABIAttr : public DeclAttribute {
friend class DeclAttribute;
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/DeclAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -832,10 +832,11 @@ DECL_ATTR(_allowFeatureSuppression, AllowFeatureSuppression,
157)
DECL_ATTR_ALIAS(_disallowFeatureSuppression, AllowFeatureSuppression)

SIMPLE_DECL_ATTR(_preInverseGenerics, PreInverseGenerics,
DECL_ATTR(_preInverseGenerics, PreInverseGenerics,
OnAbstractFunction | OnSubscript | OnVar | OnExtension,
UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr,
158)
DECL_ATTR_ALIAS(_preInverseGenericsExceptCopyable, PreInverseGenerics)

// Declares that a struct contains "sensitive" data. It enforces that the contents of such a struct value
// is zeroed out at the end of its lifetime. In other words: the content of such a value is not observable
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,9 @@ ERROR(attr_rawlayout_expected_integer_alignment,none,
ERROR(attr_rawlayout_expected_params,none,
"expected %1 argument after %0 argument in '@_rawLayout'", (StringRef, StringRef))

ERROR(attr_pre_inverse_generics_expected_except,none,
"expected 'except:' argument in '@_preInverseGenerics'", ())

ERROR(attr_extern_expected_label,none,
"expected %0 argument to '@_extern'", (StringRef))

Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4435,6 +4435,13 @@ ERROR(attr_rawlayout_invalid_count_type,none,
"'@_rawLayout' count must either be integer literal or a generic "
"argument", ())

ERROR(attr_pre_inverse_generics_invalid_except,none,
"'except' argument to '@_preInverseGenerics' must consist only of "
"inverse constraints such as '~Copyable' or '~Escapable'", ())
WARNING(attr_pre_inverse_generics_except_all,none,
"'@_preInverseGenerics' that excepts all inverse constraints is "
"equivalent to not using the attribute", ())

// lazy
ERROR(lazy_not_on_let,none,
"'lazy' cannot be used on a let", ())
Expand Down
9 changes: 5 additions & 4 deletions include/swift/AST/ExistentialLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ struct ExistentialLayout {
/// is relevant for the mangler to mangle as a symbolic link where possible
/// and for IRGen directly emitting some existentials.
///
/// If 'allowInverses' is false, then regardless of if this existential layout
/// has inverse requirements those will not influence the need for having a
/// shape.
bool needsExtendedShape(bool allowInverses = true) const;
/// If 'allowedInverses' is empty, then regardless of if this existential
/// layout has inverse requirements those will not influence the need for
/// having a shape.
bool needsExtendedShape(InvertibleProtocolSet allowedInverses =
InvertibleProtocolSet::allKnown()) const;

private:
SmallVector<ProtocolDecl *, 4> protocols;
Expand Down
22 changes: 22 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#ifndef SWIFT_TYPE_CHECK_REQUESTS_H
#define SWIFT_TYPE_CHECK_REQUESTS_H

#include "swift/ABI/InvertibleProtocols.h"
#include "swift/AST/ASTNode.h"
#include "swift/AST/ASTTypeIDs.h"
#include "swift/AST/ActorIsolation.h"
Expand Down Expand Up @@ -65,6 +66,7 @@ struct PropertyWrapperMutability;
class RequirementRepr;
class ReturnStmt;
class AbstractSpecializeAttr;
class PreInverseGenericsAttr;
class TrailingWhereClause;
class TypeAliasDecl;
class TypeLoc;
Expand Down Expand Up @@ -3846,6 +3848,26 @@ class ResolveTypeEraserTypeRequest
void cacheResult(Type value) const;
};

class ResolvePreInverseGenericsRequest
: public SimpleRequest<ResolvePreInverseGenericsRequest,
Type(Decl *, PreInverseGenericsAttr *),
RequestFlags::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

Type evaluate(Evaluator &evaluator,
Decl *decl,
PreInverseGenericsAttr *attr) const;

public:
bool isCached() const { return true; }
std::optional<Type> getCachedResult() const;
void cacheResult(Type value) const;
};

class ResolveRawLayoutTypeRequest
: public SimpleRequest<ResolveRawLayoutTypeRequest,
Type (StructDecl*, RawLayoutAttr *, bool),
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ SWIFT_REQUEST(TypeChecker, ConformanceIsolationRequest,
SWIFT_REQUEST(TypeChecker, ResolveTypeRequest,
Type (const TypeResolution *, TypeRepr *, GenericParamList *),
Uncached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ResolvePreInverseGenericsRequest,
Type(Decl *, PreInverseGenericsAttr *),
SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ResolveRawLayoutTypeRequest,
Type(StructDecl *, RawLayoutAttr *, bool),
SeparatelyCached, NoLocationInfo)
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,9 @@ EXPERIMENTAL_FEATURE(DefaultIsolationPerFile, false)
/// Enable @_lifetime attribute
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(Lifetimes, true)

/// Enable @_preInverseGenerics(except:) attribute
EXPERIMENTAL_FEATURE(PreInverseGenericsExcept, true)

/// Deprecates the compatibility memberwise initializer introduced by SE-0502,
/// and removes it in the next major language mode.
EXPERIMENTAL_FEATURE(DeprecateCompatMemberwiseInit, false)
Expand Down
7 changes: 6 additions & 1 deletion lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5143,7 +5143,6 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
TRIVIAL_ATTR_PRINTER(Override, override)
TRIVIAL_ATTR_PRINTER(Owned, owned)
TRIVIAL_ATTR_PRINTER(Postfix, postfix)
TRIVIAL_ATTR_PRINTER(PreInverseGenerics, pre_inverse_generics)
TRIVIAL_ATTR_PRINTER(Preconcurrency, preconcurrency)
TRIVIAL_ATTR_PRINTER(Prefix, prefix)
TRIVIAL_ATTR_PRINTER(PropertyWrapper, property_wrapper)
Expand Down Expand Up @@ -5503,6 +5502,12 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
Label::always("comment_range"));
printFoot();
}
void visitPreInverseGenericsAttr(PreInverseGenericsAttr *Attr, Label label) {
printCommon(Attr, "pre_inverse_generics_attr", label);
if (auto *tyR = Attr->getExceptTypeRepr())
printRec(tyR, Label::optional("except_repr"));
printFoot();
}
void visitRawLayoutAttr(RawLayoutAttr *Attr, Label label) {
printCommon(Attr, "raw_layout_attr", label);
if (auto *tyR = Attr->getScalarLikeType()) {
Expand Down
Loading