Skip to content

Commit 29672c5

Browse files
authored
Merge pull request #66381 from gottesmm/noimplicitcopy-borrow-consuming
[borrowing/consuming] Make borrowing and consuming parameters no implicit copy.
2 parents c30f7dc + 59c8cff commit 29672c5

File tree

74 files changed

+3449
-451
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+3449
-451
lines changed

docs/SIL.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8460,6 +8460,33 @@ need for the guaranteed form in the future.
84608460
@moveOnly trivial type, we convert from the non-trivial representation to the
84618461
trivial representation.
84628462

8463+
copyable_to_moveonlywrapper_addr
8464+
````````````````````````````````
8465+
::
8466+
8467+
sil-instruction ::= 'copyable_to_moveonlywrapper_addr'
8468+
8469+
`copyable_to_moveonlywrapper_addr`_ takes in a '*T' and maps it to a move only
8470+
wrapped '*@moveOnly T'. This is semantically used by a code generator
8471+
initializing a new moveOnly binding from a copyable value. It semantically acts
8472+
as an address cast. If one thinks of '@moveOnly' as a monad, this is how one
8473+
injects a copyable value into the move only space.
8474+
8475+
moveonlywrapper_to_copyable_addr
8476+
````````````````````````````````
8477+
::
8478+
8479+
sil-instruction ::= 'moveonlywrapper_to_copyable_addr'
8480+
8481+
`moveonlywrapper_to_copyable_addr`_ takes in a '*@moveOnly T' and produces a new
8482+
'*T' value. This instruction acts like an address cast that projects out the
8483+
underlying T from an @moveOnly T.
8484+
8485+
NOTE: From the perspective of the address checker, a trivial `load`_ with a
8486+
`moveonlywrapper_to_copyable_addr`_ operand is considered to be a use of a
8487+
noncopyable type.
8488+
8489+
84638490
Assertion configuration
84648491
~~~~~~~~~~~~~~~~~~~~~~~
84658492

include/swift/AST/Decl.h

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,26 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK);
225225
/// Diagnostic printing of \c ReferenceOwnership.
226226
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceOwnership RO);
227227

228+
enum class SelfAccessKind : uint8_t {
229+
NonMutating,
230+
Mutating,
231+
LegacyConsuming,
232+
Consuming,
233+
Borrowing,
234+
LastSelfAccessKind = Borrowing,
235+
};
236+
enum : unsigned {
237+
NumSelfAccessKindBits =
238+
countBitsUsed(static_cast<unsigned>(SelfAccessKind::LastSelfAccessKind))
239+
};
240+
static_assert(uint8_t(SelfAccessKind::LastSelfAccessKind) <
241+
(NumSelfAccessKindBits << 1),
242+
"Self Access Kind is too small to fit in SelfAccess kind bits. "
243+
"Please expand ");
244+
245+
/// Diagnostic printing of \c SelfAccessKind.
246+
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK);
247+
228248
/// Encapsulation of the overload signature of a given declaration,
229249
/// which is used to determine uniqueness of a declaration within a
230250
/// given context.
@@ -316,6 +336,10 @@ enum class ArtificialMainKind : uint8_t {
316336
/// Decl - Base class for all declarations in Swift.
317337
class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
318338
protected:
339+
// clang-format off
340+
//
341+
// We format these different than clang-format wishes us to... so turn if off
342+
// for the inline bitfields.
319343
union { uint64_t OpaqueBits;
320344

321345
SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1,
@@ -457,7 +481,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
457481
DistributedThunk: 1
458482
);
459483

460-
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2+1,
484+
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl,
485+
1+1+2+1+1+NumSelfAccessKindBits+1,
461486
/// Whether we've computed the 'static' flag yet.
462487
IsStaticComputed : 1,
463488

@@ -474,7 +499,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
474499
SelfAccessComputed : 1,
475500

476501
/// Backing bits for 'self' access kind.
477-
SelfAccess : 2,
502+
SelfAccess : NumSelfAccessKindBits,
478503

479504
/// Whether this is a top-level function which should be treated
480505
/// as if it were in local context for the purposes of capture
@@ -736,6 +761,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
736761
);
737762

738763
} Bits;
764+
// Turn back on clang-format now that we have defined our inline bitfields.
765+
// clang-format on
739766

740767
// Storage for the declaration attributes.
741768
DeclAttributes Attrs;
@@ -7233,17 +7260,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
72337260

72347261
class OperatorDecl;
72357262

7236-
enum class SelfAccessKind : uint8_t {
7237-
NonMutating,
7238-
Mutating,
7239-
LegacyConsuming,
7240-
Consuming,
7241-
Borrowing,
7242-
};
7243-
7244-
/// Diagnostic printing of \c SelfAccessKind.
7245-
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK);
7246-
72477263
/// FuncDecl - 'func' declaration.
72487264
class FuncDecl : public AbstractFunctionDecl {
72497265
friend class AbstractFunctionDecl;

include/swift/AST/DiagnosticsParse.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,11 @@ ERROR(sil_ref_inst_wrong_field,none,
603603
ERROR(sil_invalid_instr_operands,none,
604604
"invalid instruction operands", ())
605605
ERROR(sil_operand_not_address,none,
606-
"%0 operand of '%1' must have address type", (StringRef, StringRef))
606+
"%0 of '%1' must have address type", (StringRef, StringRef))
607+
ERROR(sil_operand_not_object,none,
608+
"%0 of '%1' must have object type", (StringRef, StringRef))
609+
ERROR(sil_operand_has_incorrect_moveonlywrapped,none,
610+
"%0 of '%1' %select{must|must not}2 be of moveonlywrapped type", (StringRef, StringRef, unsigned))
607611
ERROR(sil_operand_not_ref_storage_address,none,
608612
"%0 operand of '%1' must have address of %2 type",
609613
(StringRef, StringRef, ReferenceOwnership))
@@ -911,6 +915,8 @@ ERROR(sil_box_expected_r_brace,none,
911915
"expected '}' to complete SIL box field type list", ())
912916
ERROR(sil_box_expected_r_angle,none,
913917
"expected '>' to complete SIL box generic argument list", ())
918+
ERROR(sil_box_expected,none,
919+
"%0 expects its operand to be of SIL box field type", (StringRef))
914920

915921
// SIL function types
916922
ERROR(sil_function_subst_expected_l_angle,none,

include/swift/AST/Types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5305,7 +5305,9 @@ class SILMoveOnlyWrappedType final : public TypeBase,
53055305
SILMoveOnlyWrappedType(CanType innerType)
53065306
: TypeBase(TypeKind::SILMoveOnlyWrapped, &innerType->getASTContext(),
53075307
innerType->getRecursiveProperties()),
5308-
innerType(innerType) {}
5308+
innerType(innerType) {
5309+
assert(!innerType->isPureMoveOnly() && "Inner type must be copyable");
5310+
}
53095311

53105312
public:
53115313
CanType getInnerType() const { return innerType; }

include/swift/SIL/MemAccessUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,9 @@ inline bool isAccessStorageTypeCast(SingleValueInstruction *svi) {
15921592
default:
15931593
return false;
15941594
// Simply pass-thru the incoming address. But change its type!
1595+
case SILInstructionKind::MoveOnlyWrapperToCopyableAddrInst:
1596+
case SILInstructionKind::CopyableToMoveOnlyWrapperAddrInst:
1597+
// Simply pass-thru the incoming address. But change its type!
15951598
case SILInstructionKind::UncheckedAddrCastInst:
15961599
// Casting to RawPointer does not affect the AccessPath. When converting
15971600
// between address types, they must be layout compatible (with truncation).

include/swift/SIL/SILBuilder.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,24 @@ class SILBuilder {
14131413
CopyableToMoveOnlyWrapperValueInst::Guaranteed));
14141414
}
14151415

1416+
MoveOnlyWrapperToCopyableBoxInst *
1417+
createMoveOnlyWrapperToCopyableBox(SILLocation loc, SILValue src) {
1418+
return insert(new (getModule()) MoveOnlyWrapperToCopyableBoxInst(
1419+
getSILDebugLocation(loc), src, src->getOwnershipKind()));
1420+
}
1421+
1422+
MoveOnlyWrapperToCopyableAddrInst *
1423+
createMoveOnlyWrapperToCopyableAddr(SILLocation loc, SILValue src) {
1424+
return insert(new (getModule()) MoveOnlyWrapperToCopyableAddrInst(
1425+
getSILDebugLocation(loc), src));
1426+
}
1427+
1428+
CopyableToMoveOnlyWrapperAddrInst *
1429+
createCopyableToMoveOnlyWrapperAddr(SILLocation loc, SILValue src) {
1430+
return insert(new (getModule()) CopyableToMoveOnlyWrapperAddrInst(
1431+
getSILDebugLocation(loc), src));
1432+
}
1433+
14161434
MoveOnlyWrapperToCopyableValueInst *
14171435
createOwnedMoveOnlyWrapperToCopyableValue(SILLocation loc, SILValue src) {
14181436
return insert(new (getModule()) MoveOnlyWrapperToCopyableValueInst(

include/swift/SIL/SILCloner.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,6 +1941,33 @@ void SILCloner<ImplClass>::visitMoveOnlyWrapperToCopyableValueInst(
19411941
recordClonedInstruction(inst, cvt);
19421942
}
19431943

1944+
template <typename ImplClass>
1945+
void SILCloner<ImplClass>::visitMoveOnlyWrapperToCopyableBoxInst(
1946+
MoveOnlyWrapperToCopyableBoxInst *inst) {
1947+
getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope()));
1948+
recordClonedInstruction(
1949+
inst, getBuilder().createMoveOnlyWrapperToCopyableBox(
1950+
getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())));
1951+
}
1952+
1953+
template <typename ImplClass>
1954+
void SILCloner<ImplClass>::visitMoveOnlyWrapperToCopyableAddrInst(
1955+
MoveOnlyWrapperToCopyableAddrInst *inst) {
1956+
getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope()));
1957+
recordClonedInstruction(
1958+
inst, getBuilder().createMoveOnlyWrapperToCopyableAddr(
1959+
getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())));
1960+
}
1961+
1962+
template <typename ImplClass>
1963+
void SILCloner<ImplClass>::visitCopyableToMoveOnlyWrapperAddrInst(
1964+
CopyableToMoveOnlyWrapperAddrInst *inst) {
1965+
getBuilder().setCurrentDebugScope(getOpScope(inst->getDebugScope()));
1966+
recordClonedInstruction(
1967+
inst, getBuilder().createCopyableToMoveOnlyWrapperAddr(
1968+
getOpLocation(inst->getLoc()), getOpValue(inst->getOperand())));
1969+
}
1970+
19441971
template <typename ImplClass>
19451972
void SILCloner<ImplClass>::visitCopyableToMoveOnlyWrapperValueInst(
19461973
CopyableToMoveOnlyWrapperValueInst *inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,7 @@ FirstArgOwnershipForwardingSingleValueInst::classof(SILInstructionKind kind) {
13971397
case SILInstructionKind::InitExistentialRefInst:
13981398
case SILInstructionKind::MarkDependenceInst:
13991399
case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst:
1400+
case SILInstructionKind::MoveOnlyWrapperToCopyableBoxInst:
14001401
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
14011402
return true;
14021403
default:
@@ -8516,10 +8517,21 @@ class CopyableToMoveOnlyWrapperValueInst
85168517
DebugLoc, operand, operand->getType().addingMoveOnlyWrapper(),
85178518
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
85188519
: OwnershipKind::Owned),
8519-
initialKind(kind) {}
8520+
initialKind(kind) {
8521+
assert(!operand->getType().isMoveOnly() &&
8522+
"Cannot be moveonly or moveonly wrapped");
8523+
}
85208524

85218525
public:
85228526
InitialKind getInitialKind() const { return initialKind; }
8527+
8528+
bool hasGuaranteedInitialKind() const {
8529+
return getInitialKind() == InitialKind::Guaranteed;
8530+
}
8531+
8532+
bool hasOwnedInitialKind() const {
8533+
return getInitialKind() == InitialKind::Owned;
8534+
}
85238535
};
85248536

85258537
/// Convert from an @moveOnly wrapper type to the underlying copyable type. Can
@@ -8568,10 +8580,71 @@ class MoveOnlyWrapperToCopyableValueInst
85688580
DebugLoc, operand, operand->getType().removingMoveOnlyWrapper(),
85698581
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
85708582
: OwnershipKind::Owned),
8571-
initialKind(kind) {}
8583+
initialKind(kind) {
8584+
assert(operand->getType().isMoveOnlyWrapped() &&
8585+
"Expected moveonlywrapped argument!");
8586+
}
85728587

85738588
public:
85748589
InitialKind getInitialKind() const { return initialKind; }
8590+
8591+
bool hasGuaranteedInitialKind() const {
8592+
return getInitialKind() == InitialKind::Guaranteed;
8593+
}
8594+
8595+
bool hasOwnedInitialKind() const {
8596+
return getInitialKind() == InitialKind::Owned;
8597+
}
8598+
};
8599+
8600+
/// Convert a ${ @moveOnly T } to $T. This is a forwarding instruction that acts
8601+
/// similarly to an object cast like upcast, unlike
8602+
/// MoveOnlyWrapperToCopyableValue which provides artificial semantics injected
8603+
/// by SILGen.
8604+
class MoveOnlyWrapperToCopyableBoxInst
8605+
: public UnaryInstructionBase<
8606+
SILInstructionKind::MoveOnlyWrapperToCopyableBoxInst,
8607+
FirstArgOwnershipForwardingSingleValueInst> {
8608+
friend class SILBuilder;
8609+
8610+
MoveOnlyWrapperToCopyableBoxInst(SILDebugLocation DebugLoc, SILValue operand,
8611+
ValueOwnershipKind forwardingOwnershipKind)
8612+
: UnaryInstructionBase(
8613+
DebugLoc, operand,
8614+
operand->getType().removingMoveOnlyWrapperToBoxedType(
8615+
operand->getFunction()),
8616+
forwardingOwnershipKind) {
8617+
assert(
8618+
operand->getType().isBoxedMoveOnlyWrappedType(operand->getFunction()) &&
8619+
"Expected moveonlywrapped argument!");
8620+
}
8621+
};
8622+
8623+
class CopyableToMoveOnlyWrapperAddrInst
8624+
: public UnaryInstructionBase<
8625+
SILInstructionKind::CopyableToMoveOnlyWrapperAddrInst,
8626+
SingleValueInstruction> {
8627+
friend class SILBuilder;
8628+
8629+
CopyableToMoveOnlyWrapperAddrInst(SILDebugLocation DebugLoc, SILValue operand)
8630+
: UnaryInstructionBase(DebugLoc, operand,
8631+
operand->getType().addingMoveOnlyWrapper()) {
8632+
assert(!operand->getType().isMoveOnly() && "Expected copyable argument");
8633+
}
8634+
};
8635+
8636+
class MoveOnlyWrapperToCopyableAddrInst
8637+
: public UnaryInstructionBase<
8638+
SILInstructionKind::MoveOnlyWrapperToCopyableAddrInst,
8639+
SingleValueInstruction> {
8640+
friend class SILBuilder;
8641+
8642+
MoveOnlyWrapperToCopyableAddrInst(SILDebugLocation DebugLoc, SILValue operand)
8643+
: UnaryInstructionBase(DebugLoc, operand,
8644+
operand->getType().removingMoveOnlyWrapper()) {
8645+
assert(operand->getType().isMoveOnlyWrapped() &&
8646+
"Expected moveonlywrapped argument");
8647+
}
85758648
};
85768649

85778650
/// Given an object reference, return true iff it is non-nil and refers

include/swift/SIL/SILNodes.def

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,11 +490,25 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
490490
// and owned for assignment/owned function arguments.
491491
SINGLE_VALUE_INST(CopyableToMoveOnlyWrapperValueInst, copyable_to_moveonlywrapper,
492492
SingleValueInstruction, None, DoesNotRelease)
493-
// Convert a $@moveOnly T to $T. Ownership is fixed at construction by
493+
// Convert a $@moveOnly T object to $T. Ownership is fixed at construction by
494494
// frontend to express specific semantics: guaranteed for function arguments
495495
// and owned for assignment/return values.
496-
SINGLE_VALUE_INST(MoveOnlyWrapperToCopyableValueInst, moveonlywrapper_to_copyable,
497-
SingleValueInstruction, None, DoesNotRelease)
496+
SINGLE_VALUE_INST(MoveOnlyWrapperToCopyableValueInst,
497+
moveonlywrapper_to_copyable, SingleValueInstruction, None,
498+
DoesNotRelease)
499+
// Convert a ${ @moveOnly T } to $T. This is a forwarding instruction that
500+
// acts similarly to an object cast, unlike MoveOnlyWrapperToCopyableValue.
501+
SINGLE_VALUE_INST(MoveOnlyWrapperToCopyableBoxInst,
502+
moveonlywrapper_to_copyable_box, SingleValueInstruction, None,
503+
DoesNotRelease)
504+
// Convert a $*@moveOnly T to $*T. Acts just as a cast.
505+
SINGLE_VALUE_INST(MoveOnlyWrapperToCopyableAddrInst,
506+
moveonlywrapper_to_copyable_addr, SingleValueInstruction,
507+
None, DoesNotRelease)
508+
// Convert a $*T to $*@moveOnly T. Acts just as a cast.
509+
SINGLE_VALUE_INST(CopyableToMoveOnlyWrapperAddrInst,
510+
copyable_to_moveonlywrapper_addr, SingleValueInstruction,
511+
None, DoesNotRelease)
498512
// A move_addr is a Raw SIL only instruction that is equivalent to a copy_addr
499513
// [init]. It is lowered during the diagnostic passes to a copy_addr [init] if
500514
// the move checker found uses that prevented us from converting this to a

include/swift/SIL/SILType.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,8 +757,8 @@ class SILType {
757757
return getRawASTType()->is<SILMoveOnlyWrappedType>();
758758
}
759759

760-
/// If this is already a move only wrapped type, return *this. Otherwise, wrap
761-
/// the copyable type in the mov eonly wrapper.
760+
/// If this is already a moveonlywrapped type, return *this. Otherwise, wrap
761+
/// the copyable type in the moveonlywrapper.
762762
SILType addingMoveOnlyWrapper() const {
763763
if (isMoveOnlyWrapped())
764764
return *this;
@@ -785,6 +785,20 @@ class SILType {
785785
return *this;
786786
}
787787

788+
/// If this is a box type containing a moveonlywrapped type, return a new box
789+
/// with the moveonlywrapped type unwrapped.
790+
///
791+
/// DISCUSSION: This is separate from addingMoveOnlyWrapper since this API
792+
/// requires a SILFunction * and is specialized.
793+
SILType addingMoveOnlyWrapperToBoxedType(const SILFunction *fn);
794+
795+
/// If this is a box type containing a copyable type, return a new box type
796+
/// with the copyable type wrapped in a moveonly wrapped type.
797+
///
798+
/// DISCUSSION: This is separate from removingMoveOnlyWrapper since this API
799+
/// requires a SILFunction * and is specialized.
800+
SILType removingMoveOnlyWrapperToBoxedType(const SILFunction *fn);
801+
788802
/// Returns a SILType with any archetypes mapped out of context.
789803
SILType mapTypeOutOfContext() const;
790804

@@ -835,6 +849,12 @@ class SILType {
835849
return isBoxedNonCopyableType(&fn);
836850
}
837851

852+
bool isBoxedMoveOnlyWrappedType(const SILFunction *fn) const {
853+
if (!this->is<SILBoxType>())
854+
return false;
855+
return getSILBoxFieldType(fn).isMoveOnlyWrapped();
856+
}
857+
838858
SILType getInstanceTypeOfMetatype(SILFunction *function) const;
839859

840860
bool isOrContainsObjectiveCClass() const;

0 commit comments

Comments
 (0)