Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 13 pull requests #124672

Closed
wants to merge 11 commits into from
Closed
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down
14 changes: 5 additions & 9 deletions library/alloc/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use crate::sync::Arc;
/// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for
/// example, you can build a `CString` straight out of a [`String`] or
/// a <code>&[str]</code>, 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 <code>&[[u8]]</code>
/// does not have 0 bytes in the middle, and return an error if it
Expand Down Expand Up @@ -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>
/// );
/// ```
Expand Down
37 changes: 24 additions & 13 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>&[[u8]]</code>
/// slice, or unsafely from a raw `*const c_char`. It can then be
/// converted to a Rust <code>&[str]</code> 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 <code>&[str]</code> by performing
/// UTF-8 validation, or into an owned `CString`.
///
/// `&CStr` is to `CString` as <code>&[str]</code> 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());
Expand All @@ -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()) }
/// }
Expand All @@ -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()) };
Expand Down Expand Up @@ -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");
/// }
/// ```
///
Expand All @@ -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
Expand Down Expand Up @@ -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(())
/// # }
/// ```
Expand Down
48 changes: 48 additions & 0 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,54 @@ impl<T: ?Sized> *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.
Expand Down
103 changes: 103 additions & 0 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,57 @@ impl<T: ?Sized> *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.
Expand Down Expand Up @@ -688,6 +739,58 @@ impl<T: ?Sized> *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.
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions library/std/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/span/suggestion-raw-68962.rs
Original file line number Diff line number Diff line change
@@ -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
}
18 changes: 18 additions & 0 deletions tests/ui/span/suggestion-raw-68962.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading