Skip to content

Replace dependsOn with @lifetime #76834

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 11 commits into from
Oct 9, 2024
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
21 changes: 8 additions & 13 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2640,25 +2640,20 @@ class RawLayoutAttr final : public DeclAttribute {
}
};

class LifetimeAttr final
: public DeclAttribute,
private llvm::TrailingObjects<LifetimeAttr, LifetimeEntry> {

friend TrailingObjects;
class LifetimeAttr final : public DeclAttribute {
LifetimeEntry *entry;

unsigned NumEntries = 0;

explicit LifetimeAttr(SourceLoc atLoc, SourceRange baseRange, bool implicit,
ArrayRef<LifetimeEntry> entries);
LifetimeAttr(SourceLoc atLoc, SourceRange baseRange, bool implicit,
LifetimeEntry *entry)
: DeclAttribute(DeclAttrKind::Lifetime, atLoc, baseRange, implicit),
entry(entry) {}

public:
static LifetimeAttr *create(ASTContext &context, SourceLoc atLoc,
SourceRange baseRange, bool implicit,
ArrayRef<LifetimeEntry> entries);
LifetimeEntry *entry);

ArrayRef<LifetimeEntry> getLifetimeEntries() const {
return {getTrailingObjects<LifetimeEntry>(), NumEntries};
}
LifetimeEntry *getLifetimeEntry() const { return entry; }

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DeclAttrKind::Lifetime;
Expand Down
2 changes: 0 additions & 2 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8805,8 +8805,6 @@ class ConstructorDecl : public AbstractFunctionDecl {
Bits.ConstructorDecl.HasStubImplementation = stub;
}

bool hasLifetimeDependentReturn() const;

ConstructorDecl *getOverriddenDecl() const {
return cast_or_null<ConstructorDecl>(
AbstractFunctionDecl::getOverriddenDecl());
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/DeclAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ SIMPLE_DECL_ATTR(unsafe, Unsafe,
160)

DECL_ATTR(lifetime, Lifetime,
OnAccessor | OnConstructor | OnFunc | OnSubscript | LongAttribute | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
OnAccessor | OnConstructor | OnFunc | OnSubscript | LongAttribute | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | AllowMultipleAttributes,
161)

LAST_DECL_ATTR(Lifetime)
Expand Down
8 changes: 5 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -7948,9 +7948,9 @@ ERROR(pack_iteration_where_clause_not_supported, none,
//------------------------------------------------------------------------------

ERROR(lifetime_dependence_invalid_param_name, none,
"invalid parameter name specified %0", (Identifier))
"invalid parameter name specified '%0'", (StringRef))
ERROR(lifetime_dependence_invalid_param_index, none,
"invalid parameter index specified %0", (unsigned))
"invalid parameter index specified '%0'", (unsigned))
ERROR(lifetime_dependence_invalid_self_in_static, none,
"invalid lifetime dependence specifier on non-existent self", ())
ERROR(lifetime_dependence_invalid_self_in_init, none,
Expand Down Expand Up @@ -7992,7 +7992,7 @@ ERROR(lifetime_dependence_cannot_infer_ambiguous_candidate, none,
"Escapable",
())
ERROR(lifetime_dependence_immortal_conflict_name, none,
"conflict between the parameter name and immortal keyword", ())
"conflict between the parameter name and 'immortal' contextual keyword", ())
ERROR(lifetime_dependence_function_type, none,
"lifetime dependencies on function types are not supported",
())
Expand All @@ -8005,6 +8005,8 @@ ERROR(lifetime_dependence_invalid_inherit_escapable_type, none,
ERROR(lifetime_dependence_cannot_use_parsed_borrow_consuming, none,
"invalid use of borrow dependence with consuming ownership",
())
ERROR(lifetime_dependence_duplicate_target, none,
"invalid duplicate target lifetime dependencies on function", ())

//===----------------------------------------------------------------------===//
// MARK: Sending
Expand Down
194 changes: 125 additions & 69 deletions include/swift/AST/LifetimeDependence.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "swift/Basic/SourceLoc.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/TrailingObjects.h"

namespace swift {

Expand All @@ -43,102 +44,162 @@ enum class ParsedLifetimeDependenceKind : uint8_t {

enum class LifetimeDependenceKind : uint8_t { Inherit = 0, Scope };

enum class LifetimeEntryKind { Named, Ordered, Self, Immortal };

class LifetimeEntry {
private:
SourceLoc loc;
LifetimeEntryKind lifetimeEntryKind;
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind;
struct LifetimeDescriptor {
union Value {
struct {
Identifier name;
StringRef name;
} Named;
struct {
unsigned index;
} Ordered;
struct {
} self;
Value(Identifier name) : Named({name}) {}
} Self;
Value(StringRef name) : Named({name}) {}
Value(unsigned index) : Ordered({index}) {}
Value() {}
Value() : Self() {}
} value;

LifetimeEntry(SourceLoc loc, LifetimeEntryKind lifetimeEntryKind,
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
Value value)
: loc(loc), lifetimeEntryKind(lifetimeEntryKind),
parsedLifetimeDependenceKind(parsedLifetimeDependenceKind),
value(value) {}
enum class DescriptorKind { Named, Ordered, Self } kind;

public:
static LifetimeEntry
getNamedLifetimeEntry(SourceLoc loc, Identifier name,
ParsedLifetimeDependenceKind kind =
ParsedLifetimeDependenceKind::Default) {
return {loc, LifetimeEntryKind::Named, kind, name};
}
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind;

static LifetimeEntry getImmortalLifetimeEntry(SourceLoc loc) {
return {loc, LifetimeEntryKind::Immortal, {}, {}};
}
SourceLoc loc;

static LifetimeEntry
getOrderedLifetimeEntry(SourceLoc loc, unsigned index,
ParsedLifetimeDependenceKind kind =
ParsedLifetimeDependenceKind::Default) {
return {loc, LifetimeEntryKind::Ordered, kind, index};
}
private:
LifetimeDescriptor(StringRef name,
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
SourceLoc loc)
: value{name}, kind(DescriptorKind::Named),
parsedLifetimeDependenceKind(parsedLifetimeDependenceKind), loc(loc) {}
LifetimeDescriptor(unsigned index,
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
SourceLoc loc)
: value{index}, kind(DescriptorKind::Ordered),
parsedLifetimeDependenceKind(parsedLifetimeDependenceKind), loc(loc) {}
LifetimeDescriptor(ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
SourceLoc loc)
: value{}, kind(DescriptorKind::Self),
parsedLifetimeDependenceKind(parsedLifetimeDependenceKind), loc(loc) {}

static LifetimeEntry
getSelfLifetimeEntry(SourceLoc loc,
ParsedLifetimeDependenceKind kind =
ParsedLifetimeDependenceKind::Default) {
return {loc, LifetimeEntryKind::Self, kind, {}};
public:
static LifetimeDescriptor
forNamed(StringRef name,
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
SourceLoc loc) {
return {name, parsedLifetimeDependenceKind, loc};
}
static LifetimeDescriptor
forOrdered(unsigned index,
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
SourceLoc loc) {
return {index, parsedLifetimeDependenceKind, loc};
}
static LifetimeDescriptor
forSelf(ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
SourceLoc loc) {
return {parsedLifetimeDependenceKind, loc};
}

SourceLoc getLoc() const { return loc; }

LifetimeEntryKind getLifetimeEntryKind() const { return lifetimeEntryKind; }

ParsedLifetimeDependenceKind getParsedLifetimeDependenceKind() const {
return parsedLifetimeDependenceKind;
}

Identifier getName() const {
assert(lifetimeEntryKind == LifetimeEntryKind::Named);
StringRef getName() const {
assert(kind == DescriptorKind::Named);
return value.Named.name;
}

unsigned getIndex() const {
assert(lifetimeEntryKind == LifetimeEntryKind::Ordered);
assert(kind == DescriptorKind::Ordered);
return value.Ordered.index;
}

std::string getParamString() const {
switch (lifetimeEntryKind) {
case LifetimeEntryKind::Named:
return value.Named.name.str().str();
case LifetimeEntryKind::Self:
DescriptorKind getDescriptorKind() const { return kind; }

SourceLoc getLoc() const { return loc; }

bool isImmortal() const {
if (getDescriptorKind() != LifetimeDescriptor::DescriptorKind::Named) {
return false;
}
return getName() == "immortal";
}

std::string getString() const {
switch (kind) {
case DescriptorKind::Named:
return getName().str();
case DescriptorKind::Ordered:
return std::to_string(getIndex());
case DescriptorKind::Self:
return "self";
case LifetimeEntryKind::Ordered:
return std::to_string(value.Ordered.index);
case LifetimeEntryKind::Immortal:
return "immortal";
}
llvm_unreachable("Invalid LifetimeEntryKind");
llvm_unreachable("Invalid DescriptorKind");
}
};

class LifetimeEntry final
: private llvm::TrailingObjects<LifetimeEntry, LifetimeDescriptor> {
friend TrailingObjects;

private:
SourceLoc startLoc, endLoc;
unsigned numSources;
std::optional<LifetimeDescriptor> targetDescriptor;

LifetimeEntry(
SourceLoc startLoc, SourceLoc endLoc,
ArrayRef<LifetimeDescriptor> sources,
std::optional<LifetimeDescriptor> targetDescriptor = std::nullopt)
: startLoc(startLoc), endLoc(endLoc), numSources(sources.size()),
targetDescriptor(targetDescriptor) {
std::uninitialized_copy(sources.begin(), sources.end(),
getTrailingObjects<LifetimeDescriptor>());
}

size_t numTrailingObjects(OverloadToken<LifetimeDescriptor>) const {
return numSources;
}

public:
static LifetimeEntry *
create(const ASTContext &ctx, SourceLoc startLoc, SourceLoc endLoc,
ArrayRef<LifetimeDescriptor> sources,
std::optional<LifetimeDescriptor> targetDescriptor = std::nullopt);

SourceLoc getLoc() const { return startLoc; }
SourceLoc getStartLoc() const { return startLoc; }
SourceLoc getEndLoc() const { return endLoc; }

ArrayRef<LifetimeDescriptor> getSources() const {
return {getTrailingObjects<LifetimeDescriptor>(), numSources};
}

std::optional<LifetimeDescriptor> getTargetDescriptor() const {
return targetDescriptor;
}

std::string getDependsOnString() const {
switch (parsedLifetimeDependenceKind) {
case ParsedLifetimeDependenceKind::Default:
return "dependsOn(" + getParamString() + ")";
case ParsedLifetimeDependenceKind::Scope:
return "dependsOn(scoped " + getParamString() + ")";
case ParsedLifetimeDependenceKind::Inherit:
return "dependsOn(inherited " + getParamString() + ")";
std::string getString() const {
std::string result = "@lifetime(";
if (targetDescriptor.has_value()) {
result += targetDescriptor->getString();
result += ": ";
}

bool firstElem = true;
for (auto source : getSources()) {
if (!firstElem) {
result += ", ";
}
if (source.getParsedLifetimeDependenceKind() ==
ParsedLifetimeDependenceKind::Scope) {
result += "borrow ";
}
result += source.getString();
firstElem = false;
}
llvm_unreachable("Invalid LifetimeEntry::ParsedLifetimeDependenceKind");
result += ")";
return result;
}
};

Expand All @@ -157,11 +218,6 @@ class LifetimeDependenceInfo {
static std::optional<ArrayRef<LifetimeDependenceInfo>>
fromLifetimeAttribute(AbstractFunctionDecl *afd);

/// Builds LifetimeDependenceInfo from dependsOn type modifier
static std::optional<LifetimeDependenceInfo>
fromDependsOn(AbstractFunctionDecl *afd, TypeRepr *targetRepr,
Type targetType, unsigned targetIndex);

/// Infer LifetimeDependenceInfo on result
static std::optional<LifetimeDependenceInfo> infer(AbstractFunctionDecl *afd);

Expand Down
32 changes: 7 additions & 25 deletions include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,6 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
/// The number of elements contained.
NumElements : 32
);

SWIFT_INLINE_BITFIELD_FULL(LifetimeDependentTypeRepr, TypeRepr, 32,
: NumPadBits,
NumDependencies : 32
);
} Bits;
// clang-format on

Expand Down Expand Up @@ -1531,32 +1526,19 @@ class SILBoxTypeRepr final : public TypeRepr,
friend TypeRepr;
};

class LifetimeDependentTypeRepr final
: public SpecifierTypeRepr,
private llvm::TrailingObjects<LifetimeDependentTypeRepr, LifetimeEntry> {
friend TrailingObjects;

size_t numTrailingObjects(OverloadToken<LifetimeDependentTypeRepr>) const {
return Bits.LifetimeDependentTypeRepr.NumDependencies;
}
class LifetimeDependentTypeRepr final : public SpecifierTypeRepr {
LifetimeEntry *entry;

public:
LifetimeDependentTypeRepr(TypeRepr *base, ArrayRef<LifetimeEntry> specifiers)
LifetimeDependentTypeRepr(TypeRepr *base, LifetimeEntry *entry)
: SpecifierTypeRepr(TypeReprKind::LifetimeDependent, base,
specifiers.front().getLoc()) {
assert(base);
Bits.LifetimeDependentTypeRepr.NumDependencies = specifiers.size();
std::uninitialized_copy(specifiers.begin(), specifiers.end(),
getTrailingObjects<LifetimeEntry>());
}
entry->getLoc()),
entry(entry) {}

static LifetimeDependentTypeRepr *create(ASTContext &C, TypeRepr *base,
ArrayRef<LifetimeEntry> specifiers);
LifetimeEntry *entry);

ArrayRef<LifetimeEntry> getLifetimeDependencies() const {
return {getTrailingObjects<LifetimeEntry>(),
Bits.LifetimeDependentTypeRepr.NumDependencies};
}
LifetimeEntry *getLifetimeEntry() const { return entry; }

static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::LifetimeDependent;
Expand Down
Loading