drop(linker);
save_temp_bitcode(cgcx, &module, "lto.input");
- // Fat LTO also suffers from the invalid DWARF issue similar to Thin LTO.
- // Here we rewrite all `DICompileUnit` pointers if there is only one `DICompileUnit`.
- // This only works around the problem when codegen-units = 1.
- // Refer to the comments in the `optimize_thin_module` function for more details.
- let mut cu1 = ptr::null_mut();
- let mut cu2 = ptr::null_mut();
- unsafe { llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2) };
- if !cu2.is_null() {
- let _timer =
- cgcx.prof.generic_activity_with_arg("LLVM_fat_lto_patch_debuginfo", &*module.name);
- unsafe { llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1) };
- save_temp_bitcode(cgcx, &module, "fat-lto-after-patch");
- }
-
// Internalize everything below threshold to help strip out more modules and such.
unsafe {
let ptr = symbols_below_threshold.as_ptr();
// an error.
let mut cu1 = ptr::null_mut();
let mut cu2 = ptr::null_mut();
- llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
+ llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
if !cu2.is_null() {
let msg = "multiple source DICompileUnits found";
return Err(write::llvm_err(&diag_handler, msg));
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
- llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1);
+ llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
}
len: usize,
out_len: &mut usize,
) -> *const u8;
- pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void);
- pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
+ pub fn LLVMRustThinLTOGetDICompileUnit(
+ M: &Module,
+ CU1: &mut *mut c_void,
+ CU2: &mut *mut c_void,
+ );
+ pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
pub fn LLVMRustLinkerAdd(
// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
// the comment in `back/lto.rs` for why this exists.
extern "C" void
-LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod,
+LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
DICompileUnit **A,
DICompileUnit **B) {
Module *M = unwrap(Mod);
// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
// the comment in `back/lto.rs` for why this exists.
extern "C" void
-LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
+LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
Module *M = unwrap(Mod);
// If the original source module didn't have a `DICompileUnit` then try to
/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations.
///
/// These locals have fixed storage for the duration of the body.
-//
-// FIXME: Currently, we need to traverse the entire MIR to compute this. We should instead store it
-// as a field in the `LocalDecl` for each `Local`.
pub fn always_storage_live_locals(body: &mir::Body<'_>) -> BitSet<Local> {
let mut always_live_locals = BitSet::new_filled(body.local_decls.len());
/// [`Layout`]: crate::Layout
#[stable(feature = "box_raw", since = "1.4.0")]
#[inline]
+ #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `Box`"]
pub unsafe fn from_raw(raw: *mut T) -> Self {
unsafe { Self::from_raw_in(raw, Global) }
}
/// and other memory errors.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
-#[unstable(feature = "alloc_c_string", issue = "94079")]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub struct CString {
// Invariant 1: the slice ends with a zero byte and has a length of at least one.
// Invariant 2: the slice contains only one zero byte.
/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
-#[unstable(feature = "alloc_c_string", issue = "94079")]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub struct NulError(usize, Vec<u8>);
#[derive(Clone, PartialEq, Eq, Debug)]
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
-#[unstable(feature = "alloc_c_string", issue = "94079")]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub struct FromVecWithNulError {
error_kind: FromBytesWithNulErrorKind,
bytes: Vec<u8>,
/// This `struct` is created by [`CString::into_string()`]. See
/// its documentation for more.
#[derive(Clone, PartialEq, Eq, Debug)]
-#[unstable(feature = "alloc_c_string", issue = "94079")]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub struct IntoStringError {
inner: CString,
error: Utf8Error,
//! [`String`]: crate::string::String
//! [`CStr`]: core::ffi::CStr
-#![unstable(feature = "alloc_ffi", issue = "94079")]
+#![stable(feature = "alloc_ffi", since = "1.64.0")]
-#[unstable(feature = "alloc_c_string", issue = "94079")]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub use self::c_str::FromVecWithNulError;
-#[unstable(feature = "alloc_c_string", issue = "94079")]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub use self::c_str::{CString, IntoStringError, NulError};
mod c_str;
#![allow(explicit_outlives_requirements)]
//
// Library features:
-#![cfg_attr(not(no_global_oom_handling), feature(alloc_c_string))]
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(const_maybe_uninit_write)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_refs_to_cell)]
-#![feature(core_c_str)]
#![feature(core_intrinsics)]
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(const_nonnull_slice_from_raw_parts)]
#![feature(const_ptr_write)]
#![feature(const_try)]
-#![feature(core_c_str)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
/// [str]: prim@str "str"
#[derive(Hash)]
#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")]
-#[unstable(feature = "core_c_str", issue = "94079")]
+#[stable(feature = "core_c_str", since = "1.64.0")]
#[rustc_has_incoherent_inherent_impls]
// FIXME:
// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
-#[unstable(feature = "core_c_str", issue = "94079")]
+#[stable(feature = "core_c_str", since = "1.64.0")]
pub struct FromBytesWithNulError {
kind: FromBytesWithNulErrorKind,
}
use crate::num::*;
use crate::ops::{Deref, DerefMut};
-#[unstable(feature = "core_c_str", issue = "94079")]
+#[stable(feature = "core_c_str", since = "1.64.0")]
pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError};
mod c_str;
#![stable(feature = "rust1", since = "1.0.0")]
-/// See [alloc::ffi::FromVecWithNulError].
-#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
-pub type FromVecWithNulError = alloc::ffi::FromVecWithNulError;
-/// See [alloc::ffi::CString].
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type CString = alloc::ffi::CString;
-/// See [alloc::ffi::IntoStringError].
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type IntoStringError = alloc::ffi::IntoStringError;
-/// See [alloc::ffi::NulError].
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type NulError = alloc::ffi::NulError;
-/// See [core::ffi::CStr].
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type CStr = core::ffi::CStr;
-/// See [core::ffi::FromBytesWithNulError].
-#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-pub type FromBytesWithNulError = core::ffi::FromBytesWithNulError;
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
+pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
+#[stable(feature = "core_c_str", since = "1.64.0")]
+pub use core::ffi::{CStr, FromBytesWithNulError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsStr, OsString};
/// This function will create a file if it does not exist,
/// and will entirely replace its contents if it does.
///
+/// Depending on the platform, this function may fail if the
+/// full directory path does not exist.
+///
/// This is a convenience function for using [`File::create`] and [`write_all`]
/// with fewer imports.
///
/// This function will create a file if it does not exist,
/// and will truncate it if it does.
///
+ /// Depending on the platform, this function may fail if the
+ /// full directory path does not exist.
+ ///
/// See the [`OpenOptions::open`] function for more details.
///
/// # Examples
}
}
+ /// Attempt to downgrade the inner error to `E` if any.
+ ///
+ /// If this [`Error`] was constructed via [`new`] then this function will
+ /// attempt to perform downgrade on it, otherwise it will return [`Err`].
+ ///
+ /// If downgrade succeeds, it will return [`Ok`], otherwise it will also
+ /// return [`Err`].
+ ///
+ /// [`new`]: Error::new
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(io_error_downcast)]
+ ///
+ /// use std::fmt;
+ /// use std::io;
+ /// use std::error::Error;
+ ///
+ /// #[derive(Debug)]
+ /// enum E {
+ /// Io(io::Error),
+ /// SomeOtherVariant,
+ /// }
+ ///
+ /// impl fmt::Display for E {
+ /// // ...
+ /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ /// # todo!()
+ /// # }
+ /// }
+ /// impl Error for E {}
+ ///
+ /// impl From<io::Error> for E {
+ /// fn from(err: io::Error) -> E {
+ /// err.downcast::<E>()
+ /// .map(|b| *b)
+ /// .unwrap_or_else(E::Io)
+ /// }
+ /// }
+ /// ```
+ #[unstable(feature = "io_error_downcast", issue = "99262")]
+ pub fn downcast<E>(self) -> result::Result<Box<E>, Self>
+ where
+ E: error::Error + Send + Sync + 'static,
+ {
+ match self.repr.into_data() {
+ ErrorData::Custom(b) if b.error.is::<E>() => {
+ let res = (*b).error.downcast::<E>();
+
+ // downcast is a really trivial and is marked as inline, so
+ // it's likely be inlined here.
+ //
+ // And the compiler should be able to eliminate the branch
+ // that produces `Err` here since b.error.is::<E>()
+ // returns true.
+ Ok(res.unwrap())
+ }
+ repr_data => Err(Self { repr: Repr::new(repr_data) }),
+ }
+ }
+
/// Returns the corresponding [`ErrorKind`] for this error.
///
/// # Examples
unsafe impl Sync for Repr {}
impl Repr {
+ pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self {
+ match dat {
+ ErrorData::Os(code) => Self::new_os(code),
+ ErrorData::Simple(kind) => Self::new_simple(kind),
+ ErrorData::SimpleMessage(simple_message) => Self::new_simple_message(simple_message),
+ ErrorData::Custom(b) => Self::new_custom(b),
+ }
+ }
+
pub(super) fn new_custom(b: Box<Custom>) -> Self {
let p = Box::into_raw(b).cast::<u8>();
// Should only be possible if an allocator handed out a pointer with
pub(super) struct Repr(Inner);
impl Repr {
+ #[inline]
+ pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self {
+ Self(dat)
+ }
pub(super) fn new_custom(b: Box<Custom>) -> Self {
Self(Inner::Custom(b))
}
-use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr};
+use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage};
use crate::assert_matches::assert_matches;
use crate::error;
use crate::fmt;
}) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)),
);
}
+
+#[derive(Debug)]
+struct E;
+
+impl fmt::Display for E {
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Ok(())
+ }
+}
+
+impl error::Error for E {}
+
+#[test]
+fn test_std_io_error_downcast() {
+ // Case 1: custom error, downcast succeeds
+ let io_error = Error::new(ErrorKind::Other, Bojji(true));
+ let e: Box<Bojji> = io_error.downcast().unwrap();
+ assert!(e.0);
+
+ // Case 2: custom error, downcast fails
+ let io_error = Error::new(ErrorKind::Other, Bojji(true));
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ // ensures that the custom error is intact
+ assert_eq!(ErrorKind::Other, io_error.kind());
+ let e: Box<Bojji> = io_error.downcast().unwrap();
+ assert!(e.0);
+
+ // Case 3: os error
+ let errno = 20;
+ let io_error = Error::from_raw_os_error(errno);
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ assert_eq!(errno, io_error.raw_os_error().unwrap());
+
+ // Case 4: simple
+ let kind = ErrorKind::OutOfMemory;
+ let io_error: Error = kind.into();
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ assert_eq!(kind, io_error.kind());
+
+ // Case 5: simple message
+ const SIMPLE_MESSAGE: SimpleMessage =
+ SimpleMessage { kind: ErrorKind::Other, message: "simple message error test" };
+ let io_error = Error::from_static_message(&SIMPLE_MESSAGE);
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind());
+ assert_eq!(SIMPLE_MESSAGE.message, &*format!("{io_error}"));
+}
#![feature(atomic_mut_ptr)]
#![feature(char_error_internals)]
#![feature(char_internals)]
-#![feature(core_c_str)]
#![feature(core_intrinsics)]
#![feature(cstr_from_bytes_until_nul)]
#![feature(cstr_internals)]
//
// Library features (alloc):
#![feature(alloc_layout_extra)]
-#![feature(alloc_c_string)]
-#![feature(alloc_ffi)]
#![feature(allocator_api)]
#![feature(get_mut_unchecked)]
#![feature(map_try_insert)]
// Used only internally to construct a thread object without spawning
// Panics if the name contains nuls.
pub(crate) fn new(name: Option<CString>) -> Thread {
- // We have to use `unsafe` here to constuct the `Parker` in-place,
+ // We have to use `unsafe` here to construct the `Parker` in-place,
// which is required for the UNIX implementation.
//
// SAFETY: We pin the Arc immediately after creation, so its address never
--- /dev/null
+// Caveat - gdb doesn't know about UTF-32 character encoding and will print a
+// rust char as only its numerical value.
+
+// min-lldb-version: 310
+// min-gdb-version: 8.0
+
+// no-prefer-dynamic
+// compile-flags:-g -C lto
+// gdb-command:run
+// gdbg-command:print 'basic_types_globals::B'
+// gdbr-command:print B
+// gdb-check:$1 = false
+// gdbg-command:print 'basic_types_globals::I'
+// gdbr-command:print I
+// gdb-check:$2 = -1
+// gdbg-command:print 'basic_types_globals::C'
+// gdbr-command:print C
+// gdbg-check:$3 = 97
+// gdbr-check:$3 = 97
+// gdbg-command:print/d 'basic_types_globals::I8'
+// gdbr-command:print I8
+// gdb-check:$4 = 68
+// gdbg-command:print 'basic_types_globals::I16'
+// gdbr-command:print I16
+// gdb-check:$5 = -16
+// gdbg-command:print 'basic_types_globals::I32'
+// gdbr-command:print I32
+// gdb-check:$6 = -32
+// gdbg-command:print 'basic_types_globals::I64'
+// gdbr-command:print I64
+// gdb-check:$7 = -64
+// gdbg-command:print 'basic_types_globals::U'
+// gdbr-command:print U
+// gdb-check:$8 = 1
+// gdbg-command:print/d 'basic_types_globals::U8'
+// gdbr-command:print U8
+// gdb-check:$9 = 100
+// gdbg-command:print 'basic_types_globals::U16'
+// gdbr-command:print U16
+// gdb-check:$10 = 16
+// gdbg-command:print 'basic_types_globals::U32'
+// gdbr-command:print U32
+// gdb-check:$11 = 32
+// gdbg-command:print 'basic_types_globals::U64'
+// gdbr-command:print U64
+// gdb-check:$12 = 64
+// gdbg-command:print 'basic_types_globals::F32'
+// gdbr-command:print F32
+// gdb-check:$13 = 2.5
+// gdbg-command:print 'basic_types_globals::F64'
+// gdbr-command:print F64
+// gdb-check:$14 = 3.5
+// gdb-command:continue
+
+#![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+// N.B. These are `mut` only so they don't constant fold away.
+static mut B: bool = false;
+static mut I: isize = -1;
+static mut C: char = 'a';
+static mut I8: i8 = 68;
+static mut I16: i16 = -16;
+static mut I32: i32 = -32;
+static mut I64: i64 = -64;
+static mut U: usize = 1;
+static mut U8: u8 = 100;
+static mut U16: u16 = 16;
+static mut U32: u32 = 32;
+static mut U64: u64 = 64;
+static mut F32: f32 = 2.5;
+static mut F64: f64 = 3.5;
+
+fn main() {
+ _zzz(); // #break
+
+ let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) };
+}
+
+fn _zzz() {()}
-// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
-// as its numerical value along with its associated ASCII char, there
-// doesn't seem to be any way around this. Also, gdb doesn't know
-// about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
+// Caveat - gdb doesn't know about UTF-32 character encoding and will print a
+// rust char as only its numerical value.
// min-lldb-version: 310
-// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
+// min-gdb-version: 8.0
// compile-flags:-g
// gdb-command:run
// gdbg-command:print 'basic_types_globals::C'
// gdbr-command:print C
// gdbg-check:$3 = 97
-// gdbr-check:$3 = 97 'a'
+// gdbr-check:$3 = 97
// gdbg-command:print/d 'basic_types_globals::I8'
// gdbr-command:print I8
// gdb-check:$4 = 68
--- /dev/null
+// #99269
+
+// check-pass
+
+#![warn(unused_must_use)]
+
+unsafe fn free<T>(ptr: *mut T) {
+ Box::from_raw(ptr); //~ WARNING unused return value
+}
+
+fn main() {}
--- /dev/null
+warning: unused return value of `Box::<T>::from_raw` that must be used
+ --> $DIR/must-use-box-from-raw.rs:8:5
+ |
+LL | Box::from_raw(ptr);
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/must-use-box-from-raw.rs:5:9
+ |
+LL | #![warn(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+ = note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
+
+warning: 1 warning emitted
+