Thanks for your post.
The answer depends on the context. The example of handling all possible case values using something like ??? or !unreachable, !oops vs only handling what you care about have practically identical runtime behaviour.
However at compile time if an error/warning indicates that some case expression is “not exhaustive” the developer may likely see the problem being the case expression rather than much further up the call graph where input ought to have been sanitized earlier. You definitely want to catch these occurances and not silence them prematurely by being exhaustive BECAUSE the problem actually lies elsewhere.
However if the case expression (or some function call) actually forms part of the role of santizing values from boundary layers then you still want the heads up from the compiler, however you may choose to silence these by handling the missing case explicitly (catching actual sanitization problems, missing values, typos etc) OR you may want to express that “its ok I don’t want or need to write more code to silence the compiler and I really want to let it crash here, please don’t complain here again”.
We have discussed some notions for expressing that something should never happen however it is not quite there yet IMO because we probably do need to handle “stfu compiler” from the caller site where we don’t want to write more code and we acknowledge that we want it to crash.
What I don’t want is defensively coding the sad path for every function signature and every case statement in the core logic of my app (aka “pipeland”) nor do I want every hex utility package I include using “defensive” idioms as “best practice” because it will prematurely silence problems that ought to be handled by the caller at a layer or more above.
If we decide that we do wish to explicitly handle cases and function signatures as a programmer aid (perhaps because of deprecations), then I think we do need a language feature to signal that although we are handling this function signature or case expression we still want any call graph that arrives here to be flagged as a problem on the CALLER, and ideally the entire call graph being implicated starting from the root so that the origin of the problem is handled as far up the call graph as possible.
For this reason the compiler should list the call graph paths that are implicated in the issue of not meeting the supported type and value constraints.






















