mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
ManualOwnership: provide ability to apply to entire compilation unit
With this patch, I'm flipping the polarity of things. The flag `-enable-experimental-feature ManualOwnership` now turns on the diagnostics, but they're all silenced by default. So, you need to add -Wwarning or -Werror to your build settings to turn on the specific diagnostics you care about. These are the diagnostic groups relevant to the feature: - SemanticCopies aka "explicit copies mode" - DynamicExclusivity For example, the build setting `-Werror SemanticCopies` now gives you errors about explicit copies, just as before, but now you can make them just warnings with -Wwarning. To opt-out a declaration from everything when using the feature, use @_noManualOwnership. @_manualOwnership is no longer an attribute as a result. resolves rdar://163372569
This commit is contained in:
@@ -815,7 +815,7 @@ SIMPLE_DECL_ATTR(_noObjCBridging, NoObjCBridging,
|
||||
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
|
||||
155)
|
||||
|
||||
SIMPLE_DECL_ATTR(_manualOwnership, ManualOwnership,
|
||||
SIMPLE_DECL_ATTR(_noManualOwnership, NoManualOwnership,
|
||||
OnAbstractFunction | OnSubscript,
|
||||
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
|
||||
156)
|
||||
|
||||
@@ -2145,9 +2145,7 @@ ERROR(attr_static_exclusive_only_mutating,none,
|
||||
ERROR(attr_static_exclusive_no_setters,none,
|
||||
"variable of type %0 must not have a setter", (Type))
|
||||
|
||||
// @_manualOwnership
|
||||
ERROR(attr_manual_ownership_experimental,none,
|
||||
"'@_manualOwnership' requires '-enable-experimental-feature ManualOwnership'", ())
|
||||
// ManualOwnership
|
||||
ERROR(attr_manual_ownership_noimplicitcopy,none,
|
||||
"'@_noImplicitCopy' cannot be used with ManualOwnership", ())
|
||||
|
||||
|
||||
@@ -449,7 +449,9 @@ EXPERIMENTAL_FEATURE(LifetimeDependence, true)
|
||||
/// Enable the `@_staticExclusiveOnly` attribute.
|
||||
EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)
|
||||
|
||||
/// Enable the `@_manualOwnership` attribute.
|
||||
/// Enable the ManualOwnership diagnostic groups:
|
||||
/// * -Wwarning SemanticCopies
|
||||
/// * -Wwarning DynamicExclusivity
|
||||
EXPERIMENTAL_FEATURE(ManualOwnership, false)
|
||||
|
||||
/// Enable the @extractConstantsFromMembers attribute.
|
||||
|
||||
@@ -5024,7 +5024,7 @@ public:
|
||||
TRIVIAL_ATTR_PRINTER(NoLocks, no_locks)
|
||||
TRIVIAL_ATTR_PRINTER(NoMetadata, no_metadata)
|
||||
TRIVIAL_ATTR_PRINTER(NoObjCBridging, no_objc_bridging)
|
||||
TRIVIAL_ATTR_PRINTER(ManualOwnership, manual_ownership)
|
||||
TRIVIAL_ATTR_PRINTER(NoManualOwnership, no_manual_ownership)
|
||||
TRIVIAL_ATTR_PRINTER(NoRuntime, no_runtime)
|
||||
TRIVIAL_ATTR_PRINTER(NonEphemeral, non_ephemeral)
|
||||
TRIVIAL_ATTR_PRINTER(NonEscapable, non_escapable)
|
||||
|
||||
@@ -265,7 +265,6 @@ extension ASTGenVisitor {
|
||||
.LexicalLifetimes,
|
||||
.LLDBDebuggerFunction,
|
||||
.MainType,
|
||||
.ManualOwnership,
|
||||
.Marker,
|
||||
.MoveOnly,
|
||||
.NeverEmitIntoClient,
|
||||
@@ -276,6 +275,7 @@ extension ASTGenVisitor {
|
||||
.NoRuntime,
|
||||
.NoImplicitCopy,
|
||||
.NoLocks,
|
||||
.NoManualOwnership,
|
||||
.NoMetadata,
|
||||
.NoObjCBridging,
|
||||
.NonEphemeral,
|
||||
|
||||
@@ -208,7 +208,9 @@ void SILFunctionBuilder::addFunctionAttributes(
|
||||
F->setPerfConstraints(PerformanceConstraints::NoExistentials);
|
||||
} else if (Attrs.hasAttribute<NoObjCBridgingAttr>()) {
|
||||
F->setPerfConstraints(PerformanceConstraints::NoObjCBridging);
|
||||
} else if (Attrs.hasAttribute<ManualOwnershipAttr>()) {
|
||||
} else if (M.getASTContext().LangOpts.hasFeature(Feature::ManualOwnership) &&
|
||||
constant && constant.hasDecl() && !constant.isImplicit() &&
|
||||
!Attrs.hasAttribute<NoManualOwnershipAttr>()) {
|
||||
F->setPerfConstraints(PerformanceConstraints::ManualOwnership);
|
||||
}
|
||||
|
||||
|
||||
@@ -1368,15 +1368,15 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F,
|
||||
//
|
||||
// If ManualOwnership ends up subsuming those prior mechanisms for an
|
||||
// explicit-copy mode, we can move this somewhere else, like postEmitFunction.
|
||||
if (auto *ace = constant.getAbstractClosureExpr()) {
|
||||
if (auto *dc = ace->getOutermostFunctionContext()) {
|
||||
if (auto *decl = dc->getAsDecl()) {
|
||||
if (decl->getAttrs().hasAttribute<ManualOwnershipAttr>()) {
|
||||
F->setPerfConstraints(PerformanceConstraints::ManualOwnership);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// FIXME: maybe this should happen in SILFunctionBuilder::getOrCreateFunction
|
||||
if (getASTContext().LangOpts.hasFeature(Feature::ManualOwnership))
|
||||
if (auto *ace = constant.getAbstractClosureExpr())
|
||||
if (auto *dc = ace->getOutermostFunctionContext())
|
||||
if (auto *decl = dc->getAsDecl())
|
||||
if (!decl->isImplicit() &&
|
||||
!decl->getAttrs().hasAttribute<NoManualOwnershipAttr>())
|
||||
F->setPerfConstraints(PerformanceConstraints::ManualOwnership);
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "lowering ";
|
||||
F->printName(llvm::dbgs());
|
||||
|
||||
@@ -183,6 +183,7 @@ public:
|
||||
IGNORED_ATTR(NoAllocation)
|
||||
IGNORED_ATTR(NoRuntime)
|
||||
IGNORED_ATTR(NoExistentials)
|
||||
IGNORED_ATTR(NoManualOwnership)
|
||||
IGNORED_ATTR(NoObjCBridging)
|
||||
IGNORED_ATTR(EmitAssemblyVisionRemarks)
|
||||
IGNORED_ATTR(ShowInInterface)
|
||||
@@ -476,7 +477,6 @@ public:
|
||||
void visitUnsafeNonEscapableResultAttr(UnsafeNonEscapableResultAttr *attr);
|
||||
|
||||
void visitStaticExclusiveOnlyAttr(StaticExclusiveOnlyAttr *attr);
|
||||
void visitManualOwnershipAttr(ManualOwnershipAttr *attr);
|
||||
void visitWeakLinkedAttr(WeakLinkedAttr *attr);
|
||||
void visitSILGenNameAttr(SILGenNameAttr *attr);
|
||||
void visitLifetimeAttr(LifetimeAttr *attr);
|
||||
@@ -8408,13 +8408,6 @@ void AttributeChecker::visitStaticExclusiveOnlyAttr(
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeChecker::visitManualOwnershipAttr(ManualOwnershipAttr *attr) {
|
||||
if (Ctx.LangOpts.hasFeature(Feature::ManualOwnership))
|
||||
return;
|
||||
|
||||
diagnoseAndRemoveAttr(attr, diag::attr_manual_ownership_experimental);
|
||||
}
|
||||
|
||||
void AttributeChecker::visitWeakLinkedAttr(WeakLinkedAttr *attr) {
|
||||
if (!Ctx.LangOpts.Target.isOSBinFormatCOFF())
|
||||
return;
|
||||
|
||||
@@ -1620,8 +1620,8 @@ namespace {
|
||||
UNINTERESTING_ATTR(NoAllocation)
|
||||
UNINTERESTING_ATTR(NoRuntime)
|
||||
UNINTERESTING_ATTR(NoExistentials)
|
||||
UNINTERESTING_ATTR(NoManualOwnership)
|
||||
UNINTERESTING_ATTR(NoObjCBridging)
|
||||
UNINTERESTING_ATTR(ManualOwnership)
|
||||
UNINTERESTING_ATTR(Inlinable)
|
||||
UNINTERESTING_ATTR(Effects)
|
||||
UNINTERESTING_ATTR(Expose)
|
||||
|
||||
@@ -14,7 +14,6 @@ public struct Pair {
|
||||
var x: Int
|
||||
var y: Int
|
||||
|
||||
@_manualOwnership
|
||||
consuming func midpoint(_ other: borrowing Pair) -> Pair {
|
||||
return Pair(x: (x + other.x) / 2, y: (y + other.y) / 2)
|
||||
}
|
||||
@@ -27,10 +26,8 @@ public class Triangle {
|
||||
|
||||
var nontrivial = Whatever()
|
||||
|
||||
@_manualOwnership
|
||||
consuming func consuming() {}
|
||||
|
||||
@_manualOwnership
|
||||
borrowing func borrowing() {}
|
||||
}
|
||||
|
||||
@@ -44,51 +41,41 @@ func borrow_generic<T>(_ t: borrowing T) {}
|
||||
|
||||
/// MARK: return statements
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_return1() -> Triangle {
|
||||
let x = Triangle()
|
||||
return x
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_return2(t: Triangle) -> Triangle {
|
||||
return t // expected-warning {{independent copy of 't' is required here; write 'copy' to acknowledge or 'consume' to elide}}
|
||||
}
|
||||
@_manualOwnership
|
||||
public func basic_return2_fixed(t: Triangle) -> Triangle {
|
||||
return copy t
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_return3() -> Triangle {
|
||||
return Triangle()
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func return_borrowed(_ t: borrowing Triangle) -> Triangle {
|
||||
return t // expected-warning {{independent copy of 't' is required here; write 'copy' to acknowledge or 'consume' to elide}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func return_borrowed_fixed(_ t: borrowing Triangle) -> Triangle {
|
||||
return copy t
|
||||
}
|
||||
|
||||
// FIXME: there's no workaround to this; it acts like a var so it's the same class of problem (rdar://161359163)
|
||||
@_manualOwnership
|
||||
func return_consumingParam(_ t: consuming Triangle) -> Triangle {
|
||||
return t // expected-warning {{independent copy of 't' is required here; write 'copy' to acknowledge or 'consume' to elide}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func return_consumingParam_no_workaround(_ t: consuming Triangle) -> Triangle {
|
||||
return copy t
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func return_owned(_ t: __owned Triangle) -> Triangle {
|
||||
return t
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func reassign_with_lets() -> Triangle {
|
||||
let x = Triangle()
|
||||
let y = x
|
||||
@@ -96,7 +83,6 @@ func reassign_with_lets() -> Triangle {
|
||||
return z
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func renamed_return(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
let b = a
|
||||
let c = b
|
||||
@@ -105,7 +91,6 @@ func renamed_return(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
return c // expected-warning {{independent copy of 'c' is required}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func renamed_return_fix1(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
let b = copy a
|
||||
let c = copy b // FIXME: not needed! Is explicit_copy_value is blocking propagation? (rdar://161359163)
|
||||
@@ -114,8 +99,7 @@ func renamed_return_fix1(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
}
|
||||
|
||||
// FIXME: this crashes CopyPropagation! (rdar://161360764)
|
||||
//@_manualOwnership
|
||||
//func renamed_return_fix2(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
////func renamed_return_fix2(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
// let b = a
|
||||
// let c = b
|
||||
// if cond { return copy b }
|
||||
@@ -124,20 +108,17 @@ func renamed_return_fix1(_ cond: Bool, _ a: Triangle) -> Triangle {
|
||||
|
||||
/// MARK: method calls
|
||||
|
||||
@_manualOwnership
|
||||
func basic_methods_borrowing(_ t1: Triangle) {
|
||||
let t2 = Triangle()
|
||||
t1.borrowing()
|
||||
t2.borrowing()
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func basic_methods_consuming(_ t1: Triangle) {
|
||||
let t2 = Triangle()
|
||||
t1.consuming() // expected-warning {{independent copy of 't1' is required}}
|
||||
t2.consuming()
|
||||
}
|
||||
@_manualOwnership
|
||||
func basic_methods_consuming_fixed(_ t1: Triangle) {
|
||||
let t2 = Triangle()
|
||||
|
||||
@@ -148,19 +129,15 @@ func basic_methods_consuming_fixed(_ t1: Triangle) {
|
||||
open class OpenClass {
|
||||
open func classMethod() {}
|
||||
}
|
||||
@_manualOwnership
|
||||
func callOpenMethod(_ c: OpenClass) {
|
||||
return c.classMethod()
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
@discardableResult
|
||||
func consumingFunc(_ t0: consuming Triangle) -> Bool { return false }
|
||||
|
||||
@_manualOwnership
|
||||
func plainFunc(_ t0: Triangle) {}
|
||||
|
||||
@_manualOwnership
|
||||
func basic_function_call(_ t1: Triangle) {
|
||||
consumingFunc(t1) // expected-warning {{independent copy of 't1' is required}}
|
||||
consumingFunc(copy t1)
|
||||
@@ -169,13 +146,11 @@ func basic_function_call(_ t1: Triangle) {
|
||||
|
||||
/// MARK: control-flow
|
||||
|
||||
@_manualOwnership
|
||||
func check_vars(_ t: Triangle, _ b: Bool) -> Triangle {
|
||||
var x = Triangle()
|
||||
if b { x = t } // expected-warning {{independent copy of 't' is required}}
|
||||
return x // expected-warning {{independent copy of 'x' is required}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func check_vars_fixed(_ t: Triangle, _ b: Bool) -> Triangle {
|
||||
var x = Triangle()
|
||||
if b { x = copy t }
|
||||
@@ -185,45 +160,38 @@ func check_vars_fixed(_ t: Triangle, _ b: Bool) -> Triangle {
|
||||
// FIXME: var's still have some issues
|
||||
// (1) MandatoryRedundantLoadElimination introduces a 'copy_value' in place of a 'load [copy]' (rdar://161359163)
|
||||
|
||||
@_manualOwnership
|
||||
func reassignments_0() -> Triangle {
|
||||
var t3 = Triangle()
|
||||
t3 = Triangle()
|
||||
return t3 // expected-warning {{independent copy of 't3' is required}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func reassignments_0_fixed_1() -> Triangle {
|
||||
var t3 = Triangle()
|
||||
t3 = Triangle()
|
||||
return copy t3
|
||||
}
|
||||
@_manualOwnership
|
||||
func reassignments_0_fixed_2() -> Triangle {
|
||||
var t3 = Triangle()
|
||||
t3 = Triangle()
|
||||
return consume t3
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func reassignments_1() {
|
||||
var t3 = Triangle()
|
||||
t3 = Triangle()
|
||||
t3.borrowing() // expected-warning {{accessing 't3' may produce a copy; write 'copy' to acknowledge or 'consume' to elide}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func reassignments_1_fixed_1() {
|
||||
var t3 = Triangle()
|
||||
t3 = Triangle()
|
||||
(copy t3).borrowing()
|
||||
}
|
||||
@_manualOwnership
|
||||
func reassignments_1_fixed_2() {
|
||||
var t3 = Triangle()
|
||||
t3 = Triangle()
|
||||
(consume t3).borrowing()
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_loop_trivial_values(_ t: Triangle, _ xs: [Triangle]) {
|
||||
var p: Pair = t.a
|
||||
for x in xs { // expected-warning {{independent copy of 'xs' is required}}
|
||||
@@ -231,7 +199,6 @@ public func basic_loop_trivial_values(_ t: Triangle, _ xs: [Triangle]) {
|
||||
}
|
||||
t.a = p
|
||||
}
|
||||
@_manualOwnership
|
||||
public func basic_loop_trivial_values_fixed(_ t: Triangle, _ xs: [Triangle]) {
|
||||
var p: Pair = t.a
|
||||
for x in copy xs {
|
||||
@@ -246,7 +213,6 @@ public func basic_loop_trivial_values_fixed(_ t: Triangle, _ xs: [Triangle]) {
|
||||
// There's complexity in auto-generating a read accessor for classes, but if it's provided
|
||||
// we could then allow someone to elide the copy with a `borrow x` expression.
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_loop_nontrivial_values(_ t: Triangle, _ xs: [Triangle]) {
|
||||
var p: Pair = t.nontrivial.a // expected-warning {{accessing 't.nontrivial' may produce a copy}}
|
||||
for x in xs { // expected-warning {{independent copy of 'xs' is required}}
|
||||
@@ -255,7 +221,6 @@ public func basic_loop_nontrivial_values(_ t: Triangle, _ xs: [Triangle]) {
|
||||
t.nontrivial.a = p // expected-warning {{accessing 't.nontrivial' may produce a copy}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_loop_nontrivial_values_fixed(_ t: Triangle, _ xs: [Triangle]) {
|
||||
var p: Pair = (copy t.nontrivial).a
|
||||
for x in copy xs {
|
||||
@@ -264,7 +229,6 @@ public func basic_loop_nontrivial_values_fixed(_ t: Triangle, _ xs: [Triangle])
|
||||
(copy t.nontrivial).a = p
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
public func basic_loop_nontrivial_values_reduced_copies(_ t: Triangle, _ xs: [Triangle]) {
|
||||
// FIXME: confusing variable names are chosen (rdar://161360537)
|
||||
let nt = t.nontrivial // expected-warning {{accessing 'nt' may produce a copy}}
|
||||
@@ -275,7 +239,6 @@ public func basic_loop_nontrivial_values_reduced_copies(_ t: Triangle, _ xs: [Tr
|
||||
}
|
||||
nt.a = p
|
||||
}
|
||||
@_manualOwnership
|
||||
public func basic_loop_nontrivial_values_reduced_copies_fixed(_ t: Triangle, _ xs: [Triangle]) {
|
||||
let nt = copy t.nontrivial
|
||||
var p: Pair = nt.a
|
||||
@@ -292,24 +255,20 @@ let ref_result = [5, 13, 29]
|
||||
|
||||
// FIXME: if we had a borrow operator, we could allow people to elide these simple copies that
|
||||
// are present to avoid exclusivity issues. We'd need to start generating read coroutines.
|
||||
@_manualOwnership
|
||||
func access_global_1() -> Int {
|
||||
return ref_result[2] // expected-warning {{accessing 'ref_result' may produce a copy}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func access_global_1_fixed() -> Int {
|
||||
return (copy ref_result)[2]
|
||||
}
|
||||
|
||||
/// MARK: closures
|
||||
|
||||
@_manualOwnership
|
||||
func closure_basic(_ t: Triangle) -> () -> Triangle {
|
||||
return { // expected-warning {{closure capture of 't' requires independent copy of it; write [t = copy t]}}
|
||||
return t // expected-warning {{independent copy of 't' is required}}
|
||||
}
|
||||
}
|
||||
@_manualOwnership
|
||||
func closure_basic_almost_fixed_1(_ t: Triangle) -> () -> Triangle {
|
||||
// FIXME: Closure capture lists need to support the short-hand [copy t] that makes the
|
||||
// closure capture parameter @owned, rather than @guaranteed. Only can work for Copyable types!
|
||||
@@ -318,21 +277,18 @@ func closure_basic_almost_fixed_1(_ t: Triangle) -> () -> Triangle {
|
||||
}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func closure_basic_almost_fixed_2(_ x: Triangle) -> () -> Triangle {
|
||||
return { // expected-warning {{closure capture of 'x' requires independent copy of it; write [x = copy x]}}
|
||||
return copy x
|
||||
}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func closure_basic_fixed(_ t: Triangle) -> () -> Triangle {
|
||||
return { [x = copy t] in
|
||||
return copy x
|
||||
}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func closure_copies_in_body(_ t: Triangle) -> () -> Triangle {
|
||||
return { [x = copy t] in
|
||||
eat(x) // expected-warning {{independent copy of 'x' is required}}
|
||||
@@ -342,7 +298,6 @@ func closure_copies_in_body(_ t: Triangle) -> () -> Triangle {
|
||||
}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func closure_copies_in_body_noescape(_ t: Triangle) -> Triangle {
|
||||
let f = { [x = copy t] in
|
||||
eat(x) // expected-warning {{independent copy of 'x' is required}}
|
||||
@@ -353,25 +308,20 @@ func closure_copies_in_body_noescape(_ t: Triangle) -> Triangle {
|
||||
return f()
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func simple_assert(_ f: @autoclosure () -> Bool) {
|
||||
guard f() else { fatalError() }
|
||||
}
|
||||
@_manualOwnership
|
||||
func try_to_assert(_ n: Int, _ names: [String]) {
|
||||
simple_assert(names.count == n)
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func copy_in_autoclosure(_ t: Triangle) {
|
||||
simple_assert(consumingFunc(t)) // expected-warning {{independent copy of 't' is required}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func copy_in_autoclosure_fixed(_ t: Triangle) {
|
||||
simple_assert(consumingFunc(copy t))
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func nested_closures(_ t: Triangle) -> () -> (() -> Triangle) {
|
||||
return { // expected-warning {{closure capture of 't' requires independent copy of it; write [t = copy t]}}
|
||||
{ eat(t) }() // expected-warning {{independent copy of 't' is required}}
|
||||
@@ -381,7 +331,6 @@ func nested_closures(_ t: Triangle) -> () -> (() -> Triangle) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@_manualOwnership
|
||||
func nested_closures_fixed(_ t: Triangle) -> () -> (() -> Triangle) {
|
||||
return { [a = copy t] in
|
||||
{ eat(copy a) }()
|
||||
@@ -391,19 +340,26 @@ func nested_closures_fixed(_ t: Triangle) -> () -> (() -> Triangle) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@_noManualOwnership
|
||||
func nested_closures_DISABLED(_ t: Triangle) -> () -> (() -> Triangle) {
|
||||
return {
|
||||
{ eat(t) }()
|
||||
return {
|
||||
simple_assert(consumingFunc(t))
|
||||
return t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// MARK: generics
|
||||
|
||||
@_manualOwnership
|
||||
func return_generic<T>(_ t: T) -> T {
|
||||
return t // expected-warning {{accessing 't' may produce a copy}}
|
||||
}
|
||||
@_manualOwnership
|
||||
func return_generic_fixed<T>(_ t: T) -> T {
|
||||
return copy t
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func reassign_with_lets<T>(_ t: T) -> T {
|
||||
let x = t // expected-warning {{accessing 't' may produce a copy}}
|
||||
let y = x // expected-warning {{accessing 'x' may produce a copy}}
|
||||
@@ -412,7 +368,6 @@ func reassign_with_lets<T>(_ t: T) -> T {
|
||||
}
|
||||
|
||||
// FIXME: copy propagation has no effect on address-only types, so this is quite verbose.
|
||||
@_manualOwnership
|
||||
func reassign_with_lets_fixed<T>(_ t: T) -> T {
|
||||
let x = copy t
|
||||
let y = copy x
|
||||
@@ -420,21 +375,25 @@ func reassign_with_lets_fixed<T>(_ t: T) -> T {
|
||||
return copy z
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func copy_generic<T>(_ t: T) {
|
||||
consume_generic(t) // expected-warning {{accessing 't' may produce a copy}}
|
||||
borrow_generic(t)
|
||||
consume_generic(t) // expected-warning {{accessing 't' may produce a copy}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
@_noManualOwnership
|
||||
func copy_generic_DISABLED<T>(_ t: T) {
|
||||
consume_generic(t)
|
||||
borrow_generic(t)
|
||||
consume_generic(t)
|
||||
}
|
||||
|
||||
func copy_generic_fixed<T>(_ t: T) {
|
||||
consume_generic(copy t)
|
||||
borrow_generic(t)
|
||||
consume_generic(copy t)
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func benchCaptureProp<S : Sequence>(
|
||||
_ s: S, _ f: (S.Element, S.Element) -> S.Element) -> S.Element {
|
||||
|
||||
@@ -444,7 +403,6 @@ func benchCaptureProp<S : Sequence>(
|
||||
IteratorSequence(it) // expected-warning {{accessing 'it' may produce a copy}}
|
||||
.reduce(initial, f)
|
||||
}
|
||||
@_manualOwnership
|
||||
func benchCaptureProp_fixed<S : Sequence>(
|
||||
_ s: S, _ f: (S.Element, S.Element) -> S.Element) -> S.Element {
|
||||
|
||||
@@ -456,12 +414,10 @@ func benchCaptureProp_fixed<S : Sequence>(
|
||||
}
|
||||
|
||||
extension FixedWidthInteger {
|
||||
@_manualOwnership
|
||||
func leftRotate(_ distance: Int) -> Self {
|
||||
return (self << distance) | (self >> (Self.bitWidth - distance))
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
mutating func rotatedLeft(_ distance: Int) {
|
||||
self = (copy self).leftRotate(distance)
|
||||
}
|
||||
@@ -470,7 +426,6 @@ extension FixedWidthInteger {
|
||||
struct CollectionOf32BitLittleEndianIntegers<BaseCollection: Collection> where BaseCollection.Element == UInt8 {
|
||||
var baseCollection: BaseCollection
|
||||
|
||||
@_manualOwnership
|
||||
init(_ baseCollection: BaseCollection) {
|
||||
precondition(baseCollection.count % 4 == 0)
|
||||
self.baseCollection = baseCollection // expected-warning {{accessing 'baseCollection' may produce a copy}}
|
||||
|
||||
@@ -18,12 +18,12 @@ public class Donut : Food {
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
self.calories = 100
|
||||
self.calories = 100 // expected-warning {{exclusive access here will be checked at runtime}}
|
||||
}
|
||||
|
||||
convenience init(calories c: Int) {
|
||||
self.init()
|
||||
self.calories = c
|
||||
self.calories = c // expected-warning {{exclusive access here will be checked at runtime}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,19 +31,21 @@ extension Int { func greaterThanZero() -> Bool { self > 0 } }
|
||||
|
||||
var expectedCalories: Array<Int> = [120, 203, 1502]
|
||||
|
||||
@_manualOwnership
|
||||
func accessGlobal_map() -> Array<Donut> {
|
||||
return expectedCalories.map(Donut.init(calories:)) // expected-warning {{accessing 'expectedCalories' here may incur runtime exclusivity check, because it involves a global variable}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func accessGlobal_member() -> Int {
|
||||
return expectedCalories.count // expected-warning {{accessing 'expectedCalories' here may incur runtime exclusivity check, because it involves a global variable}}
|
||||
}
|
||||
|
||||
@_noManualOwnership
|
||||
func accessGlobal_member_DISABLED() -> Int {
|
||||
return expectedCalories.count
|
||||
}
|
||||
|
||||
var globalDonut: Donut = Donut()
|
||||
|
||||
@_manualOwnership
|
||||
func accessGlobalClass() {
|
||||
let x = globalDonut.calories // expected-warning {{accessing 'globalDonut' here may incur runtime exclusivity check, because it involves a global variable}}
|
||||
// expected-warning@-1 {{exclusive access here will be checked at runtime}}
|
||||
@@ -51,20 +53,17 @@ func accessGlobalClass() {
|
||||
expectedCalories.append(x) // expected-warning {{accessing 'expectedCalories' here may incur runtime exclusivity check, because it involves a global variable}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func accessClassSimple(_ d2: Donut) -> Int {
|
||||
let d1 = Donut()
|
||||
return d1.calories // expected-warning {{exclusive access here will be checked at runtime}}
|
||||
+ d2.calories // expected-warning {{exclusive access here will be checked at runtime}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func accessClassParam_chain(_ donut: Donut) -> Int {
|
||||
return donut.next?.next?.calories ?? Int.max
|
||||
// expected-warning@-1 {{exclusive access here will be checked at runtime}}
|
||||
}
|
||||
|
||||
@_manualOwnership
|
||||
func accessClassLocal_chain() -> Int {
|
||||
let donut = Donut()
|
||||
return donut.next?.next?.calories ?? Int.max
|
||||
|
||||
@@ -19,7 +19,6 @@ class TriangleClass {
|
||||
// CHECK-NEXT: destroy_value [[SHAPE]]
|
||||
// CHECK-NEXT: return [[COPY]]
|
||||
// CHECK-NEXT: } // end sil function 'basic_access_of_loadable'
|
||||
@_manualOwnership
|
||||
@_silgen_name("basic_access_of_loadable")
|
||||
func basic_access_of_loadable(_ t: TriangleClass) -> ShapeClass {
|
||||
return copy t.shape
|
||||
@@ -41,7 +40,6 @@ func basic_access_of_loadable(_ t: TriangleClass) -> ShapeClass {
|
||||
// CHECK-NEXT: end_access [[ADDR2]]
|
||||
// CHECK: return [[X_COPY]]
|
||||
// CHECK-NEXT: } // end sil function 'var_assign'
|
||||
@_manualOwnership
|
||||
@_silgen_name("var_assign")
|
||||
func var_assign(_ t: TriangleClass, _ b: Bool) -> TriangleClass {
|
||||
var x = TriangleClass()
|
||||
@@ -55,7 +53,6 @@ func var_assign(_ t: TriangleClass, _ b: Bool) -> TriangleClass {
|
||||
// CHECK-NEXT: [[IMPL_COPY:%.*]] = copy_value %0
|
||||
// CHECK-NEXT: return [[IMPL_COPY]]
|
||||
// CHECK-NEXT: } // end sil function 'return_borrowed'
|
||||
@_manualOwnership
|
||||
@_silgen_name("return_borrowed")
|
||||
func return_borrowed(_ t: borrowing TriangleClass) -> TriangleClass {
|
||||
return t
|
||||
@@ -74,7 +71,6 @@ func return_borrowed(_ t: borrowing TriangleClass) -> TriangleClass {
|
||||
// CHECK-NEXT: destroy_value
|
||||
// CHECK-NEXT: return [[IMPL_COPY]]
|
||||
// CHECK-NEXT: } // end sil function 'return_consumingParam'
|
||||
@_manualOwnership
|
||||
@_silgen_name("return_consumingParam")
|
||||
func return_consumingParam(_ t: consuming TriangleClass) -> TriangleClass {
|
||||
return t
|
||||
@@ -89,7 +85,6 @@ func return_consumingParam(_ t: consuming TriangleClass) -> TriangleClass {
|
||||
// CHECK-NEXT: destroy_value %0
|
||||
// CHECK-NEXT: return [[IMPL_COPY]]
|
||||
// CHECK-NEXT: } // end sil function 'return_owned'
|
||||
@_manualOwnership
|
||||
@_silgen_name("return_owned")
|
||||
func return_owned(_ t: __owned TriangleClass) -> TriangleClass {
|
||||
return t
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
class C {}
|
||||
|
||||
@_manualOwnership
|
||||
func hello() -> (C, C) {
|
||||
@_noImplicitCopy let x = C() // expected-error {{'@_noImplicitCopy' cannot be used with ManualOwnership}}
|
||||
return (x, x)
|
||||
|
||||
Reference in New Issue
Block a user