2015-05-03 47 views
3

我正在爲一門課程編寫簡單語言的編譯器,並且遇到了此警告。問題中的模式匹配很簡單,所以我不明白爲什麼會彈出。這裏所討論的圖案匹配:與tcExpr簽名是def tcExpr(expr: ExprTree, expected: Type*): TypeExprTree表示表達式和Type爲對象的情況下Scala:即使默認值也無法檢查無法匹配的匹配

(tcExpr(lhs), tcExpr(rhs)) match { 
     case (TInt, TInt) | (TString, TString) | (TBoolean, TBoolean) | (TIntArray, TIntArray) | (TObject(_), TObject(_)) => TBoolean 
     case _ => TError 

。除TObject()之外的所有內容均爲簡單對象,而TObject()將表示類的符號作爲參數。

我沒有得到的是沒有那麼多的可能性。爲什麼編譯器不能解決它?有沒有我忽視或誤解的內容?

非常感謝您的回答,

薩科

+0

編譯器向您顯示的消息是什麼。可以放在那裏? – wheaties

回答

1

我可以重現「警告:無法爲不可達檢查匹配」用下面的代碼(我不知道你有多少類型有我拿了32 + 1爲上限。):

trait Type 

case object T0 extends Type 
case object T1 extends Type 
case object T2 extends Type 
case object T3 extends Type 
case object T4 extends Type 
... 
<generated code, 32 types in total> 
... 
case object T31 extends Type 

def foo: Type = T0 

(foo, foo) match { 
    case (T0,T0) | <total 32 types> | (T31,T31) => println("true") 
    case _ => println("false") 
} 

的原因似乎是,它只是內存用完試圖檢查所有可能的情況。警告給出的建議是在運行編譯器時添加選項-Dscalac.patmat.analysisBudget=off。試圖用這個選項編譯:它工作,沒有更多的警告。

編輯:剛剛發現沒有選擇,它停止與> = 5類型的工作......這確實沒有太多的記憶。

我的建議是隻刪除永遠長枚舉,並通過一個簡短的公式改爲:

(foo, foo) match { 
    case (Obj(_), Obj(_)) => println("true") 
    case (x, y) if (x == y) => println("true") // Order is important, thx @Nico 
    case _ => println("false") 
} 

然後警告消失後,代碼將停止蔓延的80個字符/行限制。

+0

我只有5種類型,這就是爲什麼我沒有得到這個錯誤。但你的解決方案更好,更清潔,所以我要使用它,謝謝!只是想知道,第一和第二種情況不應該顛倒嗎?否則,不會(x,y)捕獲任何元組? – Nico

+0

@Nico事實上,第一和第二種情況應該交換。我編輯了我的帖子。但正如我所說,原則上你可以保留你的代碼,編譯器選項消除了這個問題。 –

+0

我無法解釋爲什麼限制太低。看起來它只是拒絕大於20個案件(5x5 = 25> 20)。也許他們試圖以這種方式避免指數級大的編譯時間......如果它是一個線性組織程序中的單個模式匹配,許多情況下不會造成太大的傷害,但是在較大的代碼庫中它可能不同,它可能導致編譯,每次需要半個星期... –