Skip to content
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
7 changes: 7 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,13 @@ BridgedDifferentiableTypeAttr BridgedDifferentiableTypeAttr_createParsed(
swift::SourceLoc nameLoc, swift::SourceRange parensRange,
BridgedDifferentiabilityKind cKind, swift::SourceLoc kindLoc);

SWIFT_NAME("BridgedLifetimeTypeAttr.createParsed(_:atLoc:nameLoc:"
"parensRange:entry:)")
BridgedLifetimeTypeAttr BridgedLifetimeTypeAttr_createParsed(
BridgedASTContext cContext, swift::SourceLoc atLoc,
swift::SourceLoc nameLoc, swift::SourceRange parensRange,
BridgedLifetimeEntry entry);

SWIFT_NAME("BridgedIsolatedTypeAttr.createParsed(_:atLoc:nameLoc:parensRange:"
"isolationKind:isolationKindLoc:)")
BridgedIsolatedTypeAttr BridgedIsolatedTypeAttr_createParsed(
Expand Down
11 changes: 9 additions & 2 deletions include/swift/AST/ASTPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,9 @@ class ASTPrinter {
return printedClangDecl.insert(d).second;
}

void printLifetimeDependence(
/// Print lifetimeDependence as a SIL lifetime attribute, attached to a
/// parameter or result of a function.
void printSILLifetimeDependence(
std::optional<LifetimeDependenceInfo> lifetimeDependence) {
if (!lifetimeDependence.has_value()) {
return;
Expand All @@ -380,10 +382,15 @@ class ASTPrinter {
ArrayRef<LifetimeDependenceInfo> lifetimeDependencies, unsigned index) {
if (auto lifetimeDependence =
getLifetimeDependenceFor(lifetimeDependencies, index)) {
printLifetimeDependence(*lifetimeDependence);
printSILLifetimeDependence(*lifetimeDependence);
}
}

/// Print lifetimeDependence as a Swift lifetime attribute.
void
printSwiftLifetimeDependence(LifetimeDependenceInfo const &lifetimeDependence,
ArrayRef<AnyFunctionType::Param> params);

private:
virtual void anchor();
};
Expand Down
24 changes: 24 additions & 0 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4274,6 +4274,17 @@ class alignas(1 << AttrAlignInBits) TypeAttribute

SWIFT_DEBUG_DUMPER(dump());
void print(ASTPrinter &Printer, const PrintOptions &Options) const;

/// Returns true if multiple instances of an attribute kind
/// can appear on a type.
static constexpr bool allowMultipleAttributes(TypeAttrKind TK) {
switch (TK) {
case swift::TypeAttrKind::Lifetime:
return true;
default:
return false;
}
}
};

class AtTypeAttrBase : public TypeAttribute {
Expand Down Expand Up @@ -4383,6 +4394,19 @@ class DifferentiableTypeAttr
void printImpl(ASTPrinter &printer, const PrintOptions &options) const;
};

class LifetimeTypeAttr : public SimpleTypeAttrWithArgs<TypeAttrKind::Lifetime> {
LifetimeEntry *entry;

public:
LifetimeTypeAttr(SourceLoc atLoc, SourceLoc kwLoc, SourceRange parens,
LifetimeEntry *entry)
: SimpleTypeAttr(atLoc, kwLoc, parens), entry(entry) {}

LifetimeEntry *getLifetimeEntry() const { return entry; }

void printImpl(ASTPrinter &printer, const PrintOptions &options) const;
};

class OpaqueReturnTypeOfTypeAttr
: public SimpleTypeAttrWithArgs<TypeAttrKind::OpaqueReturnTypeOf> {
Located<StringRef> MangledName;
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -8511,6 +8511,8 @@ ERROR(lifetime_target_requires_nonescapable, none,
"invalid lifetime dependence on an Escapable %0", (StringRef))
NOTE(lifetime_escapable_source_requires_escapable_note, none,
"use '@_lifetime(%0%1)' instead", (StringRef, StringRef))
ERROR(lifetime_dependence_unknown_type, none,
"lifetime dependence checking failed due to unknown %0 type", (StringRef))

//------------------------------------------------------------------------------
// MARK: Lifetime Dependence Requirements
Expand Down
64 changes: 54 additions & 10 deletions include/swift/AST/LifetimeDependence.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
namespace swift {

class AbstractFunctionDecl;
class AnyFunctionType;
class FunctionTypeRepr;
class LifetimeDependentTypeRepr;
class LifetimeTypeAttr;
class SILParameterInfo;
class SILResultInfo;

Expand Down Expand Up @@ -190,23 +192,28 @@ class LifetimeEntry final
class LifetimeDependenceInfo {
IndexSubset *inheritLifetimeParamIndices;
IndexSubset *scopeLifetimeParamIndices;
llvm::PointerIntPair<IndexSubset *, 1, bool>
addressableParamIndicesAndImmortal;
// The outer bool is the "isFromAnnotation" bit. The inner one is the
// "isImmortal" bit.
llvm::PointerIntPair<llvm::PointerIntPair<IndexSubset *, 1, bool>, 1, bool>
addressableParamIndicesAndImmortalAndFromAnnotation;
IndexSubset *conditionallyAddressableParamIndices;

unsigned targetIndex;

public:
/// Fully-initialized dependence info.
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
IndexSubset *scopeLifetimeParamIndices,
unsigned targetIndex, bool isImmortal,
// set during SIL type lowering
IndexSubset *addressableParamIndices = nullptr,
IndexSubset *conditionallyAddressableParamIndices = nullptr)
bool isFromAnnotation,
IndexSubset *addressableParamIndices,
IndexSubset *conditionallyAddressableParamIndices)
: inheritLifetimeParamIndices(inheritLifetimeParamIndices),
scopeLifetimeParamIndices(scopeLifetimeParamIndices),
addressableParamIndicesAndImmortal(addressableParamIndices, isImmortal),
conditionallyAddressableParamIndices(conditionallyAddressableParamIndices),
addressableParamIndicesAndImmortalAndFromAnnotation(
{addressableParamIndices, isImmortal}, isFromAnnotation),
conditionallyAddressableParamIndices(
conditionallyAddressableParamIndices),
targetIndex(targetIndex) {
ASSERT(this->isImmortal() || inheritLifetimeParamIndices ||
scopeLifetimeParamIndices);
Expand Down Expand Up @@ -238,14 +245,37 @@ class LifetimeDependenceInfo {
}
}

/// Partially-initialized dependence info, with addressable & conditionally
/// addressable parameter indices unset for now.
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
IndexSubset *scopeLifetimeParamIndices,
unsigned targetIndex, bool isImmortal,
bool isFromAnnotation)
: LifetimeDependenceInfo(inheritLifetimeParamIndices,
scopeLifetimeParamIndices, targetIndex,
isImmortal, isFromAnnotation,
// set during SIL type lowering
nullptr, nullptr) {}

operator bool() const { return !empty(); }

bool empty() const {
return !isImmortal() && inheritLifetimeParamIndices == nullptr &&
scopeLifetimeParamIndices == nullptr;
}

bool isImmortal() const { return addressableParamIndicesAndImmortal.getInt(); }
bool isImmortal() const {
return addressableParamIndicesAndImmortalAndFromAnnotation.getPointer()
.getInt();
}

/// Whether this lifetime dependence corresponds to a @lifetime annotation in
/// the source program (Swift or SIL). Such dependencies are likely to differ
/// from the default (inferred) ones, so they must be included when printing a
/// Swift function's type.
bool isFromAnnotation() const {
return addressableParamIndicesAndImmortalAndFromAnnotation.getInt();
}

unsigned getTargetIndex() const { return targetIndex; }

Expand All @@ -256,7 +286,8 @@ class LifetimeDependenceInfo {
return scopeLifetimeParamIndices != nullptr;
}
bool hasAddressableParamIndices() const {
return addressableParamIndicesAndImmortal.getPointer() != nullptr;
return addressableParamIndicesAndImmortalAndFromAnnotation.getPointer()
.getPointer() != nullptr;
}

unsigned getParamIndicesLength() const {
Expand All @@ -282,7 +313,8 @@ class LifetimeDependenceInfo {
/// not only on the value, but the memory location of a particular instance
/// of the value.
IndexSubset *getAddressableIndices() const {
return addressableParamIndicesAndImmortal.getPointer();
return addressableParamIndicesAndImmortalAndFromAnnotation.getPointer()
.getPointer();
}
/// Return the set of parameters which may have addressable dependencies
/// depending on the type of the parameter.
Expand All @@ -307,6 +339,12 @@ class LifetimeDependenceInfo {
&& scopeLifetimeParamIndices->contains(index);
}

/// Get a string representation of this LifetimeDependenceInfo suitable for
/// printing in SIL. The target is not included, since this is determined by
/// the position of the attribute in SIL.
///
/// For printing function type lifetimes in Swift, see
/// ASTPrinter::printSwiftLifetimeDependence.
std::string getString() const;
void Profile(llvm::FoldingSetNodeID &ID) const;
void getConcatenatedData(SmallVectorImpl<bool> &concatenatedData) const;
Expand All @@ -321,6 +359,12 @@ class LifetimeDependenceInfo {
getFromSIL(FunctionTypeRepr *funcRepr, ArrayRef<SILParameterInfo> params,
ArrayRef<SILResultInfo> results, DeclContext *dc);

/// Builds LifetimeDependenceInfo from a function type.
static std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
getFromAST(FunctionTypeRepr *funcRepr, AnyFunctionType *funcType,
ArrayRef<LifetimeTypeAttr *> lifetimeAttributes, DeclContext *dc,
GenericEnvironment *env);

bool operator==(const LifetimeDependenceInfo &other) const {
return this->isImmortal() == other.isImmortal() &&
this->getTargetIndex() == other.getTargetIndex() &&
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/Ownership.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ ValueOwnership asValueOwnership(ParameterOwnership o);
static inline llvm::StringRef getOwnershipSpelling(ValueOwnership ownership) {
switch (ownership) {
case ValueOwnership::Default:
return "";
return "default";
case ValueOwnership::InOut:
return "inout";
case ValueOwnership::Shared:
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ SIMPLE_TYPE_ATTR(reparented, Reparented)
SIMPLE_TYPE_ATTR(unchecked, Unchecked)
SIMPLE_TYPE_ATTR(preconcurrency, Preconcurrency)
SIMPLE_TYPE_ATTR(unsafe, Unsafe)
TYPE_ATTR(_lifetime, Lifetime)
SIMPLE_TYPE_ATTR(_local, Local)
SIMPLE_TYPE_ATTR(_noMetadata, NoMetadata)
TYPE_ATTR(_opaqueReturnTypeOf, OpaqueReturnTypeOf)
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3790,6 +3790,10 @@ class AnyFunctionType : public TypeBase {
return Bits.AnyFunctionType.HasLifetimeDependencies;
}

/// Type has lifetime dependencies derived from explicit @_lifetime
/// attributes.
bool hasExplicitLifetimeDependencies() const;

ClangTypeInfo getClangTypeInfo() const;
ClangTypeInfo getCanonicalClangTypeInfo() const;

Expand Down
1 change: 1 addition & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ LANGUAGE_FEATURE(InoutLifetimeDependence, 0, "Support @_lifetime(&)")
SUPPRESSIBLE_LANGUAGE_FEATURE(NonexhaustiveAttribute, 487, "Nonexhaustive Enums")
LANGUAGE_FEATURE(ModuleSelector, 491, "Module selectors (`Module::name` syntax)")
LANGUAGE_FEATURE(BuiltinConcurrencyStackNesting, 0, "Concurrency Stack Nesting Builtins")
LANGUAGE_FEATURE(ClosureLifetimes, 0, "Support @_lifetime on function types")

// TEMPORARY: Never use this, because it is only meant to allow us to model
// suppression of @c in Swift interfaces as a temporary measure.
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/SILBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ struct BridgedLifetimeDependenceInfo {
swift::IndexSubset *_Nullable conditionallyAddressableParamIndices;
SwiftUInt targetIndex;
bool immortal;
bool fromAnnotation;

BRIDGED_INLINE BridgedLifetimeDependenceInfo(swift::LifetimeDependenceInfo info);

Expand Down
8 changes: 5 additions & 3 deletions include/swift/SIL/SILBridgingImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,15 @@ BridgedParameterInfo BridgedParameterInfoArray::at(SwiftInt parameterIndex) cons
// BridgedLifetimeDependenceInfo
//===----------------------------------------------------------------------===//

BridgedLifetimeDependenceInfo::BridgedLifetimeDependenceInfo(swift::LifetimeDependenceInfo info)
BridgedLifetimeDependenceInfo::BridgedLifetimeDependenceInfo(
swift::LifetimeDependenceInfo info)
: inheritLifetimeParamIndices(info.getInheritIndices()),
scopeLifetimeParamIndices(info.getScopeIndices()),
addressableParamIndices(info.getAddressableIndices()),
conditionallyAddressableParamIndices(
info.getConditionallyAddressableIndices()),
targetIndex(info.getTargetIndex()), immortal(info.isImmortal()) {}
info.getConditionallyAddressableIndices()),
targetIndex(info.getTargetIndex()), immortal(info.isImmortal()),
fromAnnotation(info.isFromAnnotation()) {}

SwiftInt BridgedLifetimeDependenceInfoArray::count() const {
return lifetimeDependenceInfoArray.unbridged<swift::LifetimeDependenceInfo>().size();
Expand Down
Loading