Skip to content

Commit da49663

Browse files
committed
ManualOwnership: avoid implicit SILMoveOnlyWrappedType's
These wrappers are detected by the move checking passes, to support the implicit no-implicit-copy check for parameters with ownership specifiers. ManualOwnership already does this kind of checking, and the two passes can interfere with each other, such as intercepting diagnostics that are meant to be emitted by ManualOwnership.
1 parent 0ec0292 commit da49663

File tree

6 files changed

+86
-4
lines changed

6 files changed

+86
-4
lines changed

lib/SILGen/SILGenBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,10 @@ static ManagedValue createInputFunctionArgument(
537537
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Borrowing;
538538
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Consuming;
539539
}
540+
541+
// ManualOwnership checks everything for implicit copies already.
542+
if (B.hasManualOwnershipAttr())
543+
isNoImplicitCopy = false;
540544
}
541545
if (isNoImplicitCopy)
542546
arg->setNoImplicitCopy(isNoImplicitCopy);

lib/SILGen/SILGenDecl.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,11 @@ class LocalVariableInitialization : public SingleBufferInitialization {
561561

562562
// If our instance type is not already @moveOnly wrapped, and it's a
563563
// no-implicit-copy parameter, wrap it.
564-
if (!isNoImplicitCopy && instanceType->isCopyable()) {
564+
//
565+
// Unless the function is using ManualOwnership, which checks for
566+
// no-implicit-copies using a different mechanism.
567+
if (!isNoImplicitCopy && instanceType->isCopyable() &&
568+
!SGF.B.hasManualOwnershipAttr()) {
565569
if (auto *pd = dyn_cast<ParamDecl>(decl)) {
566570
isNoImplicitCopy = pd->isNoImplicitCopy();
567571
isNoImplicitCopy |= pd->getSpecifier() == ParamSpecifier::Consuming;

lib/SILGen/SILGenPattern.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,10 @@ void PatternMatchEmission::bindBorrow(Pattern *pattern, VarDecl *var,
14051405
auto bindValue = value.asBorrowedOperand2(SGF, pattern).getFinalManagedValue();
14061406

14071407
// Borrow bindings of copyable type should still be no-implicit-copy.
1408-
if (!bindValue.getType().isMoveOnly()) {
1408+
//
1409+
// If we're relying on ManualOwnership for explicit-copies enforcement,
1410+
// we don't need the MoveOnlyWrapper.
1411+
if (!bindValue.getType().isMoveOnly() && !SGF.B.hasManualOwnershipAttr()) {
14091412
if (bindValue.getType().isAddress()) {
14101413
bindValue = ManagedValue::forBorrowedAddressRValue(
14111414
SGF.B.createCopyableToMoveOnlyWrapperAddr(pattern, bindValue.getValue()));

lib/SILGen/SILGenProlog.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,10 @@ class ArgumentInitHelper {
793793
}
794794
}
795795
}
796+
// If we're relying on ManualOwnership for explicit-copies enforcement,
797+
// we don't need @noImplicitCopy / MoveOnlyWrapper.
798+
if (SGF.B.hasManualOwnershipAttr())
799+
isNoImplicitCopy = false;
796800

797801
// If we have a no implicit copy argument and the argument is trivial,
798802
// we need to use copyable to move only to convert it to its move only
@@ -1216,8 +1220,9 @@ static void emitCaptureArguments(SILGenFunction &SGF,
12161220
SILType ty = lowering.getLoweredType();
12171221

12181222
bool isNoImplicitCopy;
1219-
1220-
if (ty.isTrivial(SGF.F) || ty.isMoveOnly()) {
1223+
1224+
if (ty.isTrivial(SGF.F) || ty.isMoveOnly() ||
1225+
SGF.B.hasManualOwnershipAttr()) {
12211226
isNoImplicitCopy = false;
12221227
} else if (VD->isNoImplicitCopy()) {
12231228
isNoImplicitCopy = true;

test/SIL/manual_ownership.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ public func basic_return3() -> Triangle {
6363
return Triangle()
6464
}
6565

66+
@_manualOwnership
67+
func return_borrowed(_ t: borrowing Triangle) -> Triangle {
68+
return t // expected-error {{ownership of 't' is demanded and cannot not be consumed}}
69+
}
70+
@_manualOwnership
71+
func return_borrowed_fixed(_ t: borrowing Triangle) -> Triangle {
72+
return copy t
73+
}
74+
75+
// FIXME: copy propagation isn't able to simplify this. No copy should be required.
76+
@_manualOwnership
77+
func return_consumingParam(_ t: consuming Triangle) -> Triangle { // expected-error {{accessing 't' produces a copy of it}}
78+
return t
79+
}
80+
81+
@_manualOwnership
82+
func return_owned(_ t: __owned Triangle) -> Triangle {
83+
return t
84+
}
85+
6686
@_manualOwnership
6787
func reassign_with_lets() -> Triangle {
6888
let x = Triangle()

test/SILGen/manual_ownership.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,49 @@ class TriangleClass {
2626
func basic_access_of_loadable(_ t: TriangleClass) -> ShapeClass {
2727
return copy t.shape
2828
}
29+
30+
// CHECK-LABEL: sil {{.*}} [manual_ownership] [ossa] @return_borrowed
31+
// CHECK: bb0(%0 : @guaranteed $TriangleClass):
32+
// CHECK-NEXT: debug_value %0
33+
// CHECK-NEXT: [[IMPL_COPY:%.*]] = copy_value %0
34+
// CHECK-NEXT: return [[IMPL_COPY]]
35+
// CHECK-NEXT: } // end sil function 'return_borrowed'
36+
@_manualOwnership
37+
@_silgen_name("return_borrowed")
38+
func return_borrowed(_ t: borrowing TriangleClass) -> TriangleClass {
39+
return t
40+
}
41+
42+
// CHECK-LABEL: sil {{.*}} [manual_ownership] [ossa] @return_consumingParam
43+
// CHECK: bb0(%0 : @_eagerMove @owned $TriangleClass):
44+
// CHECK-NEXT: alloc_box ${ var TriangleClass }, var, name "t"
45+
// CHECK-NEXT: begin_borrow [var_decl]
46+
// CHECK-NEXT: [[ADDR:%.*]] = project_box {{.*}}, 0
47+
// CHECK-NEXT: store %0 to [init] [[ADDR]]
48+
// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [read] [unknown] [[ADDR]]
49+
// CHECK-NEXT: [[IMPL_COPY:%.*]] = load [copy] [[ACCESS]]
50+
// CHECK-NEXT: end_access [[ACCESS]]
51+
// CHECK-NEXT: end_borrow
52+
// CHECK-NEXT: destroy_value
53+
// CHECK-NEXT: return [[IMPL_COPY]]
54+
// CHECK-NEXT: } // end sil function 'return_consumingParam'
55+
@_manualOwnership
56+
@_silgen_name("return_consumingParam")
57+
func return_consumingParam(_ t: consuming TriangleClass) -> TriangleClass {
58+
return t
59+
}
60+
61+
// CHECK-LABEL: sil {{.*}} [manual_ownership] [ossa] @return_owned
62+
// CHECK: bb0(%0 : @owned $TriangleClass):
63+
// CHECK-NEXT: debug_value %0
64+
// CHECK-NEXT: [[BORROW:%.*]] = begin_borrow %0
65+
// CHECK-NEXT: [[IMPL_COPY:%.*]] = copy_value [[BORROW]]
66+
// CHECK-NEXT: end_borrow [[BORROW]]
67+
// CHECK-NEXT: destroy_value %0
68+
// CHECK-NEXT: return [[IMPL_COPY]]
69+
// CHECK-NEXT: } // end sil function 'return_owned'
70+
@_manualOwnership
71+
@_silgen_name("return_owned")
72+
func return_owned(_ t: __owned TriangleClass) -> TriangleClass {
73+
return t
74+
}

0 commit comments

Comments
 (0)