Swift 编译器挂起!这是一个错误吗?

Posted

技术标签:

【中文标题】Swift 编译器挂起!这是一个错误吗?【英文标题】:Swift compiler hangs! Is it a bug? 【发布时间】:2014-12-03 00:46:58 【问题描述】:

有一次,当我在处理一个 Swift 项目时,Xcode 卡住了状态栏中的“正在编译 Swift 源代码”消息。不管我等了多久,编译都没有完成。我回滚了我最近的更改,并很快意识到让编译器感到困惑的是一个非常简单的枚举构造。下面是一个说明问题的 Playground 示例。

创建一个新的 Playground 并粘贴此代码。看到输出了吗?

// Playground - noun: a place where people can play

import UIKit

enum FastingType: Int 
    case NoFast=0, Vegetarian, FishAllowed, FastFree, Cheesefare


class Fasting

    var allowedFood = [
        .NoFast:        ["meat", "fish", "milk", "egg", "cupcake"],
        .Vegetarian:    ["vegetables", "bread", "nuts"],
        .FishAllowed:   ["fish", "vegetables", "bread", "nuts"],
        .FastFree:      ["cupcake", "meat", "fish", "cheese"],
        .Cheesefare:    ["cheese", "cupcake", "milk", "egg"]
    ]

    func getAllowedFood(type: FastingType) -> [String] 
        return allowedFood[type]
    



var fasting = Fasting()
println(fasting.getAllowedFood(.Vegetarian))
println("Hello world")

在我的机器上,忙碌指示灯一直在旋转,并且没有消息。我在 Xcode 6.1 (6A1052c) 和 Xcode 6.2-beta (6C86e) 上都试过这个。

这看起来像 Swift 编译器中的错误吗?还是我的代码有问题?

更新:

有几个人注意到我忘记了getAllowedFood 函数中的返回类型。但是,仅此修复程序并不能解决问题。编译器仍然挂起。

在 cmets 中提出了一种解决方法:

Swift 似乎无法解释您的字典。给字典一个明确的类型来“帮助”编译器通常是个好主意。

以下添加“取消冻结”编译器:

var allowedFood: [FastingType: [String]]

【问题讨论】:

bugreport.apple.com 永远不要在操场上测试。 (我知道这就是 Apple 所说的,但不要这样做。)如果您只是在真正的应用程序而不是操场上执行所有这些操作,编译器会为您提供明确的错误消息。 哦,还有一条建议。当然,Swift 或 Cocoa 中可能存在错误,但除非你首先了解当出现问题时,是 做错了,否则你不会学习编程。 如果我做错了什么,编译器应该显示错误信息,而不是无限循环! Matt 的建议是务实的,但是是的,编译应该本质上是确定性的,并且永远不要无限循环,即使在操场上也是如此。 【参考方案1】:

是的,这可以被认为是编译器错误。编译器无法确定字典中键的类型。可以通过为字典指定显式类型或确保使用 FastingType.NoFast 完全指定第一个值来消除无限循环行为。

试试这个:

enum FastingType: Int 
    case NoFast=0, Vegetarian, FishAllowed, FastFree, Cheesefare


class Fasting

    var allowedFood:[FastingType: [String]] = [
        .NoFast:        ["meat", "fish", "milk", "egg", "cupcake"],
        .Vegetarian:    ["vegetables", "bread", "nuts"],
        .FishAllowed:   ["fish", "vegetables", "bread", "nuts"],
        .FastFree:      ["cupcake", "meat", "fish", "cheese"],
        .Cheesefare:    ["cheese", "cupcake", "milk", "egg"]
    ]

    func getAllowedFood(type: FastingType) -> [String] 
        return allowedFood[type]!
    

变化:

    allowedFood 类型 [FastingType: [String]] 以便它可以解释您的枚举值。 给getAllowedFood() 一个返回类型。 解开字典查找,因为它们总是返回可选项。

或者,您可以将getAllowedFood() 改为return allowedFood[type] ?? [],如果您的字典不详尽,这样会更安全。

【讨论】:

或者您可以在 getAllowedFood 中使用 switch 语句来避免 ! 感谢您“修复”我的代码。不过,我打算问一个不同的问题:为什么原始代码使编译器无限循环? 我猜你绝对可以称之为错误。斯威夫特似乎很难解释你的字典。为字典提供显式类型以“帮助”编译器通常是个好主意。 请注意,只需将 .NoFast 更改为 FastingType.NoFast 即可停止无限循环行为,因为它假定所有其他键也必须为 FastingType 谢谢,vacawama!我将您的答案标记为解决方案:-)

以上是关于Swift 编译器挂起!这是一个错误吗?的主要内容,如果未能解决你的问题,请参考以下文章

swift 编译器总是 100% CPU

Swift编译器在handleDeferredImports中进行segfaulting

关于未使用变量的奇怪编译器警告,这是编译器错误吗?

这是 MSVC++ 2017 更新 3 中的编译器错误吗

这是 Visual 2010 的编译错误吗?

这是一个已知的 VC14 错误吗