Skip to content

Commit 57f4b0e

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 3f2d568 commit 57f4b0e

35 files changed

+2624
-252
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5286,7 +5286,9 @@ class SILMoveOnlyWrappedType final : public TypeBase,
52865286
SILMoveOnlyWrappedType(CanType innerType)
52875287
: TypeBase(TypeKind::SILMoveOnlyWrapped, &innerType->getASTContext(),
52885288
innerType->getRecursiveProperties()),
5289-
innerType(innerType) {}
5289+
innerType(innerType) {
5290+
assert(!innerType->isPureMoveOnly() && "Inner type must be copyable");
5291+
}
52905292

52915293
public:
52925294
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
@@ -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
@@ -2502,7 +2502,7 @@ TypeConverter::~TypeConverter() {
25022502
// Destroy only the unique entries.
25032503
CanType srcType = ti.first.OrigType;
25042504
if (!srcType) continue;
2505-
CanType mappedType = ti.second->getLoweredType().getASTType();
2505+
CanType mappedType = ti.second->getLoweredType().getRawASTType();
25062506
if (srcType == mappedType)
25072507
ti.second->~TypeLowering();
25082508
}
@@ -4364,10 +4364,11 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
43644364
env->mapTypeIntoContext(contextBoxTy)
43654365
->getCanonicalType());
43664366
}
4367+
4368+
auto ty = getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy,
4369+
*this, 0);
43674370
assert(contextBoxTy->getLayout()->getFields().size() == 1 &&
4368-
getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy,
4369-
*this, 0)
4370-
.getASTType() == loweredContextType &&
4371+
ty.getRawASTType() == loweredContextType &&
43714372
"box field type doesn't match capture!");
43724373
#endif
43734374
return boxTy;
@@ -4419,7 +4420,7 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(
44194420
}
44204421

44214422
// Use the enum's signature for the box type.
4422-
auto boundEnum = enumType.getASTType();
4423+
auto boundEnum = enumType.getRawASTType();
44234424

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