Revert "Merge pull request #80540 from swiftlang/revert-80452-lifetimeinout"

This reverts commit 6eaa07a880, reversing
changes made to e75ee3f4cf.
This commit is contained in:
Meghana Gupta
2025-04-04 09:50:13 -07:00
parent 6eaa07a880
commit ef1e94577f
26 changed files with 254 additions and 159 deletions

View File

@@ -1086,8 +1086,9 @@ BridgedInlineAttr BridgedInlineAttr_createParsed(BridgedASTContext cContext,
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedParsedLifetimeDependenceKind {
BridgedParsedLifetimeDependenceKindDefault,
BridgedParsedLifetimeDependenceKindScope,
BridgedParsedLifetimeDependenceKindBorrow,
BridgedParsedLifetimeDependenceKindInherit,
BridgedParsedLifetimeDependenceKindInout
};
class BridgedLifetimeDescriptor {

View File

@@ -8169,8 +8169,11 @@ ERROR(lifetime_dependence_invalid_inherit_escapable_type, none,
"'@lifetime(borrow %0)' instead",
(StringRef))
ERROR(lifetime_dependence_cannot_use_parsed_borrow_consuming, none,
"invalid use of borrow dependence with consuming ownership",
())
"invalid use of %0 dependence with %1 ownership",
(StringRef, StringRef))
ERROR(lifetime_dependence_cannot_use_default_escapable_consuming, none,
"invalid lifetime dependence on an Escapable value with %0 ownership",
(StringRef))
ERROR(lifetime_dependence_cannot_use_parsed_borrow_inout, none,
"invalid use of borrow dependence on the same inout parameter",
())

View File

@@ -38,8 +38,9 @@ class SILResultInfo;
enum class ParsedLifetimeDependenceKind : uint8_t {
Default = 0,
Scope,
Inherit // Only used with deserialized decls
Borrow,
Inherit, // Only used with deserialized decls
Inout
};
enum class LifetimeDependenceKind : uint8_t { Inherit = 0, Scope };
@@ -182,6 +183,7 @@ public:
ArrayRef<LifetimeDescriptor> sources,
std::optional<LifetimeDescriptor> targetDescriptor = std::nullopt);
std::string getString() const;
SourceLoc getLoc() const { return startLoc; }
SourceLoc getStartLoc() const { return startLoc; }
SourceLoc getEndLoc() const { return endLoc; }
@@ -193,35 +195,6 @@ public:
std::optional<LifetimeDescriptor> getTargetDescriptor() const {
return targetDescriptor;
}
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 += ", ";
}
switch (source.getParsedLifetimeDependenceKind()) {
case ParsedLifetimeDependenceKind::Scope:
result += "borrow ";
break;
case ParsedLifetimeDependenceKind::Inherit:
result += "copy ";
break;
default:
break;
}
result += source.getString();
firstElem = false;
}
result += ")";
return result;
}
};
class LifetimeDependenceInfo {
@@ -366,6 +339,9 @@ filterEscapableLifetimeDependencies(GenericSignature sig,
SmallVectorImpl<LifetimeDependenceInfo> &outputs,
llvm::function_ref<Type (unsigned targetIndex)> getSubstTargetType);
StringRef
getNameForParsedLifetimeDependenceKind(ParsedLifetimeDependenceKind kind);
} // namespace swift
#endif

View File

@@ -416,6 +416,9 @@ EXPERIMENTAL_FEATURE(StructLetDestructuring, true)
/// Enable returning non-escapable types from functions.
EXPERIMENTAL_FEATURE(LifetimeDependence, true)
/// Enable inout lifetime dependence - @lifetime(&arg)
EXPERIMENTAL_FEATURE(InoutLifetimeDependence, true)
/// Enable the `@_staticExclusiveOnly` attribute.
EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)

View File

@@ -470,10 +470,12 @@ unbridged(BridgedParsedLifetimeDependenceKind kind) {
switch (kind) {
case BridgedParsedLifetimeDependenceKindDefault:
return swift::ParsedLifetimeDependenceKind::Default;
case BridgedParsedLifetimeDependenceKindScope:
return swift::ParsedLifetimeDependenceKind::Scope;
case BridgedParsedLifetimeDependenceKindBorrow:
return swift::ParsedLifetimeDependenceKind::Borrow;
case BridgedParsedLifetimeDependenceKindInherit:
return swift::ParsedLifetimeDependenceKind::Inherit;
case BridgedParsedLifetimeDependenceKindInout:
return swift::ParsedLifetimeDependenceKind::Inout;
}
llvm_unreachable("unhandled enum value");
}

View File

@@ -270,6 +270,18 @@ static bool usesFeatureLifetimeDependence(Decl *decl) {
return false;
}
static bool usesFeatureInoutLifetimeDependence(Decl *decl) {
for (auto attr : decl->getAttrs().getAttributes<LifetimeAttr>()) {
for (auto source : attr->getLifetimeEntry()->getSources()) {
if (source.getParsedLifetimeDependenceKind() ==
ParsedLifetimeDependenceKind::Inout) {
return true;
}
}
}
return false;
}
UNINTERESTING_FEATURE(DynamicActorIsolation)
UNINTERESTING_FEATURE(NonfrozenEnumExhaustivity)
UNINTERESTING_FEATURE(ClosureIsolation)

View File

@@ -37,6 +37,35 @@ LifetimeEntry::create(const ASTContext &ctx, SourceLoc startLoc,
return new (mem) LifetimeEntry(startLoc, endLoc, sources, targetDescriptor);
}
std::string LifetimeEntry::getString() const {
std::string result = "@lifetime(";
if (targetDescriptor.has_value()) {
result += targetDescriptor->getString();
result += ": ";
}
bool firstElem = true;
for (auto source : getSources()) {
if (!firstElem) {
result += ", ";
}
auto lifetimeKind = source.getParsedLifetimeDependenceKind();
auto kindString = getNameForParsedLifetimeDependenceKind(lifetimeKind);
bool printSpace = (lifetimeKind == ParsedLifetimeDependenceKind::Borrow ||
lifetimeKind == ParsedLifetimeDependenceKind::Inherit);
if (!kindString.empty()) {
result += kindString;
}
if (printSpace) {
result += " ";
}
result += source.getString();
firstElem = false;
}
result += ")";
return result;
}
std::optional<LifetimeDependenceInfo>
getLifetimeDependenceFor(ArrayRef<LifetimeDependenceInfo> lifetimeDependencies,
unsigned index) {
@@ -74,6 +103,20 @@ filterEscapableLifetimeDependencies(GenericSignature sig,
return didRemoveLifetimeDependencies;
}
StringRef
getNameForParsedLifetimeDependenceKind(ParsedLifetimeDependenceKind kind) {
switch (kind) {
case ParsedLifetimeDependenceKind::Borrow:
return "borrow";
case ParsedLifetimeDependenceKind::Inherit:
return "copy";
case ParsedLifetimeDependenceKind::Inout:
return "&";
default:
return "";
}
}
std::string LifetimeDependenceInfo::getString() const {
std::string lifetimeDependenceString = "@lifetime(";
auto addressable = getAddressableIndices();
@@ -138,16 +181,6 @@ void LifetimeDependenceInfo::Profile(llvm::FoldingSetNodeID &ID) const {
}
}
// Infer the kind of dependence that would be implied by assigning into a stored
// property of 'sourceType'.
static LifetimeDependenceKind
inferLifetimeDependenceKindFromType(Type sourceType) {
if (sourceType->isEscapable()) {
return LifetimeDependenceKind::Scope;
}
return LifetimeDependenceKind::Inherit;
}
// Warning: this is incorrect for Setter 'newValue' parameters. It should only
// be called for a Setter's 'self'.
static ValueOwnership getLoweredOwnership(AbstractFunctionDecl *afd) {
@@ -456,6 +489,26 @@ protected:
}
}
bool isCompatibleWithOwnership(ParsedLifetimeDependenceKind kind, Type type,
ValueOwnership ownership) const {
if (kind == ParsedLifetimeDependenceKind::Inherit) {
return true;
}
// Lifetime dependence always propagates through temporary BitwiseCopyable
// values, even if the dependence is scoped.
if (isBitwiseCopyable(type, ctx)) {
return true;
}
auto loweredOwnership = ownership != ValueOwnership::Default
? ownership : getLoweredOwnership(afd);
if (kind == ParsedLifetimeDependenceKind::Borrow) {
return loweredOwnership == ValueOwnership::Shared;
}
assert(kind == ParsedLifetimeDependenceKind::Inout);
return loweredOwnership == ValueOwnership::InOut;
}
bool isCompatibleWithOwnership(LifetimeDependenceKind kind, Type type,
ValueOwnership ownership) const {
if (kind == LifetimeDependenceKind::Inherit) {
@@ -466,16 +519,13 @@ protected:
if (isBitwiseCopyable(type, ctx)) {
return true;
}
assert(kind == LifetimeDependenceKind::Scope);
auto loweredOwnership = ownership != ValueOwnership::Default
? ownership : getLoweredOwnership(afd);
? ownership
: getLoweredOwnership(afd);
if (loweredOwnership == ValueOwnership::InOut ||
loweredOwnership == ValueOwnership::Shared) {
return true;
}
assert(loweredOwnership == ValueOwnership::Owned);
return false;
assert(kind == LifetimeDependenceKind::Scope);
return loweredOwnership == ValueOwnership::Shared ||
loweredOwnership == ValueOwnership::InOut;
}
struct TargetDeps {
@@ -552,43 +602,57 @@ protected:
getDependenceKindFromDescriptor(LifetimeDescriptor descriptor,
ParamDecl *decl) {
auto loc = descriptor.getLoc();
auto ownership = decl->getValueOwnership();
auto type = decl->getTypeInContext();
auto parsedLifetimeKind = descriptor.getParsedLifetimeDependenceKind();
auto ownership = decl->getValueOwnership();
auto loweredOwnership = ownership != ValueOwnership::Default
? ownership
: getLoweredOwnership(afd);
LifetimeDependenceKind kind;
switch (descriptor.getParsedLifetimeDependenceKind()) {
case ParsedLifetimeDependenceKind::Default:
switch (parsedLifetimeKind) {
case ParsedLifetimeDependenceKind::Default: {
if (type->isEscapable()) {
kind = LifetimeDependenceKind::Scope;
} else if (useLazyInference()) {
kind = LifetimeDependenceKind::Inherit;
} else {
diagnose(loc, diag::lifetime_dependence_cannot_infer_kind,
diagnosticQualifier(), descriptor.getString());
if (loweredOwnership == ValueOwnership::Shared ||
loweredOwnership == ValueOwnership::InOut) {
return LifetimeDependenceKind::Scope;
}
diagnose(
loc,
diag::lifetime_dependence_cannot_use_default_escapable_consuming,
getOwnershipSpelling(loweredOwnership));
return std::nullopt;
}
break;
case ParsedLifetimeDependenceKind::Scope:
kind = LifetimeDependenceKind::Scope;
break;
case ParsedLifetimeDependenceKind::Inherit:
kind = LifetimeDependenceKind::Inherit;
break;
}
// @lifetime(borrow x) is invalid for consuming parameters.
if (!isCompatibleWithOwnership(kind, type, ownership)) {
diagnose(loc,
diag::lifetime_dependence_cannot_use_parsed_borrow_consuming);
if (useLazyInference()) {
return LifetimeDependenceKind::Inherit;
}
diagnose(loc, diag::lifetime_dependence_cannot_infer_kind,
diagnosticQualifier(), descriptor.getString());
return std::nullopt;
}
case ParsedLifetimeDependenceKind::Borrow: LLVM_FALLTHROUGH;
case ParsedLifetimeDependenceKind::Inout: {
// @lifetime(borrow x) is valid only for borrowing parameters.
// @lifetime(inout x) is valid only for inout parameters.
if (!isCompatibleWithOwnership(parsedLifetimeKind, type,
loweredOwnership)) {
diagnose(loc,
diag::lifetime_dependence_cannot_use_parsed_borrow_consuming,
getNameForParsedLifetimeDependenceKind(parsedLifetimeKind),
getOwnershipSpelling(loweredOwnership));
return std::nullopt;
}
return LifetimeDependenceKind::Scope;
}
case ParsedLifetimeDependenceKind::Inherit:
// @lifetime(copy x) is only invalid for Escapable types.
if (kind == LifetimeDependenceKind::Inherit && type->isEscapable()) {
if (type->isEscapable()) {
diagnose(loc, diag::lifetime_dependence_invalid_inherit_escapable_type,
descriptor.getString());
return std::nullopt;
}
return kind;
return LifetimeDependenceKind::Inherit;
}
}
// Finds the ParamDecl* and its index from a LifetimeDescriptor
@@ -829,15 +893,35 @@ protected:
return;
}
}
auto kind = inferLifetimeDependenceKindFromType(selfTypeInContext);
auto selfOwnership = afd->getImplicitSelfDecl()->getValueOwnership();
if (!isCompatibleWithOwnership(kind, selfTypeInContext, selfOwnership)) {
auto kind = inferLifetimeDependenceKind(
selfTypeInContext, afd->getImplicitSelfDecl()->getValueOwnership());
if (!kind) {
diagnose(returnLoc,
diag::lifetime_dependence_cannot_infer_scope_ownership,
"self", diagnosticQualifier());
return;
}
pushDeps(createDeps(resultIndex).add(selfIndex, kind));
pushDeps(createDeps(resultIndex).add(selfIndex, *kind));
}
std::optional<LifetimeDependenceKind>
inferLifetimeDependenceKind(Type sourceType, ValueOwnership ownership) {
if (!sourceType->isEscapable()) {
return LifetimeDependenceKind::Inherit;
}
// Lifetime dependence always propagates through temporary BitwiseCopyable
// values, even if the dependence is scoped.
if (isBitwiseCopyable(sourceType, ctx)) {
return LifetimeDependenceKind::Scope;
}
auto loweredOwnership = ownership != ValueOwnership::Default
? ownership
: getLoweredOwnership(afd);
if (loweredOwnership != ValueOwnership::Shared &&
loweredOwnership != ValueOwnership::InOut) {
return std::nullopt;
}
return LifetimeDependenceKind::Scope;
}
// Infer implicit initialization. The dependence kind can be inferred, similar
@@ -861,16 +945,15 @@ protected:
if (paramTypeInContext->hasError()) {
continue;
}
auto kind = inferLifetimeDependenceKindFromType(paramTypeInContext);
auto paramOwnership = param->getValueOwnership();
if (!isCompatibleWithOwnership(kind, paramTypeInContext, paramOwnership))
{
auto kind = inferLifetimeDependenceKind(paramTypeInContext,
param->getValueOwnership());
if (!kind) {
diagnose(returnLoc,
diag::lifetime_dependence_cannot_infer_scope_ownership,
param->getParameterName().str(), diagnosticQualifier());
continue;
}
targetDeps = std::move(targetDeps).add(paramIndex, kind);
targetDeps = std::move(targetDeps).add(paramIndex, *kind);
}
pushDeps(std::move(targetDeps));
}
@@ -954,9 +1037,8 @@ protected:
}
candidateLifetimeKind =
inferLifetimeDependenceKindFromType(paramTypeInContext);
if (!isCompatibleWithOwnership(
*candidateLifetimeKind, paramTypeInContext, paramOwnership)) {
inferLifetimeDependenceKind(paramTypeInContext, paramOwnership);
if (!candidateLifetimeKind) {
continue;
}
if (candidateParamIndex) {
@@ -1025,11 +1107,12 @@ protected:
if (paramTypeInContext->hasError()) {
return;
}
auto kind = inferLifetimeDependenceKindFromType(paramTypeInContext);
auto kind = inferLifetimeDependenceKind(paramTypeInContext,
param->getValueOwnership());
pushDeps(createDeps(selfIndex)
.add(selfIndex, LifetimeDependenceKind::Inherit)
.add(newValIdx, kind));
.add(selfIndex, LifetimeDependenceKind::Inherit)
.add(newValIdx, *kind));
break;
}
default:
@@ -1119,7 +1202,7 @@ static std::optional<LifetimeDependenceInfo> checkSILTypeModifiers(
auto loc = descriptor.getLoc();
auto kind = descriptor.getParsedLifetimeDependenceKind();
if (kind == ParsedLifetimeDependenceKind::Scope &&
if (kind == ParsedLifetimeDependenceKind::Borrow &&
isConsumedParameterInCallee(paramConvention)) {
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "_scope",
getStringForParameterConvention(paramConvention));
@@ -1134,7 +1217,7 @@ static std::optional<LifetimeDependenceInfo> checkSILTypeModifiers(
if (kind == ParsedLifetimeDependenceKind::Inherit) {
inheritLifetimeParamIndices.set(paramIndexToSet);
} else {
assert(kind == ParsedLifetimeDependenceKind::Scope);
assert(kind == ParsedLifetimeDependenceKind::Borrow);
scopeLifetimeParamIndices.set(paramIndexToSet);
}
return false;

View File

@@ -1105,8 +1105,11 @@ extension ASTGenVisitor {
lifetimeDependenceKind = .inherit
descriptorExpr = copyExpr.expression
} else if let borrowExpr = node.as(BorrowExprSyntax.self) {
lifetimeDependenceKind = .scope
lifetimeDependenceKind = .borrow
descriptorExpr = borrowExpr.expression
} else if let inoutExpr = node.as(InOutExprSyntax.self) {
lifetimeDependenceKind = .inout
descriptorExpr = inoutExpr.expression
} else {
lifetimeDependenceKind = .default
descriptorExpr = node

View File

@@ -5019,7 +5019,12 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
if (Tok.isContextualKeyword("borrow") &&
peekToken().isAny(tok::identifier, tok::integer_literal,
tok::kw_self)) {
return ParsedLifetimeDependenceKind::Scope;
return ParsedLifetimeDependenceKind::Borrow;
}
if (Tok.is(tok::amp_prefix) &&
peekToken().isAny(tok::identifier, tok::integer_literal,
tok::kw_self)) {
return ParsedLifetimeDependenceKind::Inout;
}
return std::nullopt;
};

View File

@@ -631,6 +631,7 @@ function(_compile_swift_files
list(APPEND swift_flags "-enable-experimental-feature" "NonescapableTypes")
list(APPEND swift_flags "-enable-experimental-feature" "LifetimeDependence")
list(APPEND swift_flags "-enable-experimental-feature" "InoutLifetimeDependence")
list(APPEND swift_flags "-enable-upcoming-feature" "MemberImportVisibility")

View File

@@ -1732,7 +1732,7 @@ extension Array {
@available(SwiftStdlib 6.2, *)
public var mutableSpan: MutableSpan<Element> {
@lifetime(/*inout*/borrow self)
@lifetime(&self)
@_alwaysEmitIntoClient
mutating get {
_makeMutableAndUnique()

View File

@@ -1302,7 +1302,7 @@ extension ArraySlice {
@available(SwiftStdlib 6.2, *)
public var mutableSpan: MutableSpan<Element> {
@lifetime(/*inout*/borrow self)
@lifetime(/*inout*/&self)
@_alwaysEmitIntoClient
mutating get {
_makeMutableAndUnique()

View File

@@ -1244,7 +1244,7 @@ extension ContiguousArray {
@available(SwiftStdlib 6.2, *)
public var mutableSpan: MutableSpan<Element> {
@lifetime(/*inout*/borrow self)
@lifetime(&self)
@_alwaysEmitIntoClient
mutating get {
_makeMutableAndUnique()

View File

@@ -325,7 +325,7 @@ internal func _overrideLifetime<
@_unsafeNonescapableResult
@_alwaysEmitIntoClient
@_transparent
@lifetime(borrow source)
@lifetime(&source)
internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>(

View File

@@ -190,7 +190,7 @@ extension MutableRawSpan {
@unsafe
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
public mutating func _unsafeMutableView<T: BitwiseCopyable>(
as type: T.Type
) -> MutableSpan<T> {
@@ -448,7 +448,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(_ bounds: Range<Int>) -> Self {
_precondition(
UInt(bitPattern: bounds.lowerBound) <= UInt(bitPattern: _count) &&
@@ -475,7 +475,7 @@ extension MutableRawSpan {
/// - Complexity: O(1)
@unsafe
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(unchecked bounds: Range<Int>) -> Self {
let newStart = unsafe _pointer?.advanced(by: bounds.lowerBound)
let newSpan = unsafe Self(_unchecked: newStart, byteCount: bounds.count)
@@ -496,7 +496,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(
_ bounds: some RangeExpression<Int>
) -> Self {
@@ -520,7 +520,7 @@ extension MutableRawSpan {
/// - Complexity: O(1)
@unsafe
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(unchecked bounds: ClosedRange<Int>) -> Self {
let range = unsafe Range(
_uncheckedBounds: (bounds.lowerBound, bounds.upperBound+1)
@@ -538,7 +538,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(_: UnboundedRange) -> Self {
let newSpan = unsafe Self(_unchecked: _start(), byteCount: _count)
return unsafe _overrideLifetime(newSpan, mutating: &self)
@@ -565,7 +565,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(first maxLength: Int) -> Self {
_precondition(maxLength >= 0, "Can't have a prefix of negative length")
let newCount = min(maxLength, byteCount)
@@ -588,7 +588,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(droppingLast k: Int) -> Self {
_precondition(k >= 0, "Can't drop a negative number of elements")
let droppedCount = min(k, byteCount)
@@ -613,7 +613,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(last maxLength: Int) -> Self {
_precondition(maxLength >= 0, "Can't have a suffix of negative length")
let newCount = min(maxLength, byteCount)
@@ -637,7 +637,7 @@ extension MutableRawSpan {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(droppingFirst k: Int) -> Self {
_precondition(k >= 0, "Can't drop a negative number of bytes")
let droppedCount = min(k, byteCount)

View File

@@ -666,7 +666,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(_ bounds: Range<Index>) -> Self {
_precondition(
UInt(bitPattern: bounds.lowerBound) <= UInt(bitPattern: _count) &&
@@ -693,7 +693,7 @@ extension MutableSpan where Element: ~Copyable {
/// - Complexity: O(1)
@unsafe
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(unchecked bounds: Range<Index>) -> Self {
let delta = bounds.lowerBound &* MemoryLayout<Element>.stride
let newStart = unsafe _pointer?.advanced(by: delta)
@@ -715,7 +715,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(
_ bounds: some RangeExpression<Index>
) -> Self {
@@ -739,7 +739,7 @@ extension MutableSpan where Element: ~Copyable {
/// - Complexity: O(1)
@unsafe
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(
unchecked bounds: ClosedRange<Index>
) -> Self {
@@ -759,7 +759,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(_: UnboundedRange) -> Self {
let newSpan = unsafe Self(_unchecked: _start(), count: _count)
return unsafe _overrideLifetime(newSpan, mutating: &self)
@@ -786,7 +786,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(first maxLength: Int) -> Self {
_precondition(maxLength >= 0, "Can't have a prefix of negative length")
let newCount = min(maxLength, count)
@@ -809,7 +809,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(droppingLast k: Int) -> Self {
_precondition(k >= 0, "Can't drop a negative number of elements")
let droppedCount = min(k, count)
@@ -834,7 +834,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(last maxLength: Int) -> Self {
_precondition(maxLength >= 0, "Can't have a suffix of negative length")
let newCount = min(maxLength, count)
@@ -859,7 +859,7 @@ extension MutableSpan where Element: ~Copyable {
///
/// - Complexity: O(1)
@_alwaysEmitIntoClient
@lifetime(borrow self)
@lifetime(&self)
mutating public func extracting(droppingFirst k: Int) -> Self {
_precondition(k >= 0, "Can't drop a negative number of elements")
let droppedCount = min(k, count)

View File

@@ -40,7 +40,7 @@ internal func _overrideLifetime<
@_unsafeNonescapableResult
@_alwaysEmitIntoClient
@_transparent
@lifetime(borrow source)
@lifetime(&source)
internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>(
@@ -310,7 +310,7 @@ extension MutableSpan where Element: ~Copyable {
precondition(indices.contains(position), "index out of bounds")
yield self[unchecked: position]
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
precondition(indices.contains(position), "index out of bounds")
yield &self[unchecked: position]

View File

@@ -39,7 +39,7 @@ public struct NEInt: ~Escapable {
var iprop: NEInt {
@lifetime(copy self)
_read { yield self }
@lifetime(borrow self)
@lifetime(&self)
_modify { yield &self }
}

View File

@@ -41,7 +41,7 @@ internal func _overrideLifetime<
/// the `source` argument.
@_unsafeNonescapableResult
@_transparent
@lifetime(borrow source)
@lifetime(&source)
internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>(
@@ -112,7 +112,7 @@ struct NC : ~Copyable {
let c: Int
// Requires a mutable borrow.
@lifetime(borrow self)
@lifetime(&self)
mutating func getMutableSpan() -> MutableSpan {
MutableSpan(p, c)
}

View File

@@ -49,7 +49,7 @@ internal func _overrideLifetime<
/// the `source` argument.
@_unsafeNonescapableResult
@_transparent
@lifetime(borrow source)
@lifetime(&source)
internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>(
@@ -110,7 +110,7 @@ struct MutableSpan<T>: ~Escapable, ~Copyable {
let base: UnsafeMutablePointer<T>
let count: Int
@lifetime(borrow base)
@lifetime(&base)
init(base: UnsafeMutablePointer<T>, count: Int) {
self.base = base
self.count = count
@@ -128,7 +128,7 @@ extension Array {
}
extension Array {
@lifetime(borrow self)
@lifetime(&self)
mutating func mutableSpan() -> MutableSpan<Element> {
/* not the real implementation */
let p = self.withUnsafeMutableBufferPointer { $0.baseAddress! }
@@ -263,7 +263,7 @@ struct MutableView: ~Escapable, ~Copyable {
self.owner = copy owner // OK
}
@lifetime(borrow mutableOwner)
@lifetime(&mutableOwner)
init(mutableOwner: inout AnyObject) {
// Initialization of a ~Escapable value is unenforced. So we can initialize
// the `owner` property without locally borrowing `mutableOwner`.
@@ -432,13 +432,13 @@ func testGlobal(local: InnerTrivial) -> Span<Int> {
// Scoped dependence on mutable values
// =============================================================================
@lifetime(borrow a)
@lifetime(&a)
func testInoutBorrow(a: inout [Int]) -> Span<Int> {
a.span() // expected-error {{lifetime-dependent value escapes its scope}}
// expected-note @-1{{it depends on this scoped access to variable 'a'}}
} // expected-note {{this use causes the lifetime-dependent value to escape}}
@lifetime(borrow a)
@lifetime(&a)
func testInoutMutableBorrow(a: inout [Int]) -> MutableSpan<Int> {
a.mutableSpan()
}
@@ -460,7 +460,7 @@ extension Container {
View(owner: self.owner) // OK
}
@lifetime(borrow self)
@lifetime(&self)
mutating func mutableView() -> MutableView {
// Reading 'self.owner' creates a local borrow scope. This new MutableView
// depends on a the local borrow scope for 'self.owner', so it cannot be
@@ -469,7 +469,7 @@ extension Container {
// expected-note @-1{{it depends on this scoped access to variable 'self'}}
} // expected-note {{this use causes the lifetime-dependent value to escape}}
@lifetime(borrow self)
@lifetime(&self)
mutating func mutableViewModifiesOwner() -> MutableView {
// Passing '&self.owner' inout creates a nested exclusive access that must extend to all uses of the new
// MutableView. This is allowed because the nested access is logically extended to the end of the function (without
@@ -477,7 +477,7 @@ extension Container {
MutableView(mutableOwner: &self.owner)
}
@lifetime(borrow self)
@lifetime(&self)
mutating func mutableSpan() -> MutableSpan<T> {
// Reading 'self.pointer' creates a local borrow scope. The local borrow
// scope is ignored because 'pointer' is a trivial value. Instead, the new

View File

@@ -40,7 +40,7 @@ public struct NonEscapableSelf : ~Swift.Escapable {
public mutating func mutatingMethodNoParamCopy() -> lifetime_depend_infer.NonEscapableSelf
#endif
#if $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodNoParamBorrow() -> lifetime_depend_infer.NonEscapableSelf
#endif
#if $LifetimeDependence
@@ -67,7 +67,7 @@ public struct NonEscapableSelf : ~Swift.Escapable {
public mutating func mutatingMethodOneParamCopy(_: Swift.Int) -> lifetime_depend_infer.NonEscapableSelf
#endif
#if $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodOneParamBorrow(_: Swift.Int) -> lifetime_depend_infer.NonEscapableSelf
#endif
}
@@ -85,7 +85,7 @@ public struct EscapableTrivialSelf {
public mutating func mutatingMethodNoParamLifetime() -> lifetime_depend_infer.NEImmortal
#endif
#if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodNoParamBorrow() -> lifetime_depend_infer.NEImmortal
#endif
#if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
@@ -101,7 +101,7 @@ public struct EscapableTrivialSelf {
public mutating func mutatingMethodOneParamLifetime(_: Swift.Int) -> lifetime_depend_infer.NEImmortal
#endif
#if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodOneParamBorrow(_: Swift.Int) -> lifetime_depend_infer.NEImmortal
#endif
}
@@ -126,7 +126,7 @@ public struct EscapableNonTrivialSelf {
public mutating func mutatingMethodNoParamLifetime() -> lifetime_depend_infer.NEImmortal
#endif
#if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodNoParamBorrow() -> lifetime_depend_infer.NEImmortal
#endif
#if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
@@ -148,7 +148,7 @@ public struct EscapableNonTrivialSelf {
public mutating func mutatingMethodOneParamLifetime(_: Swift.Int) -> lifetime_depend_infer.NEImmortal
#endif
#if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodOneParamBorrow(_: Swift.Int) -> lifetime_depend_infer.NEImmortal
#endif
}
@@ -256,7 +256,7 @@ public struct NonescapableSelfAccessors : ~Swift.Escapable {
#if $LifetimeDependence
public var neYielded: lifetime_depend_infer.NE {
_read
@lifetime(borrow self)
@lifetime(&self)
_modify
}
#endif
@@ -272,7 +272,7 @@ public struct NoncopyableSelfAccessors : ~Copyable & ~Escapable {
#if $LifetimeDependence
public var neYielded: lifetime_depend_infer.NE {
_read
@lifetime(borrow self)
@lifetime(&self)
_modify
}
#endif
@@ -312,7 +312,7 @@ public struct NoncopyableSelfAccessors : ~Copyable & ~Escapable {
public var neComputedBorrow: lifetime_depend_infer.NE {
@lifetime(borrow self)
get
@lifetime(borrow self)
@lifetime(&self)
set
}
#endif
@@ -320,7 +320,7 @@ public struct NoncopyableSelfAccessors : ~Copyable & ~Escapable {
public var neYieldedBorrow: lifetime_depend_infer.NE {
@lifetime(borrow self)
_read
@lifetime(borrow self)
@lifetime(&self)
_modify
}
#endif
@@ -346,7 +346,7 @@ public struct NonEscapableMutableSelf : ~Swift.Escapable {
public mutating func mutatingMethodOneParamCopy(_: lifetime_depend_infer.NE)
#endif
#if $LifetimeDependence
@lifetime(borrow self)
@lifetime(&self)
public mutating func mutatingMethodOneParamBorrow(_: lifetime_depend_infer.NE)
#endif
}

View File

@@ -63,3 +63,9 @@ do {
// rdar://146401190 ([nonescapable] implement non-inout parameter dependencies)
@lifetime(span: borrow holder)
func testParameterDep(holder: AnyObject, span: Span<Int>) {} // expected-error{{lifetime-dependent parameter must be 'inout'}}
@lifetime(&ne)
func inoutLifetimeDependence(_ ne: inout NE) -> NE {
ne
}

View File

@@ -137,7 +137,7 @@ struct EscapableNonTrivialSelf {
@lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@lifetime(borrow self)' instead}}
mutating func mutatingMethodNoParamCopy() -> NEImmortal { NEImmortal() }
@lifetime(borrow self)
@lifetime(&self)
mutating func mutatingMethodNoParamBorrow() -> NEImmortal { NEImmortal() }
func methodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a method with a ~Escapable result requires '@lifetime(...)'}}
@@ -159,7 +159,7 @@ struct EscapableNonTrivialSelf {
@lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@lifetime(borrow self)' instead}}
mutating func mutatingMethodOneParamCopy(_: Int) -> NEImmortal { NEImmortal() }
@lifetime(borrow self)
@lifetime(&self)
mutating func mutatingMethodOneParamBorrow(_: Int) -> NEImmortal { NEImmortal() }
}
@@ -224,7 +224,7 @@ func oneParamLifetime(c: C) -> NEImmortal { NEImmortal() }
func oneParamConsume(c: consuming C) -> NEImmortal { NEImmortal() } // expected-error{{cannot borrow the lifetime of 'c', which has consuming ownership on a function}}
@lifetime(c) // expected-error{{invalid use of borrow dependence with consuming ownership}}
@lifetime(c) // expected-error{{invalid lifetime dependence on an Escapable value with consuming ownership}}
func oneParamConsumeLifetime(c: consuming C) -> NEImmortal { NEImmortal() }
func oneParamBorrow(c: borrowing C) -> NEImmortal { NEImmortal() } // OK
@@ -424,7 +424,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
yield ne
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
yield &ne
}
@@ -484,7 +484,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
ne
}
@lifetime(borrow self)
@lifetime(&self)
set {
ne = newValue
}
@@ -496,7 +496,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
yield ne
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
yield &ne
}

View File

@@ -106,7 +106,7 @@ struct EscapableNonTrivialSelf {
@lifetime(self)
mutating func mutatingMethodNoParamLifetime() -> NEImmortal { NEImmortal() }
@lifetime(borrow self)
@lifetime(&self)
mutating func mutatingMethodNoParamBorrow() -> NEImmortal { NEImmortal() }
func methodOneParam(_: Int) -> NEImmortal { NEImmortal() } // OK
@@ -122,7 +122,7 @@ struct EscapableNonTrivialSelf {
@lifetime(self) // OK
mutating func mutatingMethodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() }
@lifetime(borrow self) // OK
@lifetime(&self) // OK
mutating func mutatingMethodOneParamBorrow(_: Int) -> NEImmortal { NEImmortal() }
}
@@ -351,7 +351,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
yield ne
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
yield &ne
}
@@ -411,7 +411,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
ne
}
@lifetime(borrow self)
@lifetime(&self)
set {
ne = newValue
}
@@ -423,7 +423,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
yield ne
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
yield &ne
}

View File

@@ -72,7 +72,7 @@ public struct Wrapper : ~Escapable {
_read {
yield _view
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
yield &_view
}

View File

@@ -62,7 +62,7 @@ public struct Wrapper : ~Escapable {
_read {
yield _view
}
@lifetime(borrow self)
@lifetime(&self)
_modify {
yield &_view
}