Skip to content

ICE: rustdoc: unreachable #150154

@matthiaskrgr

Description

@matthiaskrgr

Code

//@ check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
use std::marker::PhantomData;

pub struct Equal<const T: usize, const R: usize>();
pub trait True {}
impl<const T: usize> True for Equal<T, T> {}

// replacement for generativity
pub struct Id<'id>(PhantomData<fn(&'id ()) -> &'id ()>);
pub struct Guard<'id>(Id<'id>);
fn make_guard<'id>(i: &'id Id<'id>) -> Guard<'id> {
    Guard(Id(PhantomData))
}

impl<'id> Into<Id<'id>> for Guard<'id> {
    fn into(self) -> Id<'id> {
        self.0
    }
}

pub struct Arena<'life> {
    bytes: *mut [u8],
    //bitmap: RefCell<RoaringBitmap>,
    _token: PhantomData<Id<'life>>,
}

#[repr(transparent)]
pub struct Item<'life, T> {
    data: T,
    _phantom: PhantomData<Id<'life>>,
}

#[repr(transparent)]
pub struct Token<'life, 'borrow, 'compact, 'reborrow, T>
where
    'life: 'reborrow,
    T: Tokenize<'life, 'borrow, 'compact, 'reborrow>,
{
    //ptr: *mut <T as Tokenize>::Tokenized,
    ptr: core::ptr::NonNull<T::Tokenized>,
    _phantom: PhantomData<Id<'life>>,
    _compact: PhantomData<&'borrow Guard<'compact>>,
    _result: PhantomData<&'reborrow T::Untokenized>,
}

impl<'life> Arena<'life> {
    pub fn tokenize<'before, 'compact, 'borrow, 'reborrow, T, U>(
        &self,
        guard: &'borrow Guard<'compact>,
        item: Item<'life, &'before mut T>,
    ) -> Token<'life, 'borrow, 'compact, 'reborrow, U>
    where
        T: Tokenize<'life, 'borrow, 'compact, 'reborrow, Untokenized = U>,
        T::Untokenized: Tokenize<'life, 'borrow, 'compact, 'reborrow>,
        Equal<{ core::mem::size_of::<T>() }, { core::mem::size_of::<U>() }>: True,
        'compact: 'borrow,
        'life: 'reborrow,
        'life: 'compact,
        'life: 'borrow,
        // 'borrow: 'before ??
    {
        let dst = item.data as *mut T as *mut T::Tokenized;
        Token {
            ptr: core::ptr::NonNull::new(dst as *mut _).unwrap(),
            _phantom: PhantomData,
            _compact: PhantomData,
            _result: PhantomData,
        }
    }
}

pub trait Tokenize<'life, 'borrow, 'compact, 'reborrow>
where
    'compact: 'borrow,
    'life: 'reborrow,
    'life: 'borrow,
    'life: 'compact,
{
    type Tokenized;
    type Untokenized;
    const TO: fn(&Arena<'life>, &'borrow Guard<'compact>, Self) -> Self::Tokenized;
    const FROM: fn(&'reborrow Arena<'life>, Self::Tokenized) -> Self::Untokenized;
}

macro_rules! tokenize {
    ($to:expr, $from:expr) => {
        const TO: fn(&Arena<'life>, &'borrow Guard<'compact>, Self) -> Self::Tokenized = $to;
        const FROM: fn(&'reborrow Arena<'life>, Self::Tokenized) -> Self::Untokenized = $from;
    };
}

struct Foo<'life, 'borrow>(Option<Item<'life, &'borrow mut Bar>>);
struct TokenFoo<'life, 'borrow, 'compact, 'reborrow>(
    Option<Token<'life, 'borrow, 'compact, 'reborrow, Bar>>,
);
struct Bar(u8);

impl<'life, 'before, 'borrow, 'compact, 'reborrow> Tokenize<'life, 'borrow, 'compact, 'reborrow>
    for Foo<'life, 'before>
where
    'compact: 'borrow,
    'life: 'reborrow,
    'life: 'borrow,
    'life: 'compact,
{
    type Tokenized = TokenFoo<'life, 'borrow, 'compact, 'reborrow>;
    type Untokenized = Foo<'life, 'reborrow>;
    tokenize!(foo_to, foo_from);
}

impl<'life, 'borrow, 'compact, 'reborrow> Tokenize<'life, 'borrow, 'compact, 'reborrow> for Bar
where
    'compact: 'borrow,
    'life: 'reborrow,
    'life: 'borrow,
    'life: 'compact,
{
    type Tokenized = Bar;
    type Untokenized = Bar;
    tokenize!(bar_to, bar_from);
}

fn bar_to<'life, 'borrow, 'compact>(
    arena: &Arena<'life>,
    guard: &'borrow Guard<'compact>,
    s: Bar,
) -> Bar {
    s
}
fn bar_from<'life, 'reborrow>(arena: &'reborrow Arena<'life>, s: Bar) -> Bar {
    s
}

fn foo_to<'life, 'borrow, 'compact, 'reborrow, 'before>(
    arena: &'before Arena<'life>,
    guard: &'borrow Guard<'compact>,
    s: Foo<'life, 'before>,
) -> TokenFoo<'life, 'borrow, 'compact, 'reborrow> {
    let Foo(bar) = s;
    TokenFoo(bar.map(|bar| arena.tokenize(guard, bar)))
}
fn foo_from<'life, 'borrow, 'compact, 'reborrow>(
    arena: &'reborrow Arena<'life>,
    s: TokenFoo<'life, 'borrow, 'compact, 'reborrow>,
) -> Foo<'life, 'reborrow> {
    Foo(s.0.map(|bar| panic!()))
}

fn main() {}

Meta

rustc --version --verbose:

rustdoc 1.94.0-nightly (0f0d850e9 2025-12-19)
binary: rustdoc
commit-hash: 0f0d850e9146f53b16fb1c6a56ed2f821962ff94
commit-date: 2025-12-19
host: x86_64-unknown-linux-gnu
release: 1.94.0-nightly
LLVM version: 21.1.8

Error output

rustdoc -Zunstable-options --generate-macro-expansion

<output>
Backtrace

thread 'rustc' (1132107) panicked at compiler/rustc_ast_pretty/src/pprust/state.rs:1728:33:
internal error: entered unreachable code
stack backtrace:
   0:     0x7f113fc0bfe3 - <<std[a1521911952c6a5]::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core[4ea4c2fa426a8d3b]::fmt::Display>::fmt
   1:     0x7f11402106c8 - core[4ea4c2fa426a8d3b]::fmt::write
   2:     0x7f113fc22756 - <std[a1521911952c6a5]::sys::stdio::unix::Stderr as std[a1521911952c6a5]::io::Write>::write_fmt
   3:     0x7f113fbe26d8 - std[a1521911952c6a5]::panicking::default_hook::{closure#0}
   4:     0x7f113fbffe53 - std[a1521911952c6a5]::panicking::default_hook
   5:     0x7f113ebedb57 - std[a1521911952c6a5]::panicking::update_hook::<alloc[5350b0840b7819c6]::boxed::Box<rustc_driver_impl[bdf936d5e37c8e64]::install_ice_hook::{closure#1}>>::{closure#0}
   6:     0x7f113fc00132 - std[a1521911952c6a5]::panicking::panic_with_hook
   7:     0x7f113fbe27ca - std[a1521911952c6a5]::panicking::panic_handler::{closure#0}
   8:     0x7f113fbd7029 - std[a1521911952c6a5]::sys::backtrace::__rust_end_short_backtrace::<std[a1521911952c6a5]::panicking::panic_handler::{closure#0}, !>
   9:     0x7f113fbe434d - __rustc[f25f47d7eb20112d]::rust_begin_unwind
  10:     0x7f113cd0a77c - core[4ea4c2fa426a8d3b]::panicking::panic_fmt
  11:     0x7f113c38c2d2 - core[4ea4c2fa426a8d3b]::panicking::panic
  12:     0x7f11418cc042 - <rustc_ast_pretty[a1609c3b8abb2104]::pprust::state::State>::print_pat
  13:     0x7f113c3fd56a - rustc_ast_pretty[a1609c3b8abb2104]::pprust::pat_to_string
  14:     0x55d3c8770cfc - <rustdoc[83e91a9e8aa8a489]::html::macro_expansion::ExpandedCodeVisitor>::handle_new_span::<<rustdoc[83e91a9e8aa8a489]::html::macro_expansion::ExpandedCodeVisitor as rustc_ast[399afdd0ea17ddac]::visit::Visitor>::visit_pat::{closure#0}>
  15:     0x55d3c8ae1a14 - <rustc_ast[399afdd0ea17ddac]::ast::TyKind as rustc_ast[399afdd0ea17ddac]::visit::Walkable<rustdoc[83e91a9e8aa8a489]::html::macro_expansion::ExpandedCodeVisitor>>::walk_ref
  16:     0x55d3c8ae25f1 - <rustc_ast[399afdd0ea17ddac]::ast::ConstItem as rustc_ast[399afdd0ea17ddac]::visit::Walkable<rustdoc[83e91a9e8aa8a489]::html::macro_expansion::ExpandedCodeVisitor>>::walk_ref
  17:     0x55d3c88fd24f - <rustc_ast[399afdd0ea17ddac]::ast::ItemKind as rustc_ast[399afdd0ea17ddac]::visit::WalkItemKind>::walk::<rustdoc[83e91a9e8aa8a489]::html::macro_expansion::ExpandedCodeVisitor>
  18:     0x55d3c8a2cb9b - rustdoc[83e91a9e8aa8a489]::core::run_global_ctxt
  19:     0x55d3c8921ba3 - rustdoc[83e91a9e8aa8a489]::main_args::{closure#2}::{closure#0}
  20:     0x55d3c891938b - rustc_interface[eb353023e064c6f7]::interface::run_compiler::<(), rustdoc[83e91a9e8aa8a489]::main_args::{closure#2}>::{closure#1}
  21:     0x55d3c8853438 - std[a1521911952c6a5]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[eb353023e064c6f7]::util::run_in_thread_with_globals<rustc_interface[eb353023e064c6f7]::util::run_in_thread_pool_with_globals<rustc_interface[eb353023e064c6f7]::interface::run_compiler<(), rustdoc[83e91a9e8aa8a489]::main_args::{closure#2}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  22:     0x55d3c89491e7 - <std[a1521911952c6a5]::thread::lifecycle::spawn_unchecked<rustc_interface[eb353023e064c6f7]::util::run_in_thread_with_globals<rustc_interface[eb353023e064c6f7]::util::run_in_thread_pool_with_globals<rustc_interface[eb353023e064c6f7]::interface::run_compiler<(), rustdoc[83e91a9e8aa8a489]::main_args::{closure#2}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[4ea4c2fa426a8d3b]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  23:     0x7f11412c0978 - <std[a1521911952c6a5]::sys::thread::unix::Thread>::new::thread_start
  24:     0x7f113ac9698b - <unknown>
  25:     0x7f113ad1a9cc - <unknown>
  26:                0x0 - <unknown>

error: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md

note: please make sure that you have updated to the latest nightly

note: please attach the file at `/home/matthias/vcs/github/rust_misc_stuff/tests/rustc-ice-2025-12-19T12_47_24-1132090.txt` to your bug report

note: compiler flags: -Z unstable-options

query stack during panic:
end of query stack

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions