簡體   English   中英

將非轉義值轉換為 'Any' 可能允許它轉義錯誤 - 在非轉義函數內

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

我的問題來自以下日本問題。 這不是我的問題,但我正在嘗試回答以下問題,但我找不到合適的答案。

https://teratail.com/questions/298998

上面的問題會像下面一樣簡單。

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

這個編譯器要求在operation:后加上@escaping關鍵字operation: label,如

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

但實際上,似乎operation塊並沒有從這個塊中逃脫。

其它的辦法,

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

編譯器還需要添加@escaping關鍵字。 它只是向上轉換Any 在其他情況下,只是強制轉換為相同的類型,似乎是錯誤的。

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

我不確定為什么我需要添加沒有轉義條件的@escaping關鍵字。

只需添加@escaping關鍵字就可以了,但我想知道為什么編譯器在這種情況下需要關鍵字。

print接受(可變數量的) Any作為參數,所以這就是為什么當您將閉包傳遞給print時,它說您將閉包轉換為Any

許多檢查應用於閉包類型的參數,以確保非轉義閉包不會轉義(關於閉包“轉義”的含義,請閱讀此內容):

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

但是,這些檢查僅適用於閉包類型。 如果將閉包強制轉換為Any ,則該閉包會丟失其閉包類型,並且編譯器無法檢查它是否轉義。 假設編譯器允許您將非轉義閉包轉換為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
}

因此,編譯器被設計為保守的並將“強制轉換為Any ”視為“進行閉包逃逸”。

但是我們確信print不會逃脫閉包,所以我們可以使用withoutActuallyEscaping

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

將閉包轉換為它自己的類型也會使閉包逃逸。 這是因為operation as () -> Void是一個“相當復雜”的表達式,產生類型() -> Void “相當復雜”我的意思是它足夠復雜,以至於在將其傳遞給非轉義參數時,編譯器不會費心檢查您正在投射的內容是否真的是非轉義的,因此它假定所有類型轉換都在轉義.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM