Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICE with inner function #[test_case] #107454

Closed
Evryon75 opened this issue Jan 29, 2023 · 5 comments · Fixed by #109301
Closed

ICE with inner function #[test_case] #107454

Evryon75 opened this issue Jan 29, 2023 · 5 comments · Fixed by #109301
Assignees
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Evryon75
Copy link

Evryon75 commented Jan 29, 2023

Minimized

fn init() {
    #[test_case]
    fn function27() {}
}

Original report

This happens when a test function is declared inside another function, the one where the tests start running to be precise, using a custom testing framework in a no_std environment.

thread 'rustc' panicked at 'expected Item', compiler\rustc_expand\src\base.rs:148:18
stack backtrace:

   0:     0x7ffd3cc89da2 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h51cbe37f66a51707
   1:     0x7ffd3ccc5b0b - core::fmt::write::h5c78deaf4d8a1717
   2:     0x7ffd3cc7ce3a - <std::io::IoSlice as core::fmt::Debug>::fmt::he493d27c141d515f
   3:     0x7ffd3cc89aeb - std::sys::common::alloc::realloc_fallback::h8441730297e6dd3d
   4:     0x7ffd3cc8d499 - std::panicking::default_hook::h1fc51507de475e03
   5:     0x7ffd3cc8d11b - std::panicking::default_hook::h1fc51507de475e03
   6:     0x7ffd256910cf - rustc_driver[f6c6ae1dae99c3a4]::describe_lints
   7:     0x7ffd3cc8ddff - std::panicking::rust_panic_with_hook::h9b4ec48ed01143e7
   8:     0x7ffd3cc8db1b - <std::panicking::begin_panic_handler::StrPanicPayload as core::panic::BoxMeUp>::get::hafe6d61d6276438c
   9:     0x7ffd3cc8aa9f - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h51cbe37f66a51707
  10:     0x7ffd3cc8d810 - rust_begin_unwind
  11:     0x7ffd3ccfb9a5 - core::panicking::panic_fmt::h60c5d107fadefb54
  12:     0x7ffd228566ff - <rustc_expand[d208009879dd3b2d]::base::Annotatable>::expect_item
  13:     0x7ffd25484a57 - <rustc_builtin_macros[3f8ae38c2d7d73a1]::format::PositionUsedAs as core[ac0928afaaba8a6b]::fmt::Debug>::fmt
  14:     0x7ffd239eea5e - <rustc_expand[d208009879dd3b2d]::expand::MacroExpander>::fully_expand_fragment
  15:     0x7ffd2284e0c9 - <rustc_expand[d208009879dd3b2d]::expand::MacroExpander>::expand_crate
  16:     0x7ffd229a8e4c - rustc_interface[eee0500530781d4a]::interface::parse_check_cfg
  17:     0x7ffd229cdc02 - rustc_interface[eee0500530781d4a]::passes::configure_and_expand
  18:     0x7ffd22998531 - <rustc_interface[eee0500530781d4a]::queries::Queries>::expansion
  19:     0x7ffd229990d5 - <rustc_interface[eee0500530781d4a]::queries::Queries>::global_ctxt
  20:     0x7ffd227ad48d - rustc_driver[f6c6ae1dae99c3a4]::args::arg_expand_all
  21:     0x7ffd2279133c - <rustc_data_structures[cc058e1d54c120e6]::temp_dir::MaybeTempDir>::new
  22:     0x7ffd227acc77 - rustc_driver[f6c6ae1dae99c3a4]::args::arg_expand_all
  23:     0x7ffd2279ae63 - <rustc_data_structures[cc058e1d54c120e6]::temp_dir::MaybeTempDir>::new
  24:     0x7ffd227934ad - <rustc_data_structures[cc058e1d54c120e6]::temp_dir::MaybeTempDir>::new
  25:     0x7ffd3cca057c - std::sys::windows::thread::Thread::new::hf27b16c8cd567952
  26:     0x7ffdc2f57614 - BaseThreadInitThunk
  27:     0x7ffdc40626a1 - RtlUserThreadStart

error: internal compiler error: unexpected panic

note: 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-compiler&template=ice.md

note: rustc 1.69.0-nightly (1e225413a 2023-01-28) running on x86_64-pc-windows-msvc

note: compiler flags: -C embed-bitcode=no -C debuginfo=2 -C incremental=[REDACTED] -Z unstable-options

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
end of query stack
@Noratrieb Noratrieb added I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Jan 29, 2023
@Noratrieb
Copy link
Member

Running cargo test on your current master branch (478118744dbf9096e3b0711d02f23fa4488a47f1) doesn't reproduce the issue for me, all tests pass.

@Evryon75
Copy link
Author

Evryon75 commented Jan 29, 2023

Running cargo test on your current master branch (478118744dbf9096e3b0711d02f23fa4488a47f1) doesn't reproduce the issue for me, all tests pass.

That is because the section causing the issue is commented out, if you remove function27 (dont mind the name) from main.rs and replace the comment from the function init() in main.rs with function27, it should reproduce the issue (just checked again)
image
I shouldve pushed and linked a version that reproduces the issue, my bad

@langston-barrett
Copy link

langston-barrett commented Mar 17, 2023

I'm able to reproduce this with nightly

rustc 1.70.0-nightly (511364e78 2023-03-16)
binary: rustc
commit-hash: 511364e7874dba9649a264100407e4bffe7b5425
commit-date: 2023-03-16
host: x86_64-unknown-linux-gnu
release: 1.70.0-nightly
LLVM version: 15.0.7
rustc +nightly --test ice.rs
long file

#![no_std] // Dont use the Rust standard library
#![no_main] // Dont use rust entry points
#![feature(custom_test_frameworks)] // Lines 3, 4, 5: For testing purposes
#![test_runner(clarissa::test_runner)]
#![reexport_test_harness_main = "run_tests"]

use core::fmt;
use core::fmt::Write;
use lazy_static::lazy_static;
use spin::Mutex;
use volatile::Volatile;

// Assigning values to the enums to be used in the ColorCode constructor
#[allow(dead_code)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[repr(u8)] // Displays memory as u8
pub enum Color {
    Black = 0,
    Blue = 1,
    Green = 2,
    Cyan = 3,
    Red = 4,
    Magenta = 5,
    Brown = 6,
    LightGray = 7,
    DarkGray = 8,
    LightBlue = 9,
    LightGreen = 10,
    LightCyan = 11,
    LightRed = 12,
    Pink = 13,
    Yellow = 14,
    White = 15,
}

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct ColorCode(u8);
impl ColorCode {
    pub fn new(background: Color, foreground: Color) -> ColorCode {
        // Bit manipulation operations
        // the first 4 bits are used to specify the background color of the character, the last 4 are used to specify the foreground color
        ColorCode((background as u8) << 4 | (foreground as u8)) // Somehow the enum values were not considered u8, a casting fixed this
    }
}

#[allow(dead_code)]
#[derive(PartialEq, Eq, Copy, Clone)]
struct VgaChar {
    character: u8,
    color: ColorCode,
}

const BUFFER_HEIGHT: usize = 25;
const BUFFER_WIDTH: usize = 80;

struct Buffer {
    // A matrix of characters representing the cga buffer in the gpu ram
    chars: [[Volatile<VgaChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}

pub struct Writer {
    column: usize, // Starting column on the buffer matrix, used to know where the next character should be written
    color: ColorCode,
    buffer: &'static mut Buffer, // Needs to be mutable because we need to write to it
}

impl Writer {
    pub fn write_string(&mut self, s: &str) {
        for byte in s.bytes() {
            match byte {
                0x20..=0x7e | b'\n' => self.write_byte(byte),
                _ => self.write_byte(0xfe),
            }
        }
    }
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.new_line();
        } else {
            let row = BUFFER_HEIGHT - 1;
            let col = self.column;
            self.buffer.chars[row][col + 1].write(VgaChar {
                character: byte,
                color: self.color,
            });
            self.column += 1;
        }
    }
    fn new_line(&mut self) {
        // Shifts the characters written on the buffer up by one row and clears the bottom row
        for row in 1..BUFFER_HEIGHT {
            for col in 0..BUFFER_WIDTH {
                self.buffer.chars[row - 1][col].write(self.buffer.chars[row][col].read())
            }
        }
        for col in 0..BUFFER_WIDTH {
            self.buffer.chars[BUFFER_HEIGHT - 1][col].write(VgaChar {
                character: b' ',
                color: self.color,
            });
        }
        self.column = 0;
    }
    pub fn change_color(&mut self, color: ColorCode) {
        self.color = color
    }
}

impl Write for Writer {
    // Trait that allows formatting arguments
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.write_string(s);
        Ok(()) // We return Ok(()) because with our buffer system we can be sure that we are only performing safe writes to memory
    }
}

// We need a static instance of Writer that is also mutable
lazy_static! {
    pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer {
        column: 0,
        color: ColorCode::new(Color::Black, Color::White),
        // Make a mutable pointer to the vga buffer, dereference it, and borrow it as a mutable Buffer
        buffer: unsafe {&mut *(0xb8000 as *mut Buffer)}
    });
}

#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ($crate::vga_buffer::_print(format_args!($($arg)*)));
}
#[macro_export]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
    WRITER.lock().write_fmt(args).unwrap();
}

#[macro_export]
macro_rules! print_color {
    ($color: expr, $($arg:tt)*) => ($crate::color_macros::_print_color($color, format_args!($($arg)*)));
}
#[macro_export]
macro_rules! println_color {
    () => ($crate::print!("\n"));
    ($color: expr, $($arg:tt)*) => ($crate::print_color!($color, "{}\n", format_args!($($arg)*)));
}
#[doc(hidden)]
pub fn _print_color(color: ColorCode, args: fmt::Arguments) {
    WRITER.lock().change_color(color);
    WRITER.lock().write_fmt(args).unwrap();
    WRITER.lock().change_color(ColorCode::new(Black, White));
}
#[macro_export]
macro_rules! blackln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Black), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! blueln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Blue), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! greenln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Green), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! cyanln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Cyan), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! redln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Red), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! magentaln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Magenta), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! brownln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Brown), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! lightgrayln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, LightGray), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! darkgrayln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, DarkGray), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! lightblueln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, LightBlue), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! lightgreenln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, LightGreen), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! lightcyanln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, LightCyan), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! lightredln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, LightRed), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! pinkln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Pink), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! yellowln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, Yellow), "{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! whiteln {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ($crate::print_color!(ColorCode::new(Black, White), "{}\n", format_args!($($arg)*)));
}

const VER: &str = "0.2.0"; // y.x.z = Section Z from chapter X, if Y is 0 the guide isn't finished, if its 1 or above it is
const NAME: &str = "try to remove old commits without breaking\nEVERYTHINNG CHALLENGE [IMPOSSOBLE 0.000000001% ONLY]";

// reminder of what mangling is: https://en.wikipedia.org/wiki/Name_mangling
#[no_mangle] // Dont mangle the function name
pub extern "C" fn _start() -> ! {
    init();
    loop {}
}

// Panic function
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
    // Modern registry for kernel panics 😌
    lightredln!("Bruh moment! {}", _info);
    loop {}
}

#[test_case]
fn function27() {
    return ();
}
fn init() {
    redln!("Clarissa");
    darkgrayln!("        \\\\");
    lightgrayln!("          Ver {} - {}", VER, NAME);

    #[test_case]
    fn function27() {
        return ();
    }

    #[cfg(test)]
    println_serial!("\n          [main.rs]");
    #[cfg(test)]
    run_tests();
}

// Plans: Make tetris IN the operating system insanity

@langston-barrett
Copy link

langston-barrett commented Mar 17, 2023

Got it down to this:

fn init() {
    #[test_case]
    fn function27() {}
}

using icemelter ice.rs -- rustc +nightly --test (see icemelter).

@Noratrieb Noratrieb changed the title When running cargo test, internal compiler error: unexpected panic ICE with inner function #[test_case] Mar 17, 2023
@Noratrieb Noratrieb added the S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue label Mar 17, 2023
@Ezrashaw
Copy link
Contributor

@rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants