2016-01-25 73 views
2

考慮下面的代碼片斷:Scala的:不正確的警告「匹配可能並不詳盡」

sealed abstract class Bar 
object B1 extends Bar 
object B2 extends Bar 
object B3 extends Bar 
case class A(bar:Bar) 

def foo(a:A) = a match { 
    case A([email protected](B1|B2)) => 
     bar match { // gives warning here 
      case B1 => 
      case B2 => 
     } 
    case _ => 
} 

在上文中,我確保第一種情況下僅匹配時AA(B1)類型或A(B2)(至少這就是我認爲的意思)。但是,我收到以下錯誤:

warning: match may not be exhaustive. 
It would fail on the following input: B3 
     bar match { 
    ^

任何人都可以詳細說明爲什麼警告即將到來嗎?

編輯:在答案後,似乎編譯器類型bar作爲Bar沒有記住它匹配。這絕對不是一個錯誤。該compilier是足夠聰明,不給下面的一個警告:

sealed abstract class Bar 
object B1 extends Bar 
object B2 extends Bar 
object B3 extends Bar 
case class A(bar:Bar) 

def foo(a:A) = a match { 
    case A(B1|B2) => 
     a match { // no warning 
      case A(B1) => 
      case A(B2) => 
     } 
    case _ => 
} 

回答

5

我想這是因爲給bar類型是超(bar可能是一個B1B2和唯一的常見的類型是Bar)所以理論上它仍然可能是一個B3和編譯器是不夠聰明此:

def foo(a:A) = a match { 
    case A([email protected](B1|B2)) => 
    bar match { // bar here has a Bar type 
     case B1 => 
     case B2 => 
    } 
    case _ => 
} 

無論如何,這將是在這裏有一個嵌套的比賽時,你可以有相同的結果平坦的比賽呢?

+0

它實際上是一個更復雜的情況,有幾個「Bar」的子類型。如果需要,我可以舉一個更好的例子。 – Jus12

+0

如果你想保持這種匹配結構,你需要一個更精緻的層次結構實現,例如'B1'和'B2'可以是Bar'和Bar1And2'的子類型,然後有更好的參數匹配,儘管我不知道你想要這個,對我看起來不太好。 –

+0

它似乎是編譯器中的一個錯誤。這場比賽在其他情況下效果很好。 – Jus12