一尘不染

Swift编译器错误:字符串连接中的“表达式过于复杂”

swift

我发现这比任何事情都有趣。我已经解决了,但是我想知道原因。错误如下:DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions。为什么抱怨呢?似乎是最简单的表达方式之一。

编译器指向该columns + ");";部分

func tableName() -> String { return("users"); }

func createTableStatement(schema: [String]) -> String {

    var schema = schema;

    schema.append("id string");
    schema.append("created integer");
    schema.append("updated integer");
    schema.append("model blob");

    var columns: String = ",".join(schema);

    var statement = "create table if not exists " + self.tableName() + "(" + columns + ");";

    return(statement);
}

解决方法是:

var statement = "create table if not exists " + self.tableName();
statement += "(" + columns + ");";

这也可以(通过@efischency)起作用,但是我不太喜欢它,因为我认为(迷路了:

var statement = "create table if not exists \(self.tableName()) (\(columns))"


阅读 221

收藏
2020-07-07

共1个答案

一尘不染

我不是编译器专家-我不知道这个答案是否会“以有意义的方式改变您的想法”,但是我对问题的理解是:

它与类型推断有关。每次使用+运算符时,Swift都必须搜索所有可能的重载,+并推断出+您正在使用哪个版本。我为+操作员算出了不到30个重载。这有很多可能性,当您将4或5个+操作链接在一起并要求编译器推断所有参数时,您所要求的远远超过乍看上去的情况。

这种推论可能会变得很复杂-例如,如果添加a UInt8Intusing +,则输出将为an
Int,但是还有一些工作需要评估混合类型与运算符的规则。

当您使用文字时,如String示例中的文字,编译器将把String文字转换为String,然后为+运算符推断参数和返回类型,等等。

如果表达式足够复杂(即,它要求编译器对参数和运算符进行过多推断),它将退出并告诉您退出。

一旦表达式达到一定程度的复杂性,让编译器退出是有意的。另一种选择是让编译器尝试做,看看是否可以,但这是有风险的-
编译器可能会一直尝试下去,陷入困境,甚至崩溃。因此,我的理解是,对于表达式的复杂度有一个静态阈值,编译器将无法超越。

我的理解是,Swift团队正在致力于编译器优化,这将使这些错误的发生率降低。您可以通过单击此链接在Apple
Developer论坛上了解一点

在开发人员论坛上,克里斯·拉特纳(Chris Lattner)要求人们将这些错误作为雷达报告提出,因为他们正在积极致力于修复这些错误。

在阅读了这里和开发论坛上的许多帖子后,我就是这样理解的,但是我对编译器的理解很幼稚,我希望对他们如何处理这些任务有更深入了解的人能够在我的基础上得到扩展已经写在这里。

2020-07-07