Skip to content

Commit 107475b

Browse files
committed
SILType: Avoid asking ASTType if it is Noncopyable
It's better to ask SILType if it is MoveOnly than go to the AST type and ask if it is noncopyable, because some types in SIL do not have a well-defined notion of conformance in the AST.
1 parent ec10d1a commit 107475b

12 files changed

+38
-31
lines changed

include/swift/SIL/SILType.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -763,9 +763,13 @@ class SILType {
763763
/// Returns true if this is the AnyObject SILType;
764764
bool isAnyObject() const { return getASTType()->isAnyObject(); }
765765

766-
/// Returns true if this type is a first class move only type or a move only
767-
/// wrapped type.
768-
bool isMoveOnly() const;
766+
/// Returns true if this type is a noncopyable type. Otherwise, if the type
767+
/// satisfies \c isMoveOnlyWrapped(), then it returns true iff \c orWrapped
768+
/// is true. That is,
769+
///
770+
/// orWrapped == false --> isNoncopyable
771+
/// orWrapped == true --> isNoncopyable || isMoveOnlyWrapped
772+
bool isMoveOnly(bool orWrapped=true) const;
769773

770774
/// Return true if this is a value type (struct/enum) that requires
771775
/// deinitialization beyond destruction of its members.

lib/AST/Type.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,6 @@ static CanType preprocessTypeForInvertibleQuery(Type orig) {
184184
// Strip off any StorageType wrapper.
185185
type = type->getReferenceStorageReferent();
186186

187-
// Always strip off SILMoveOnlyWrapper.
188-
if (auto wrapper = type->getAs<SILMoveOnlyWrappedType>())
189-
type = wrapper->getInnerType();
190-
191187
// Pack expansions such as `repeat T` themselves do not have conformances,
192188
// so check its pattern type for conformance.
193189
if (auto *pet = type->getAs<PackExpansionType>()) {

lib/SIL/IR/SILType.cpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -1049,16 +1049,19 @@ bool SILType::isEscapable() const {
10491049
return getASTType()->isEscapable();
10501050
}
10511051

1052-
bool SILType::isMoveOnly() const {
1052+
bool SILType::isMoveOnly(bool orWrapped) const {
1053+
// If it's inside the move-only wrapper, return true iff we want to include
1054+
// such types as "move-only" in this query. Such values are typically
1055+
// just "no-implicit-copy" and not "move-only".
1056+
if (isMoveOnlyWrapped())
1057+
return orWrapped;
1058+
10531059
// Legacy check.
10541060
if (!getASTContext().LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
1055-
return getASTType()->isNoncopyable() || isMoveOnlyWrapped();
1061+
return getASTType()->isNoncopyable();
10561062
}
10571063

1058-
// Anything within the move-only wrapper is move-only.
1059-
if (isMoveOnlyWrapped())
1060-
return true;
1061-
1064+
// NOTE: getASTType strips the MoveOnlyWrapper off!
10621065
auto ty = getASTType();
10631066

10641067
// All kinds of references are copyable.

lib/SIL/Verifier/SILVerifier.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -6223,7 +6223,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
62236223
auto type = ddi->getType();
62246224
require(type == ddi->getOperand()->getType(),
62256225
"Result and operand must have the same type.");
6226-
require(type.getASTType()->isNoncopyable(),
6226+
require(type.isMoveOnly(/*orWrapped=*/false),
62276227
"drop_deinit only allowed for move-only types");
62286228
require(type.getNominalOrBoundGenericNominal()
62296229
->getValueTypeDestructor(), "drop_deinit only allowed for "

lib/SILGen/SILGenApply.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3267,7 +3267,7 @@ Expr *ArgumentSource::findStorageReferenceExprForMoveOnly(
32673267

32683268
SILType ty =
32693269
SGF.getLoweredType(type->getWithoutSpecifierType()->getCanonicalType());
3270-
bool isMoveOnly = ty.getASTType()->isNoncopyable();
3270+
bool isMoveOnly = ty.isMoveOnly(/*orWrapped=*/false);
32713271
if (auto *pd = dyn_cast<ParamDecl>(storage)) {
32723272
isMoveOnly |= pd->getSpecifier() == ParamSpecifier::Borrowing;
32733273
isMoveOnly |= pd->getSpecifier() == ParamSpecifier::Consuming;

lib/SILGen/SILGenBuilder.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ static ManagedValue createInputFunctionArgument(
530530
"Function arguments of non-bare functions must have a decl");
531531
auto *arg = F.begin()->createFunctionArgument(type, decl);
532532
if (auto *pd = dyn_cast_or_null<ParamDecl>(decl)) {
533-
if (!arg->getType().getASTType()->isNoncopyable()) {
533+
if (!arg->getType().isMoveOnly()) {
534534
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Borrowing;
535535
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Consuming;
536536
}

lib/SILGen/SILGenDecl.cpp

+13-8
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,14 @@ class LocalVariableInitialization : public SingleBufferInitialization {
515515
auto instanceType = SGF.SGM.Types.getLoweredRValueType(
516516
TypeExpansionContext::minimal(), decl->getTypeInContext());
517517

518-
// If we have a no implicit copy param decl, make our instance type
519-
// @moveOnly.
520-
if (!instanceType->isNoncopyable()) {
518+
519+
bool isNoImplicitCopy = instanceType->is<SILMoveOnlyWrappedType>();
520+
521+
// If our instance type is not already @moveOnly wrapped, and it's a
522+
// no-implicit-copy parameter, wrap it.
523+
if (!isNoImplicitCopy && !instanceType->isNoncopyable()) {
521524
if (auto *pd = dyn_cast<ParamDecl>(decl)) {
522-
bool isNoImplicitCopy = pd->isNoImplicitCopy();
525+
isNoImplicitCopy = pd->isNoImplicitCopy();
523526
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Consuming;
524527
if (pd->isSelfParameter()) {
525528
auto *dc = pd->getDeclContext();
@@ -533,9 +536,11 @@ class LocalVariableInitialization : public SingleBufferInitialization {
533536
}
534537
}
535538

539+
const bool isCopyable = isNoImplicitCopy || !instanceType->isNoncopyable();
540+
536541
auto boxType = SGF.SGM.Types.getContextBoxTypeForCapture(
537542
decl, instanceType, SGF.F.getGenericEnvironment(),
538-
/*mutable*/ !instanceType->isNoncopyable() || !decl->isLet());
543+
/*mutable=*/ isCopyable || !decl->isLet());
539544

540545
// The variable may have its lifetime extended by a closure, heap-allocate
541546
// it using a box.
@@ -689,7 +694,7 @@ class LetValueInitialization : public Initialization {
689694
// For noncopyable types, we always need to box them.
690695
needsTemporaryBuffer =
691696
(lowering->isAddressOnly() && SGF.silConv.useLoweredAddresses()) ||
692-
lowering->getLoweredType().getASTType()->isNoncopyable();
697+
lowering->getLoweredType().isMoveOnly(/*orWrapped=*/false);
693698
}
694699

695700
// Make sure that we have a non-address only type when binding a
@@ -774,7 +779,7 @@ class LetValueInitialization : public Initialization {
774779
if (value->getOwnershipKind() == OwnershipKind::None) {
775780
// Then check if we have a pure move only type. In that case, we need to
776781
// insert a no implicit copy
777-
if (value->getType().getASTType()->isNoncopyable()) {
782+
if (value->getType().isMoveOnly(/*orWrapped=*/false)) {
778783
value = SGF.B.createMoveValue(PrologueLoc, value, /*isLexical*/ true);
779784
return SGF.B.createMarkUnresolvedNonCopyableValueInst(
780785
PrologueLoc, value,
@@ -824,7 +829,7 @@ class LetValueInitialization : public Initialization {
824829
// We do this before the begin_borrow "normal" path below since move only
825830
// types do not have no implicit copy attr on them.
826831
if (value->getOwnershipKind() == OwnershipKind::Owned &&
827-
value->getType().getASTType()->isNoncopyable()) {
832+
value->getType().isMoveOnly(/*orWrapped=*/false)) {
828833
value = SGF.B.createMoveValue(PrologueLoc, value, true /*isLexical*/);
829834
return SGF.B.createMarkUnresolvedNonCopyableValueInst(
830835
PrologueLoc, value,

lib/SILGen/SILGenProlog.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ class ArgumentInitHelper {
703703
// - @_eagerMove
704704
// - @_noEagerMove
705705
bool isNoImplicitCopy = pd->isNoImplicitCopy();
706-
if (!argrv.getType().getASTType()->isNoncopyable()) {
706+
if (!argrv.getType().isMoveOnly(/*orWrapped=*/false)) {
707707
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Borrowing;
708708
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Consuming;
709709
if (pd->isSelfParameter()) {
@@ -1167,7 +1167,7 @@ static void emitCaptureArguments(SILGenFunction &SGF,
11671167
// in SIL since it is illegal to capture an inout value in an escaping
11681168
// closure. The later code knows how to handle that we have the
11691169
// mark_unresolved_non_copyable_value here.
1170-
if (isInOut && ty.getASTType()->isNoncopyable()) {
1170+
if (isInOut && ty.isMoveOnly(/*orWrapped=*/false)) {
11711171
arg = SGF.B.createMarkUnresolvedNonCopyableValueInst(
11721172
Loc, arg,
11731173
MarkUnresolvedNonCopyableValueInst::CheckKind::

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ struct AllocStackAnalyzer : SILInstructionVisitor<AllocStackAnalyzer> {
379379
// analysis assumes memory is deinitialized on all paths, which is not the
380380
// case for discarded values. Eventually copyable types may also be
381381
// discarded; to support that, we will leave a drop_deinit_addr in place.
382-
if (ASI->getType().getASTType()->isNoncopyable()) {
382+
if (ASI->getType().isMoveOnly(/*orWrapped=*/false)) {
383383
LegalUsers = false;
384384
return;
385385
}

lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static bool shouldExpandShim(SILFunction *fn, SILType type) {
5252
// shouldExpand returns false for struct-with-deinit types, so bypassing it is
5353
// incorrect for move-only types
5454
if (EnableExpandAll) {
55-
assert(!type.getASTType()->isNoncopyable()
55+
assert(!type.isMoveOnly(/*orWrapped=*/false)
5656
&& "sil-lower-agg-instrs-expand-all is incompatible with move-only "
5757
"types");
5858
return true;

lib/SILOptimizer/Utils/InstructionDeleter.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ static bool isScopeAffectingInstructionDead(SILInstruction *inst,
7171
// getSingleValueCopyOrCast returns true. That function returns true for
7272
// move_value instructions. And `move_value %moveOnlyValue` must not be
7373
// deleted.
74-
auto type = result->getType();
75-
if (type.isMoveOnly() && !type.isMoveOnlyWrapped() &&
74+
if (result->getType().isMoveOnly() &&
7675
result->getOwnershipKind() == OwnershipKind::Owned) {
7776
return false;
7877
}

lib/Sema/TypeCheckInvertible.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ static bool conformsToInvertible(CanType type, InvertibleProtocolKind ip) {
170170
assert(!type->is<PackExpansionType>());
171171

172172
// The SIL types in the AST do not have real conformances, and should have
173-
// been handled earlier.
173+
// been handled in SILType instead.
174174
assert(!(type->is<SILBoxType,
175175
SILMoveOnlyWrappedType,
176176
SILPackType,

0 commit comments

Comments
 (0)