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

A-link-to-definitionrustdoc --generate-link-to-definition nightly-only featureA-prettyArea: Pretty printing (including `-Z unpretty`)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.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions