mirror of
https://github.com/apple/swift.git
synced 2026-10-30 22:15:52 +01:00
swift::getLoweredOwnership() decides the ownership that a parameter has after lowering when it doesn't specify one, but it disagreed with SIL type lowering in a few cases. It treated an init accessor's parameters as borrowed instead of owned, the `self` of a non-mutating setter, modify accessor, or yielding mutate accessor as `inout` instead of borrowed, and the `self` of a noncopyable type's deinit as borrowed instead of owned. As a result, `@_lifetime(borrow self)` was rejected on a non-mutating modify accessor. Fix those cases so that SIL type lowering can use the same decision to choose the conventions of setters and init accessors. Return a new LoweredOwnership enum, which has no default case, so that callers don't have to handle one. Also add a ParamDecl method that takes the ownership of a closure's unannotated parameter from the closure's type.
82 lines
2.8 KiB
C++
82 lines
2.8 KiB
C++
//===--- Ownership.cpp - Swift ASTs for Ownership ------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2026 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/Ownership.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/StorageImpl.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
using namespace swift;
|
|
|
|
llvm::StringRef swift::getOwnershipSpelling(ValueOwnership ownership) {
|
|
switch (ownership) {
|
|
case ValueOwnership::Default:
|
|
return "default";
|
|
case ValueOwnership::InOut:
|
|
return "inout";
|
|
case ValueOwnership::Shared:
|
|
return "borrowing";
|
|
case ValueOwnership::Owned:
|
|
return "consuming";
|
|
}
|
|
llvm_unreachable("Invalid ValueOwnership");
|
|
}
|
|
|
|
ValueOwnership swift::asValueOwnership(LoweredOwnership ownership) {
|
|
switch (ownership) {
|
|
case LoweredOwnership::Shared:
|
|
return ValueOwnership::Shared;
|
|
case LoweredOwnership::InOut:
|
|
return ValueOwnership::InOut;
|
|
case LoweredOwnership::Owned:
|
|
return ValueOwnership::Owned;
|
|
}
|
|
llvm_unreachable("Invalid LoweredOwnership");
|
|
}
|
|
|
|
llvm::StringRef swift::getOwnershipSpelling(LoweredOwnership ownership) {
|
|
return getOwnershipSpelling(asValueOwnership(ownership));
|
|
}
|
|
|
|
LoweredOwnership swift::getLoweredOwnership(ValueOwnership written,
|
|
const AbstractFunctionDecl *fn,
|
|
bool isSelf) {
|
|
switch (written) {
|
|
case ValueOwnership::Shared:
|
|
return LoweredOwnership::Shared;
|
|
case ValueOwnership::InOut:
|
|
return LoweredOwnership::InOut;
|
|
case ValueOwnership::Owned:
|
|
return LoweredOwnership::Owned;
|
|
case ValueOwnership::Default:
|
|
break;
|
|
}
|
|
// A mutating function writes `self` as `inout`, so the defaults below only
|
|
// apply to the `self` of a function that isn't mutating.
|
|
if (isa_and_nonnull<ConstructorDecl>(fn))
|
|
return LoweredOwnership::Owned;
|
|
if (auto *ad = dyn_cast_or_null<AccessorDecl>(fn)) {
|
|
// A setter or an init accessor owns its parameters other than `self`.
|
|
if (ad->getAccessorKind() == AccessorKind::Set ||
|
|
ad->getAccessorKind() == AccessorKind::Init)
|
|
return isSelf ? LoweredOwnership::Shared : LoweredOwnership::Owned;
|
|
}
|
|
// The deinit of a noncopyable struct or enum owns `self`, unlike the deinit
|
|
// of a class, whose body only borrows it.
|
|
if (auto *dd = dyn_cast_or_null<DestructorDecl>(fn)) {
|
|
if (isSelf && !dd->getDeclContext()->getSelfClassDecl())
|
|
return LoweredOwnership::Owned;
|
|
}
|
|
return LoweredOwnership::Shared;
|
|
}
|