rust-lang / rust-lang/rust

Never type doesn't coerce within type paramaters

Open
#162,522 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-type-system C-discussion F-never_type needs-triage
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

fn consume(_: Result<(), ()>) {}

fn type_err() {
    let t: Result<!, ()> = Result::Err(());
    consume(t)
}

I expected to see this happen: it compiles, since if you have a Result<!, ()> you vacuously have a Result<T, ()>

Instead, this happened:

error[E0308]: mismatched types
 --> src/main.rs:5:13
  |
5 |     consume(t)
  |     ------- ^ expected `Result<(), ()>`, found `Result<!, ()>`
  |     |
  |     arguments to this function are incorrect
  |
  = note: expected enum `Result<(), _>`
             found enum `Result<!, _>`
note: function defined here
 --> src/main.rs:1:4
  |
1 | fn consume(_: Result<(), ()>) {}
  |    ^^^^^^^ -----------------

I guess the problem is that the Result<!, ()> is sized early, which limits its ability to coerce into other (potentially larger) types.

The motivating example was being able to call functions which return Result<...> in a function which returns ControlFlow<Result<...>>:

#![feature(try_trait_v2)]

use std::ops::{ControlFlow, Try};

fn maybe_fails() -> Result<(), ()> {
    Err(())
}

fn motivating_example() -> ControlFlow<Result<(), ()>> {
    maybe_fails().branch()?; // fails because we can't coerce Result<!, ()> into Result<(), ()>
    ControlFlow::Break(Ok(()))
}
Meta

rustc --version --verbose:

rustc 1.100.0-nightly (4aa1fbcf4 2026-09-08)
binary: rustc
commit-hash: 4aa1fbcf467cf38ce58abfa8eb9213a789c5381c
commit-date: 2026-09-08
host: x86_64-unknown-linux-gnu
release: 1.100.0-nightly
LLVM version: 23.1.1
Backtrace

<backtrace>

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the Result<!, ()> reproducer in src/main.rs with the reported nightly toolchain, then compare it with the ControlFlow<Result<(), ()>> motivating example. Read the compiler's handling of never-type coercions within generic type parameters. Done means the shown calls compile with the expected coercion, with regression coverage for both examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.