blob: 9f4eb9878a52745e33fe41430eb53ec25c549628 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -enforce-exclusivity=unchecked -diagnose-static-exclusivity -verify | %FileCheck %s
sil_stage raw
import Builtin
import Swift
sil @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
sil @takesOneInout : $@convention(thin) (@inout Int) -> ()
sil @makesInt : $@convention(thin) () -> Int
sil @takesInoutAndNoEscapeClosure : $@convention(thin) (@inout Int, @noescape @owned @callee_owned () -> ()) -> ()
sil @takesInoutAndNoEscapeClosureTakingArgument : $@convention(thin) (@inout Int, @noescape @owned @callee_owned (Int) -> ()) -> ()
sil @takesInoutAndNoEscapeGuaranteedClosureTakingArgument : $@convention(thin) (@inout Int, @noescape @guaranteed @callee_guaranteed (Int) -> ()) -> ()
sil @takesInoutAndNoEscapeClosureWithGenericReturn : $@convention(thin) <T> (@inout Int, @noescape @callee_owned (Int) -> @out T) -> ()
sil @takesInoutAndNoEscapeBlockClosure : $@convention(thin) (@inout Int, @owned @convention(block) @noescape () -> ()) -> ()
sil @takesInoutAndNoEscapeOptionalBlockClosure : $@convention(thin) (@inout Int, @owned Optional<@convention(block) @noescape () -> ()>) -> ()
// CHECK-LABEL: sil hidden @twoLocalInoutsDisaliased
sil hidden @twoLocalInoutsDisaliased : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%5 = alloc_box ${ var Int }
%6 = project_box %5 : ${ var Int }, 0
store %0 to [trivial] %6 : $*Int
%8 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%9 = begin_access [modify] [unknown] %3 : $*Int
%10 = begin_access [modify] [unknown] %6 : $*Int // no-error
%11 = apply %8(%9, %10) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %10 : $*Int
end_access %9: $*Int
destroy_value %5 : ${ var Int }
destroy_value %2 : ${ var Int }
%14 = tuple ()
return %14 : $()
}
// CHECK-LABEL: sil hidden @twoLocalInoutsSimpleAliasing
sil hidden @twoLocalInoutsSimpleAliasing : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%7 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden @conflictingPriorAccess
sil hidden @conflictingPriorAccess : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %5 : $*Int
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: sil hidden @twoSequentialInouts
sil hidden @twoSequentialInouts : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesOneInout : $@convention(thin) (@inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int
%6 = apply %4(%5) : $@convention(thin) (@inout Int) -> ()
end_access %5 : $*Int
%7 = begin_access [modify] [unknown] %3 : $*Int // no-error
%8 = apply %4(%7) : $@convention(thin) (@inout Int) -> ()
end_access %7: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden @unconditionalBranch
sil hidden @unconditionalBranch : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = begin_access [modify] [unknown] %3 : $*Int
br finish
finish:
end_access %4: $*Int
destroy_value %2 : ${ var Int }
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @diamondMergeStacks
sil hidden @diamondMergeStacks : $@convention(thin) (Int, Builtin.Int1) -> () {
bb0(%0 : $Int, %1 : $Builtin.Int1):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = begin_access [modify] [unknown] %3 : $*Int
cond_br %1, then, else
then:
br finish
else:
br finish
finish:
end_access %4: $*Int
destroy_value %2 : ${ var Int }
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @loopMergeStacks
sil hidden @loopMergeStacks : $@convention(thin) (Int, Builtin.Int1) -> () {
bb0(%0 : $Int, %1 : $Builtin.Int1):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = begin_access [modify] [unknown] %3 : $*Int
br bb1
bb1:
cond_br %1, bb1, bb2
bb2:
end_access %4: $*Int
destroy_value %2 : ${ var Int }
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @loopWithError
sil hidden @loopWithError : $@convention(thin) (Int, Builtin.Int1) -> () {
bb0(%0 : $Int, %1 : $Builtin.Int1):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
br bb1
bb1:
// Make sure we don't diagnose twice.
%4 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
end_access %5: $*Int
end_access %4: $*Int
cond_br %1, bb1, bb2
bb2:
destroy_value %2 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil hidden @modifySubAccessesAreAllowed
sil hidden @modifySubAccessesAreAllowed : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int
%6 = begin_access [modify] [unknown] %5 : $*Int // no-error
%7 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%8 = tuple ()
return %8 : $()
}
// Multiple access kinds
// CHECK-LABEL: sil hidden @twoLocalReadsSimpleAliasing
sil hidden @twoLocalReadsSimpleAliasing : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
store %0 to [trivial] %2 : $*Int
%4 = begin_access [read] [unknown] %2 : $*Int
%5 = begin_access [read] [unknown] %2 : $*Int // no-error
end_access %5 : $*Int
end_access %4: $*Int
destroy_value %1 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil hidden @localReadFollowedByModify
sil hidden @localReadFollowedByModify : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
store %0 to [trivial] %2 : $*Int
%4 = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
%5 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
end_access %5 : $*Int
end_access %4: $*Int
destroy_value %1 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil hidden @localModifyFollowedByRead
sil hidden @localModifyFollowedByRead : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
store %0 to [trivial] %2 : $*Int
%4 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%5 = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
end_access %5 : $*Int
end_access %4: $*Int
destroy_value %1 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
class ClassWithStoredProperty {
@sil_stored var f: Int
init()
}
// CHECK-LABEL: sil hidden @classStoredProperty
sil hidden @classStoredProperty : $@convention(thin) (ClassWithStoredProperty) -> () {
bb0(%0 : $ClassWithStoredProperty):
%1 = ref_element_addr %0 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-error@+1{{overlapping accesses to 'f', but modification requires exclusive access; consider copying to a local variable}}
%2 = begin_access [modify] [dynamic] %1 : $*Int
%3 = ref_element_addr %0 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-note@+1{{conflicting access is here}}
%4 = begin_access [modify] [dynamic] %3 : $*Int
end_access %4 : $*Int
end_access %2 : $*Int
destroy_value %0 : $ClassWithStoredProperty
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @lookThroughBeginBorrow
sil hidden @lookThroughBeginBorrow : $@convention(thin) (ClassWithStoredProperty) -> () {
bb0(%0 : $ClassWithStoredProperty):
%1 = begin_borrow %0 : $ClassWithStoredProperty
%2 = begin_borrow %0 : $ClassWithStoredProperty
%3 = ref_element_addr %1 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-error@+1{{overlapping accesses to 'f', but modification requires exclusive access; consider copying to a local variable}}
%4 = begin_access [modify] [dynamic] %3 : $*Int
%5 = ref_element_addr %2 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-note@+1{{conflicting access is here}}
%6 = begin_access [modify] [dynamic] %5 : $*Int
end_access %6 : $*Int
end_access %4 : $*Int
end_borrow %2 from %0 : $ClassWithStoredProperty, $ClassWithStoredProperty
end_borrow %1 from %0 : $ClassWithStoredProperty, $ClassWithStoredProperty
destroy_value %0 : $ClassWithStoredProperty
%7 = tuple ()
return %7 : $()
}
// Tests for address identity
// Treat 'alloc_box' as identity for project_box
// CHECK-LABEL: sil hidden @twoAllocBoxProjections
sil hidden @twoAllocBoxProjections : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = copy_value %2 : ${ var Int }
%5 = project_box %4 : ${ var Int }, 0
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%7 = begin_access [modify] [unknown] %5 : $*Int // expected-note {{conflicting access is here}}
end_access %7 : $*Int
end_access %6: $*Int
destroy_value %2 : ${ var Int }
destroy_value %4 : ${ var Int }
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden @lookThroughMarkUninitialized
sil hidden @lookThroughMarkUninitialized : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = mark_uninitialized [rootself] %1 : ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = project_box %2 : ${ var Int }, 0
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %4 : $*Int // expected-note {{conflicting access is here}}
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%7 = tuple ()
return %7 : $()
}
// Treat global as identity for global_addr instruction-
sil_global hidden @global1 : $Int
sil_global hidden @global2 : $Int
// CHECK-LABEL: sil hidden @modifySameGlobal
sil hidden @modifySameGlobal : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = global_addr @global1 :$*Int
%2 = global_addr @global1 :$*Int
%3 = begin_access [modify] [unknown] %1 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%4 = begin_access [modify] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
end_access %4 : $*Int
end_access %3: $*Int
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @modifyDifferentGlobal
sil hidden @modifyDifferentGlobal : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = global_addr @global1 :$*Int
%2 = global_addr @global2 :$*Int
%3 = begin_access [modify] [unknown] %1 : $*Int
%4 = begin_access [modify] [unknown] %2 : $*Int // no-error
end_access %4 : $*Int
end_access %3: $*Int
%5 = tuple ()
return %5 : $()
}
// Multiple errors accessing the same location
// If we have a sequence of begin read - begin write - begin read accesses make
// sure the second read doesn't report a confusing read-read conflict.
// CHECK-LABEL: sil hidden @readWriteReadConflictingThirdAccess
sil hidden @readWriteReadConflictingThirdAccess : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [read] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%7 = begin_access [read] [unknown] %3 : $*Int // no-error
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// If we have a sequence of begin write - begin write - begin write accesses make sure the
// third write doesn't report a conflict.
// CHECK-LABEL: sil hidden @writeWriteWriteConflictingThirdAccess
sil hidden @writeWriteWriteConflictingThirdAccess : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%7 = begin_access [modify] [unknown] %3 : $*Int // no-error
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// If we have a sequence of begin write - end write - begin write - begin write
// accesses make sure the it is the second begin write that gets the note
// about the conflict and not the first
// CHECK-LABEL: sil hidden @resetFirstAccessForNote
sil hidden @resetFirstAccessForNote : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // no-note
end_access %5 : $*Int
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// Check for iterator invalidation issues when the hash from
// basic blocks to analysis state is re-hashed. The number of
// blocks in this test is determined by the initial size of the
// 'BlockOutAccesses' DenseMap in the implementation.
//
// The unreachable block below must branch to bN where
// N = 3/4 * INITIAL_SIZE - 2
sil @blockMapRehash : $@convention(method) (Builtin.Int1) -> () {
bb0(%0: $Builtin.Int1):
br bb1
bb1:
br bb2
bb2:
br bb3
bb3:
br bb4
bb4:
br bb5
bb5:
br bb6
bb6:
br bb7
bb7:
br bb8
bb8:
br bb9
bb9:
br bb10
bb10:
br bb11
bb11:
br bb12
bb12:
br bb13
bb13:
br bb14
bb14:
br bb15
bb15:
br bb16
bb16:
br bb17
bb17:
br bb18
bb18:
br bb19
bb19:
br bb20
bb20:
br bb21
bb21:
br bb22
bb22:
br bb23 // no-crash
bb23:
%1 = tuple ()
return %1 : $()
bbUnreachable:
br bb22
}
// Check that a pointer_to_address access passes diagnostics.
//
// CHECK-LABEL: sil hidden @pointerToAddr
sil hidden @pointerToAddr : $@convention(thin) (Builtin.RawPointer) -> Int {
bb0(%0: $Builtin.RawPointer):
%adr = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int
%access = begin_access [read] [dynamic] %adr : $*Int
%val = load [trivial] %access : $*Int
end_access %access : $*Int
return %val : $Int
}
// Helper.
struct S {
var x: Int
}
// Check inlined struct element access.
// This only happens when mandatory passes are applied repeatedly.
// e.g. importing from a debug standard library.
//
// CHECK-LABEL: sil hidden @inlinedStructElement
sil hidden @inlinedStructElement : $@convention(thin) (@inout S) -> Int {
bb0(%0 : $*S):
%2 = begin_access [modify] [static] %0 : $*S
%3 = struct_element_addr %2 : $*S, #S.x
%4 = begin_access [read] [static] %3 : $*Int
%5 = load [trivial] %4 : $*Int
end_access %4 : $*Int
end_access %2 : $*S
return %5 : $Int
}
// Check inlined tuple element access.
// This only happens when mandatory passes are applied repeatedly.
//
// CHECK-LABEL: sil hidden @inlinedTupleElement
sil hidden @inlinedTupleElement : $@convention(thin) (@inout (Int, Int)) -> Int {
bb0(%0 : $*(Int, Int)):
%2 = begin_access [modify] [static] %0 : $*(Int, Int)
%3 = tuple_element_addr %2 : $*(Int, Int), 0
%4 = begin_access [read] [static] %3 : $*Int
%5 = load [trivial] %4 : $*Int
end_access %4 : $*Int
end_access %2 : $*(Int, Int)
return %5 : $Int
}
// Check inlined enum access.
// This only happens when mandatory passes are applied repeatedly.
//
// CHECK-LABEL: sil hidden @inlinedEnumValue
sil hidden @inlinedEnumValue : $@convention(thin) (Int) -> (@out Optional<Int>, Int) {
bb0(%0 : $*Optional<Int>, %1 : $Int):
%6 = unchecked_take_enum_data_addr %0 : $*Optional<Int>, #Optional.some!enumelt.1
%7 = begin_access [read] [static] %6 : $*Int
%8 = load [trivial] %7 : $*Int
end_access %7 : $*Int
return %8 : $Int
}
// Helper.
class Storage {}
// Check inlined array access.
// This only happens when mandatory passes are applied repeatedly.
//
// CHECK-LABEL: sil hidden @inlinedArrayProp
sil hidden @inlinedArrayProp : $@convention(thin) (@guaranteed Storage, Builtin.Word) -> Int {
bb0(%0 : $Storage, %1 : $Builtin.Word):
%2 = ref_tail_addr %0 : $Storage, $UInt
%3 = begin_access [read] [static] %2 : $*UInt
%4 = tail_addr %3 : $*UInt, %1 : $Builtin.Word, $Int
%5 = begin_access [read] [static] %4 : $*Int
%6 = index_addr %5 : $*Int, %1 : $Builtin.Word
%7 = begin_access [read] [static] %6 : $*Int
%8 = load [trivial] %7 : $*Int
end_access %7 : $*Int
end_access %5 : $*Int
end_access %3 : $*UInt
return %8 : $Int
}
// Conflicts involving noescape closures.
sil hidden @closureThatModifiesCaptureAndTakesInout: $@convention(thin) (@inout Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $*Int):
%2 = begin_access [modify] [unknown] %1 : $*Int // expected-note {{conflicting access is here}}
end_access %2 : $*Int
%3 = tuple ()
return %3 : $()
}
// FIXME: We should prevent SILGen from emitting such a thing because the only
// way to distinguish a capture from a regular @inout argument here is by the
// @inout_aliasable convention. When we eliminate that convention we should make
// sure that whenever we promote a closure from a @callee_guaranteed @noescape
// function type to @conventio(thin), we insert access enforcement on the caller
// side for captured variables.
//
// CHECK-LABEL: sil hidden @inProgressModifyModifyConflictWithCallToClosure
sil hidden @inProgressModifyModifyConflictWithCallToClosure : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @closureThatModifiesCaptureAndTakesInout: $@convention(thin) (@inout Int, @inout_aliasable Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%8 = apply %4(%5, %3) : $@convention(thin) (@inout Int, @inout_aliasable Int) -> ()
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
sil hidden @closureWithArgument_1 : $@convention(thin) (Int, @inout_aliasable Int) -> () {
bb0(%0 : $Int, %1 : $*Int):
%2 = begin_access [modify] [unknown] %1 : $*Int // expected-note 2 {{conflicting access is here}}
end_access %2 : $*Int
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil hidden @inProgressConflictWithNoEscapeClosureArgument
sil hidden @inProgressConflictWithNoEscapeClosureArgument : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeClosureTakingArgument : $@convention(thin) (@inout Int, @noescape @owned @callee_owned (Int) -> ()) -> ()
%5 = function_ref @closureWithArgument_1 : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%6 = partial_apply %5(%3) : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%conv = convert_escape_to_noescape %6 : $@callee_owned (Int) -> () to $@callee_owned @noescape (Int) -> ()
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%8 = apply %4(%7, %conv) : $@convention(thin) (@inout Int, @noescape @owned @callee_owned (Int) -> ()) -> ()
end_access %7: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: sil hidden @inProgressConflictWithNoEscapeGuaranteedClosureArgument : $@convention(thin) (Int) -> () {
sil hidden @inProgressConflictWithNoEscapeGuaranteedClosureArgument : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeGuaranteedClosureTakingArgument : $@convention(thin) (@inout Int, @noescape @guaranteed @callee_guaranteed (Int) -> ()) -> ()
%5 = function_ref @closureWithArgument_1 : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%6 = partial_apply [callee_guaranteed] %5(%3) : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%conv = convert_escape_to_noescape %6 : $@callee_guaranteed (Int) -> () to $@callee_guaranteed @noescape (Int) -> ()
%bconv = begin_borrow %conv : $@callee_guaranteed @noescape (Int) -> ()
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%8 = apply %4(%7, %bconv) : $@convention(thin) (@inout Int, @noescape @guaranteed @callee_guaranteed (Int) -> ()) -> ()
end_access %7: $*Int
end_borrow %bconv from %conv : $@callee_guaranteed @noescape (Int) -> (), $@callee_guaranteed @noescape (Int) -> ()
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
sil hidden @closureThatModifiesCapture_2 : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
end_access %1 : $*Int
%2 = tuple ()
return %2 : $()
}
// CHECK-LABEL: sil hidden @inProgressReadModifyConflictWithNoEscapeClosureArgument
sil hidden @inProgressReadModifyConflictWithNoEscapeClosureArgument : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeClosure : $@convention(thin) (@inout Int, @noescape @owned @callee_owned () -> ()) -> ()
%5 = function_ref @closureThatModifiesCapture_2 : $@convention(thin) (@inout_aliasable Int) -> ()
%6 = partial_apply %5(%3) : $@convention(thin) (@inout_aliasable Int) -> ()
%conv = convert_escape_to_noescape %6 : $@callee_owned () -> () to $@callee_owned @noescape () -> ()
%7 = begin_access [read] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%8 = apply %4(%3, %conv) : $@convention(thin) (@inout Int, @noescape @owned @callee_owned () -> ()) -> ()
end_access %7: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
sil hidden @closureWithConcreteReturn : $@convention(thin) (Int, @inout_aliasable Int) -> (Int) {
bb0(%0 : $Int, %1 : $*Int):
%2 = begin_access [modify] [unknown] %1 : $*Int // expected-note {{conflicting access is here}}
end_access %2 : $*Int
return %0 : $Int
}
sil [reabstraction_thunk] @thunkForClosureWithConcreteReturn : $@convention(thin) (Int, @noescape @callee_owned (Int) -> Int) -> @out Int
// CHECK-LABEL: sil hidden @inProgressConflictWithNoEscapeClosureWithReabstractionThunk
sil hidden @inProgressConflictWithNoEscapeClosureWithReabstractionThunk : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeClosureWithGenericReturn : $@convention(thin) <T_0> (@inout Int, @noescape @callee_owned (Int) -> @out T_0) -> ()
%5 = function_ref @closureWithConcreteReturn : $@convention(thin) (Int, @inout_aliasable Int) -> (Int)
%6 = partial_apply %5(%3) : $@convention(thin) (Int, @inout_aliasable Int) -> (Int)
%7 = convert_escape_to_noescape %6 : $@callee_owned (Int) -> Int to $@noescape @callee_owned (Int) -> Int
%8 = function_ref @thunkForClosureWithConcreteReturn : $@convention(thin) (Int, @noescape @callee_owned (Int) -> Int) -> @out Int
%9 = partial_apply %8(%7) : $@convention(thin) (Int, @noescape @callee_owned (Int) -> Int) -> @out Int
%10 = convert_escape_to_noescape %9 : $@callee_owned (Int) -> @out Int to $@noescape @callee_owned (Int) -> @out Int
%11 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%12 = apply %4<Int>(%11, %10) : $@convention(thin) <T_0> (@inout Int, @noescape @callee_owned (Int) -> @out T_0) -> ()
end_access %11: $*Int
destroy_value %2 : ${ var Int }
%13 = tuple ()
return %13 : $()
}
sil [reabstraction_thunk] @thunkForCalleeGuaranteed : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
sil [reabstraction_thunk] @withoutActuallyEscapingThunk : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
sil hidden @closureThatModifiesCapture_1: $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int // expected-note 2{{conflicting access is here}}
end_access %1 : $*Int
%2 = tuple ()
return %2 : $()
}
// CHECK-LABEL: sil hidden @inProgressConflictWithNoEscapeClosureWithBlockStorage
sil hidden @inProgressConflictWithNoEscapeClosureWithBlockStorage : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeBlockClosure : $@convention(thin) (@inout Int, @owned @convention(block) @noescape () -> ()) -> ()
%5 = function_ref @closureThatModifiesCapture_1 : $@convention(thin) (@inout_aliasable Int) -> ()
%6 = partial_apply [callee_guaranteed] %5(%3) : $@convention(thin) (@inout_aliasable Int) -> ()
%conv = convert_escape_to_noescape %6 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
%thunk = function_ref @withoutActuallyEscapingThunk : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
%sentinel = partial_apply [callee_guaranteed] %thunk(%conv) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
%sentinel2 = mark_dependence %sentinel : $@callee_guaranteed () -> () on %conv : $@noescape @callee_guaranteed () -> ()
%sentinel3 = copy_value %sentinel2 : $@callee_guaranteed () -> ()
%7 = alloc_stack $@block_storage @callee_guaranteed () -> ()
%8 = project_block_storage %7 : $*@block_storage @callee_guaranteed () -> ()
store %sentinel3 to [init] %8 : $*@callee_guaranteed () -> ()
%10 = function_ref @thunkForCalleeGuaranteed : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
%11 = init_block_storage_header %7 : $*@block_storage @callee_guaranteed () -> (), invoke %10 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
%12 = copy_block %11 : $@convention(block) @noescape () -> ()
%13 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%14 = apply %4(%13, %12) : $@convention(thin) (@inout Int, @owned @convention(block) @noescape () -> ()) -> ()
end_access %13 : $*Int
destroy_addr %8 : $*@callee_guaranteed() -> ()
dealloc_stack %7 : $*@block_storage @callee_guaranteed () -> ()
destroy_value %2 : ${ var Int }
%ret = tuple ()
return %ret : $()
}
// CHECK-LABEL: sil hidden @inProgressConflictWithNoEscapeClosureWithOptionalBlockStorage
sil hidden @inProgressConflictWithNoEscapeClosureWithOptionalBlockStorage : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeOptionalBlockClosure : $@convention(thin) (@inout Int, @owned Optional<@convention(block) @noescape () -> ()>) -> ()
%5 = function_ref @closureThatModifiesCapture_1 : $@convention(thin) (@inout_aliasable Int) -> ()
%6 = partial_apply [callee_guaranteed] %5(%3) : $@convention(thin) (@inout_aliasable Int) -> ()
%conv = convert_escape_to_noescape %6 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
%thunk = function_ref @withoutActuallyEscapingThunk : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
%sentinel = partial_apply [callee_guaranteed] %thunk(%conv) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
%sentinel2 = mark_dependence %sentinel : $@callee_guaranteed () -> () on %conv : $@noescape @callee_guaranteed () -> ()
%sentinel3 = copy_value %sentinel2 : $@callee_guaranteed () -> ()
%7 = alloc_stack $@block_storage @callee_guaranteed () -> ()
%8 = project_block_storage %7 : $*@block_storage @callee_guaranteed () -> ()
store %sentinel3 to [init] %8 : $*@callee_guaranteed () -> ()
%10 = function_ref @thunkForCalleeGuaranteed : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
%11 = init_block_storage_header %7 : $*@block_storage @callee_guaranteed () -> (), invoke %10 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
%12 = copy_block %11 : $@convention(block) @noescape () -> ()
%13 = enum $Optional<@convention(block) @noescape () -> ()>, #Optional.some!enumelt.1, %12 : $@convention(block) @noescape () -> ()
%14 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%15 = apply %4(%14, %13) : $@convention(thin) (@inout Int, @owned Optional<@convention(block) @noescape () -> ()>) -> ()
end_access %14 : $*Int
destroy_addr %8 : $*@callee_guaranteed () -> ()
dealloc_stack %7 : $*@block_storage @callee_guaranteed () -> ()
destroy_value %2 : ${ var Int }
%ret = tuple ()
return %ret : $()
}
// Stored property relaxation.
struct NestedStructWithStoredProps {
var a: Int
var b: Int
}
struct StructWithStoredProps {
var x: Int
var y: Int
var n: NestedStructWithStoredProps
}
sil @takesInoutIntAndStructWithStoredProps : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
// CHECK-LABEL: sil hidden @twoSeparateStoredProperties
sil hidden @twoSeparateStoredProperties : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.x
%7 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // no-error
%8 = struct_element_addr %7 : $*StructWithStoredProps, #StructWithStoredProps.y
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @twoSeparateNestedStoredProperties
sil hidden @twoSeparateNestedStoredProperties : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.n
%7 = struct_element_addr %6 : $*NestedStructWithStoredProps, #NestedStructWithStoredProps.a
%8 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // no-error
%9 = struct_element_addr %8 : $*StructWithStoredProps, #StructWithStoredProps.n
%10 = struct_element_addr %9 : $*NestedStructWithStoredProps, #NestedStructWithStoredProps.b
%11 = apply %4(%7, %10) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %8 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%12 = tuple ()
return %12 : $()
}
// CHECK-LABEL: sil hidden @theSameStoredProperty
sil hidden @theSameStoredProperty : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.x
%7 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-note {{conflicting access is here}}
%8 = struct_element_addr %7 : $*StructWithStoredProps, #StructWithStoredProps.x
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @storedPropertyAndAggregate
sil hidden @storedPropertyAndAggregate : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesInoutIntAndStructWithStoredProps : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.x
%7 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-note {{conflicting access is here}}
%8 = apply %4(%6, %7) : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
end_access %7 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: sil hidden @nestedStoredPropertyAndAggregate
sil hidden @nestedStoredPropertyAndAggregate : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesInoutIntAndStructWithStoredProps : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.n
%7 = struct_element_addr %6 : $*NestedStructWithStoredProps, #NestedStructWithStoredProps.a
%8 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-note {{conflicting access is here}}
%9 = struct_element_addr %8 : $*StructWithStoredProps, #StructWithStoredProps.n
end_access %8 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @twoSeparateTupleElements
sil hidden @twoSeparateTupleElements : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var (Int, Int) }
%3 = project_box %2 : ${ var (Int, Int) }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*(Int, Int)
%6 = tuple_element_addr %5 : $*(Int, Int), 0
%7 = begin_access [modify] [unknown] %3 : $*(Int, Int) // no-error
%8 = tuple_element_addr %7 : $*(Int, Int), 1
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*(Int, Int)
end_access %5: $*(Int, Int)
destroy_value %2 : ${ var (Int, Int) }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @sameTupleElement
sil hidden @sameTupleElement : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var (Int, Int) }
%3 = project_box %2 : ${ var (Int, Int) }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*(Int, Int) // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = tuple_element_addr %5 : $*(Int, Int), 0
%7 = begin_access [modify] [unknown] %3 : $*(Int, Int) // expected-note {{conflicting access is here}}
%8 = tuple_element_addr %7 : $*(Int, Int), 0
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*(Int, Int)
end_access %5: $*(Int, Int)
destroy_value %2 : ${ var (Int, Int) }
%10 = tuple ()
return %10 : $()
}
sil hidden @passNilToNoEscape : $@convention(thin) (Int) -> () {
bb0( %0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
%4 = enum $Optional<@convention(block) @noescape () -> ()>, #Optional.none!enumelt
%5 = function_ref @takesInoutAndNoEscapeOptionalBlockClosure : $@convention(thin) (@inout Int, @owned Optional<@convention(block) @noescape () -> ()>) -> ()
%6 = apply %5(%3, %4) : $@convention(thin) (@inout Int, @owned Optional<@convention(block) @noescape () -> ()>) -> ()
%7 = tuple ()
return %7 : $()
}
sil private @closureForDirectPartialApplyTakingInout : $@convention(thin) (@inout Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $*Int):
%access = begin_access [read] [unknown] %1 : $*Int // expected-note {{conflicting access is here}}
%val = load [trivial] %access : $*Int
end_access %access : $*Int
%v = tuple ()
return %v : $()
}
sil hidden @directPartialApplyTakingInout : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%box = alloc_box ${ var Int }, var, name "i"
%boxadr = project_box %box : ${ var Int }, 0
store %0 to [trivial] %boxadr : $*Int
%f = function_ref @closureForDirectPartialApplyTakingInout : $@convention(thin) (@inout Int, @inout_aliasable Int) -> ()
%pa = partial_apply [callee_guaranteed] %f(%boxadr) : $@convention(thin) (@inout Int, @inout_aliasable Int) -> ()
%nepa = convert_escape_to_noescape %pa : $@callee_guaranteed (@inout Int) -> () to $@noescape @callee_guaranteed (@inout Int) -> ()
%access = begin_access [modify] [unknown] %boxadr : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%call = apply %nepa(%access) : $@noescape @callee_guaranteed (@inout Int) -> ()
end_access %access : $*Int
destroy_value %box : ${ var Int }
%v = tuple ()
return %v : $()
}
sil private @closureForDirectPartialApplyChain : $@convention(thin) (@inout Int, Int, @inout_aliasable Int) -> () {
bb0(%0 : $*Int, %1 : $Int, %2 : $*Int):
%access = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
%val = load [trivial] %access : $*Int
end_access %access : $*Int
%v = tuple ()
return %v : $()
}
sil hidden @directPartialApplyChain : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%box = alloc_box ${ var Int }, var, name "i"
%boxadr = project_box %box : ${ var Int }, 0
store %0 to [trivial] %boxadr : $*Int
%f = function_ref @closureForDirectPartialApplyChain : $@convention(thin) (@inout Int, Int, @inout_aliasable Int) -> ()
%pa1 = partial_apply [callee_guaranteed] %f(%boxadr) : $@convention(thin) (@inout Int, Int, @inout_aliasable Int) -> ()
%pa2 = partial_apply [callee_guaranteed] %pa1(%0) : $@callee_guaranteed (@inout Int, Int) -> ()
%nepa = convert_escape_to_noescape %pa2 : $@callee_guaranteed (@inout Int) -> () to $@noescape @callee_guaranteed (@inout Int) -> ()
%access = begin_access [modify] [unknown] %boxadr : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%call = apply %nepa(%access) : $@noescape @callee_guaranteed (@inout Int) -> ()
end_access %access : $*Int
destroy_value %box : ${ var Int }
%v = tuple ()
return %v : $()
}
sil private @closureForPartialApplyArgChain : $@convention(thin) (Int, @inout_aliasable Int) -> () {
bb0(%0 : $Int, %1 : $*Int):
%access = begin_access [read] [unknown] %1 : $*Int // expected-note {{conflicting access is here}}
%val = load [trivial] %access : $*Int
end_access %access : $*Int
%v = tuple ()
return %v : $()
}
sil hidden @partialApplyArgChain : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeClosure : $@convention(thin) (@inout Int, @noescape @owned @callee_owned () -> ()) -> ()
%5 = function_ref @closureForPartialApplyArgChain : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%6 = partial_apply %5(%3) : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%7 = partial_apply %6(%0) : $@callee_owned (Int) -> ()
%conv = convert_escape_to_noescape %7 : $@callee_owned () -> () to $@callee_owned @noescape () -> ()
%8 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%9 = apply %4(%8, %conv) : $@convention(thin) (@inout Int, @noescape @owned @callee_owned () -> ()) -> ()
end_access %8: $*Int
destroy_value %2 : ${ var Int }
%v = tuple ()
return %v : $()
}