2016-02-12 55 views
0

雖然Swift編譯器(Xcode 7.2)在診斷與以下內容等同的某些源文本的錯誤時看起來非常正確,但花費很長時間才能檢測到實際錯誤。原因:程序員需要看在標註文字,但在其他地方,從而誤導,不知道爲什麼一個可選的字符串和非可選的字符串,不可能是??操作數...應對Swift編譯器的誤導性錯誤消息(上下文相關性,類型推斷)

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. 上下文!
  3. ...

一開始?有更系統的方法嗎?檢查清單?

更新(我添加到列表中的答案進來,謝謝!)

  1. break語句分開,以便有幾行單獨檢查(@vacawama)
  2. 當心自選(如從值字典得到),見下面testSwitchOpt

另外一個

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),從而使類型檢查地址類型正確,我猜。

我可以或許應該在蘋果公司提交報告,但這個問題似乎代表了一個反覆出現的主題 - 我曾與其他編譯器一起看過這個問題 - 並且我希望提供一些通用和可重用的提示,如果您不希望不介意分享他們。

回答

3

Swift的類型推斷系統通常很棒,但它可能導致非常容易混淆錯誤的錯誤信息。

當你收到其中一個毫無意義的Swift錯誤消息時,一個好的策略是將該行分解成多個部分。這將允許Swift在錯誤路徑走得太遠之前返回更好的錯誤消息。

例如,在你的情況下,如果你引入一個臨時變量,真正的問題變得清晰:

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

現在的錯誤信息上寫着:

無法指定類型的值「字符串'鍵入'Outer'