Skip to content

Commit 72cd7c5

Browse files
committed
[borrowing] Add support for borrowing/consuming copyable types to be a noimplicitcopy type.
rdar://108383660 (cherry picked from commit 59c8cff)
1 parent 617fd26 commit 72cd7c5

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
@@ -5291,7 +5291,9 @@ class SILMoveOnlyWrappedType final : public TypeBase,
52915291
SILMoveOnlyWrappedType(CanType innerType)
52925292
: TypeBase(TypeKind::SILMoveOnlyWrapped, &innerType->getASTContext(),
52935293
innerType->getRecursiveProperties()),
5294-
innerType(innerType) {}
5294+
innerType(innerType) {
5295+
assert(!innerType->isPureMoveOnly() && "Inner type must be copyable");
5296+
}
52955297

52965298
public:
52975299
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
@@ -8483,10 +8483,21 @@ class CopyableToMoveOnlyWrapperValueInst
84838483
DebugLoc, operand, operand->getType().addingMoveOnlyWrapper(),
84848484
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
84858485
: OwnershipKind::Owned),
8486-
initialKind(kind) {}
8486+
initialKind(kind) {
8487+
assert(!operand->getType().isMoveOnly() &&
8488+
"Cannot be moveonly or moveonly wrapped");
8489+
}
84878490

84888491
public:
84898492
InitialKind getInitialKind() const { return initialKind; }
8493+
8494+
bool hasGuaranteedInitialKind() const {
8495+
return getInitialKind() == InitialKind::Guaranteed;
8496+
}
8497+
8498+
bool hasOwnedInitialKind() const {
8499+
return getInitialKind() == InitialKind::Owned;
8500+
}
84908501
};
84918502

84928503
/// Convert from an @moveOnly wrapper type to the underlying copyable type. Can
@@ -8535,10 +8546,21 @@ class MoveOnlyWrapperToCopyableValueInst
85358546
DebugLoc, operand, operand->getType().removingMoveOnlyWrapper(),
85368547
kind == InitialKind::Guaranteed ? OwnershipKind::Guaranteed
85378548
: OwnershipKind::Owned),
8538-
initialKind(kind) {}
8549+
initialKind(kind) {
8550+
assert(operand->getType().isMoveOnlyWrapped() &&
8551+
"Expected moveonlywrapped argument!");
8552+
}
85398553

85408554
public:
85418555
InitialKind getInitialKind() const { return initialKind; }
8556+
8557+
bool hasGuaranteedInitialKind() const {
8558+
return getInitialKind() == InitialKind::Guaranteed;
8559+
}
8560+
8561+
bool hasOwnedInitialKind() const {
8562+
return getInitialKind() == InitialKind::Owned;
8563+
}
85428564
};
85438565

85448566
/// Convert a ${ @moveOnly T } to $T. This is a forwarding instruction that acts
@@ -8572,7 +8594,9 @@ class CopyableToMoveOnlyWrapperAddrInst
85728594

85738595
CopyableToMoveOnlyWrapperAddrInst(SILDebugLocation DebugLoc, SILValue operand)
85748596
: UnaryInstructionBase(DebugLoc, operand,
8575-
operand->getType().addingMoveOnlyWrapper()) {}
8597+
operand->getType().addingMoveOnlyWrapper()) {
8598+
assert(!operand->getType().isMoveOnly() && "Expected copyable argument");
8599+
}
85768600
};
85778601

85788602
class MoveOnlyWrapperToCopyableAddrInst
@@ -8583,7 +8607,10 @@ class MoveOnlyWrapperToCopyableAddrInst
85838607

85848608
MoveOnlyWrapperToCopyableAddrInst(SILDebugLocation DebugLoc, SILValue operand)
85858609
: UnaryInstructionBase(DebugLoc, operand,
8586-
operand->getType().removingMoveOnlyWrapper()) {}
8610+
operand->getType().removingMoveOnlyWrapper()) {
8611+
assert(operand->getType().isMoveOnlyWrapped() &&
8612+
"Expected moveonlywrapped argument");
8613+
}
85878614
};
85888615

85898616
/// 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
@@ -852,6 +852,8 @@ AbstractionPattern AbstractionPattern::removingMoveOnlyWrapper() const {
852852
case Kind::Tuple:
853853
llvm_unreachable("cannot apply move-only wrappers to open-coded patterns");
854854
case Kind::Opaque:
855+
// Opaque is opaque. We do not remove anything.
856+
return *this;
855857
case Kind::Type:
856858
if (auto mvi = dyn_cast<SILMoveOnlyWrappedType>(getType())) {
857859
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
@@ -2524,7 +2524,7 @@ TypeConverter::~TypeConverter() {
25242524
// Destroy only the unique entries.
25252525
CanType srcType = ti.first.OrigType;
25262526
if (!srcType) continue;
2527-
CanType mappedType = ti.second->getLoweredType().getASTType();
2527+
CanType mappedType = ti.second->getLoweredType().getRawASTType();
25282528
if (srcType == mappedType)
25292529
ti.second->~TypeLowering();
25302530
}
@@ -4394,10 +4394,11 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
43944394
env->mapTypeIntoContext(contextBoxTy)
43954395
->getCanonicalType());
43964396
}
4397+
4398+
auto ty = getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy,
4399+
*this, 0);
43974400
assert(contextBoxTy->getLayout()->getFields().size() == 1 &&
4398-
getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy,
4399-
*this, 0)
4400-
.getASTType() == loweredContextType &&
4401+
ty.getRawASTType() == loweredContextType &&
44014402
"box field type doesn't match capture!");
44024403
#endif
44034404
return boxTy;
@@ -4449,7 +4450,7 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(
44494450
}
44504451

44514452
// Use the enum's signature for the box type.
4452-
auto boundEnum = enumType.getASTType();
4453+
auto boundEnum = enumType.getRawASTType();
44534454

44544455
// Lower the enum element's argument in the box's context.
44554456
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)