class Foo {
var bar:Int
func functionA() {
func nested() {
bar++
}
externalFunction(nested)
}
func functionB() -> (Int -> Int) {
func nested(x:Int) -> Int {
return bar + x
}
return nested
}
}
--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swift-languag...@googlegroups.com.
To post to this group, send email to swift-l...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/7eabe4f2-9e8a-40b6-9232-0eed6f7b1bf3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
class Test {
var bar:Int = 0
func functionA() -> (() -> ()) {
func nestedA() {
bar++
}
return nestedA
}
func closureA() -> (() -> ()) {
let nestedClosureA = { [unowned self] () -> () in
self.bar++
}
return nestedClosureA
}
}
xcrun swiftc -emit-silgen test.swift | xcrun swift-demangle > test.silgen
--- This is part of the implementation of the method 'functionA'. There is a 'strong_retain %0' that get a strong reference to self and pass it to %2 which is a reference to the nested function obtained in the line before. Also, the type of 'partial_apply %2(%0)' tells that the parameter has type "@owned Test".
....
--- Get a constant reference to self.
debug_value %0 : $Test // let self // id: %1
--- Get a reference to the nested function.
%2 = function_ref @test.Test.(functionA (test.Test) -> () -> () -> ()).(nestedA #1) ()() : $@convention(thin) (@owned Test) -> () // user: %4
--- Make the self reference strong.
strong_retain %0 : $Test // id: %3
--- Partially apply the nested function. This result in a function without parameters. Note the "@owned Test" in the type of the parameter
%4 = partial_apply %2(%0) : $@convention(thin) (@owned Test) -> () // user: %5
--- And the "@callee_owned" in the type of the result function
return %4 : $@callee_owned () -> () // id: %5
}
....
--- This is part of the implementation of 'closureA'. This code is a little messy but basically it create a new reference container with "alloc_box" and store an unowned reference to self there. Then partially apply the closure with the unowned argument and return the result.
....
--- Get a constant reference to self
debug_value %0 : $Test // let self // id: %1
--- Store an unowned reference to self in a box
%2 = alloc_box $@sil_unowned Test // let self // users: %5, %7, %15
%3 = ref_to_unowned %0 : $Test to $@sil_unowned Test // users: %4, %5
unowned_retain %3 : $@sil_unowned Test // id: %4
store %3 to %2#1 : $*@sil_unowned Test // id: %5
--- Get a reference to the nested closure
%6 = function_ref @test.Test.(closureA (test.Test) -> () -> () -> ()).(closure #1) : $@convention(thin) (@owned @sil_unowned Test) -> () // user: %13
--- Read the unowned reference from the box
%7 = load %2#1 : $*@sil_unowned Test // users: %8, %9
strong_retain_unowned %7 : $@sil_unowned Test // id: %8
%9 = unowned_to_ref %7 : $@sil_unowned Test to $Test // users: %10, %12
%10 = ref_to_unowned %9 : $Test to $@sil_unowned Test // users: %11, %13
unowned_retain %10 : $@sil_unowned Test // id: %11
strong_release %9 : $Test // id: %12
--- Partially apply the nested closure, this time the type of the closure is "@owned @sil_unowned Test"
%13 = partial_apply %6(%10) : $@convention(thin) (@owned @sil_unowned Test) -> () // users: %14, %16
debug_value %13 : $@callee_owned () -> () // let nestedClosureA // id: %14
strong_release %2#0 : $@box @sil_unowned Test // id: %15
return %13 : $@callee_owned () -> () // id: %16
}
To unsubscribe from this group and stop receiving emails from it, send an email to swift-language+unsubscribe@googlegroups.com.
To post to this group, send email to swift-language@googlegroups.com.
On Dec 1, 2015, at 6:31 AM, Bruno Berisso <goja...@gmail.com> wrote:I think I found something. If my calculous are correct the nested functions approach hold an strong reference to self silently.