mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
We used to take all the captures of a local function and treat them all as read and write usages of vars from an outer scope. Instead, let's refactor the analysis to walk into local functions.
115 lines
4.3 KiB
Swift
115 lines
4.3 KiB
Swift
// RUN: %target-swift-emit-silgen -verify %s | %FileCheck %s
|
|
|
|
if true {
|
|
var x = 0 // expected-warning {{variable 'x' was never mutated; consider changing to 'let' constant}}
|
|
func local() -> Int { return 0 }
|
|
func localWithContext() -> Int { return x }
|
|
func transitiveWithoutContext() -> Int { return local() }
|
|
|
|
// Can't convert a closure with context to a C function pointer
|
|
let _: @convention(c) () -> Int = { x } // expected-error{{cannot be formed from a closure that captures context}}
|
|
let _: @convention(c) () -> Int = { [x] in x } // expected-error{{cannot be formed from a closure that captures context}}
|
|
let _: @convention(c) () -> Int = localWithContext // expected-error{{cannot be formed from a local function that captures context}}
|
|
|
|
let _: @convention(c) () -> Int = local
|
|
let _: @convention(c) () -> Int = transitiveWithoutContext
|
|
}
|
|
|
|
class C {
|
|
static func staticMethod() -> Int { return 0 }
|
|
class func classMethod() -> Int { return 0 }
|
|
}
|
|
|
|
class Generic<X : C> {
|
|
func f<Y : C>(_ y: Y) {
|
|
let _: @convention(c) () -> Int = { return 0 }
|
|
let _: @convention(c) () -> Int = { return X.staticMethod() } // expected-error{{cannot be formed from a closure that captures generic parameters}}
|
|
let _: @convention(c) () -> Int = { return Y.staticMethod() } // expected-error{{cannot be formed from a closure that captures generic parameters}}
|
|
}
|
|
}
|
|
|
|
func values(_ arg: @escaping @convention(c) (Int) -> Int) -> @convention(c) (Int) -> Int {
|
|
return arg
|
|
}
|
|
// CHECK-LABEL: sil hidden [ossa] @$s19c_function_pointers6valuesyS2iXCS2iXCF
|
|
// CHECK: bb0(%0 : $@convention(c) (Int) -> Int):
|
|
// CHECK: return %0 : $@convention(c) (Int) -> Int
|
|
|
|
@discardableResult
|
|
func calls(_ arg: @convention(c) (Int) -> Int, _ x: Int) -> Int {
|
|
return arg(x)
|
|
}
|
|
// CHECK-LABEL: sil hidden [ossa] @$s19c_function_pointers5callsyS3iXC_SitF
|
|
// CHECK: bb0(%0 : $@convention(c) @noescape (Int) -> Int, %1 : $Int):
|
|
// CHECK: [[RESULT:%.*]] = apply %0(%1)
|
|
// CHECK: return [[RESULT]]
|
|
|
|
@discardableResult
|
|
func calls_no_args(_ arg: @convention(c) () -> Int) -> Int {
|
|
return arg()
|
|
}
|
|
|
|
func global(_ x: Int) -> Int { return x }
|
|
|
|
func no_args() -> Int { return 42 }
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s19c_function_pointers0B19_to_swift_functionsyySiF
|
|
func pointers_to_swift_functions(_ x: Int) {
|
|
// CHECK: bb0([[X:%.*]] : $Int):
|
|
|
|
func local(_ y: Int) -> Int { return y }
|
|
|
|
// CHECK: [[GLOBAL_C:%.*]] = function_ref @$s19c_function_pointers6globalyS2iFTo
|
|
// CHECK: [[CVT:%.*]] = convert_function [[GLOBAL_C]]
|
|
// CHECK: apply {{.*}}([[CVT]], [[X]])
|
|
calls(global, x)
|
|
|
|
// CHECK: [[LOCAL_C:%.*]] = function_ref @$s19c_function_pointers0B19_to_swift_functionsyySiF5localL_yS2iFTo
|
|
// CHECK: [[CVT:%.*]] = convert_function [[LOCAL_C]]
|
|
// CHECK: apply {{.*}}([[CVT]], [[X]])
|
|
calls(local, x)
|
|
|
|
// CHECK: [[CLOSURE_C:%.*]] = function_ref @$s19c_function_pointers0B19_to_swift_functionsyySiFS2iXEfU_To
|
|
// CHECK: [[CVT:%.*]] = convert_function [[CLOSURE_C]]
|
|
// CHECK: apply {{.*}}([[CVT]], [[X]])
|
|
calls({ $0 + 1 }, x)
|
|
|
|
calls_no_args(no_args)
|
|
// CHECK: [[NO_ARGS_C:%.*]] = function_ref @$s19c_function_pointers7no_argsSiyFTo
|
|
// CHECK: [[CVT:%.*]] = convert_function [[NO_ARGS_C]]
|
|
// CHECK: apply {{.*}}([[CVT]])
|
|
}
|
|
|
|
func unsupported(_ a: Any) -> Int { return 0 }
|
|
|
|
func pointers_to_bad_swift_functions(_ x: Int) {
|
|
calls(unsupported, x) // expected-error{{C function pointer signature '(Any) -> Int' is not compatible with expected type '@convention(c) (Int) -> Int'}}
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s19c_function_pointers22StructWithInitializersV3fn1yyXCvpfiyycfU_ : $@convention(thin) () -> () {
|
|
// CHECK-LABEL: sil private [thunk] [ossa] @$s19c_function_pointers22StructWithInitializersV3fn1yyXCvpfiyycfU_To : $@convention(c) () -> () {
|
|
|
|
struct StructWithInitializers {
|
|
let fn1: @convention(c) () -> () = {}
|
|
|
|
init(a: ()) {}
|
|
init(b: ()) {}
|
|
}
|
|
|
|
func pointers_to_nested_local_functions_in_generics<T>(x: T) -> Int{
|
|
func foo(y: Int) -> Int { return y }
|
|
|
|
return calls(foo, 0)
|
|
}
|
|
|
|
func capture_list_no_captures(x: Int) {
|
|
calls({ [x] in $0 }, 0) // expected-warning {{capture 'x' was never used}}
|
|
}
|
|
|
|
class Selfless {
|
|
func capture_dynamic_self() {
|
|
calls_no_args { _ = Self.self; return 0 }
|
|
// expected-error@-1 {{a C function pointer cannot be formed from a closure that captures dynamic Self type}}
|
|
}
|
|
}
|