Skip to content

Comments

Add more rules about when expressions diverge#2186

Open
ehuss wants to merge 1 commit intorust-lang:masterfrom
ehuss:more-divergence
Open

Add more rules about when expressions diverge#2186
ehuss wants to merge 1 commit intorust-lang:masterfrom
ehuss:more-divergence

Conversation

@ehuss
Copy link
Contributor

@ehuss ehuss commented Feb 20, 2026

#2067 added a chapter on divergence along with rules for some of the more subtle expressions like if or match. This adds rules for almost all the rest of the expressions.

Most of these are pretty straightforward propagation rules which could be left implicit. It may seem a little excessive to have a separate rule for each one, but I think the consistency is worth it because there are various subtleties. This also may help us be clear about these things when adding new expressions to the language to ensure we think about the divergence rules.

This does not cover const expressions (const blocks, static, const, array repeat, etc.) because I still do not yet fully know how those should be documented (see #2153).

I'm not entirely excited by having the long list of rules in the divergence chapter, mostly because of the length. However, I think it is helpful to cross-index these kinds of things.

There are some interesting subtleties that I noticed:

  • while loops cannot diverge. It's a little surprising to me (I would expect the condition to allow it to diverge). I suspect this is due to the desugaring to a loop expression using break, which does not diverge.
  • Updated details for let-chains.
  • I couldn't think of a way for a path expression to refer to a never type on stable, so I left a comment in there to update it when never type is stabilized. I am writing this as-if the uninhabited-static lint is an error and not supported.

References for the implementation:

Closes #2152

rust-lang#2067 added a chapter on
divergence along with rules for some of the more subtle expressions like
`if` or `match`. This adds rules for almost all the rest of the
expressions.

Most of these are pretty straightforward propagation rules which could
be left implicit. It may seem a little excessive to have a separate rule
for each one, but I think the consistency is worth it because there are
various subtleties. This also may help us be clear about these things
when adding new expressions to the language to ensure we think about the
divergence rules.

This does not cover const expressions (const blocks, static, const,
array repeat, etc.) because I still do not yet fully know how those
should be documented (see
rust-lang#2153).

I'm not entirely excited by having the long list of rules in the
divergence chapter, mostly because of the length. However, I think it is
helpful to cross-index these kinds of things.

There are some interesting subtleties that I noticed:

- `while` loops cannot diverge. It's a little surprising to me (I would
  expect the condition to allow it to diverge). I suspect this is due to
  the desugaring to a loop expression using `break`, which does not
  diverge.
- Updated details for let-chains.
- I couldn't think of a way for a `path` expression to refer to a never
  type on stable, so I left a comment in there to update it when never
  type is stabilized. I am writing this as-if the uninhabited-static
  lint is an error and not supported.

References for the implementation:
- Place expression with never must be read: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/expr.rs#L318-L326
- `break` is never: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/expr.rs#L819-L820
- `continue` is never: https://github.com/rust-lang/rust/blob/0376d43d443cba463a0b6a6ec9140ea17d7b7130/compiler/rustc_hir_typeck/src/expr.rs#L861
- `return` is never: https://github.com/rust-lang/rust/blob/0376d43d443cba463a0b6a6ec9140ea17d7b7130/compiler/rustc_hir_typeck/src/expr.rs#L921
- `if` divergence: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/expr.rs#L1236-L1242
- `loop`: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/expr.rs#L1450-L1456
- `asm!`: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/expr.rs#L3684
- `match`: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/_match.rs#L19-L178
- block break: https://github.com/rust-lang/rust/blob/59fd4ef94daa991e6797b5aa6127e824f3067def/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L1167-L1171
- lazy bool: https://github.com/rust-lang/rust/blob/0376d43d443cba463a0b6a6ec9140ea17d7b7130/compiler/rustc_hir_typeck/src/op.rs#L111

Closes rust-lang#2152
@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Feb 20, 2026
@ehuss
Copy link
Contributor Author

ehuss commented Feb 20, 2026

@jackh726 Would you be able to review this?

Copy link
Member

@jackh726 jackh726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good to me. Definitely the expression list in divergence.md is pretty long now.

> The future type that rustc generates is roughly equivalent to an enum with one variant per `await` point, where each variant stores the data needed to resume from its corresponding point.

r[expr.block.async.diverging]
An async block expression does not itself [diverge], but evaluating the future (such as through `await`) diverges if the output type is the [never type].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter half is covered by expr.await.diverging. Is the duplication worth it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: The marked PR is awaiting review from a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detail divergence for the rest of the expressions

3 participants