Description
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