处理Swift编译器的误导性错误消息(上下文依赖,类型推断)

时间:2016-02-12 13:25:28

标签: xcode swift compiler-errors

虽然Swift编译器(Xcode 7.2)在诊断等同于以下内容的某些源文本的错误时似乎完全正确,但检测到实际错误需要很长时间。原因:程序员需要在标记的文本上看 not ,但在其他地方,因此误导,想知道为什么可选字符串和非可选字符串不能是??的操作数...

struct Outer {
    var text : String
}

var     opt : String?
var context : Outer


context = opt ?? "abc"

显然,最后一行应该有context.text作为要分配的变量。这是诊断出来的:

confusion2.swift:9:19: error: binary operator '??' cannot be applied\
                                to operands of type 'String?' and 'String'
    context = opt ?? "abc"
              ~~~ ^  ~~~~~

消息正式正确。 (我假设左侧的类型检查为右侧建立了一个期望的类型(Outer),然后,这使得表达式在类型方面不起作用。)但从字面上看,诊断错误,正如修复左侧时所见:??可应用于String?String类型的操作数。

现在,如果目前这样,就编译器消息而言,这是一个很好的应对策略?记得

  1. 类型推断!
  2. 上下文<!/ LI>
  3. ...
  4. 一开始?有更系统的方法吗?检查清单?

    更新(我正在添加到列表中,因为答案进来了。谢谢!)

    1. 分开陈述,以便分别检查几行(@vacawama)
    2. 谨防选项(例如从词典中获取的值),请参阅下面的testSwitchOpt
    3. 另一个

      enum T {
          case Str(String)
          case Integer(Int)
      }
      
      func testSwitchOpt(x : T?) -> Int {
          switch x {
          case .Integer(let r): return r
          default: return 0
          }
      }
      

      编译器说

      optandswitch.swift:8:15: error: enum case 'Integer' not found in type 'T?'
             case .Integer(let r): return r
      

      修复是写switch x!(或更谨慎的let),以便使类型检查地址成为正确的类型,我想。

      我可能,也许应该,在Apple上提交一些报告,但问题似乎代表了一个反复出现的主题 - 我已经在其他编译器中看到了这一点 - 我希望能提供一些通用和可重复使用的提示,如果你不这样做的话小心分享他们。

1 个答案:

答案 0 :(得分:3)

Swift的类型推理系统通常很棒,但它可能会导致非常混淆错误的错误消息。

当你得到其中一条没有意义的Swift错误信息时,一个好的策略就是将这条线分成几部分。这将允许Swift在它走错路径之前返回更好的错误消息。

例如,在您的情况下,如果引入临时变量,真正的问题就变得清晰了:

// context = opt ?? "abc"
let temp = opt ?? "abc"
context = temp

现在错误消息显示为:

  

无法指定类型&#39;字符串&#39;的值输入&#39; Outer&#39;