Skip to content

Commit 59c8cff

Browse files
committed
[borrowing] Add support for borrowing/consuming copyable types to be a noimplicitcopy type.
rdar://108383660
1 parent 70ab38d commit 59c8cff

35 files changed

+2621
-250
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5300,7 +5300,9 @@ class SILMoveOnlyWrappedType final : public TypeBase,
53005300
SILMoveOnlyWrappedType(CanType innerType)
53015301
: TypeBase(TypeKind::SILMoveOnlyWrapped, &innerType->getASTContext(),
53025302
innerType->getRecursiveProperties()),
5303-
innerType(innerType) {}
5303+
innerType(innerType) {
5304+
assert(!innerType->isPureMoveOnly() && "Inner type must be copyable");
5305+
}
53045306

53055307
public:
53065308
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/SILInstruction.h

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8517,10 +8517,21 @@ class CopyableToMoveOnlyWrapperValueInst
85178517
DebugLoc, operand, operand->getType().addingMoveOnlyWrapper(),
85188518
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
85198519
: OwnershipKind::Owned),
8520-
initialKind(kind) {}
8520+
initialKind(kind) {
8521+
assert(!operand->getType().isMoveOnly() &&
8522+
"Cannot be moveonly or moveonly wrapped");
8523+
}
85218524

85228525
public:
85238526
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+
}
85248535
};
85258536

85268537
/// Convert from an @moveOnly wrapper type to the underlying copyable type. Can
@@ -8569,10 +8580,21 @@ class MoveOnlyWrapperToCopyableValueInst
85698580
DebugLoc, operand, operand->getType().removingMoveOnlyWrapper(),
85708581
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
85718582
: OwnershipKind::Owned),
8572-
initialKind(kind) {}
8583+
initialKind(kind) {
8584+
assert(operand->getType().isMoveOnlyWrapped() &&
8585+
"Expected moveonlywrapped argument!");
8586+
}
85738587

85748588
public:
85758589
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+
}
85768598
};
85778599

85788600
/// Convert a ${ @moveOnly T } to $T. This is a forwarding instruction that acts
@@ -8606,7 +8628,9 @@ class CopyableToMoveOnlyWrapperAddrInst
86068628

86078629
CopyableToMoveOnlyWrapperAddrInst(SILDebugLocation DebugLoc, SILValue operand)
86088630
: UnaryInstructionBase(DebugLoc, operand,
8609-
operand->getType().addingMoveOnlyWrapper()) {}
8631+
operand->getType().addingMoveOnlyWrapper()) {
8632+
assert(!operand->getType().isMoveOnly() && "Expected copyable argument");
8633+
}
86108634
};
86118635

86128636
class MoveOnlyWrapperToCopyableAddrInst
@@ -8617,7 +8641,10 @@ class MoveOnlyWrapperToCopyableAddrInst
86178641

86188642
MoveOnlyWrapperToCopyableAddrInst(SILDebugLocation DebugLoc, SILValue operand)
86198643
: UnaryInstructionBase(DebugLoc, operand,
8620-
operand->getType().removingMoveOnlyWrapper()) {}
8644+
operand->getType().removingMoveOnlyWrapper()) {
8645+
assert(operand->getType().isMoveOnlyWrapped() &&
8646+
"Expected moveonlywrapped argument");
8647+
}
86218648
};
86228649

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

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ AbstractionPattern AbstractionPattern::removingMoveOnlyWrapper() const {
815815
case Kind::Tuple:
816816
llvm_unreachable("cannot apply move-only wrappers to open-coded patterns");
817817
case Kind::Opaque:
818+
// Opaque is opaque. We do not remove anything.
819+
return *this;
818820
case Kind::Type:
819821
if (auto mvi = dyn_cast<SILMoveOnlyWrappedType>(getType())) {
820822
return AbstractionPattern(getGenericSubstitutions(),

lib/SIL/IR/SILType.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ SILType SILType::getFieldType(VarDecl *field, TypeConverter &TC,
329329
if (field->hasClangNode()) {
330330
substFieldTy = origFieldTy.getType();
331331
} else {
332+
// We want to specifically use getASTType() here instead of getRawASTType()
333+
// to ensure that we can correctly get our substituted field type. If we
334+
// need to rewrap the type layer, we do it below.
332335
substFieldTy =
333336
getASTType()->getTypeOfMember(&TC.M, field)->getCanonicalType();
334337
}
@@ -655,8 +658,8 @@ CanType swift::getSILBoxFieldLoweredType(TypeExpansionContext context,
655658
LookUpConformanceInSubstitutionMap(subMap),
656659
sig);
657660
}
658-
659-
return fieldTy.getASTType();
661+
662+
return fieldTy.getRawASTType();
660663
}
661664

662665
ValueOwnershipKind

lib/SIL/IR/SILTypeSubstitution.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class SILTypeSubstituter :
292292
}
293293

294294
SILType subst(SILType type) {
295-
return SILType::getPrimitiveType(visit(type.getASTType()),
295+
return SILType::getPrimitiveType(visit(type.getRawASTType()),
296296
type.getCategory());
297297
}
298298

lib/SIL/IR/TypeLowering.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,7 +2514,7 @@ TypeConverter::~TypeConverter() {
25142514
// Destroy only the unique entries.
25152515
CanType srcType = ti.first.OrigType;
25162516
if (!srcType) continue;
2517-
CanType mappedType = ti.second->getLoweredType().getASTType();
2517+
CanType mappedType = ti.second->getLoweredType().getRawASTType();
25182518
if (srcType == mappedType)
25192519
ti.second->~TypeLowering();
25202520
}
@@ -4380,10 +4380,11 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
43804380
env->mapTypeIntoContext(contextBoxTy)
43814381
->getCanonicalType());
43824382
}
4383+
4384+
auto ty = getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy,
4385+
*this, 0);
43834386
assert(contextBoxTy->getLayout()->getFields().size() == 1 &&
4384-
getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy,
4385-
*this, 0)
4386-
.getASTType() == loweredContextType &&
4387+
ty.getRawASTType() == loweredContextType &&
43874388
"box field type doesn't match capture!");
43884389
#endif
43894390
return boxTy;
@@ -4435,7 +4436,7 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(
44354436
}
44364437

44374438
// Use the enum's signature for the box type.
4438-
auto boundEnum = enumType.getASTType();
4439+
auto boundEnum = enumType.getRawASTType();
44394440

44404441
// Lower the enum element's argument in the box's context.
44414442
auto eltIntfTy = elt->getArgumentInterfaceType();

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,12 @@ class AccessPathVisitor : public FindAccessVisitorImpl<AccessPathVisitor> {
13491349
// as such when it operates on unchecked_take_enum_data_addr.
13501350
|| isa<ProjectBoxInst>(projectedAddr)
13511351
// Ignore mark_must_check, we just look through it when we see it.
1352-
|| isa<MarkMustCheckInst>(projectedAddr));
1352+
|| isa<MarkMustCheckInst>(projectedAddr)
1353+
// Ignore moveonlywrapper_to_copyable_addr and
1354+
// copyable_to_moveonlywrapper_addr, we just look through it when
1355+
// we see it
1356+
|| isa<MoveOnlyWrapperToCopyableAddrInst>(projectedAddr) ||
1357+
isa<CopyableToMoveOnlyWrapperAddrInst>(projectedAddr));
13531358
}
13541359
return sourceAddr->get();
13551360
}
@@ -1874,6 +1879,12 @@ AccessPathDefUseTraversal::visitSingleValueUser(SingleValueInstruction *svi,
18741879
return IgnoredUse;
18751880
}
18761881

1882+
// Look through both of these.
1883+
case SILInstructionKind::MoveOnlyWrapperToCopyableAddrInst:
1884+
case SILInstructionKind::CopyableToMoveOnlyWrapperAddrInst:
1885+
pushUsers(svi, dfs);
1886+
return IgnoredUse;
1887+
18771888
// MARK: Access projections
18781889

18791890
case SILInstructionKind::StructElementAddrInst:

0 commit comments

Comments
 (0)