leanprover / lean4

Lean 4 programming language and theorem prover
https://lean-lang.org
Apache License 2.0
4.02k stars 345 forks source link

Failure of exhaustiveness checker when matching on `Exception` #4555

Open JLimperg opened 6 days ago

JLimperg commented 6 days ago

Prerequisites

Please put an X between the brackets as you perform the following steps:

Description

MWE:

import Lean

open Lean

example (e : Exception) : True :=
  match e with
  | .internal .. => sorry
  | .error .. => sorry

-- missing cases:
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofSyntax _)) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofInt (Int.negSucc _))) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofInt (Int.ofNat _))) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofNat _)) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofName _)) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofBool true)) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofBool false)) _)))
-- (@Exception.internal _ (KVMap.mk (List.cons (Prod.mk _ (DataValue.ofString (String.mk _))) _)))

Versions

"4.10.0-nightly-2024-06-24"

Impact

Add :+1: to issues you consider important. If others are impacted by this issue, please ask them to add :+1: to it.

leodemoura commented 5 days ago

The issue here is that Exception.internal has a default argument.

inductive Exception where
  | error (ref : Syntax) (msg : MessageData)
  | internal (id : InternalExceptionId) (extra : KVMap := {})

Thus, .internal .. is equivalent to .internal _ {}. Possible solutions:

leodemoura commented 5 days ago

Workaround.

import Lean

open Lean

example (e : Exception) : True :=
  match e with
  | .internal _ _ => sorry
  | .error .. => sorry
JLimperg commented 5 days ago

Ah, it's the default argument! I understand .. as "ignore all other arguments", so I would prefer if there was no distinction between arguments with and without a default value.