diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 12484462f82f4..01e279b6d04fa 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1617,7 +1617,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate); (span, snippet, post) } else { - (span, suggestion.candidate.to_string(), String::new()) + (span, suggestion.candidate.to_ident_string(), String::new()) }; let msg = match suggestion.target { SuggestionTarget::SimilarlyNamed => format!( diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 6a64eaf576bb9..f143e5578717f 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -41,6 +41,7 @@ use crate::sync::Arc; /// or anything that implements [Into]<[Vec]<[u8]>> (for /// example, you can build a `CString` straight out of a [`String`] or /// a &[str], since both implement that trait). +/// You can create a `CString` from a literal with `CString::from(c"Text")`. /// /// The [`CString::new`] method will actually check that the provided &[[u8]] /// does not have 0 bytes in the middle, and return an error if it @@ -1069,27 +1070,22 @@ impl CStr { /// /// # Examples /// - /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8: + /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8. The leading + /// `c` on the string literal denotes a `CStr`. /// /// ``` /// use std::borrow::Cow; - /// use std::ffi::CStr; /// - /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0") - /// .expect("CStr::from_bytes_with_nul failed"); - /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World")); + /// assert_eq!(c"Hello World".to_string_lossy(), Cow::Borrowed("Hello World")); /// ``` /// /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8: /// /// ``` /// use std::borrow::Cow; - /// use std::ffi::CStr; /// - /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") - /// .expect("CStr::from_bytes_with_nul failed"); /// assert_eq!( - /// cstr.to_string_lossy(), + /// c"Hello \xF0\x90\x80World".to_string_lossy(), /// Cow::Owned(String::from("Hello �World")) as Cow<'_, str> /// ); /// ``` diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index aefb30463d33b..297f52e756bc6 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -23,28 +23,32 @@ use crate::str; /// /// This type represents a borrowed reference to a nul-terminated /// array of bytes. It can be constructed safely from a &[[u8]] -/// slice, or unsafely from a raw `*const c_char`. It can then be -/// converted to a Rust &[str] by performing UTF-8 validation, or -/// into an owned `CString`. +/// slice, or unsafely from a raw `*const c_char`. It can be expressed as a +/// literal in the form `c"Hello world"`. +/// +/// The `CStr` can then be converted to a Rust &[str] by performing +/// UTF-8 validation, or into an owned `CString`. /// /// `&CStr` is to `CString` as &[str] is to `String`: the former /// in each pair are borrowed references; the latter are owned /// strings. /// /// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)` -/// notwithstanding) and is not recommended to be placed in the signatures of FFI functions. -/// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor -/// to provide a safe interface to other consumers. +/// notwithstanding) and should not be placed in the signatures of FFI functions. +/// Instead, safe wrappers of FFI functions may leverage [`CStr::as_ptr`] and the unsafe +/// [`CStr::from_ptr`] constructor to provide a safe interface to other consumers. /// /// # Examples /// /// Inspecting a foreign C string: /// -/// ```ignore (extern-declaration) +/// ``` /// use std::ffi::CStr; /// use std::os::raw::c_char; /// +/// # /* Extern functions are awkward in doc comments - fake it instead /// extern "C" { fn my_string() -> *const c_char; } +/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() } /// /// unsafe { /// let slice = CStr::from_ptr(my_string()); @@ -54,12 +58,14 @@ use crate::str; /// /// Passing a Rust-originating C string: /// -/// ```ignore (extern-declaration) +/// ``` /// use std::ffi::{CString, CStr}; /// use std::os::raw::c_char; /// /// fn work(data: &CStr) { +/// # /* Extern functions are awkward in doc comments - fake it instead /// extern "C" { fn work_with(data: *const c_char); } +/// # */ unsafe extern "C" fn work_with(s: *const c_char) {} /// /// unsafe { work_with(data.as_ptr()) } /// } @@ -70,11 +76,13 @@ use crate::str; /// /// Converting a foreign C string into a Rust `String`: /// -/// ```ignore (extern-declaration) +/// ``` /// use std::ffi::CStr; /// use std::os::raw::c_char; /// +/// # /* Extern functions are awkward in doc comments - fake it instead /// extern "C" { fn my_string() -> *const c_char; } +/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() } /// /// fn my_string_safe() -> String { /// let cstr = unsafe { CStr::from_ptr(my_string()) }; @@ -241,16 +249,16 @@ impl CStr { /// /// # Examples /// - /// ```ignore (extern-declaration) + /// ``` /// use std::ffi::{c_char, CStr}; /// - /// extern "C" { - /// fn my_string() -> *const c_char; + /// fn my_string() -> *const c_char { + /// c"hello".as_ptr() /// } /// /// unsafe { /// let slice = CStr::from_ptr(my_string()); - /// println!("string returned: {}", slice.to_str().unwrap()); + /// assert_eq!(slice.to_str().unwrap(), "hello"); /// } /// ``` /// @@ -264,6 +272,8 @@ impl CStr { /// BYTES.as_ptr().cast() /// }; /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; + /// + /// assert_eq!(c"Hello, world!", HELLO); /// ``` /// /// [valid]: core::ptr#safety @@ -549,6 +559,7 @@ impl CStr { /// /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?; /// assert!(empty_cstr.is_empty()); + /// assert!(c"".is_empty()); /// # Ok(()) /// # } /// ``` diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index e9eeb3153307f..73bb256518d89 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -358,6 +358,54 @@ impl *const T { if self.is_null() { None } else { unsafe { Some(&*self) } } } + /// Returns a shared reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); + /// } + /// ``` + // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[inline] + #[must_use] + pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &*self } + } + /// Returns `None` if the pointer is null, or else returns a shared reference to /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require /// that the value has to be initialized. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index c5a188dc7d4f2..b67930503e015 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -367,6 +367,57 @@ impl *mut T { if self.is_null() { None } else { unsafe { Some(&*self) } } } + /// Returns a shared reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_ref`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_ref`] must be used instead. + /// + /// For the mutable counterpart see [`as_mut_unchecked`]. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_mut_unchecked`]: #method.as_mut_unchecked + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); + /// } + /// ``` + // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[inline] + #[must_use] + pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &*self } + } + /// Returns `None` if the pointer is null, or else returns a shared reference to /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require /// that the value has to be initialized. @@ -688,6 +739,58 @@ impl *mut T { if self.is_null() { None } else { unsafe { Some(&mut *self) } } } + /// Returns a unique reference to the value behind the pointer. + /// If the pointer may be null or the value may be uninitialized, [`as_uninit_mut`] must be used instead. + /// If the pointer may be null, but the value is known to have been initialized, [`as_mut`] must be used instead. + /// + /// For the shared counterpart see [`as_ref_unchecked`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref_unchecked`]: #method.as_mut_unchecked + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, while this reference exists, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// (The part about being initialized is not yet fully decided, but until + /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_as_ref_unchecked)] + /// let mut s = [1, 2, 3]; + /// let ptr: *mut u32 = s.as_mut_ptr(); + /// let first_value = unsafe { ptr.as_mut_unchecked() }; + /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); + /// println!("{s:?}"); // It'll print: "[4, 2, 3]". + /// ``` + // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. + #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[inline] + #[must_use] + pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { + // SAFETY: the caller must guarantee that `self` is valid for a reference + unsafe { &mut *self } + } + /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require /// that the value has to be initialized. diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 78494b866b108..72f6a3b773bb5 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -1437,10 +1437,10 @@ impl TryFromFloatSecsError { const fn description(&self) -> &'static str { match self.kind { TryFromFloatSecsErrorKind::Negative => { - "can not convert float seconds to Duration: value is negative" + "cannot convert float seconds to Duration: value is negative" } TryFromFloatSecsErrorKind::OverflowOrNan => { - "can not convert float seconds to Duration: value is either too big or NaN" + "cannot convert float seconds to Duration: value is either too big or NaN" } } } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index dc0e302a81088..b98fbbf762fa2 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -353,6 +353,12 @@ fn default_alloc_error_hook(layout: Layout) { if unsafe { __rust_alloc_error_handler_should_panic != 0 } { panic!("memory allocation of {} bytes failed", layout.size()); } else { + // This is the default path taken on OOM, and the only path taken on stable with std. + // Crucially, it does *not* call any user-defined code, and therefore users do not have to + // worry about allocation failure causing reentrancy issues. That makes it different from + // the default `__rdl_oom` defined in alloc (i.e., the default alloc error handler that is + // called when there is no `#[alloc_error_handler]`), which triggers a regular panic and + // thus can invoke a user-defined panic hook, executing arbitrary user-defined code. rtprintpanic!("memory allocation of {} bytes failed\n", layout.size()); } } diff --git a/tests/ui/span/suggestion-raw-68962.rs b/tests/ui/span/suggestion-raw-68962.rs new file mode 100644 index 0000000000000..0b581308f6628 --- /dev/null +++ b/tests/ui/span/suggestion-raw-68962.rs @@ -0,0 +1,11 @@ +fn r#fn() {} + +fn main() { + let r#final = 1; + + // Should correctly suggest variable defined using raw identifier. + fina; //~ ERROR cannot find value + + // Should correctly suggest function defined using raw identifier. + f(); //~ ERROR cannot find function +} diff --git a/tests/ui/span/suggestion-raw-68962.stderr b/tests/ui/span/suggestion-raw-68962.stderr new file mode 100644 index 0000000000000..2e25f5cbdf58d --- /dev/null +++ b/tests/ui/span/suggestion-raw-68962.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find value `fina` in this scope + --> $DIR/suggestion-raw-68962.rs:7:5 + | +LL | fina; + | ^^^^ help: a local variable with a similar name exists: `r#final` + +error[E0425]: cannot find function `f` in this scope + --> $DIR/suggestion-raw-68962.rs:10:5 + | +LL | fn r#fn() {} + | --------- similarly named function `r#fn` defined here +... +LL | f(); + | ^ help: a function with a similar name exists: `r#fn` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`.