提交 9957c5bf 编写于 作者: W Weilong Chen 提交者: Zheng Zengkai

Adaptation of rust for openEuler

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5J75G
CVE: NA

--------------------------------

The version of openeuler is different from the latest
version of the mainline, so need adapted
Signed-off-by: NWeilong Chen <chenweilong@huawei.com>
上级 9b80acc6
......@@ -16,6 +16,8 @@ use core::ptr::{self, NonNull};
#[doc(inline)]
pub use core::alloc::*;
use core::marker::Destruct;
#[cfg(test)]
mod tests;
......@@ -331,7 +333,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
// well.
// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`,
// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well.
pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Drop>(
pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Destruct>(
ptr: Unique<T>,
alloc: A,
) {
......@@ -387,7 +389,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
#[cfg(all(not(no_global_oom_handling), test))]
pub use std::alloc::handle_alloc_error;
#[cfg(all(not(no_global_oom_handling), not(any(target_os = "hermit", test))))]
#[cfg(all(not(no_global_oom_handling), not(test)))]
#[doc(hidden)]
#[allow(unused_attributes)]
#[unstable(feature = "alloc_internals", issue = "none")]
......@@ -399,7 +401,7 @@ pub mod __alloc_error_handler {
// if there is no `#[alloc_error_handler]`
#[rustc_std_internal_symbol]
pub unsafe extern "C-unwind" fn __rdl_oom(size: usize, _align: usize) -> ! {
panic!("memory allocation of {} bytes failed", size)
panic!("memory allocation of {size} bytes failed")
}
// if there is an `#[alloc_error_handler]`
......
......@@ -163,7 +163,7 @@ where
/// let readonly = [1, 2];
/// let borrowed = Items::new((&readonly[..]).into());
/// match borrowed {
/// Items { values: Cow::Borrowed(b) } => println!("borrowed {:?}", b),
/// Items { values: Cow::Borrowed(b) } => println!("borrowed {b:?}"),
/// _ => panic!("expect borrowed value"),
/// }
///
......@@ -294,8 +294,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
///
/// # Examples
///
/// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data
/// and becomes a `Cow::Owned`:
/// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data:
///
/// ```
/// use std::borrow::Cow;
......@@ -309,7 +308,8 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
/// );
/// ```
///
/// Calling `into_owned` on a `Cow::Owned` is a no-op:
/// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the
/// `Cow` without being cloned.
///
/// ```
/// use std::borrow::Cow;
......
......@@ -33,7 +33,7 @@
//! }
//!
//! let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//! println!("{:?}", list);
//! println!("{list:?}");
//! ```
//!
//! This will print `Cons(1, Cons(2, Nil))`.
......@@ -145,7 +145,7 @@ use core::hash::{Hash, Hasher};
#[cfg(not(no_global_oom_handling))]
use core::iter::FromIterator;
use core::iter::{FusedIterator, Iterator};
use core::marker::{Unpin, Unsize};
use core::marker::{Destruct, Unpin, Unsize};
use core::mem;
use core::ops::{
CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver,
......@@ -165,6 +165,11 @@ use crate::str::from_boxed_utf8_unchecked;
#[cfg(not(no_global_oom_handling))]
use crate::vec::Vec;
#[unstable(feature = "thin_box", issue = "92791")]
pub use thin::ThinBox;
mod thin;
/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
......@@ -353,7 +358,7 @@ impl<T, A: Allocator> Box<T, A> {
#[inline]
pub const fn new_in(x: T, alloc: A) -> Self
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Destruct,
{
let mut boxed = Self::new_uninit_in(alloc);
unsafe {
......@@ -382,8 +387,8 @@ impl<T, A: Allocator> Box<T, A> {
#[inline]
pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError>
where
T: ~const Drop,
A: ~const Allocator + ~const Drop,
T: ~const Destruct,
A: ~const Allocator + ~const Destruct,
{
let mut boxed = Self::try_new_uninit_in(alloc)?;
unsafe {
......@@ -419,7 +424,7 @@ impl<T, A: Allocator> Box<T, A> {
// #[unstable(feature = "new_uninit", issue = "63291")]
pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
......@@ -457,7 +462,7 @@ impl<T, A: Allocator> Box<T, A> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate(layout)?.cast();
......@@ -491,7 +496,7 @@ impl<T, A: Allocator> Box<T, A> {
#[must_use]
pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
......@@ -529,7 +534,7 @@ impl<T, A: Allocator> Box<T, A> {
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate_zeroed(layout)?.cast();
......@@ -545,7 +550,7 @@ impl<T, A: Allocator> Box<T, A> {
#[inline(always)]
pub const fn pin_in(x: T, alloc: A) -> Pin<Self>
where
A: 'static + ~const Allocator + ~const Drop,
A: 'static + ~const Allocator + ~const Destruct,
{
Self::into_pin(Self::new_in(x, alloc))
}
......@@ -576,7 +581,7 @@ impl<T, A: Allocator> Box<T, A> {
#[inline]
pub const fn into_inner(boxed: Self) -> T
where
Self: ~const Drop,
Self: ~const Destruct,
{
*boxed
}
......@@ -1189,17 +1194,25 @@ impl<T: Default> Default for Box<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
impl<T> const Default for Box<[T]> {
fn default() -> Self {
Box::<[T; 0]>::new([])
let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
Box(ptr, Global)
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "default_box_extra", since = "1.17.0")]
impl Default for Box<str> {
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
impl const Default for Box<str> {
fn default() -> Self {
unsafe { from_boxed_utf8_unchecked(Default::default()) }
// SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
let ptr: Unique<str> = unsafe {
let bytes: Unique<[u8]> = Unique::<[u8; 0]>::dangling();
Unique::new_unchecked(bytes.as_ptr() as *mut str)
};
Box(ptr, Global)
}
}
......@@ -1358,6 +1371,12 @@ impl<T: ?Sized + Hasher, A: Allocator> Hasher for Box<T, A> {
fn write_isize(&mut self, i: isize) {
(**self).write_isize(i)
}
fn write_length_prefix(&mut self, len: usize) {
(**self).write_length_prefix(len)
}
fn write_str(&mut self, s: &str) {
(**self).write_str(s)
}
}
#[cfg(not(no_global_oom_handling))]
......@@ -1409,7 +1428,7 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
/// let slice: &[u8] = &[104, 101, 108, 108, 111];
/// let boxed_slice: Box<[u8]> = Box::from(slice);
///
/// println!("{:?}", boxed_slice);
/// println!("{boxed_slice:?}");
/// ```
fn from(slice: &[T]) -> Box<[T]> {
let len = slice.len();
......@@ -1451,7 +1470,7 @@ impl From<&str> for Box<str> {
///
/// ```rust
/// let boxed: Box<str> = Box::from("hello");
/// println!("{}", boxed);
/// println!("{boxed}");
/// ```
#[inline]
fn from(s: &str) -> Box<str> {
......@@ -1476,14 +1495,14 @@ impl From<Cow<'_, str>> for Box<str> {
///
/// let unboxed = Cow::Borrowed("hello");
/// let boxed: Box<str> = Box::from(unboxed);
/// println!("{}", boxed);
/// println!("{boxed}");
/// ```
///
/// ```rust
/// # use std::borrow::Cow;
/// let unboxed = Cow::Owned("hello".to_string());
/// let boxed: Box<str> = Box::from(unboxed);
/// println!("{}", boxed);
/// println!("{boxed}");
/// ```
#[inline]
fn from(cow: Cow<'_, str>) -> Box<str> {
......@@ -1530,7 +1549,7 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> {
///
/// ```rust
/// let boxed: Box<[u8]> = Box::from([4, 2]);
/// println!("{:?}", boxed);
/// println!("{boxed:?}");
/// ```
fn from(array: [T; N]) -> Box<[T]> {
box array
......
// Based on
// https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs
// by matthieu-m
use crate::alloc::{self, Layout, LayoutError};
use core::fmt::{self, Debug, Display, Formatter};
use core::marker::PhantomData;
#[cfg(not(no_global_oom_handling))]
use core::marker::Unsize;
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::Pointee;
use core::ptr::{self, NonNull};
/// ThinBox.
///
/// A thin pointer for heap allocation, regardless of T.
///
/// # Examples
///
/// ```
/// #![feature(thin_box)]
/// use std::boxed::ThinBox;
///
/// let five = ThinBox::new(5);
/// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
///
/// use std::mem::{size_of, size_of_val};
/// let size_of_ptr = size_of::<*const ()>();
/// assert_eq!(size_of_ptr, size_of_val(&five));
/// assert_eq!(size_of_ptr, size_of_val(&thin_slice));
/// ```
#[unstable(feature = "thin_box", issue = "92791")]
pub struct ThinBox<T: ?Sized> {
ptr: WithHeader<<T as Pointee>::Metadata>,
_marker: PhantomData<T>,
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T> ThinBox<T> {
/// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
/// the stack.
///
/// # Examples
///
/// ```
/// #![feature(thin_box)]
/// use std::boxed::ThinBox;
///
/// let five = ThinBox::new(5);
/// ```
#[cfg(not(no_global_oom_handling))]
pub fn new(value: T) -> Self {
let meta = ptr::metadata(&value);
let ptr = WithHeader::new(meta, value);
ThinBox { ptr, _marker: PhantomData }
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<Dyn: ?Sized> ThinBox<Dyn> {
/// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
/// the stack.
///
/// # Examples
///
/// ```
/// #![feature(thin_box)]
/// use std::boxed::ThinBox;
///
/// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
/// ```
#[cfg(not(no_global_oom_handling))]
pub fn new_unsize<T>(value: T) -> Self
where
T: Unsize<Dyn>,
{
let meta = ptr::metadata(&value as &Dyn);
let ptr = WithHeader::new(meta, value);
ThinBox { ptr, _marker: PhantomData }
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized + Debug> Debug for ThinBox<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.deref(), f)
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized + Display> Display for ThinBox<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(self.deref(), f)
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized> Deref for ThinBox<T> {
type Target = T;
fn deref(&self) -> &T {
let value = self.data();
let metadata = self.meta();
let pointer = ptr::from_raw_parts(value as *const (), metadata);
unsafe { &*pointer }
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized> DerefMut for ThinBox<T> {
fn deref_mut(&mut self) -> &mut T {
let value = self.data();
let metadata = self.meta();
let pointer = ptr::from_raw_parts_mut::<T>(value as *mut (), metadata);
unsafe { &mut *pointer }
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized> Drop for ThinBox<T> {
fn drop(&mut self) {
unsafe {
let value = self.deref_mut();
let value = value as *mut T;
self.ptr.drop::<T>(value);
}
}
}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized> ThinBox<T> {
fn meta(&self) -> <T as Pointee>::Metadata {
// Safety:
// - NonNull and valid.
unsafe { *self.ptr.header() }
}
fn data(&self) -> *mut u8 {
self.ptr.value()
}
}
/// A pointer to type-erased data, guaranteed to have a header `H` before the pointed-to location.
struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
impl<H> WithHeader<H> {
#[cfg(not(no_global_oom_handling))]
fn new<T>(header: H, value: T) -> WithHeader<H> {
let value_layout = Layout::new::<T>();
let Ok((layout, value_offset)) = Self::alloc_layout(value_layout) else {
// We pass an empty layout here because we do not know which layout caused the
// arithmetic overflow in `Layout::extend` and `handle_alloc_error` takes `Layout` as
// its argument rather than `Result<Layout, LayoutError>`, also this function has been
// stable since 1.28 ._.
//
// On the other hand, look at this gorgeous turbofish!
alloc::handle_alloc_error(Layout::new::<()>());
};
unsafe {
let ptr = alloc::alloc(layout);
if ptr.is_null() {
alloc::handle_alloc_error(layout);
}
// Safety:
// - The size is at least `aligned_header_size`.
let ptr = ptr.add(value_offset) as *mut _;
let ptr = NonNull::new_unchecked(ptr);
let result = WithHeader(ptr, PhantomData);
ptr::write(result.header(), header);
ptr::write(result.value().cast(), value);
result
}
}
// Safety:
// - Assumes that `value` can be dereferenced.
unsafe fn drop<T: ?Sized>(&self, value: *mut T) {
unsafe {
// SAFETY: Layout must have been computable if we're in drop
let (layout, value_offset) =
Self::alloc_layout(Layout::for_value_raw(value)).unwrap_unchecked();
ptr::drop_in_place::<T>(value);
// We only drop the value because the Pointee trait requires that the metadata is copy
// aka trivially droppable
alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
}
}
fn header(&self) -> *mut H {
// Safety:
// - At least `size_of::<H>()` bytes are allocated ahead of the pointer.
// - We know that H will be aligned because the middle pointer is aligned to the greater
// of the alignment of the header and the data and the header size includes the padding
// needed to align the header. Subtracting the header size from the aligned data pointer
// will always result in an aligned header pointer, it just may not point to the
// beginning of the allocation.
unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }
}
fn value(&self) -> *mut u8 {
self.0.as_ptr()
}
const fn header_size() -> usize {
mem::size_of::<H>()
}
fn alloc_layout(value_layout: Layout) -> Result<(Layout, usize), LayoutError> {
Layout::new::<H>().extend(value_layout)
}
}
......@@ -223,10 +223,12 @@
//!
//! 3. An asterisk `.*`:
//!
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
//! first input holds the `usize` precision, and the second holds the value to print. Note that
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one:
//! - If a format string in the fashion of `{:<spec>.*}` is used, then the first input holds
//! the `usize` precision, and the second holds the value to print.
//! - If a format string in the fashion of `{<arg>:<spec>.*}` is used, then the `<arg>` part
//! refers to the value to print, and the `precision` is taken like it was specified with an
//! omitted positional parameter (`{}` instead of `{<arg>:}`).
//!
//! For example, the following calls all print the same thing `Hello x is 0.01000`:
//!
......@@ -240,15 +242,19 @@
//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
//!
//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
//! // specified in first of next two args (5)}
//! // Hello {next arg -> arg 0 ("x")} is {second of next two args -> arg 2 (0.01) with precision
//! // specified in first of next two args -> arg 1 (5)}
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
//!
//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
//! // specified in its predecessor (5)}
//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision
//! // specified in next arg -> arg 0 (5)}
//! println!("Hello {1} is {2:.*}", 5, "x", 0.01);
//!
//! // Hello {next arg -> arg 0 ("x")} is {arg 2 (0.01) with precision
//! // specified in next arg -> arg 1 (5)}
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
//!
//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
//! // Hello {next arg -> arg 0 ("x")} is {arg "number" (0.01) with precision specified
//! // in arg "prec" (5)}
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
//! ```
......@@ -306,7 +312,7 @@
//! ```text
//! format_string := text [ maybe_format text ] *
//! maybe_format := '{' '{' | '}' '}' | format
//! format := '{' [ argument ] [ ':' format_spec ] '}'
//! format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}'
//! argument := integer | identifier
//!
//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type
......@@ -319,7 +325,12 @@
//! count := parameter | integer
//! parameter := argument '$'
//! ```
//! In the above grammar, `text` must not contain any `'{'` or `'}'` characters.
//! In the above grammar,
//! - `text` must not contain any `'{'` or `'}'` characters,
//! - `ws` is any character for which [`char::is_whitespace`] returns `true`, has no semantic
//! meaning and is completely optional,
//! - `integer` is a decimal integer that may contain leading zeroes and
//! - `identifier` is an `IDENTIFIER_OR_KEYWORD` (not an `IDENTIFIER`) as defined by the [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html).
//!
//! # Formatting traits
//!
......@@ -360,9 +371,9 @@
//! ```
//!
//! Your type will be passed as `self` by-reference, and then the function
//! should emit output into the `f.buf` stream. It is up to each format trait
//! implementation to correctly adhere to the requested formatting parameters.
//! The values of these parameters will be listed in the fields of the
//! should emit output into the Formatter `f` which implements `fmt::Write`. It is up to each
//! format trait implementation to correctly adhere to the requested formatting parameters.
//! The values of these parameters can be accessed with methods of the
//! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also
//! provides some helper methods.
//!
......@@ -418,9 +429,9 @@
//! fn main() {
//! let myvector = Vector2D { x: 3, y: 4 };
//!
//! println!("{}", myvector); // => "(3, 4)"
//! println!("{:?}", myvector); // => "Vector2D {x: 3, y:4}"
//! println!("{:10.3b}", myvector); // => " 5.000"
//! println!("{myvector}"); // => "(3, 4)"
//! println!("{myvector:?}"); // => "Vector2D {x: 3, y:4}"
//! println!("{myvector:10.3b}"); // => " 5.000"
//! }
//! ```
//!
......@@ -451,7 +462,7 @@
//!
//! ```ignore (only-for-syntax-highlight)
//! format! // described above
//! write! // first argument is a &mut io::Write, the destination
//! write! // first argument is either a &mut io::Write or a &mut fmt::Write, the destination
//! writeln! // same as write but appends a newline
//! print! // the format string is printed to the standard output
//! println! // same as print but appends a newline
......@@ -462,11 +473,11 @@
//!
//! ### `write!`
//!
//! This and [`writeln!`] are two macros which are used to emit the format string
//! [`write!`] and [`writeln!`] are two macros which are used to emit the format string
//! to a specified stream. This is used to prevent intermediate allocations of
//! format strings and instead directly write the output. Under the hood, this
//! function is actually invoking the [`write_fmt`] function defined on the
//! [`std::io::Write`] trait. Example usage is:
//! [`std::io::Write`] and the [`std::fmt::Write`] trait. Example usage is:
//!
//! ```
//! # #![allow(unused_must_use)]
......@@ -493,7 +504,7 @@
//!
//! ### `format_args!`
//!
//! This is a curious macro used to safely pass around
//! [`format_args!`] is a curious macro used to safely pass around
//! an opaque object describing the format string. This object
//! does not require any heap allocations to create, and it only
//! references information on the stack. Under the hood, all of
......@@ -531,10 +542,12 @@
//! [`to_string`]: crate::string::ToString::to_string "ToString::to_string"
//! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt
//! [`std::io::Write`]: ../../std/io/trait.Write.html
//! [`std::fmt::Write`]: ../../std/fmt/trait.Write.html
//! [`print!`]: ../../std/macro.print.html "print!"
//! [`println!`]: ../../std/macro.println.html "println!"
//! [`eprint!`]: ../../std/macro.eprint.html "eprint!"
//! [`eprintln!`]: ../../std/macro.eprintln.html "eprintln!"
//! [`format_args!`]: ../../std/macro.format_args.html "format_args!"
//! [`fmt::Arguments`]: Arguments "fmt::Arguments"
//! [`format`]: format() "fmt::format"
......
......@@ -88,11 +88,13 @@
#![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(array_methods)]
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(async_iterator)]
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
......@@ -106,14 +108,18 @@
#![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(core_ffi_c)]
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(cstr_from_bytes_until_nul)]
#![feature(dispatch_from_dyn)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(hasher_prefixfree_extras)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(layout_for_ptr)]
......@@ -122,6 +128,8 @@
#![feature(nonnull_slice_from_raw_parts)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(ptr_metadata)]
#![feature(ptr_sub_ptr)]
#![feature(receiver_trait)]
#![feature(set_ptr_value)]
#![feature(slice_group_by)]
......@@ -129,9 +137,11 @@
#![feature(slice_ptr_len)]
#![feature(slice_range)]
#![feature(str_internals)]
#![feature(strict_provenance)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
#![feature(try_trait_v2)]
#![feature(unchecked_math)]
#![feature(unicode_internals)]
#![feature(unsize)]
//
......@@ -141,9 +151,7 @@
#![feature(associated_type_bounds)]
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![cfg_attr(bootstrap, feature(cfg_target_has_atomic))]
#![feature(const_deref)]
#![feature(const_fn_trait_bound)]
#![feature(const_mut_refs)]
#![feature(const_ptr_write)]
#![feature(const_precise_live_drops)]
......@@ -153,13 +161,16 @@
#![feature(exclusive_range_pattern)]
#![feature(fundamental)]
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(hashmap_internals)]
#![feature(lang_items)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nll)] // Not necessary, but here to test the `nll` feature.
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(slice_internals)]
#![feature(staged_api)]
#![cfg_attr(test, feature(test))]
#![feature(unboxed_closures)]
......@@ -205,6 +216,8 @@ mod boxed {
}
pub mod borrow;
pub mod collections;
#[cfg(not(no_global_oom_handling))]
pub mod ffi;
pub mod fmt;
#[cfg(not(no_rc))]
pub mod rc;
......
......@@ -57,7 +57,8 @@ macro_rules! vec {
// required for this macro definition, is not available. Instead use the
// `slice::into_vec` function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
#[cfg(all(not(no_global_oom_handling), test))]
#[cfg_attr(not(bootstrap), allow(unused_macro_rules))]
macro_rules! vec {
() => (
$crate::vec::Vec::new()
......
......@@ -120,7 +120,6 @@ impl<T, A: Allocator> RawVec<T, A> {
/// Like `new`, but parameterized over the choice of allocator for
/// the returned `RawVec`.
#[rustc_allow_const_fn_unstable(const_fn)]
pub const fn new_in(alloc: A) -> Self {
// `cap: 0` means "unallocated". zero-sized types are ignored.
Self { ptr: Unique::dangling(), cap: 0, alloc }
......@@ -177,7 +176,8 @@ impl<T, A: Allocator> RawVec<T, A> {
#[cfg(not(no_global_oom_handling))]
fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
if mem::size_of::<T>() == 0 {
// Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
if mem::size_of::<T>() == 0 || capacity == 0 {
Self::new_in(alloc)
} else {
// We avoid `unwrap_or_else` here because it bloats the amount of
......@@ -211,7 +211,8 @@ impl<T, A: Allocator> RawVec<T, A> {
}
fn try_allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Result<Self, TryReserveError> {
if mem::size_of::<T>() == 0 {
// Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
if mem::size_of::<T>() == 0 || capacity == 0 {
return Ok(Self::new_in(alloc));
}
......@@ -276,9 +277,7 @@ impl<T, A: Allocator> RawVec<T, A> {
// We have an allocated chunk of memory, so we can bypass runtime
// checks to get our current layout.
unsafe {
let align = mem::align_of::<T>();
let size = mem::size_of::<T>() * self.cap;
let layout = Layout::from_size_align_unchecked(size, align);
let layout = Layout::array::<T>(self.cap).unwrap_unchecked();
Some((self.ptr.cast().into(), layout))
}
}
......@@ -475,10 +474,11 @@ impl<T, A: Allocator> RawVec<T, A> {
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
let new_size = cap * mem::size_of::<T>();
let ptr = unsafe {
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
// `Layout::array` cannot overflow here because it would have
// overflowed earlier when capacity was larger.
let new_layout = Layout::array::<T>(cap).unwrap_unchecked();
self.alloc
.shrink(ptr, layout, new_layout)
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
......
......@@ -50,7 +50,7 @@
//! ```
//! let numbers = &[0, 1, 2];
//! for n in numbers {
//! println!("{} is a number!", n);
//! println!("{n} is a number!");
//! }
//! ```
//!
......@@ -155,7 +155,7 @@ pub use hack::to_vec;
// functions are actually methods that are in `impl [T]` but not in
// `core::slice::SliceExt` - we need to supply these functions for the
// `test_permutations` test
mod hack {
pub(crate) mod hack {
use core::alloc::Allocator;
use crate::boxed::Box;
......@@ -287,7 +287,6 @@ mod hack {
}
}
#[lang = "slice_alloc"]
#[cfg(not(test))]
impl<T> [T] {
/// Sorts the slice.
......@@ -317,6 +316,7 @@ impl<T> [T] {
/// assert!(v == [-5, -3, 1, 2, 4]);
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sort(&mut self)
......@@ -372,6 +372,7 @@ impl<T> [T] {
/// assert!(v == [5, 4, 3, 2, 1]);
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sort_by<F>(&mut self, mut compare: F)
......@@ -413,6 +414,7 @@ impl<T> [T] {
/// assert!(v == [1, 2, -3, 4, -5]);
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
#[inline]
pub fn sort_by_key<K, F>(&mut self, mut f: F)
......@@ -459,6 +461,7 @@ impl<T> [T] {
///
/// [pdqsort]: https://github.com/orlp/pdqsort
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
#[inline]
pub fn sort_by_cached_key<K, F>(&mut self, f: F)
......@@ -517,6 +520,7 @@ impl<T> [T] {
/// // Here, `s` and `x` can be modified independently.
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[rustc_conversion_suggestion]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
......@@ -536,6 +540,7 @@ impl<T> [T] {
/// let x = s.try_to_vec().unwrap();
/// // Here, `s` and `x` can be modified independently.
/// ```
#[rustc_allow_incoherent_impl]
#[inline]
#[stable(feature = "kernel", since = "1.0.0")]
pub fn try_to_vec(&self) -> Result<Vec<T>, TryReserveError>
......@@ -559,6 +564,7 @@ impl<T> [T] {
/// // Here, `s` and `x` can be modified independently.
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
......@@ -582,6 +588,7 @@ impl<T> [T] {
/// let x = s.try_to_vec_in(System).unwrap();
/// // Here, `s` and `x` can be modified independently.
/// ```
#[rustc_allow_incoherent_impl]
#[inline]
#[stable(feature = "kernel", since = "1.0.0")]
pub fn try_to_vec_in<A: Allocator>(&self, alloc: A) -> Result<Vec<T, A>, TryReserveError>
......@@ -606,6 +613,7 @@ impl<T> [T] {
///
/// assert_eq!(x, vec![10, 40, 30]);
/// ```
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
......@@ -633,6 +641,7 @@ impl<T> [T] {
/// // this will panic at runtime
/// b"0123456789abcdef".repeat(usize::MAX);
/// ```
#[rustc_allow_incoherent_impl]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
pub fn repeat(&self, n: usize) -> Vec<T>
......@@ -701,6 +710,7 @@ impl<T> [T] {
/// assert_eq!(["hello", "world"].concat(), "helloworld");
/// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
/// ```
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
where
......@@ -719,6 +729,7 @@ impl<T> [T] {
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
/// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
/// ```
#[rustc_allow_incoherent_impl]
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where
......@@ -737,8 +748,9 @@ impl<T> [T] {
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
/// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
/// ```
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
#[deprecated(since = "1.3.0", note = "renamed to join")]
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where
Self: Join<Separator>,
......@@ -747,7 +759,6 @@ impl<T> [T] {
}
}
#[lang = "slice_u8_alloc"]
#[cfg(not(test))]
impl [u8] {
/// Returns a vector containing a copy of this slice where each byte
......@@ -760,6 +771,7 @@ impl [u8] {
///
/// [`make_ascii_uppercase`]: slice::make_ascii_uppercase
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "this returns the uppercase bytes as a new Vec, \
without modifying the original"]
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
......@@ -780,6 +792,7 @@ impl [u8] {
///
/// [`make_ascii_lowercase`]: slice::make_ascii_lowercase
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "this returns the lowercase bytes as a new Vec, \
without modifying the original"]
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
......@@ -1134,9 +1147,9 @@ where
impl<T> Drop for MergeHole<T> {
fn drop(&mut self) {
// `T` is not a zero-sized type, so it's okay to divide by its size.
let len = (self.end as usize - self.start as usize) / mem::size_of::<T>();
// `T` is not a zero-sized type, and these are pointers into a slice's elements.
unsafe {
let len = self.end.sub_ptr(self.start);
ptr::copy_nonoverlapping(self.start, self.dest, len);
}
}
......
......@@ -238,7 +238,6 @@ impl ToOwned for str {
}
/// Methods for string slices.
#[lang = "str_alloc"]
#[cfg(not(test))]
impl str {
/// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
......@@ -253,6 +252,7 @@ impl str {
/// let boxed_bytes = boxed_str.into_boxed_bytes();
/// assert_eq!(*boxed_bytes, *s.as_bytes());
/// ```
#[rustc_allow_incoherent_impl]
#[stable(feature = "str_box_extras", since = "1.20.0")]
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
......@@ -283,6 +283,7 @@ impl str {
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "this returns the replaced string as a new allocation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
......@@ -323,6 +324,7 @@ impl str {
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "this returns the replaced string as a new allocation, \
without modifying the original"]
#[stable(feature = "str_replacen", since = "1.16.0")]
......@@ -379,6 +381,7 @@ impl str {
/// assert_eq!(new_year, new_year.to_lowercase());
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "this returns the lowercase string as a new String, \
without modifying the original"]
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
......@@ -461,6 +464,7 @@ impl str {
/// assert_eq!("TSCHÜSS", s.to_uppercase());
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "this returns the uppercase string as a new String, \
without modifying the original"]
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
......@@ -496,6 +500,7 @@ impl str {
/// assert_eq!(boxed_str.into_string(), string);
/// ```
#[stable(feature = "box_str", since = "1.4.0")]
#[rustc_allow_incoherent_impl]
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub fn into_string(self: Box<str>) -> String {
......@@ -524,6 +529,7 @@ impl str {
/// let huge = "0123456789abcdef".repeat(usize::MAX);
/// ```
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use]
#[stable(feature = "repeat_str", since = "1.16.0")]
pub fn repeat(&self, n: usize) -> String {
......@@ -552,6 +558,7 @@ impl str {
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
/// [`to_uppercase`]: #method.to_uppercase
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
......@@ -584,6 +591,7 @@ impl str {
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
/// [`to_lowercase`]: #method.to_lowercase
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
......@@ -604,6 +612,7 @@ impl str {
/// let s: &str = "a";
/// let ss: String = s.try_to_owned().unwrap();
/// ```
#[rustc_allow_incoherent_impl]
#[inline]
#[stable(feature = "kernel", since = "1.0.0")]
pub fn try_to_owned(&self) -> Result<String, TryReserveError> {
......
......@@ -119,27 +119,99 @@ use crate::vec::Vec;
///
/// # UTF-8
///
/// `String`s are always valid UTF-8. This has a few implications, the first of
/// which is that if you need a non-UTF-8 string, consider [`OsString`]. It is
/// similar, but without the UTF-8 constraint. The second implication is that
/// you cannot index into a `String`:
/// `String`s are always valid UTF-8. If you need a non-UTF-8 string, consider
/// [`OsString`]. It is similar, but without the UTF-8 constraint. Because UTF-8
/// is a variable width encoding, `String`s are typically smaller than an array of
/// the same `chars`:
///
/// ```
/// use std::mem;
///
/// // `s` is ASCII which represents each `char` as one byte
/// let s = "hello";
/// assert_eq!(s.len(), 5);
///
/// // A `char` array with the same contents would be longer because
/// // every `char` is four bytes
/// let s = ['h', 'e', 'l', 'l', 'o'];
/// let size: usize = s.into_iter().map(|c| mem::size_of_val(&c)).sum();
/// assert_eq!(size, 20);
///
/// // However, for non-ASCII strings, the difference will be smaller
/// // and sometimes they are the same
/// let s = "💖💖💖💖💖";
/// assert_eq!(s.len(), 20);
///
/// let s = ['💖', '💖', '💖', '💖', '💖'];
/// let size: usize = s.into_iter().map(|c| mem::size_of_val(&c)).sum();
/// assert_eq!(size, 20);
/// ```
///
/// This raises interesting questions as to how `s[i]` should work.
/// What should `i` be here? Several options include byte indices and
/// `char` indices but, because of UTF-8 encoding, only byte indices
/// would provide constant time indexing. Getting the `i`th `char`, for
/// example, is available using [`chars`]:
///
/// ```
/// let s = "hello";
/// let third_character = s.chars().nth(2);
/// assert_eq!(third_character, Some('l'));
///
/// let s = "💖💖💖💖💖";
/// let third_character = s.chars().nth(2);
/// assert_eq!(third_character, Some('💖'));
/// ```
///
/// Next, what should `s[i]` return? Because indexing returns a reference
/// to underlying data it could be `&u8`, `&[u8]`, or something else similar.
/// Since we're only providing one index, `&u8` makes the most sense but that
/// might not be what the user expects and can be explicitly achieved with
/// [`as_bytes()`]:
///
/// ```
/// // The first byte is 104 - the byte value of `'h'`
/// let s = "hello";
/// assert_eq!(s.as_bytes()[0], 104);
/// // or
/// assert_eq!(s.as_bytes()[0], b'h');
///
/// // The first byte is 240 which isn't obviously useful
/// let s = "💖💖💖💖💖";
/// assert_eq!(s.as_bytes()[0], 240);
/// ```
///
/// Due to these ambiguities/restrictions, indexing with a `usize` is simply
/// forbidden:
///
/// ```compile_fail,E0277
/// let s = "hello";
///
/// println!("The first letter of s is {}", s[0]); // ERROR!!!
/// // The following will not compile!
/// println!("The first letter of s is {}", s[0]);
/// ```
///
/// It is more clear, however, how `&s[i..j]` should work (that is,
/// indexing with a range). It should accept byte indices (to be constant-time)
/// and return a `&str` which is UTF-8 encoded. This is also called "string slicing".
/// Note this will panic if the byte indices provided are not character
/// boundaries - see [`is_char_boundary`] for more details. See the implementations
/// for [`SliceIndex<str>`] for more details on string slicing. For a non-panicking
/// version of string slicing, see [`get`].
///
/// [`OsString`]: ../../std/ffi/struct.OsString.html "ffi::OsString"
/// [`SliceIndex<str>`]: core::slice::SliceIndex
/// [`as_bytes()`]: str::as_bytes
/// [`get`]: str::get
/// [`is_char_boundary`]: str::is_char_boundary
///
/// Indexing is intended to be a constant-time operation, but UTF-8 encoding
/// does not allow us to do this. Furthermore, it's not clear what sort of
/// thing the index should return: a byte, a codepoint, or a grapheme cluster.
/// The [`bytes`] and [`chars`] methods return iterators over the first
/// two, respectively.
/// The [`bytes`] and [`chars`] methods return iterators over the bytes and
/// codepoints of the string, respectively. To iterate over codepoints along
/// with byte indices, use [`char_indices`].
///
/// [`bytes`]: str::bytes
/// [`chars`]: str::chars
/// [`char_indices`]: str::char_indices
///
/// # Deref
///
......@@ -700,7 +772,10 @@ impl String {
/// * The first `length` bytes at `buf` need to be valid UTF-8.
///
/// Violating these may cause problems like corrupting the allocator's
/// internal data structures.
/// internal data structures. For example, it is normally **not** safe to
/// build a `String` from a pointer to a C `char` array containing UTF-8
/// _unless_ you are certain that array was originally allocated by the
/// Rust standard library's allocator.
///
/// The ownership of `buf` is effectively transferred to the
/// `String` which may then deallocate, reallocate or change the
......@@ -1040,7 +1115,7 @@ impl String {
}
/// Tries to reserve the minimum capacity for exactly `additional` more elements to
/// be inserted in the given `String`. After calling `reserve_exact`,
/// be inserted in the given `String`. After calling `try_reserve_exact`,
/// capacity will be greater than or equal to `self.len() + additional`.
/// Does nothing if the capacity is already sufficient.
///
......@@ -2720,7 +2795,7 @@ impl From<String> for Vec<u8> {
/// let v1 = Vec::from(s1);
///
/// for b in v1 {
/// println!("{}", b);
/// println!("{b}");
/// }
/// ```
fn from(string: String) -> Vec<u8> {
......
......@@ -36,6 +36,18 @@ macro_rules! define_panicking_intrinsics(
}
);
define_panicking_intrinsics!("`f32` should not be used", {
__eqsf2,
__gesf2,
__lesf2,
__nesf2,
__unordsf2,
});
define_panicking_intrinsics!("`f64` should not be used", {
__unorddf2,
});
define_panicking_intrinsics!("`i128` should not be used", {
__ashrti3,
__muloti4,
......@@ -50,8 +62,18 @@ define_panicking_intrinsics!("`u128` should not be used", {
__umodti3,
});
#[cfg(target_arch = "arm")]
define_panicking_intrinsics!("`f32` should not be used", {
__aeabi_fcmpeq,
__aeabi_fcmpun,
});
#[cfg(target_arch = "arm")]
define_panicking_intrinsics!("`f64` should not be used", {
__aeabi_dcmpun,
});
#[cfg(target_arch = "arm")]
define_panicking_intrinsics!("`u64` division/modulo should not be used", {
__aeabi_uldivmod,
__mulodi4,
});
......@@ -504,13 +504,13 @@ EXPORT_SYMBOL_GPL(rust_helper_read_seqcount_retry);
void rust_helper_write_seqcount_begin(seqcount_t *s)
{
do_write_seqcount_begin(s);
//do_write_seqcount_begin(s);
}
EXPORT_SYMBOL_GPL(rust_helper_write_seqcount_begin);
void rust_helper_write_seqcount_end(seqcount_t *s)
{
do_write_seqcount_end(s);
//do_write_seqcount_end(s);
}
EXPORT_SYMBOL_GPL(rust_helper_write_seqcount_end);
......
......@@ -63,7 +63,7 @@ pub trait Driver {
/// Cleans any resources up that are associated with the device.
///
/// This is called when the driver is detached from the device.
fn remove(_data: &Self::Data) {}
fn remove(_data: &Self::Data) -> i32;
}
/// An adapter for the registration of Amba drivers.
......@@ -133,7 +133,7 @@ unsafe extern "C" fn probe_callback<T: Driver>(
}
}
unsafe extern "C" fn remove_callback<T: Driver>(adev: *mut bindings::amba_device) {
unsafe extern "C" fn remove_callback<T: Driver>(adev: *mut bindings::amba_device) -> i32 {
// SAFETY: `adev` is valid by the contract with the C code.
let ptr = unsafe { bindings::amba_get_drvdata(adev) };
// SAFETY: The value returned by `amba_get_drvdata` was stored by a previous call to
......@@ -142,6 +142,7 @@ unsafe extern "C" fn remove_callback<T: Driver>(adev: *mut bindings::amba_device
let data = unsafe { T::Data::from_pointer(ptr) };
T::remove(&data);
<T::Data as driver::DeviceRemoval>::device_remove(&data);
0
}
/// An Amba device.
......
......@@ -148,7 +148,7 @@ pub unsafe trait RawDevice {
// `fmt::Arguments`, which is what we're passing as the last argument.
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_dev_printk(
bindings::dev_printk(
klevel as *const _ as *const c_types::c_char,
self.raw_device(),
c_str!("%pA").as_char_ptr(),
......
......@@ -539,6 +539,10 @@ impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
} else {
None
},
kabi_reserved1: 0,
kabi_reserved2: 0,
kabi_reserved3: 0,
kabi_reserved4: 0,
};
/// Builds an instance of [`struct file_operations`].
......
......@@ -375,7 +375,7 @@ impl Domain {
/// `ChainedGuard` instance.
pub fn generic_handle_chained(&self, hwirq: u32, _guard: &ChainedGuard<'_>) {
// SAFETY: `ptr` is valid by the type invariants.
unsafe { bindings::generic_handle_domain_irq(self.ptr, hwirq) };
//unsafe { bindings::generic_handle_domain_irq(self.ptr, hwirq) };
}
}
......
......@@ -108,9 +108,8 @@ unsafe impl AlwaysRefCounted for SkBuff {
unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
unsafe {
bindings::kfree_skb_reason(
obj.cast().as_ptr(),
bindings::skb_drop_reason_SKB_DROP_REASON_NOT_SPECIFIED,
bindings::__kfree_skb(
obj.cast().as_ptr()
)
};
}
......
......@@ -205,7 +205,7 @@ impl<T: Filter> Registration<T> {
this.hook.priority = pri_base.saturating_add(priority);
this.hook.priv_ = data_pointer as _;
this.hook.hook = Some(Self::hook_callback);
crate::static_assert!(bindings::nf_hook_ops_type_NF_HOOK_OP_UNDEFINED == 0);
// crate::static_assert!(bindings::nf_hook_ops_type_NF_HOOK_OP_UNDEFINED == 0);
if let Some(ref device) = dev {
this.hook.dev = device.0.get();
......@@ -276,13 +276,13 @@ pub mod netdev {
use crate::bindings;
/// Hooks allowed in the [`super::Family::NetDev`] family.
#[repr(u32)]
//#[repr(u32)]
pub enum Hook {
/// All inbound packets through the given device.
Ingress = bindings::nf_dev_hooks_NF_NETDEV_INGRESS,
// /// All inbound packets through the given device.
// Ingress = bindings::nf_dev_hooks_NF_NETDEV_INGRESS,
/// All outbound packets through the given device.
Egress = bindings::nf_dev_hooks_NF_NETDEV_EGRESS,
// /// All outbound packets through the given device.
// Egress = bindings::nf_dev_hooks_NF_NETDEV_EGRESS,
}
}
......
......@@ -104,7 +104,7 @@ pub unsafe fn call_printk(
// `_printk` does not seem to fail in any path.
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
bindings::printk(
format_string.as_ptr() as _,
module_name.as_ptr(),
&args as *const _ as *const c_void,
......@@ -125,7 +125,7 @@ pub fn call_printk_cont(args: fmt::Arguments<'_>) {
// SAFETY: The format string is fixed.
#[cfg(CONFIG_PRINTK)]
unsafe {
bindings::_printk(
bindings::printk(
format_strings::CONT.as_ptr() as _,
&args as *const _ as *const c_void,
);
......
......@@ -17,7 +17,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result {
}
unsafe {
bindings::get_random_bytes(dest.as_mut_ptr() as *mut c_types::c_void, dest.len());
bindings::get_random_bytes(dest.as_mut_ptr() as *mut c_types::c_void, dest.len() as i32);
}
Ok(())
}
......@@ -37,6 +37,6 @@ pub fn getrandom_nonblock(dest: &mut [u8]) -> Result {
/// Does *not* credit the kernel entropy counter though.
pub fn add_randomness(data: &[u8]) {
unsafe {
bindings::add_device_randomness(data.as_ptr() as *const c_types::c_void, data.len());
bindings::add_device_randomness(data.as_ptr() as *const c_types::c_void, data.len() as u32);
}
}
......@@ -11,6 +11,5 @@ obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE) += rust_semaphore.o
obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE_C) += rust_semaphore_c.o
obj-$(CONFIG_SAMPLE_RUST_RANDOM) += rust_random.o
obj-$(CONFIG_SAMPLE_RUST_PLATFORM) += rust_platform.o
obj-$(CONFIG_SAMPLE_RUST_NETFILTER) += rust_netfilter.o
subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Print the C compiler name and its version in a 5 or 6-digit form.
# Also, perform the minimum version check.
set -e
# Print the C compiler name and some version components.
get_c_compiler_info()
{
cat <<- EOF | "$@" -E -P -x c - 2>/dev/null
#if defined(__clang__)
Clang __clang_major__ __clang_minor__ __clang_patchlevel__
#elif defined(__INTEL_COMPILER)
ICC __INTEL_COMPILER __INTEL_COMPILER_UPDATE
#elif defined(__GNUC__)
GCC __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
#else
unknown
#endif
EOF
}
# Convert the version string x.y.z to a canonical 5 or 6-digit form.
get_canonical_version()
{
IFS=.
set -- $1
echo $((10000 * $1 + 100 * $2 + $3))
}
# $@ instead of $1 because multiple words might be given, e.g. CC="ccache gcc".
orig_args="$@"
set -- $(get_c_compiler_info "$@")
name=$1
min_tool_version=$(dirname $0)/min-tool-version.sh
case "$name" in
GCC)
version=$2.$3.$4
min_version=$($min_tool_version gcc)
;;
Clang)
version=$2.$3.$4
min_version=$($min_tool_version llvm)
;;
ICC)
version=$(($2 / 100)).$(($2 % 100)).$3
min_version=$($min_tool_version icc)
;;
*)
echo "$orig_args: unknown C compiler" >&2
exit 1
;;
esac
cversion=$(get_canonical_version $version)
min_cversion=$(get_canonical_version $min_version)
if [ "$cversion" -lt "$min_cversion" ]; then
echo >&2 "***"
echo >&2 "*** C compiler is too old."
echo >&2 "*** Your $name version: $version"
echo >&2 "*** Minimum $name version: $min_version"
echo >&2 "***"
exit 1
fi
echo $name $cversion
......@@ -1043,13 +1043,162 @@ static int conf_touch_deps(void)
return 0;
}
/* The returned pointer must be freed on the caller side */
static char *escape_string_value(const char *in)
{
const char *p;
char *out;
size_t len;
len = strlen(in) + strlen("\"\"") + 1;
p = in;
while (1) {
p += strcspn(p, "\"\\");
if (p[0] == '\0')
break;
len++;
p++;
}
out = xmalloc(len);
out[0] = '\0';
strcat(out, "\"");
p = in;
while (1) {
len = strcspn(p, "\"\\");
strncat(out, p, len);
p += len;
if (p[0] == '\0')
break;
strcat(out, "\\");
strncat(out, p++, 1);
}
strcat(out, "\"");
return out;
}
static void print_symbol_for_rustccfg(FILE *fp, struct symbol *sym)
{
const char *val;
const char *val_prefix = "";
char *val_prefixed = NULL;
size_t val_prefixed_len;
char *escaped = NULL;
if (sym->type == S_UNKNOWN)
return;
val = sym_get_string_value(sym);
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
/*
* We do not care about disabled ones, i.e. no need for
* what otherwise are "comments" in other printers.
*/
if (*val == 'n')
return;
/*
* To have similar functionality to the C macro `IS_ENABLED()`
* we provide an empty `--cfg CONFIG_X` here in both `y`
* and `m` cases.
*
* Then, the common `fprintf()` below will also give us
* a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can
* be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`.
*/
fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name);
break;
case S_HEX:
if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
val_prefix = "0x";
break;
default:
break;
}
if (strlen(val_prefix) > 0) {
val_prefixed_len = strlen(val) + strlen(val_prefix) + 1;
val_prefixed = xmalloc(val_prefixed_len);
snprintf(val_prefixed, val_prefixed_len, "%s%s", val_prefix, val);
val = val_prefixed;
}
/* All values get escaped: the `--cfg` option only takes strings */
escaped = escape_string_value(val);
val = escaped;
fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, val);
free(escaped);
free(val_prefixed);
}
static int __conf_write_autoconf(const char *filename,
void (*print_symbol)(FILE *, struct symbol *),
const struct comment_style *comment_style)
{
char tmp[PATH_MAX];
FILE *file;
struct symbol *sym;
int ret, i;
if (make_parent_dir(filename))
return -1;
ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename);
if (ret >= sizeof(tmp)) /* check truncation */
return -1;
file = fopen(tmp, "w");
if (!file) {
perror("fopen");
return -1;
}
for_all_symbols(i, sym)
if ((sym->flags & SYMBOL_WRITE) && sym->name)
print_symbol(file, sym);
/* check possible errors in conf_write_heading() and print_symbol() */
if (ferror(file))
return -1;
fclose(file);
if (rename(tmp, filename)) {
perror("rename");
return -1;
}
return 0;
}
static const char *conf_get_rustccfg_name(void)
{
char *name = getenv("KCONFIG_RUSTCCFG");
return name ? name : "include/generated/rustc_cfg";
}
int conf_write_autoconf(int overwrite)
{
struct symbol *sym;
const char *name;
const char *autoconf_name = conf_get_autoconfig_name();
FILE *out, *out_h;
int i;
int ret, i;
if (!overwrite && is_present(autoconf_name))
return 0;
......@@ -1101,7 +1250,10 @@ int conf_write_autoconf(int overwrite)
if (rename(".tmpconfig", autoconf_name))
return 1;
return 0;
ret = __conf_write_autoconf(conf_get_rustccfg_name(),
print_symbol_for_rustccfg,
NULL);
return ret;
}
static int sym_change_count;
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
#
# Print the minimum supported version of the given tool.
# When you raise the minimum version, please update
# Documentation/process/changes.rst as well.
set -e
if [ $# != 1 ]; then
echo "Usage: $0 toolname" >&2
exit 1
fi
case "$1" in
binutils)
echo 2.23.0
;;
gcc)
echo 5.1.0
;;
icc)
# temporary
echo 16.0.3
;;
llvm)
if [ "$SRCARCH" = s390 ]; then
echo 14.0.0
else
echo 11.0.0
fi
;;
rustc)
echo 1.62.0
;;
bindgen)
echo 0.56.0
;;
*)
echo "$1: unknown tool" >&2
exit 1
;;
esac
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册