簡體   English   中英

#file 是否被視為 Swift 中的文字字符串?

[英]Is #file considered a literal String in Swift?

錯誤> Swift >枚舉>字符串協議


我試圖創建一個枚舉,其中所有元素都是文件名,我偶然發現了一些有趣的東西。 像這樣:

enum FileNames: String {
     case main = #file
}

這導致了內部錯誤。 (分段錯誤:11)


我能夠弄清楚如何獲得實際的錯誤消息:

enum Foo: String {
    case one = "\(1)"
}

Error: Raw value for enum case must be a literal


相關問題:
#file是否被視為字符串文字?
• 為什么#file破壞枚舉? 這是否應該在 bugs.swift.org 上報告?
• 我注意到將String替換為Int並將#file#line會導致同樣的問題。 這是提示嗎?


顏色文字不起作用

我以為他們做到了,但我犯了一個錯誤。 它也會導致相同的內部錯誤。

import UIKit

enum ColorEnum: UIColor {
    case foo = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0)
}

Swift 編程語言 (Swift 5.2)

根據 Apple 的說法, #file被認為是文字:

#file 根據 Apple 描述為文字


那么 nil 字面量呢?

這些也會使編譯器崩潰。

enum Foo: String? {
    case breaks = nil
}

Mass Destruction enum I:Int?{case a=nil} 23 個字符


錯誤修復

崩潰現已修復,它已正式合並到 Swift 中: Merged on GitHub這是錯誤報告: SR-12998 已在 Swift 5.4 中正式實現

添加支持!
這里支持使用魔法文字作為枚舉案例的原始值: SR-13022

是的, #file#line文字表達式,但您的程序仍然是格式錯誤的。

Swift 語言參考

文字表達式由普通文字(例如字符串或數字)、數組或字典文字、游樂場文字或以下特殊文字之一組成:

#file — 字符串 — 出現的文件的名稱。

#line — Int — 它出現的行號。

[...]

我們還要注意語法:

literal-expression → literal
literal-expression → array-literal | dictionary-literal | playground-literal
literal-expression → #file | #line | #column | #function | #dsohandle

現在讓我們考慮您正在定義的枚舉的語法 我在這里只包括最相關的部分,您可以自己驗證完整的推論:

enum-declaration → attributes opt access-level-modifier opt raw-value-style-enum
[...]
raw-value-style-enum → enum enum-name generic-parameter-clause opt type-inheritance-clause generic-where-clause opt { raw-value-style-enum-members }
[...]
raw-value-assignment → = raw-value-literal
raw-value-literal → numeric-literal | static-string-literal | boolean-literal

值得注意的是,只允許numeric-literalstatic-string-literalboolean-literal 如果我們查看它們的定義,很明顯這些#字面量因此與raw-value-literal規則不匹配:

numeric-literal → -opt integer-literal | -opt floating-point-literal
boolean-literal → true | false
static-string-literal → string-literal-opening-delimiter quoted-text opt string-literal-closing-delimiter
static-string-literal → multiline-string-literal-opening-delimiter multiline-quoted-text opt multiline-string-literal-closing-delimiter

完全定義static-string-literal的所有相關規則都很長,但是看到static-string-literal不能推導出為#file並且不能包含插值仍然是微不足道的。 (這就是使它成為 static 的原因。)

所以 Swift 編譯器拒絕你的程序確實是正確的。 盡管如此,現代編譯器不應該簡單地在非法程序上崩潰,因此可能值得報告這個問題。

這絕對是一個錯誤,因此值得向 Apple 提交反饋(盡管他們記錄了那些 #file、#function 等是特殊文字

無論如何,在某些用例中,以下解決方法可能會有所幫助:

enum FileNames {
    static let main = FileNames.file(#file)
    case file(String)
}

Swift 5.4 修復了崩潰

Swift 5.4 實現了來自SR-12998的錯誤修復

它現在顯示描述性錯誤消息,而不是編譯器崩潰:


來自字符串的魔法文字

enum Foo: String {
    // Compiler Error: Use of '#file' literal as raw value for enum case is not supported
    case b = #file
    // Compiler Error: Use of '#function' literal as raw value for enum case is not supported
    case c = #function
}

來自 Ints 的魔法文字

enum B: Int {
    // Compiler Error: Use of '#line' literal as raw value for enum case is not supported
    case b = #line
    // Compiler Error: Use of '#column' literal as raw value for enum case is not supported
    case c = #column
}

UnsafeRawPointers 中的魔法文字

extension UnsafeRawPointer: ExpressibleByIntegerLiteral {}
enum Wo: UnsafeRawPointer {
    // Compiler Error: Use of '#dsohandle' literal as raw value for enum case is not supported
    case wo = #dsohandle
}

以這種方式使用 Magic Literal nil現在會顯示不同的錯誤,而不是使編譯器崩潰。

enum Foo: String? {
    case breaks = nil
}
enum I:Int?{case a=nil}

它沒有完全修復:

然而,神奇的文字nil仍然會導致編譯器崩潰:

extension Optional: ExpressibleByIntegerLiteral where Wrapped == Int {}
enum Foo: Int? {
    // Compiler Crashes: Segmentation fault: 11
    case c = nil
}

UIColor 的魔法文字仍然會導致編譯器崩潰:

import UIKit
extension UIColor: ExpressibleByIntegerLiteral {}
enum ColorEnum: UIColor {
    // Compiler Crashes: Segmentation fault: 11
    case foo = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0)
}

暫無
暫無

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

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