Why would I use divergent functions?

It has several uses. It can be used for functions which are designed to panic or exit the program. panic!() itself is one such function, but it can also be applied to functions which wrap panic!(), such as printing out more detailed error information and then panicking.

It can also be used for functions that never return. If a function goes into an infinite loop, such as the main loop of a server, and thus never returns, it could be defined this way.

Another possible use would be a wrapper around the Unix exec family of functions, in which the current process is replaced with the one being executed.

It is useful to have such a type because it is compatible with all other types. In order to be type safe, Rust has to ensure that all branches of a match or if statement return the same type. But if there are some branches that are unreachable or indicate an error, you need some way to throw an error that will unify with the type returned by the other branches. Because ! unifies with all types, it can be used in any such case.

There is an interesting RFC (and discussion) at the moment that argues (in part) for expanding the places where ! can be used, arguing that it should be treated as a full fledged type like () is; ! being a type with no values that unifies with all other types, while () being a distinct type with a single value. I’m not sure I agree with the full RFC, but the discussion of treating ! as a full-fledged type is interesting and I think could be proposed separately from the rest of the RFC.

Update: Since I wrote the above, the part of the RFC about promoting ! to a full fledged type was split into a separate RFC and merged, and is in the process of being implemented (currently available in nightly builds behind a feature gate). As a full-fledged type, it can be used in more contexts, such as in Result<T, !> indicating a result that can never fail, or Result<!, E> as one that can never succeed. These are useful in generic contexts; if you have some trait that requires a method to return a result, but for that particular implementation it can only possibly succeed, you don’t need to fill in some dummy error type.

Leave a Comment