Skip to content

rustc panics during compilation #23217

Closed
Closed
@CtrlZvi

Description

@CtrlZvi

I tried this code:

#![feature(core, libc, os, unicode)]
extern crate libc;
extern crate unicode;

use std::mem;
use std::num::ToPrimitive;
use std::os;

#[cfg(target_family = "windows")]
#[link(name = "kernel32")]
#[allow(non_snake_case)]
extern "system" {
    fn SetEnvironmentVariableW(lpName : *const ::libc::wchar_t, lpValue: *const ::libc::wchar_t) -> ::libc::c_int;
    fn GetModuleHandleW(lpModuleName : *const ::libc::wchar_t) -> HINSTANCE;
}

#[stable]
pub fn get_module_handle(name: Option<&str>) -> Result<Module, String> {
    let handle = match name {
        Some(val) => {
            let n = unicode::str::Utf16Encoder::new(val.chars()).collect::<Vec<::libc::wchar_t>>();
            unsafe { GetModuleHandleW(n.as_ptr()) }
        },
        None => unsafe { GetModuleHandleW(0 as *const ::libc::wchar_t) },
    };
    match handle {
        val if val != 0 as HINSTANCE => Ok(Module { handle : val }),
        _ => Err(os::last_os_error()),
    }
}

#[stable]
pub fn set_environment_variable(name: &str, value: &str) -> Result<(), String> {
    let n = unicode::str::Utf16Encoder::new(name.chars()).collect::<Vec<::libc::wchar_t>>();
    let v = unicode::str::Utf16Encoder::new(value.chars()).collect::<Vec<::libc::wchar_t>>();
    let error = unsafe { SetEnvironmentVariableW(n.as_ptr(), v.as_ptr()) };
    match error {
        0 => Err(os::last_os_error()),
        _ => Ok(()),
    }
}

type HANDLE = *mut ::libc::c_void;
type HWND = HANDLE;
type HMENU = HANDLE;
type HINSTANCE = HANDLE;
type HICON = HANDLE;
type HCURSOR = HANDLE;
type HBRUSH = HANDLE;
pub type WNDPROC = extern "system" fn(HWND, u32, ::libc::uintptr_t, ::libc::uintptr_t) -> ::libc::uintptr_t;

#[repr(C)]
#[allow(non_snake_case)]
struct WNDCLASSEX {
    cbSize : ::libc::c_uint,
    style : ::libc::c_uint,
    lpfnWndProc : WNDPROC,
    cbClsExtra : ::libc::c_int,
    cbWndExtra : ::libc::c_int,
    hInstance : HINSTANCE,
    hIcon : HICON,
    hCursor : HCURSOR,
    hbrBackground : HBRUSH,
    lpszMenuName : *const ::libc::wchar_t,
    lpszClassName : *const ::libc::wchar_t,
    hIconSm : HICON,
}

#[repr(C)]
#[allow(non_snake_case)]
struct POINT {
    x : ::libc::c_long,
    y : ::libc::c_long,
}

#[repr(C)]
#[allow(non_snake_case)]
struct MSG {
    hwnd : HWND,
    message : ::libc::c_uint,
    wParam : ::libc::uintptr_t,
    lParam : ::libc::uintptr_t,
    time : u32,
    pt : POINT,
}

#[cfg(target_family = "windows")]
#[link(name = "user32")]
#[allow(non_snake_case)]
extern "system" {
    fn CreateWindowExW(dwExStyle: u32, lpClassName: *const ::libc::wchar_t, lpWindowName: *const ::libc::wchar_t, dwStyle: u32, x: ::libc::c_int, y: ::libc::c_int, nWidth: ::libc::c_int, nHeight: ::libc::c_int, hWndParent: HWND, hMenu : HMENU, hInstance : HINSTANCE, lpParam : *mut ::libc::c_void) -> HWND;
    fn ShowWindow(hWnd : HWND, nCmdShow : ::libc::c_int) -> ::libc::c_int;
    fn RegisterClassExW(lpwcx : *const WNDCLASSEX) -> u16;
    fn GetMessageW(lpMsg : *mut MSG, hWnd : HWND, wMsgFilterMin : ::libc::c_uint, wMsgFilterMax : ::libc::c_uint) -> ::libc::c_int;
    fn TranslateMessage(lpMsg : *const MSG) -> ::libc::c_int;
    fn DispatchMessageW(lpMsg : *const MSG) -> ::libc::uintptr_t;
    fn DefWindowProcW(hWnd : HWND, Msg : u32, wParam : ::libc::uintptr_t, lParam : ::libc::uintptr_t) -> ::libc::uintptr_t;
}

#[unstable]
pub fn default_window_procedure(window_handle : *mut ::libc::c_void, message_identifier : u32, parameter1 : ::libc::uintptr_t, parameter2 : ::libc::uintptr_t) -> ::libc::uintptr_t {
    unsafe { DefWindowProcW(window_handle, message_identifier, parameter1, parameter2) }
}

pub struct Message {
    message : MSG,
    pub number : ::libc::c_uint,
}

#[unstable]
pub fn show_window(window : &Window, show_command : ::libc::c_int) -> bool {
    match unsafe { ShowWindow(window.handle, show_command) } {
        0 => true,
        _ => false,
    }
}

#[unstable]
pub fn get_message(window : Option<&Window>, message_filter_minimum : ::libc::c_uint, message_filter_maximum : ::libc::c_uint) -> Result<Message, String> {
    let mut message = MSG {
        hwnd : 0 as HWND,
        message : 0,
        wParam : 0,
        lParam : 0,
        time : 0,
        pt : POINT { x : 0, y : 0 },
    };
    let result = unsafe { GetMessageW(
        &mut message,
        match window {
            Some(val) => val.handle,
            None => 0 as HWND,
        },
        message_filter_minimum,
        message_filter_maximum
    ) };
    match result {
        -1 => Err(os::last_os_error()),
        0 => Ok(Message { number : message.message, message : message }), // TODO(zeffron 2015 03 03) Figure out how to indicate WM_QUIT without requiring the user to read the message number (probably via Enum)
        _ => Ok(Message { number : message.message, message : message,  }),
    }
}

#[unstable]
pub fn translate_message(message : &Message) -> bool {
    let result = unsafe { TranslateMessage(&message.message) };
    match result {
        0 => false,
        _ => true,
    }
}

#[unstable]
pub fn dispatch_message(message : &Message) -> ::libc::uintptr_t {
    unsafe { DispatchMessageW(&message.message) }
}    

pub struct WindowClassExtended {
    pub style : ::libc::c_uint,
    pub window_procedure : WNDPROC,
    pub class_extra : ::libc::c_int,
    pub window_extra : ::libc::c_int,
    pub module : Option<Module>,
    pub icon : Option<Icon>,
    pub cursor : Option<Cursor>,
    pub background_brush : Option<Brush>,
    pub menu_name : String,
    pub class_name : String,
    pub small_icon : Option<Icon>,
}

#[unstable]
pub fn register_class_extended(class : WindowClassExtended) -> Result<u16, String> {
    let window_class = WNDCLASSEX {
        cbSize : mem::size_of::<WNDCLASSEX>().to_u32().unwrap(),
        style : class.style,
        lpfnWndProc : class.window_procedure,
        cbClsExtra : class.class_extra,
        cbWndExtra : class.window_extra,
        hInstance : match class.module {
            Some(val) => val.handle,
            None => 0 as *mut ::libc::c_void,
        },
        hIcon : match class.icon {
            Some(val) => val.handle,
            None => 0 as *mut ::libc::c_void,
        },
        hCursor : match class.cursor {
            Some(val) => val.handle,
            None => 0 as *mut ::libc::c_void,
        },
        hbrBackground : match class.background_brush {
            Some(val) => val.handle,
            None => 0 as *mut ::libc::c_void,
        },
        lpszMenuName : unicode::str::Utf16Encoder::new(class.menu_name.chars()).collect::<Vec<::libc::wchar_t>>().as_ptr(),
        lpszClassName : unicode::str::Utf16Encoder::new(class.class_name.chars()).collect::<Vec<::libc::wchar_t>>().as_ptr(),
        hIconSm : match class.small_icon {
            Some(val) => val.handle,
            None => 0 as *mut ::libc::c_void,
        },
    };
    let atom = unsafe { RegisterClassExW(&window_class) };
    match atom {
        0 =>  Err(os::last_os_error()),
        val => Ok(val),
    }
}

pub struct Window {
    handle : HWND,
}

pub struct Menu {
    handle : HMENU,
}

pub struct Module {
    handle : HINSTANCE,
}

pub struct Icon {
    handle : HICON,
}

pub struct Cursor {
    handle : HCURSOR,
}

pub struct Brush {
    handle : HBRUSH,
}

const CW_USEDEFAULT : ::libc::c_int = -0x80000000;

#[unstable]
pub fn create_window_extended(extended_style: u32, class_name: Option<&str>, window_name: Option<&str>, style: u32, x: Option<::libc::c_int>, y: Option<::libc::c_int>, width: Option<::libc::c_int>, height: Option<::libc::c_int>, parent_window : Option<&Window>, menu : Option<&Menu>, module : Option<&Module>) -> Result<Window, String> {
    let window_handle = unsafe { CreateWindowExW(
        extended_style,
        match class_name {
            Some(val) => unicode::str::Utf16Encoder::new(val.chars()).collect::<Vec<::libc::wchar_t>>().as_ptr(),
            None => 0 as *const ::libc::wchar_t,
        },
        match window_name {
            Some(val) => unicode::str::Utf16Encoder::new(val.chars()).collect::<Vec<::libc::wchar_t>>().as_ptr(),
            None => 0 as *const ::libc::wchar_t,
        },
        style,
        match x {
            Some(val) => val,
            None => CW_USEDEFAULT,
        },
        match y {
            Some(val) => val,
            None => CW_USEDEFAULT,
        },
        match width {
            Some(val) => val,
            None => CW_USEDEFAULT,
        },
        match height {
            Some(val) => val,
            None => CW_USEDEFAULT,
        },
        match parent_window {
            Some(val) => val.handle,
            None => 0 as HWND,
        },
        match menu {
            Some(val) => val.handle,
            None => 0 as HMENU,
        },
        match module{
            Some(val) => val.handle,
            None => 0 as HINSTANCE,
        },
        0 as *mut ::libc::c_void
    )};
    match window_handle {
        val if val == 0 as HWND => Err(os::last_os_error()),
        val => Ok(Window { handle : val as *mut ::libc::c_void }),
    }
}

#[stable]
#[repr(u32)]
pub enum ClassStyle {
    VerticalRedraw = 0x0001,
    HorizontalRedraw = 0x0002,
    DoubleClicks = 0x0008,
    OwnDeviceContext = 0x0020,
    ClassDeviceContext = 0x0040,
    ParentDeviceContext = 0x0080,
    NoClose = 0x0200,
    SaveBits = 0x0800,
    ByteAlignClient = 0x1000,
    ByteAlignWindow = 0x2000,
    GlobalClass = 0x4000,
    DropShadow = 0x00020000,
}

#[stable]
#[repr(u32)]
pub enum WindowStyle {
    Border = 0x00800000,
    Caption = 0x00C00000,
    Child = 0x40000000,
    ClipChildren = 0x02000000,
    ClipSiblings = 0x04000000,
    Disabled = 0x08000000,
    DialogFrame = 0x00400000,
    Group = 0x00020000,
    HorizontalScrollBar = 0x00100000,
    Maximize = 0x01000000,
    MaximizeBox = 0x00010000 | WindowStyle::SystemMenu as u32,
    Minimize = 0x20000000,
    MinimizeBox = 0x00020000 | WindowStyle::SystemMenu as u32,
    Overlapped = 0x00000000,
    OverlappedWindow = WindowStyle::Overlapped as u32 | WindowStyle::Caption as u32 | WindowStyle::SystemMenu as u32 | WindowStyle::ThickFrame as u32 | WindowStyle::MinimizeBox as u32 | WindowStyle::MaximizeBox as u32,
    Popup = 0x80000000,
    PopupWindow = WindowStyle::Popup as u32 | WindowStyle::Border as u32 | WindowStyle::SystemMenu as u32,
    SizeBox = 0x00040000,
    SystemMenu = 0x00080000,
    TabStop = 0x00010000,
    Visible = 0x10000000,
    VerticalScrollBar = 0x00200000,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_get_module_handle_current_module() {
        assert!(match get_module_handle(None) {
            Ok(_) => true,
            Err(_) => false,
        });
    }

    #[test]
    fn test_get_module_handle_unknown_module() {
        assert!(match get_module_handle("foo") {
            Ok(_) => false,
            Err(_) => true,
        });
    }

    #[test]
    fn test_set_environment_variable() {
        use std::env;

        let name = "key";
        let value = "value";
        assert!(set_environment_variable(name, value) == Ok(()));
        assert!(env::var(name) == Ok(value.to_string()));
    }

    #[test]
    fn test_register_class_extended() {
        extern "system" fn window_procedure(window_handle : *mut ::libc::c_void, message_identifier : u32, parameter1 : ::libc::uintptr_t, parameter2 : ::libc::uintptr_t) -> ::libc::uintptr_t {
            match message_identifier {
                _ => default_window_procedure(window_handle, message_identifier, parameter1, parameter2)
            }
        }
        let window_class = WindowClassExtended {
            style : 0,
            window_procedure : window_procedure,
            class_extra : 0,
            window_extra : 0,
            module : None,
            icon : None,
            cursor : None,
            background_brush : None,
            menu_name : "".to_string(),
            class_name : "RustSampleWindowClass".to_string(),
            small_icon : None,
        };
        let atom = register_class_extended(window_class);
        assert!(match atom {
            Ok(_) => true,
            Err(_) => false,
        });
    }
}

Then ran this command:

rustc minimumrepro.rs --crate-name win32 --crate-type lib -g --emit=dep-info,link --verbose

I expected to see successful compilation followed by tests running.

Instead, this happened:

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/blob/m
aster/CONTRIBUTING.md#bug-reports
note: run with `RUST_BACKTRACE=1` for a backtrace
thread 'rustc' panicked at 'path not fully resolved: PathResolution { base_def:
DefTy(DefId { krate: 0, node: 894 }, true), last_private: LastMod(AllPublic), de
pth: 1 }', C:/bot/slave/nightly-dist-rustc-win-64/build/src/librustc\middle\def.
rs:79

stack backtrace:
   1:         0x71217094 - sys::backtrace::write::h669f8e0f2a2c73f7UVA
   2:         0x71231708 - rt::unwind::register::hcda86f4971e7940bZpJ
   3:         0x71183427 - rt::unwind::begin_unwind_inner::ha77dc9ac3cfb5574onJ
   4:         0x71183beb - rt::unwind::begin_unwind_fmt::h8ea5d25622c032c4ZlJ
   5:          0x15991f7 - middle::const_eval::eval_const_expr_partial::ha9d8d88f013a10ad7lh
   6:          0x1597788 - middle::const_eval::eval_const_expr_partial::ha9d8d88f013a10ad7lh
   7:          0x1597baa - middle::const_eval::eval_const_expr_partial::ha9d8d88f013a10ad7lh

Meta

rustc --version --verbose:
rustc 1.0.0-nightly (2fc8b1e 2015-03-07) (built 2015-03-08)
binary: rustc
commit-hash: 2fc8b1e
commit-date: 2015-03-07
build-date: 2015-03-08
host: x86_64-pc-windows-gnu
release: 1.0.0-nightly

Backtrace:
1: 0x71217094 - sys::backtrace::write::h669f8e0f2a2c73f7UVA
2: 0x71231708 - rt::unwind::register::hcda86f4971e7940bZpJ
3: 0x71183427 - rt::unwind::begin_unwind_inner::ha77dc9ac3cfb5574onJ
4: 0x71183beb - rt::unwind::begin_unwind_fmt::h8ea5d25622c032c4ZlJ
5: 0x15991f7 - middle::const_eval::eval_const_expr_partial::ha9d8d88f013a10ad7lh
6: 0x1597788 - middle::const_eval::eval_const_expr_partial::ha9d8d88f013a10ad7lh
7: 0x1597baa - middle::const_eval::eval_const_expr_partial::ha9d8d88f013a10ad7lh

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyE-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions