Skip to content

ICE: TooGeneric when set opt-level=1Β #101

@makai410

Description

@makai410

Minimal reproducible example

#![feature(rustc_private)]

extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;

use std::io::Write;
use std::ops::ControlFlow;
use rustc_smir::rustc_internal;

const CRATE_NAME: &str = "ice";

fn test() -> ControlFlow<()> {
    let local = stable_mir::local_crate();
    for def in local.fn_defs() {
        let _ = def.body();
    }

    ControlFlow::Continue(())
}

fn main() {
    let path = "input.rs";
    generate_input(&path).unwrap();
    let args = &[
        "rustc".to_string(),
        "-Copt-level=1".to_string(),
        "--crate-type=lib".to_string(),
        "--crate-name".to_string(),
        CRATE_NAME.to_string(),
        path.to_string(),
    ];
    run!(args.to_vec(), test).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {
    let mut file = std::fs::File::create(path)?;
    write!(
        file,
        r#"
        #![allow(dead_code, unused_variables)]
        use std::fmt::Debug;

        pub trait Meow<A: Clone + Debug> {{
            fn foo(&self, a: Option<&A>) -> A;

            fn fzz(&self) -> A {{
                self.foo(None)
            }}
        }}

        fn main() {{}}
    "#
    )?;
    Ok(())
}

Backtrace

thread 'rustc' panicked at compiler/rustc_smir/src/rustc_smir/alloc.rs:30:10:
Failed to convert: Scalar(0x0000000000000000) to std::option::Option<&'{erased} A/#1>: Error("TooGeneric(Alias(Projection, AliasTy { args: [A/#1], def_id: DefId(2:2374 ~ core[9e5e]::ptr::metadata::Pointee::Metadata), .. }))")
stack backtrace:
   0: rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::result::unwrap_failed
   3: rustc_smir::rustc_smir::alloc::new_allocation
   4: <rustc_middle::mir::consts::Const as rustc_smir::rustc_smir::Stable>::stable
   5: <rustc_middle::mir::syntax::Operand as rustc_smir::rustc_smir::Stable>::stable
   6: <rustc_middle::mir::syntax::TerminatorKind as rustc_smir::rustc_smir::Stable>::stable
   7: <rustc_middle::mir::terminator::Terminator as rustc_smir::rustc_smir::Stable>::stable
   8: <rustc_middle::mir::Body as rustc_smir::rustc_smir::Stable>::stable
   9: <rustc_smir::rustc_smir::context::TablesWrapper as stable_mir::compiler_interface::Context>::mir_body
  10: <stable_mir::ty::FnDef>::body
  11: reprod::test
             at ./reprod/src/main.rs:19:17
  12: reprod::main::{{closure}}
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:279:31
  13: <reprod::main::StableMir<B,C,F> as rustc_driver_impl::Callbacks>::after_analysis::{{closure}}
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:386:44
  14: rustc_smir::rustc_internal::init::{{closure}}
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:196:33
  15: scoped_tls::ScopedKey<T>::set
             at /rust/deps/scoped-tls-1.0.1/src/lib.rs:137:9
  16: rustc_smir::rustc_internal::init
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:196:5
  17: rustc_smir::rustc_internal::run::{{closure}}
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:227:53
  18: stable_mir::compiler_interface::run::{{closure}}
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/stable_mir/src/compiler_interface.rs:268:40
  19: scoped_tls::ScopedKey<T>::set
             at /rust/deps/scoped-tls-1.0.1/src/lib.rs:137:9
  20: stable_mir::compiler_interface::run
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/stable_mir/src/compiler_interface.rs:268:9
  21: rustc_smir::rustc_internal::run
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:227:5
  22: <reprod::main::StableMir<B,C,F> as rustc_driver_impl::Callbacks>::after_analysis
             at /home/gh-makai410/.rustup/toolchains/nightly-2025-03-02-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/compiler/rustc_smir/src/rustc_internal/mod.rs:385:21
  23: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}
  24: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Context

When compiling with -Copt-level=1, rustc optimizes the None parameter in self.foo(None) into const transmute(0): Option<&A>, while the unoptimized version generates a temporary variable to pass Option::<&A>::None.

The unoptimized mir output:

// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
// HINT: See also -Z dump-mir for MIR at specific points during compilation.
fn Meow::fzz(_1: &Self) -> A {
    debug self => _1;
    let mut _0: A;
    let mut _2: std::option::Option<&A>;

    bb0: {
        _2 = Option::<&A>::None;
        _0 = <Self as Meow<A>>::foo(copy _1, move _2) -> [return: bb1, unwind continue];
    }

    bb1: {
        return;
    }
}

fn main() -> () {
    let mut _0: ();

    bb0: {
        return;
    }
}

with -Copt-level=1:

// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
// HINT: See also -Z dump-mir for MIR at specific points during compilation.
fn Meow::fzz(_1: &Self) -> A {
    debug self => _1;
    let mut _0: A;

    bb0: {
        _0 = <Self as Meow<A>>::foo(move _1, const {transmute(0x0000000000000000): Option<&A>}) -> [return: bb1, unwind continue];
    }

    bb1: {
        return;
    }
}

fn main() -> () {
    let mut _0: ();

    bb0: {
        return;
    }
}

Possibly related code

https://github.com/rust-lang/rust/blob/c43786c9b7b8d8dcc3f9c604e0e3074c16ed69d3/compiler/rustc_smir/src/rustc_smir/alloc.rs#L45-L56

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions