#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::zeroed` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn zeroed<T>() -> T {
+ #[cfg(not(stage0))]
+ intrinsics::panic_if_uninhabited::<T>();
intrinsics::init()
}
#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn uninitialized<T>() -> T {
+ #[cfg(not(stage0))]
+ intrinsics::panic_if_uninhabited::<T>();
intrinsics::uninit()
}
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub unsafe fn into_inner(self) -> T {
+ #[cfg(not(stage0))]
+ intrinsics::panic_if_uninhabited::<T>();
ManuallyDrop::into_inner(self.value)
}
_ => bx.new_fn_type(sig, &extra_args)
};
- // emit a panic instead of instantiating an uninhabited type
- if (intrinsic == Some("init") || intrinsic == Some("uninit")) &&
- fn_ty.ret.layout.abi.is_uninhabited()
- {
- let loc = bx.sess().source_map().lookup_char_pos(span.lo());
- let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
- let filename = bx.const_str_slice(filename);
- let line = bx.const_u32(loc.line as u32);
- let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
- let align = tcx.data_layout.aggregate_align.abi
- .max(tcx.data_layout.i32_align.abi)
- .max(tcx.data_layout.pointer_align.abi);
-
- let str = format!(
- "Attempted to instantiate uninhabited type {} using mem::{}",
- sig.output(),
- if intrinsic == Some("init") { "zeroed" } else { "uninitialized" }
- );
- let msg_str = Symbol::intern(&str).as_str();
- let msg_str = bx.const_str_slice(msg_str);
- let msg_file_line_col = bx.const_struct(
- &[msg_str, filename, line, col],
- false,
- );
- let msg_file_line_col = bx.static_addr_of(
- msg_file_line_col,
- align,
- Some("panic_loc"),
- );
+ // emit a panic or a NOP for `panic_if_uninhabited`
+ if intrinsic == Some("panic_if_uninhabited") {
+ let ty = match callee.layout.ty.sty {
+ ty::FnDef(_, substs) => {
+ substs.type_at(0)
+ }
+ _ => bug!("{} is not callable as intrinsic", callee.layout.ty)
+ };
+ let layout = bx.layout_of(ty);
+ if layout.abi.is_uninhabited() {
+ let loc = bx.sess().source_map().lookup_char_pos(span.lo());
+ let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
+ let filename = bx.const_str_slice(filename);
+ let line = bx.const_u32(loc.line as u32);
+ let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
+ let align = tcx.data_layout.aggregate_align.abi
+ .max(tcx.data_layout.i32_align.abi)
+ .max(tcx.data_layout.pointer_align.abi);
+
+ let str = format!(
+ "Attempted to instantiate uninhabited type {}",
+ ty
+ );
+ let msg_str = Symbol::intern(&str).as_str();
+ let msg_str = bx.const_str_slice(msg_str);
+ let msg_file_line_col = bx.const_struct(
+ &[msg_str, filename, line, col],
+ false,
+ );
+ let msg_file_line_col = bx.static_addr_of(
+ msg_file_line_col,
+ align,
+ Some("panic_loc"),
+ );
- // Obtain the panic entry point.
- let def_id =
- common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
- let instance = ty::Instance::mono(bx.tcx(), def_id);
- let fn_ty = bx.fn_type_of_instance(&instance);
- let llfn = bx.get_fn(instance);
-
- // Codegen the actual panic invoke/call.
- do_call(
- self,
- &mut bx,
- fn_ty,
- llfn,
- &[msg_file_line_col],
- destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
- cleanup,
- );
+ // Obtain the panic entry point.
+ let def_id =
+ common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
+ let instance = ty::Instance::mono(bx.tcx(), def_id);
+ let fn_ty = bx.fn_type_of_instance(&instance);
+ let llfn = bx.get_fn(instance);
+
+ // Codegen the actual panic invoke/call.
+ do_call(
+ self,
+ &mut bx,
+ fn_ty,
+ llfn,
+ &[msg_file_line_col],
+ destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
+ cleanup,
+ );
+ } else {
+ // a NOP
+ funclet_br(self, &mut bx, destination.as_ref().unwrap().1);
+ }
return;
}
// This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results
// in a runtime panic.
-#![feature(never_type)]
+#![feature(never_type, maybe_uninit)]
use std::{mem, panic};
panic::catch_unwind(|| {
mem::uninitialized::<!>()
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
- s == "Attempted to instantiate uninhabited type ! using mem::uninitialized"
+ s == "Attempted to instantiate uninhabited type !"
})),
Some(true)
);
panic::catch_unwind(|| {
mem::zeroed::<!>()
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
- s == "Attempted to instantiate uninhabited type ! using mem::zeroed"
+ s == "Attempted to instantiate uninhabited type !"
+ })),
+ Some(true)
+ );
+
+ assert_eq!(
+ panic::catch_unwind(|| {
+ mem::MaybeUninit::<!>::uninitialized().into_inner()
+ }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
+ s == "Attempted to instantiate uninhabited type !"
})),
Some(true)
);
panic::catch_unwind(|| {
mem::uninitialized::<Foo>()
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
- s == "Attempted to instantiate uninhabited type Foo using mem::uninitialized"
+ s == "Attempted to instantiate uninhabited type Foo"
})),
Some(true)
);
panic::catch_unwind(|| {
mem::zeroed::<Foo>()
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
- s == "Attempted to instantiate uninhabited type Foo using mem::zeroed"
+ s == "Attempted to instantiate uninhabited type Foo"
+ })),
+ Some(true)
+ );
+
+ assert_eq!(
+ panic::catch_unwind(|| {
+ mem::MaybeUninit::<Foo>::uninitialized().into_inner()
+ }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
+ s == "Attempted to instantiate uninhabited type Foo"
})),
Some(true)
);
panic::catch_unwind(|| {
mem::uninitialized::<Bar>()
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
- s == "Attempted to instantiate uninhabited type Bar using mem::uninitialized"
+ s == "Attempted to instantiate uninhabited type Bar"
})),
Some(true)
);
panic::catch_unwind(|| {
mem::zeroed::<Bar>()
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
- s == "Attempted to instantiate uninhabited type Bar using mem::zeroed"
+ s == "Attempted to instantiate uninhabited type Bar"
+ })),
+ Some(true)
+ );
+
+ assert_eq!(
+ panic::catch_unwind(|| {
+ mem::MaybeUninit::<Bar>::uninitialized().into_inner()
+ }).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
+ s == "Attempted to instantiate uninhabited type Bar"
})),
Some(true)
);