Divergence
A diverging expression is an expression that never completes normal execution.
!
See the following rules for specific expression divergence behavior:
- expr.block.diverging --- Block expressions.
- expr.if.diverging ---
ifexpressions. - expr.loop.block-labels.type --- Labeled block expressions with
break. - expr.loop.break-value.diverging ---
loopexpressions withbreak. - expr.loop.break.diverging ---
breakexpressions. - expr.loop.continue.diverging ---
continueexpressions. - expr.loop.infinite.diverging --- Infinite
loopexpressions. - expr.match.diverging ---
matchexpressions. - expr.match.empty --- Empty
matchexpressions. - expr.return.diverging ---
returnexpressions. - type.never.constraint --- Function calls returning
!.
Note
The [
panic!] macro and related panic-generating macros like [unreachable!] also have the type!and are diverging.
Any expression of type ! is a diverging expression. However, diverging expressions are not limited to type !; expressions of other types may also diverge (e.g., Some(loop {}) has type Option<!>).
Note
Though
!is considered an uninhabited type, a type being uninhabited is not sufficient for it to diverge.! ! !
Note
Divergence can propagate to the surrounding block. See expr.block.diverging.
Fallback
If a type to be inferred is only unified with diverging expressions, then that type will be inferred to be !.
Example
match foo ;
2024 Edition differences
Before the 2024 edition, the type was inferred to instead be
().
Note
Importantly, type unification may happen structurally, so the fallback
!may be part of a larger type. The following compiles:// This has the type `Option<!>`, not `!` match foo ;