[英]Is #file considered a literal String in Swift?
Bug > Swift > Enum > String Protocol错误> Swift >枚举>字符串协议
I was attempting to create an enumeration in which all its elements were file names, and I stumbled across something interesting.我试图创建一个枚举,其中所有元素都是文件名,我偶然发现了一些有趣的东西。 Like so:
像这样:
enum FileNames: String {
case main = #file
}
This resulted in an internal error.这导致了内部错误。 (Segmentation Fault: 11)
(分段错误:11)
I was able to figure how to get an actual error message:我能够弄清楚如何获得实际的错误消息:
enum Foo: String {
case one = "\(1)"
}
Error: Raw value for enum case must be a literal
Related Questions:相关问题:
• Is #file
considered a String literal? •
#file
是否被视为字符串文字?
• Why does #file
break the enum? • 为什么
#file
破坏枚举? Should this be reported on bugs.swift.org?这是否应该在 bugs.swift.org 上报告?
• I noticed that replacing String
to Int
and #file
to #line
causes the same issue. • 我注意到将
String
替换为Int
并将#file
为#line
会导致同样的问题。 Is this a hint?这是提示吗?
I thought they did, but I made a mistake.我以为他们做到了,但我犯了一个错误。 It also causes the same internal error.
它也会导致相同的内部错误。
import UIKit
enum ColorEnum: UIColor {
case foo = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0)
}
According to Apple, #file
is considered a literal:根据 Apple 的说法,
#file
被认为是文字:
These also crash the compiler.这些也会使编译器崩溃。
enum Foo: String? {
case breaks = nil
}
23 Characters of Mass Destruction enum I:Int?{case a=nil}
Mass Destruction
enum I:Int?{case a=nil}
23 个字符
The crash has now been fixed, it has been merged officially into Swift here: Merged on GitHub Here's the bug report: SR-12998 .崩溃现已修复,它已正式合并到 Swift 中: Merged on GitHub这是错误报告: SR-12998 。 It has officially been implemented in Swift 5.4
已在 Swift 5.4 中正式实现
Adding Support!添加支持!
The use of magic literals as raw values for enum cases is being supported here: SR-13022这里支持使用魔法文字作为枚举案例的原始值: SR-13022
Yes, #file
and #line
are literal expressions but your program is still ill-formed.是的,
#file
和#line
是文字表达式,但您的程序仍然是格式错误的。
The Swift language reference says : Swift 语言参考说:
A literal expression consists of either an ordinary literal (such as a string or a number), an array or dictionary literal, a playground literal, or one of the following special literals:
文字表达式由普通文字(例如字符串或数字)、数组或字典文字、游乐场文字或以下特殊文字之一组成:
#file
— String — The name of the file in which it appears.#file
— 字符串 — 出现的文件的名称。
#line
— Int — The line number on which it appears.#line
— Int — 它出现的行号。[...]
[...]
Let's also note the grammar:我们还要注意语法:
literal-expression → literal
literal-expression → array-literal | dictionary-literal | playground-literal
literal-expression → #file | #line | #column | #function | #dsohandle
Now let us consider the grammar of the enum you are defining.现在让我们考虑您正在定义的枚举的语法。 I am only including the most relevant parts here you can verify the complete deduction yourself:
我在这里只包括最相关的部分,您可以自己验证完整的推论:
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
It's noteworthy that only numeric-literal , static-string-literal , boolean-literal are allowed.值得注意的是,只允许numeric-literal 、 static-string-literal 、 boolean-literal 。 If we look at their definitions, it's clear that those
#
literals thus do not match the raw-value-literal
rule:如果我们查看它们的定义,很明显这些
#
字面量因此与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
All relevant rules for completely defining static-string-literal are long, but it's still trivial to see that static-string-literal cannot be deduced to #file
and cannot include interpolation.完全定义static-string-literal的所有相关规则都很长,但是看到static-string-literal不能推导出为
#file
并且不能包含插值仍然是微不足道的。 (That's what makes it static.) (这就是使它成为 static 的原因。)
So the Swift compiler is indeed right in refusing your program.所以 Swift 编译器拒绝你的程序确实是正确的。 Still, a modern compiler shouldn't simply crash on an illegal program, so it might be worth reporting this issue.
尽管如此,现代编译器不应该简单地在非法程序上崩溃,因此可能值得报告这个问题。
This is definitely a bug, so worth submitting feedback to Apple (although they documented that those #file, #function, etc. are special literals )这绝对是一个错误,因此值得向 Apple 提交反馈(尽管他们记录了那些 #file、#function 等是特殊文字)
Anyway, probably the following workaround can be helpful in some use-cases:无论如何,在某些用例中,以下解决方法可能会有所帮助:
enum FileNames {
static let main = FileNames.file(#file)
case file(String)
}
Swift 5.4 implements the bugfix from SR-12998 Swift 5.4 实现了来自SR-12998的错误修复
Instead of the compiler crashing, it now displays descriptive error messages:它现在显示描述性错误消息,而不是编译器崩溃:
Magic Literals from Strings来自字符串的魔法文字
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
}
Magic Literals from Ints来自 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
}
Magic Literals from UnsafeRawPointers 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
}
Using the Magic Literal nil
in this way now displays a different error instead of crashing the compiler.以这种方式使用 Magic Literal
nil
现在会显示不同的错误,而不是使编译器崩溃。
enum Foo: String? {
case breaks = nil
}
enum I:Int?{case a=nil}
However, the magic literal nil
still can cause the compiler to crash:然而,神奇的文字
nil
仍然会导致编译器崩溃:
extension Optional: ExpressibleByIntegerLiteral where Wrapped == Int {}
enum Foo: Int? {
// Compiler Crashes: Segmentation fault: 11
case c = nil
}
Also the magic literal for UIColor still cause the compiler to crash: 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.