简体   繁体   English

将非转义值转换为 'Any' 可能允许它转义错误 - 在非转义函数内

[英]Converting non-escaping value to 'Any' may allow it to escape error - within not escaping function

My question is derived from the following Japanese question.我的问题来自以下日本问题。 It's not my question, but I'm trying to answer the following problem but I cannot find the suitable answer.这不是我的问题,但我正在尝试回答以下问题,但我找不到合适的答案。

https://teratail.com/questions/298998 https://teratail.com/questions/298998

The question above will be simpled like below.上面的问题会像下面一样简单。

func executetwice(operation:() -> Void) {
    print(operation)
    operation()
}

This compiler required to add @escaping keyword after operation: label, such as这个编译器要求在operation:后加上@escaping关键字operation: label,如

func executetwice(operation: @escaping () -> Void) {
    print(operation)
    operation()
}

But in fact, it seems that operation block does not escape from this block.但实际上,似乎operation块并没有从这个块中逃脱。

Another way,其它的办法,

func executetwice(operation:() -> Void) {
    let f = operation as Any
    operation()
}

also compiler requires to add @escaping keyword.编译器还需要添加@escaping关键字。 It is just upcasting to Any .它只是向上转换Any In other case, just casting to same type, it seems to be error.在其他情况下,只是强制转换为相同的类型,似乎是错误的。

func executetwice(operation:() -> Void) {
    let f = operation as () -> Void //Converting non-escaping value to '() -> Void' may allow it to escape
    operation()
}

I'm not sure why I need to add @escaping keyword with no escaping condition.我不确定为什么我需要添加没有转义条件的@escaping关键字。

Just adding @escaping keyword will be Ok, but I would like to know why the compiler required the keyword in this case.只需添加@escaping关键字就可以了,但我想知道为什么编译器在这种情况下需要关键字。

print accepts (a variable number of) Any as arguments, so that is why it's saying that you are converting a closure to Any when you pass it to print . print接受(可变数量的) Any作为参数,所以这就是为什么当您将闭包传递给print时,它说您将闭包转换为Any

Many checks are applied on closure-typed parameters to make sure a non-escaping closure don't escape (for what it means for a closure to "escape", read this ):许多检查应用于闭包类型的参数,以确保非转义闭包不会转义(关于闭包“转义”的含义,请阅读此内容):

var c: (() -> Void)?
func f(operation:() -> Void) {
    c = operation // compiler can detect that operation escapes here, and produces an error
}

However, these checks are only applied on closure types.但是,这些检查仅适用于闭包类型。 If you cast a closure to Any , the closure loses its closure type, and the compiler can't check for whether it escapes or not.如果将闭包强制转换为Any ,则该闭包会丢失其闭包类型,并且编译器无法检查它是否转义。 Let's suppose the compiler allowed you to cast a non-escaping closure to Any , and you passed it to g below:假设编译器允许您将非转义闭包转换为Any ,并且您将其传递给下面的g

var c: Any?
func g(operation: Any) {
    // the compiler doesn't know that "operation" is a closure! 
    // You have successfully made a non-escaping closure escape!
    c = operation
}

Therefore, the compiler is designed to be conservative and treats "casting to Any " as "making a closure escape".因此,编译器被设计为保守的并将“强制转换为Any ”视为“进行闭包逃逸”。

But we are sure that print doesn't escape the closure, so we can use withoutActuallyEscaping :但是我们确信print不会逃脱闭包,所以我们可以使用withoutActuallyEscaping

func executetwice(operation:() -> Void) {
    withoutActuallyEscaping(operation) { 
        print($0)
    }
    operation()
}

Casting a closure to its own type also makes the closure escape.将闭包转换为它自己的类型也会使闭包逃逸。 This is because operation as () -> Void is a "rather complex" expression producing a value of type () -> Void .这是因为operation as () -> Void是一个“相当复杂”的表达式,产生类型() -> Void And by "rather complex" I mean it is complex enough that when passing that to a non-escaping parameter, the compiler doesn't bother to check whether what you are casting really is non-escaping, so it assumes that all casts are escaping. “相当复杂”我的意思是它足够复杂,以至于在将其传递给非转义参数时,编译器不会费心检查您正在投射的内容是否真的是非转义的,因此它假定所有类型转换都在转义.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复 escaping 关闭? 错误是:转换非转义值可能允许它转义 - How to fix escaping closure? Error is: Converting non-escaping value may allow it to escape Xcode 10 Swift构建错误:“将非转义的值转换为'T'可能会使其逸出” - Xcode 10 Swift build error: “Converting non-escaping value to 'T' may allow it to escape” 非转义参数的关闭使用可能允许它转义 - Closure use of non-escaping parameter may allow it to escape Swift 3:关闭使用非转义参数可能允许它逃脱 - Swift 3 :Closure use of non-escaping parameter may allow it to escape 在闭包中捕获闭包:Xcode 抛出错误:Escaping 闭包捕获非转义参数 - Capturing closures within closures: Xcode throws error: Escaping closure captures non-escaping parameter 转义闭包捕获非转义参数“函数”Xcode 说 - Escaping closure captures non-escaping parameter 'function' Xcode says 将非转义闭包传递给 function 期望 @escaping 闭包 - Passing non-escaping closure to function expecting an @escaping closure 错误:将非转义参数'publicationQuery'分配给@escaping闭包 - Error: Assigning non-escaping parameter 'publicationQuery' to an @escaping closure 您可以异步分派非转义的闭包函数吗? - Can you dispatch a non-escaping closure function asynchronously? 在Swift 3中实现Church Numerals时出现非转义错误 - Non-escaping error when implementing Church Numerals in Swift 3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM