diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e7d243bfcb0f7..b22eb1ff6354b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -245,7 +245,7 @@ where fn replace(&mut self, key: K) -> Option<K> { let root = Self::ensure_is_owned(&mut self.root); match search::search_tree::<marker::Mut<'_>, K, (), K>(root.node_as_mut(), &key) { - Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), + Found(handle) => Some(mem::replace(handle.into_key_mut(), key)), GoDown(handle) => { VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData } .insert(()); @@ -811,7 +811,7 @@ impl<K: Ord, V> BTreeMap<K, V> { { let root_node = self.root.as_mut()?.node_as_mut(); match search::search_tree(root_node, key) { - Found(handle) => Some(handle.into_kv_mut().1), + Found(handle) => Some(handle.into_val_mut()), GoDown(_) => None, } } @@ -2748,7 +2748,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_mut(self) -> &'a mut V { - self.handle.into_kv_mut().1 + self.handle.into_val_mut() } /// Sets the value of the entry with the `OccupiedEntry`'s key, @@ -3024,3 +3024,6 @@ impl<K: Ord, V, I: Iterator<Item = (K, V)>> Iterator for MergeIter<K, V, I> { } } } + +#[cfg(test)] +mod tests; diff --git a/library/alloc/tests/btree/map.rs b/library/alloc/src/collections/btree/map/tests.rs similarity index 99% rename from library/alloc/tests/btree/map.rs rename to library/alloc/src/collections/btree/map/tests.rs index 5777bd6090714..910e7043092a5 100644 --- a/library/alloc/tests/btree/map.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1,16 +1,20 @@ -use std::collections::btree_map::Entry::{Occupied, Vacant}; -use std::collections::BTreeMap; +use crate::boxed::Box; +use crate::collections::btree_map::Entry::{Occupied, Vacant}; +use crate::collections::BTreeMap; +use crate::fmt::Debug; +use crate::rc::Rc; +use crate::string::String; +use crate::string::ToString; +use crate::vec::Vec; use std::convert::TryFrom; -use std::fmt::Debug; use std::iter::FromIterator; use std::mem; use std::ops::Bound::{self, Excluded, Included, Unbounded}; use std::ops::RangeBounds; use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering}; -use super::DeterministicRng; +use super::super::DeterministicRng; // Value of node::CAPACITY, thus capacity of a tree with a single level, // i.e. a tree who's root is a leaf node at height 0. diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index 543ff41a4d48d..6c8a588eb58f3 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -25,3 +25,30 @@ pub unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T { } }) } + +#[cfg(test)] +/// XorShiftRng +struct DeterministicRng { + x: u32, + y: u32, + z: u32, + w: u32, +} + +#[cfg(test)] +impl DeterministicRng { + fn new() -> Self { + DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } + } + + fn next(&mut self) -> u32 { + let x = self.x; + let t = x ^ (x << 11); + self.x = self.y; + self.y = self.z; + self.z = self.w; + let w_ = self.w; + self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); + self.w + } +} diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index c0b75fd5eacec..acc2ae73572ba 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -43,6 +43,9 @@ use crate::boxed::Box; const B: usize = 6; pub const MIN_LEN: usize = B - 1; pub const CAPACITY: usize = 2 * B - 1; +const KV_IDX_CENTER: usize = B - 1; +const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1; +const EDGE_IDX_RIGHT_OF_CENTER: usize = B; /// The underlying representation of leaf nodes. #[repr(C)] @@ -834,38 +837,12 @@ enum InsertionPlace { fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) { debug_assert!(edge_idx <= CAPACITY); // Rust issue #74834 tries to explain these symmetric rules. - let middle_kv_idx; - let insertion; - if edge_idx <= B - 2 { - middle_kv_idx = B - 2; - insertion = InsertionPlace::Left(edge_idx); - } else if edge_idx == B - 1 { - middle_kv_idx = B - 1; - insertion = InsertionPlace::Left(edge_idx); - } else if edge_idx == B { - middle_kv_idx = B - 1; - insertion = InsertionPlace::Right(0); - } else { - middle_kv_idx = B; - let new_edge_idx = edge_idx - (B + 1); - insertion = InsertionPlace::Right(new_edge_idx); - } - let mut left_len = middle_kv_idx; - let mut right_len = CAPACITY - middle_kv_idx - 1; - match insertion { - InsertionPlace::Left(edge_idx) => { - debug_assert!(edge_idx <= left_len); - left_len += 1; - } - InsertionPlace::Right(edge_idx) => { - debug_assert!(edge_idx <= right_len); - right_len += 1; - } + match edge_idx { + 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)), + EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)), + EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)), + _ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))), } - debug_assert!(left_len >= MIN_LEN); - debug_assert!(right_len >= MIN_LEN); - debug_assert!(left_len + right_len == CAPACITY); - (middle_kv_idx, insertion) } impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::Edge> { @@ -1067,6 +1044,16 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Immut<'a>, K, V, NodeTyp } impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> { + pub fn into_key_mut(self) -> &'a mut K { + let keys = self.node.into_key_slice_mut(); + unsafe { keys.get_unchecked_mut(self.idx) } + } + + pub fn into_val_mut(self) -> &'a mut V { + let vals = self.node.into_val_slice_mut(); + unsafe { vals.get_unchecked_mut(self.idx) } + } + pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) { unsafe { let (keys, vals) = self.node.into_slices_mut(); @@ -1261,8 +1248,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: unsafe { let (k, v, edge) = self.reborrow_mut().left_edge().descend().pop(); - let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k); - let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v); + let k = mem::replace(self.kv_mut().0, k); + let v = mem::replace(self.kv_mut().1, v); match self.reborrow_mut().right_edge().descend().force() { ForceResult::Leaf(mut leaf) => leaf.push_front(k, v), @@ -1278,8 +1265,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: unsafe { let (k, v, edge) = self.reborrow_mut().right_edge().descend().pop_front(); - let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k); - let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v); + let k = mem::replace(self.kv_mut().0, k); + let v = mem::replace(self.kv_mut().1, v); match self.reborrow_mut().left_edge().descend().force() { ForceResult::Leaf(mut leaf) => leaf.push(k, v), @@ -1307,7 +1294,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: let left_kv = left_node.reborrow_mut().into_kv_pointers_mut(); let right_kv = right_node.reborrow_mut().into_kv_pointers_mut(); let parent_kv = { - let kv = self.reborrow_mut().into_kv_mut(); + let kv = self.kv_mut(); (kv.0 as *mut K, kv.1 as *mut V) }; @@ -1364,7 +1351,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: let left_kv = left_node.reborrow_mut().into_kv_pointers_mut(); let right_kv = right_node.reborrow_mut().into_kv_pointers_mut(); let parent_kv = { - let kv = self.reborrow_mut().into_kv_mut(); + let kv = self.kv_mut(); (kv.0 as *mut K, kv.1 as *mut V) }; @@ -1590,3 +1577,6 @@ unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T { ret } } + +#[cfg(test)] +mod tests; diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs new file mode 100644 index 0000000000000..e2416974ddca3 --- /dev/null +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -0,0 +1,25 @@ +use super::*; + +#[test] +fn test_splitpoint() { + for idx in 0..=CAPACITY { + let (middle_kv_idx, insertion) = splitpoint(idx); + + // Simulate performing the split: + let mut left_len = middle_kv_idx; + let mut right_len = CAPACITY - middle_kv_idx - 1; + match insertion { + InsertionPlace::Left(edge_idx) => { + assert!(edge_idx <= left_len); + left_len += 1; + } + InsertionPlace::Right(edge_idx) => { + assert!(edge_idx <= right_len); + right_len += 1; + } + } + assert!(left_len >= MIN_LEN); + assert!(right_len >= MIN_LEN); + assert!(left_len + right_len == CAPACITY); + } +} diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 35f4ef1d9b4c7..a559e87e4e298 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1572,3 +1572,6 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { #[stable(feature = "fused", since = "1.26.0")] impl<T: Ord> FusedIterator for Union<'_, T> {} + +#[cfg(test)] +mod tests; diff --git a/library/alloc/tests/btree/set.rs b/library/alloc/src/collections/btree/set/tests.rs similarity index 98% rename from library/alloc/tests/btree/set.rs rename to library/alloc/src/collections/btree/set/tests.rs index b6c34b7c6c346..f4e957e22fe15 100644 --- a/library/alloc/tests/btree/set.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -1,9 +1,10 @@ -use std::collections::BTreeSet; +use crate::collections::BTreeSet; +use crate::vec::Vec; use std::iter::FromIterator; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::atomic::{AtomicU32, Ordering}; -use super::DeterministicRng; +use super::super::DeterministicRng; #[test] fn test_clone_eq() { @@ -15,24 +16,6 @@ fn test_clone_eq() { assert_eq!(m.clone(), m); } -#[test] -fn test_hash() { - use crate::hash; - - let mut x = BTreeSet::new(); - let mut y = BTreeSet::new(); - - x.insert(1); - x.insert(2); - x.insert(3); - - y.insert(3); - y.insert(2); - y.insert(1); - - assert_eq!(hash(&x), hash(&y)); -} - #[test] fn test_iter_min_max() { let mut a = BTreeSet::new(); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 9ac23886d4e15..2d25941a52412 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -80,6 +80,7 @@ #![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(btree_drain_filter)] #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] @@ -93,6 +94,7 @@ #![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(exclusive_range_pattern)] #![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] @@ -101,6 +103,8 @@ #![feature(lang_items)] #![feature(layout_for_ptr)] #![feature(libc)] +#![feature(map_first_last)] +#![feature(map_into_keys_values)] #![feature(negative_impls)] #![feature(new_uninit)] #![feature(nll)] diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index de707a71a8c9e..8ca0a0883cb16 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2620,9 +2620,6 @@ where /// /// This `struct` is created by the `into_iter` method on [`Vec`] (provided /// by the [`IntoIterator`] trait). -/// -/// [`Vec`]: struct.Vec.html -/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter<T> { buf: NonNull<T>, @@ -2802,10 +2799,7 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter<T> { /// A draining iterator for `Vec<T>`. /// -/// This `struct` is created by the [`drain`] method on [`Vec`]. -/// -/// [`drain`]: struct.Vec.html#method.drain -/// [`Vec`]: struct.Vec.html +/// This `struct` is created by [`Vec::drain`]. #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, T: 'a> { /// Index of tail to preserve @@ -2933,11 +2927,8 @@ impl<T> FusedIterator for Drain<'_, T> {} /// A splicing iterator for `Vec`. /// -/// This struct is created by the [`splice()`] method on [`Vec`]. See its -/// documentation for more. -/// -/// [`splice()`]: struct.Vec.html#method.splice -/// [`Vec`]: struct.Vec.html +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. #[derive(Debug)] #[stable(feature = "vec_splice", since = "1.21.0")] pub struct Splice<'a, I: Iterator + 'a> { diff --git a/library/alloc/tests/btree/mod.rs b/library/alloc/tests/btree/mod.rs deleted file mode 100644 index 1d08ae13e0540..0000000000000 --- a/library/alloc/tests/btree/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -mod map; -mod set; - -/// XorShiftRng -struct DeterministicRng { - x: u32, - y: u32, - z: u32, - w: u32, -} - -impl DeterministicRng { - fn new() -> Self { - DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } - } - - fn next(&mut self) -> u32 { - let x = self.x; - let t = x ^ (x << 11); - self.x = self.y; - self.y = self.z; - self.z = self.w; - let w_ = self.w; - self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); - self.w - } -} diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs new file mode 100644 index 0000000000000..e06a95ded94c7 --- /dev/null +++ b/library/alloc/tests/btree_set_hash.rs @@ -0,0 +1,19 @@ +use std::collections::BTreeSet; + +#[test] +fn test_hash() { + use crate::hash; + + let mut x = BTreeSet::new(); + let mut y = BTreeSet::new(); + + x.insert(1); + x.insert(2); + x.insert(3); + + y.insert(3); + y.insert(2); + y.insert(1); + + assert_eq!(hash(&x), hash(&y)); +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3aacd4a687e38..f2ba1ab64810b 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -1,10 +1,7 @@ #![feature(allocator_api)] #![feature(box_syntax)] -#![feature(btree_drain_filter)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] -#![feature(map_first_last)] -#![feature(map_into_keys_values)] #![feature(new_uninit)] #![feature(pattern)] #![feature(str_split_once)] @@ -25,7 +22,7 @@ mod arc; mod binary_heap; mod borrow; mod boxed; -mod btree; +mod btree_set_hash; mod cow_str; mod fmt; mod heap; diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 920f5e9c0bd28..e45aa86c0795a 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -56,9 +56,9 @@ use crate::ptr; /// working with [pinned] data, where reusing the memory without calling the destructor could lead /// to Undefined Behaviour. /// -/// [`mem::zeroed`]: fn.zeroed.html -/// [`MaybeUninit<T>`]: union.MaybeUninit.html -/// [pinned]: ../pin/index.html +/// [`mem::zeroed`]: crate::mem::zeroed +/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit +/// [pinned]: crate::pin #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -116,8 +116,6 @@ impl<T> ManuallyDrop<T> { /// leaving the state of this container unchanged. /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. /// - /// [`ManuallyDrop::drop`]: #method.drop - /// [`ManuallyDrop::into_inner`]: #method.into_inner #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[stable(feature = "manually_drop_take", since = "1.42.0")] #[inline] @@ -148,9 +146,7 @@ impl<T: ?Sized> ManuallyDrop<T> { /// This is normally prevented by the type system, but users of `ManuallyDrop` must /// uphold those guarantees without assistance from the compiler. /// - /// [`ManuallyDrop::into_inner`]: #method.into_inner - /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html - /// [pinned]: ../pin/index.html + /// [pinned]: crate::pin #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 027498d3911c8..d2d65fd2fa517 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -247,7 +247,7 @@ impl<T> MaybeUninit<T> { /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. /// - /// [`assume_init`]: #method.assume_init + /// [`assume_init`]: MaybeUninit::assume_init #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] #[inline(always)] @@ -525,7 +525,7 @@ impl<T> MaybeUninit<T> { /// to ensure that that data may indeed be duplicated. /// /// [inv]: #initialization-invariant - /// [`assume_init`]: #method.assume_init + /// [`assume_init`]: MaybeUninit::assume_init /// /// # Examples /// diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index fc07fa77b85e7..ef0ef415b4cba 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -16,7 +16,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.74", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.32" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index da25a0ede729d..11b3f22503e83 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -1,3 +1,4 @@ +#![deny(unsafe_op_in_unsafe_fn)] use crate::ascii; use crate::borrow::{Borrow, Cow}; use crate::cmp::Ordering; @@ -35,23 +36,23 @@ use crate::sys; /// example, you can build a `CString` straight out of a [`String`] or /// a [`&str`], since both implement that trait). /// -/// The [`new`] method will actually check that the provided `&[u8]` +/// 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 /// finds one. /// /// # Extracting a raw pointer to the whole C string /// -/// `CString` implements a [`as_ptr`] method through the [`Deref`] +/// `CString` implements a [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`] /// trait. This method will give you a `*const c_char` which you can /// feed directly to extern functions that expect a nul-terminated -/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a +/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a /// read-only pointer; if the C code writes to it, that causes /// undefined behavior. /// /// # Extracting a slice of the whole C string /// /// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a -/// `CString` with the [`as_bytes`] method. Slices produced in this +/// `CString` with the [`CString::as_bytes`] method. Slices produced in this /// way do *not* contain the trailing nul terminator. This is useful /// when you will be calling an extern function that takes a `*const /// u8` argument which is not necessarily nul-terminated, plus another @@ -60,7 +61,7 @@ use crate::sys; /// [`len`][slice.len] method. /// /// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you -/// can use [`as_bytes_with_nul`] instead. +/// can use [`CString::as_bytes_with_nul`] instead. /// /// Once you have the kind of slice you need (with or without a nul /// terminator), you can call the slice's own @@ -68,20 +69,11 @@ use crate::sys; /// extern functions. See the documentation for that function for a /// discussion on ensuring the lifetime of the raw pointer. /// -/// [`Into`]: ../convert/trait.Into.html -/// [`Vec`]: ../vec/struct.Vec.html -/// [`String`]: ../string/struct.String.html -/// [`&str`]: ../primitive.str.html -/// [`u8`]: ../primitive.u8.html -/// [`new`]: #method.new -/// [`as_bytes`]: #method.as_bytes -/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul -/// [`as_ptr`]: #method.as_ptr +/// [`&str`]: str /// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr /// [slice.len]: ../primitive.slice.html#method.len -/// [`Deref`]: ../ops/trait.Deref.html -/// [`CStr`]: struct.CStr.html -/// [`&CStr`]: struct.CStr.html +/// [`Deref`]: ops::Deref +/// [`&CStr`]: CStr /// /// # Examples /// @@ -113,7 +105,6 @@ use crate::sys; /// documentation of `CString` before use, as improper ownership management /// of `CString` instances can lead to invalid memory accesses, memory leaks, /// and other memory errors. - #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct CString { @@ -137,8 +128,8 @@ pub struct CString { /// /// Note that this structure is **not** `repr(C)` and is not recommended to be /// placed in the signatures of FFI functions. Instead, safe wrappers of FFI -/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe -/// interface to other consumers. +/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide +/// a safe interface to other consumers. /// /// # Examples /// @@ -189,11 +180,7 @@ pub struct CString { /// println!("string: {}", my_string_safe()); /// ``` /// -/// [`u8`]: ../primitive.u8.html -/// [`&str`]: ../primitive.str.html -/// [`String`]: ../string/struct.String.html -/// [`CString`]: struct.CString.html -/// [`from_ptr`]: #method.from_ptr +/// [`&str`]: str #[derive(Hash)] #[stable(feature = "rust1", since = "1.0.0")] // FIXME: @@ -218,9 +205,6 @@ pub struct CStr { /// This error is created by the [`new`][`CString::new`] method on /// [`CString`]. See its documentation for more. /// -/// [`CString`]: struct.CString.html -/// [`CString::new`]: struct.CString.html#method.new -/// /// # Examples /// /// ``` @@ -237,12 +221,9 @@ pub struct NulError(usize, Vec<u8>); /// The slice used to create a [`CStr`] must have one and only one nul byte, /// positioned at the end. /// -/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`]. +/// This error is created by the [`CStr::from_bytes_with_nul`] method. /// See its documentation for more. /// -/// [`CStr`]: struct.CStr.html -/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul -/// /// # Examples /// /// ``` @@ -261,12 +242,9 @@ pub struct FromBytesWithNulError { /// The vector used to create a [`CString`] must have one and only one nul byte, /// positioned at the end. /// -/// This error is created by the [`from_vec_with_nul`] method on [`CString`]. +/// This error is created by the [`CString::from_vec_with_nul`] method. /// See its documentation for more. /// -/// [`CString`]: struct.CString.html -/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul -/// /// # Examples /// /// ``` @@ -316,8 +294,6 @@ impl FromVecWithNulError { /// /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); /// ``` - /// - /// [`CString`]: struct.CString.html pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -343,8 +319,6 @@ impl FromVecWithNulError { /// /// assert_eq!(bytes, value.unwrap_err().into_bytes()); /// ``` - /// - /// [`CString`]: struct.CString.html pub fn into_bytes(self) -> Vec<u8> { self.bytes } @@ -352,17 +326,12 @@ impl FromVecWithNulError { /// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`]. /// -/// `CString` is just a wrapper over a buffer of bytes with a nul -/// terminator; [`into_string`][`CString::into_string`] performs UTF-8 -/// validation on those bytes and may return this error. +/// `CString` is just a wrapper over a buffer of bytes with a nul terminator; +/// [`CString::into_string`] performs UTF-8 validation on those bytes and may +/// return this error. /// -/// This `struct` is created by the -/// [`into_string`][`CString::into_string`] method on [`CString`]. See +/// This `struct` is created by [`CString::into_string()`]. See /// its documentation for more. -/// -/// [`String`]: ../string/struct.String.html -/// [`CString`]: struct.CString.html -/// [`CString::into_string`]: struct.CString.html#method.into_string #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstring_into", since = "1.7.0")] pub struct IntoStringError { @@ -398,8 +367,6 @@ impl CString { /// This function will return an error if the supplied bytes contain an /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as /// the position of the nul byte. - /// - /// [`NulError`]: struct.NulError.html #[stable(feature = "rust1", since = "1.0.0")] pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> { trait SpecIntoVec { @@ -439,11 +406,9 @@ impl CString { /// Creates a C-compatible string by consuming a byte vector, /// without checking for interior 0 bytes. /// - /// This method is equivalent to [`new`] except that no runtime assertion - /// is made that `v` contains no 0 bytes, and it requires an actual - /// byte vector, not anything that can be converted to one with Into. - /// - /// [`new`]: #method.new + /// This method is equivalent to [`CString::new`] except that no runtime + /// assertion is made that `v` contains no 0 bytes, and it requires an + /// actual byte vector, not anything that can be converted to one with Into. /// /// # Examples /// @@ -462,21 +427,22 @@ impl CString { CString { inner: v.into_boxed_slice() } } - /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`]. + /// Retakes ownership of a `CString` that was transferred to C via + /// [`CString::into_raw`]. /// /// Additionally, the length of the string will be recalculated from the pointer. /// /// # Safety /// /// This should only ever be called with a pointer that was earlier - /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g., trying to take + /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take /// ownership of a string that was allocated by foreign code) is likely to lead /// to undefined behavior or allocator corruption. /// /// It should be noted that the length isn't just "recomputed," but that /// the recomputed length must match the original length from the - /// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods - /// should not be used when passing the string to C functions that can + /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw` + /// methods should not be used when passing the string to C functions that can /// modify the string's length. /// /// > **Note:** If you need to borrow a string that was allocated by @@ -485,9 +451,6 @@ impl CString { /// > make your own provisions for freeing it appropriately, likely /// > with the foreign code's API to do that. /// - /// [`into_raw`]: #method.into_raw - /// [`CStr`]: struct.CStr.html - /// /// # Examples /// /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake @@ -510,26 +473,31 @@ impl CString { /// ``` #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { - let len = sys::strlen(ptr) + 1; // Including the NUL byte - let slice = slice::from_raw_parts_mut(ptr, len as usize); - CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } + // SAFETY: This is called with a pointer that was obtained from a call + // to `CString::into_raw` and the length has not been modified. As such, + // we know there is a NUL byte (and only one) at the end and that the + // information about the size of the allocation is correct on Rust's + // side. + unsafe { + let len = sys::strlen(ptr) + 1; // Including the NUL byte + let slice = slice::from_raw_parts_mut(ptr, len as usize); + CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } + } } /// Consumes the `CString` and transfers ownership of the string to a C caller. /// /// The pointer which this function returns must be returned to Rust and reconstituted using - /// [`from_raw`] to be properly deallocated. Specifically, one + /// [`CString::from_raw`] to be properly deallocated. Specifically, one /// should *not* use the standard C `free()` function to deallocate /// this string. /// - /// Failure to call [`from_raw`] will lead to a memory leak. + /// Failure to call [`CString::from_raw`] will lead to a memory leak. /// /// The C side must **not** modify the length of the string (by writing a /// `NULL` somewhere inside the string or removing the final one) before - /// it makes it back into Rust using [`from_raw`]. See the safety section - /// in [`from_raw`]. - /// - /// [`from_raw`]: #method.from_raw + /// it makes it back into Rust using [`CString::from_raw`]. See the safety section + /// in [`CString::from_raw`]. /// /// # Examples /// @@ -560,8 +528,6 @@ impl CString { /// /// On failure, ownership of the original `CString` is returned. /// - /// [`String`]: ../string/struct.String.html - /// /// # Examples /// /// ``` @@ -608,10 +574,8 @@ impl CString { vec } - /// Equivalent to the [`into_bytes`] function except that the returned vector - /// includes the trailing nul terminator. - /// - /// [`into_bytes`]: #method.into_bytes + /// Equivalent to [`CString::into_bytes()`] except that the + /// returned vector includes the trailing nul terminator. /// /// # Examples /// @@ -632,9 +596,7 @@ impl CString { /// The returned slice does **not** contain the trailing nul /// terminator, and it is guaranteed to not have any interior nul /// bytes. If you need the nul terminator, use - /// [`as_bytes_with_nul`] instead. - /// - /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul + /// [`CString::as_bytes_with_nul`] instead. /// /// # Examples /// @@ -651,10 +613,8 @@ impl CString { &self.inner[..self.inner.len() - 1] } - /// Equivalent to the [`as_bytes`] function except that the returned slice - /// includes the trailing nul terminator. - /// - /// [`as_bytes`]: #method.as_bytes + /// Equivalent to [`CString::as_bytes()`] except that the + /// returned slice includes the trailing nul terminator. /// /// # Examples /// @@ -673,8 +633,6 @@ impl CString { /// Extracts a [`CStr`] slice containing the entire string. /// - /// [`CStr`]: struct.CStr.html - /// /// # Examples /// /// ``` @@ -693,8 +651,6 @@ impl CString { /// Converts this `CString` into a boxed [`CStr`]. /// - /// [`CStr`]: struct.CStr.html - /// /// # Examples /// /// ``` @@ -711,8 +667,6 @@ impl CString { } /// Bypass "move out of struct which implements [`Drop`] trait" restriction. - /// - /// [`Drop`]: ../ops/trait.Drop.html fn into_inner(self) -> Box<[u8]> { // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)` // so we use `ManuallyDrop` to ensure `self` is not dropped. @@ -722,12 +676,12 @@ impl CString { unsafe { ptr::read(&this.inner) } } - /// Converts a `Vec` of `u8` to a `CString` without checking the invariants - /// on the given `Vec`. + /// Converts a [`Vec`]`<u8>` to a [`CString`] without checking the + /// invariants on the given [`Vec`]. /// /// # Safety /// - /// The given `Vec` **must** have one nul byte as its last element. + /// The given [`Vec`] **must** have one nul byte as its last element. /// This means it cannot be empty nor have any other nul byte anywhere else. /// /// # Example @@ -745,10 +699,10 @@ impl CString { Self { inner: v.into_boxed_slice() } } - /// Attempts to converts a `Vec` of `u8` to a `CString`. + /// Attempts to converts a [`Vec`]`<u8>` to a [`CString`]. /// /// Runtime checks are present to ensure there is only one nul byte in the - /// `Vec`, its last element. + /// [`Vec`], its last element. /// /// # Errors /// @@ -757,8 +711,8 @@ impl CString { /// /// # Examples /// - /// A successful conversion will produce the same result as [`new`] when - /// called without the ending nul byte. + /// A successful conversion will produce the same result as [`CString::new`] + /// when called without the ending nul byte. /// /// ``` /// #![feature(cstring_from_vec_with_nul)] @@ -770,7 +724,7 @@ impl CString { /// ); /// ``` /// - /// A incorrectly formatted vector will produce an error. + /// A incorrectly formatted [`Vec`] will produce an error. /// /// ``` /// #![feature(cstring_from_vec_with_nul)] @@ -780,8 +734,6 @@ impl CString { /// // No nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); /// ``` - /// - /// [`new`]: #method.new #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> { let nul_pos = memchr::memchr(0, &v); @@ -838,9 +790,6 @@ impl From<CString> for Vec<u8> { /// Converts a [`CString`] into a [`Vec`]`<u8>`. /// /// The conversion consumes the [`CString`], and removes the terminating NUL byte. - /// - /// [`Vec`]: ../vec/struct.Vec.html - /// [`CString`]: ../ffi/struct.CString.html #[inline] fn from(s: CString) -> Vec<u8> { s.into_bytes() @@ -913,9 +862,6 @@ impl From<Cow<'_, CStr>> for Box<CStr> { #[stable(feature = "c_string_from_box", since = "1.18.0")] impl From<Box<CStr>> for CString { /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`CString`]: ../ffi/struct.CString.html #[inline] fn from(s: Box<CStr>) -> CString { s.into_c_string() @@ -926,10 +872,6 @@ impl From<Box<CStr>> for CString { impl From<Vec<NonZeroU8>> for CString { /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without /// copying nor checking for inner null bytes. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html - /// [`Vec`]: ../vec/struct.Vec.html #[inline] fn from(v: Vec<NonZeroU8>) -> CString { unsafe { @@ -959,9 +901,6 @@ impl Clone for Box<CStr> { #[stable(feature = "box_from_c_string", since = "1.20.0")] impl From<CString> for Box<CStr> { /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`Box`]: ../boxed/struct.Box.html #[inline] fn from(s: CString) -> Box<CStr> { s.into_boxed_c_str() @@ -995,9 +934,6 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<CString> for Arc<CStr> { /// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`Arc`]: ../sync/struct.Arc.html #[inline] fn from(s: CString) -> Arc<CStr> { let arc: Arc<[u8]> = Arc::from(s.into_inner()); @@ -1017,9 +953,6 @@ impl From<&CStr> for Arc<CStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<CString> for Rc<CStr> { /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`Rc`]: ../rc/struct.Rc.html #[inline] fn from(s: CString) -> Rc<CStr> { let rc: Rc<[u8]> = Rc::from(s.into_inner()); @@ -1048,8 +981,6 @@ impl NulError { /// Returns the position of the nul byte in the slice that caused /// [`CString::new`] to fail. /// - /// [`CString::new`]: struct.CString.html#method.new - /// /// # Examples /// /// ``` @@ -1101,9 +1032,6 @@ impl fmt::Display for NulError { #[stable(feature = "rust1", since = "1.0.0")] impl From<NulError> for io::Error { /// Converts a [`NulError`] into a [`io::Error`]. - /// - /// [`NulError`]: ../ffi/struct.NulError.html - /// [`io::Error`]: ../io/struct.Error.html fn from(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte") } @@ -1154,8 +1082,6 @@ impl fmt::Display for FromVecWithNulError { impl IntoStringError { /// Consumes this error, returning original [`CString`] which generated the /// error. - /// - /// [`CString`]: struct.CString.html #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_cstring(self) -> CString { self.inner @@ -1228,9 +1154,21 @@ impl CStr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { - let len = sys::strlen(ptr); - let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + // SAFETY: The caller has provided a pointer that points to a valid C + // string with a NUL terminator of size less than `isize::MAX`, whose + // content remain valid and doesn't change for the lifetime of the + // returned `CStr`. + // + // Thus computing the length is fine (a NUL byte exists), the call to + // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning + // the call to `from_bytes_with_nul_unchecked` is correct. + // + // The cast from c_char to u8 is ok because a c_char is always one byte. + unsafe { + let len = sys::strlen(ptr); + let ptr = ptr as *const u8; + CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + } } /// Creates a C string wrapper from a byte slice. @@ -1299,7 +1237,12 @@ impl CStr { #[stable(feature = "cstr_from_bytes", since = "1.10.0")] #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { - &*(bytes as *const [u8] as *const CStr) + // SAFETY: Casting to CStr is safe because its internal representation + // is a [u8] too (safe only inside std). + // Dereferencing the obtained pointer is safe because it comes from a + // reference. Making a reference is then safe because its lifetime + // is bound by the lifetime of the given `bytes`. + unsafe { &*(bytes as *const [u8] as *const CStr) } } /// Returns the inner pointer to this C string. @@ -1330,7 +1273,8 @@ impl CStr { /// /// This happens because the pointer returned by `as_ptr` does not carry any /// lifetime information and the [`CString`] is deallocated immediately after - /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated. + /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` + /// expression is evaluated. /// To fix the problem, bind the `CString` to a local variable: /// /// ```no_run @@ -1345,10 +1289,8 @@ impl CStr { /// } /// ``` /// - /// This way, the lifetime of the `CString` in `hello` encompasses + /// This way, the lifetime of the [`CString`] in `hello` encompasses /// the lifetime of `ptr` and the `unsafe` block. - /// - /// [`CString`]: struct.CString.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] @@ -1382,15 +1324,13 @@ impl CStr { /// Converts this C string to a byte slice containing the trailing 0 byte. /// - /// This function is the equivalent of [`to_bytes`] except that it will retain - /// the trailing nul terminator instead of chopping it off. + /// This function is the equivalent of [`CStr::to_bytes`] except that it + /// will retain the trailing nul terminator instead of chopping it off. /// /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. /// - /// [`to_bytes`]: #method.to_bytes - /// /// # Examples /// /// ``` @@ -1411,7 +1351,7 @@ impl CStr { /// function will return the corresponding [`&str`] slice. Otherwise, /// it will return an error with details of where UTF-8 validation failed. /// - /// [`&str`]: ../primitive.str.html + /// [`&str`]: str /// /// # Examples /// @@ -1439,12 +1379,9 @@ impl CStr { /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result. /// - /// [`Cow`]: ../borrow/enum.Cow.html - /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed - /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned - /// [`str`]: ../primitive.str.html - /// [`String`]: ../string/struct.String.html - /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html + /// [`Borrowed`]: Cow::Borrowed + /// [`Owned`]: Cow::Owned + /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER /// /// # Examples /// @@ -1479,9 +1416,6 @@ impl CStr { /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating. /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`CString`]: struct.CString.html - /// /// # Examples /// /// ``` diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index f442d7fde1a5e..0184495eecf09 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -88,7 +88,7 @@ //! [`env::var_os()`] is used to query environment variables; it //! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable //! exists you will get a [`Some`]`(os_string)`, which you can *then* try to -//! convert to a Rust string. This yields a [`Result<>`], so that +//! convert to a Rust string. This yields a [`Result`], so that //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! @@ -124,34 +124,22 @@ //! method is an [`OsString`] which can be round-tripped to a Windows //! string losslessly. //! -//! [`String`]: ../string/struct.String.html -//! [`str`]: ../primitive.str.html -//! [`char`]: ../primitive.char.html -//! [`u8`]: ../primitive.u8.html -//! [`u16`]: ../primitive.u16.html //! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: http://www.unicode.org/glossary/#code_point -//! [`CString`]: struct.CString.html -//! [`CStr`]: struct.CStr.html -//! [`OsString`]: struct.OsString.html -//! [`OsStr`]: struct.OsStr.html -//! [`env::set_var()`]: ../env/fn.set_var.html -//! [`env::var_os()`]: ../env/fn.var_os.html -//! [`Result<>`]: ../result/enum.Result.html -//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html -//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec -//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec -//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html -//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes -//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes -//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html -//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html -//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide -//! [`collect`]: ../iter/trait.Iterator.html#method.collect -//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html -//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide -//! [`Option`]: ../option/enum.Option.html -//! [`Some`]: ../option/enum.Option.html#variant.Some +//! [`env::set_var()`]: crate::env::set_var +//! [`env::var_os()`]: crate::env::var_os +//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt +//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec +//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec +//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt +//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes +//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes +//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt +//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt +//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide +//! [`collect`]: crate::iter::Iterator::collect +//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt +//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index d1eaf3c583f2d..262d39d98ee2e 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -47,14 +47,14 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// create an `OsString` from a normal Rust string. /// /// **From slices:** Just like you can start with an empty Rust -/// [`String`] and then [`push_str`][String.push_str] `&str` +/// [`String`] and then [`String::push_str`] `&str` /// sub-string slices into it, you can create an empty `OsString` with -/// the [`new`] method and then push string slices into it with the -/// [`push`] method. +/// the [`OsString::new`] method and then push string slices into it with the +/// [`OsString::push`] method. /// /// # Extracting a borrowed reference to the whole OS string /// -/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from +/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from /// an `OsString`; this is effectively a borrowed reference to the /// whole string. /// @@ -63,18 +63,9 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// See the [module's toplevel documentation about conversions][conversions] for a discussion on /// the traits which `OsString` implements for [conversions] from/to native representations. /// -/// [`OsStr`]: struct.OsStr.html -/// [`&OsStr`]: struct.OsStr.html -/// [`CStr`]: struct.CStr.html -/// [`From`]: ../convert/trait.From.html -/// [`String`]: ../string/struct.String.html -/// [`&str`]: ../primitive.str.html -/// [`u8`]: ../primitive.u8.html -/// [`u16`]: ../primitive.u16.html -/// [String.push_str]: ../string/struct.String.html#method.push_str -/// [`new`]: #method.new -/// [`push`]: #method.push -/// [`as_os_str`]: #method.as_os_str +/// [`&OsStr`]: OsStr +/// [`&str`]: str +/// [`CStr`]: crate::ffi::CStr /// [conversions]: index.html#conversions #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] @@ -93,9 +84,7 @@ pub struct OsString { /// See the [module's toplevel documentation about conversions][conversions] for a discussion on /// the traits which `OsStr` implements for [conversions] from/to native representations. /// -/// [`OsString`]: struct.OsString.html -/// [`&str`]: ../primitive.str.html -/// [`String`]: ../string/struct.String.html +/// [`&str`]: str /// [conversions]: index.html#conversions #[stable(feature = "rust1", since = "1.0.0")] // FIXME: @@ -125,8 +114,6 @@ impl OsString { /// Converts to an [`OsStr`] slice. /// - /// [`OsStr`]: struct.OsStr.html - /// /// # Examples /// /// ``` @@ -145,8 +132,6 @@ impl OsString { /// /// On failure, ownership of the original `OsString` is returned. /// - /// [`String`]: ../../std/string/struct.String.html - /// /// # Examples /// /// ``` @@ -163,7 +148,7 @@ impl OsString { /// Extends the string with the given [`&OsStr`] slice. /// - /// [`&OsStr`]: struct.OsStr.html + /// [`&OsStr`]: OsStr /// /// # Examples /// @@ -333,8 +318,6 @@ impl OsString { /// Converts this `OsString` into a boxed [`OsStr`]. /// - /// [`OsStr`]: struct.OsStr.html - /// /// # Examples /// /// ``` @@ -356,8 +339,6 @@ impl From<String> for OsString { /// Converts a [`String`] into a [`OsString`]. /// /// The conversion copies the data, and includes an allocation on the heap. - /// - /// [`OsString`]: ../../std/ffi/struct.OsString.html fn from(s: String) -> OsString { OsString { inner: Buf::from_string(s) } } @@ -544,7 +525,7 @@ impl OsStr { /// /// This conversion may entail doing a check for UTF-8 validity. /// - /// [`&str`]: ../../std/primitive.str.html + /// [`&str`]: str /// /// # Examples /// @@ -564,9 +545,7 @@ impl OsStr { /// Any non-Unicode sequences are replaced with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. /// - /// [`Cow`]: ../../std/borrow/enum.Cow.html - /// [`str`]: ../../std/primitive.str.html - /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html + /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER /// /// # Examples /// @@ -613,8 +592,6 @@ impl OsStr { /// Copies the slice into an owned [`OsString`]. /// - /// [`OsString`]: struct.OsString.html - /// /// # Examples /// /// ``` @@ -662,9 +639,6 @@ impl OsStr { /// This number is simply useful for passing to other methods, like /// [`OsString::with_capacity`] to avoid reallocations. /// - /// [`OsString`]: struct.OsString.html - /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity - /// /// # Examples /// /// ``` @@ -682,9 +656,6 @@ impl OsStr { } /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`OsString`]: struct.OsString.html #[stable(feature = "into_boxed_os_str", since = "1.20.0")] pub fn into_os_string(self: Box<OsStr>) -> OsString { let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) }; @@ -706,9 +677,7 @@ impl OsStr { /// but non-ASCII letters are unchanged. /// /// To return a new lowercased value without modifying the existing one, use - /// [`to_ascii_lowercase`]. - /// - /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + /// [`OsStr::to_ascii_lowercase`]. /// /// # Examples /// @@ -733,9 +702,7 @@ impl OsStr { /// but non-ASCII letters are unchanged. /// /// To return a new uppercased value without modifying the existing one, use - /// [`to_ascii_uppercase`]. - /// - /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + /// [`OsStr::to_ascii_uppercase`]. /// /// # Examples /// @@ -760,9 +727,7 @@ impl OsStr { /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. /// - /// To lowercase the value in-place, use [`make_ascii_lowercase`]. - /// - /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`]. /// /// # Examples /// @@ -784,9 +749,7 @@ impl OsStr { /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. /// - /// To uppercase the value in-place, use [`make_ascii_uppercase`]. - /// - /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`]. /// /// # Examples /// @@ -865,9 +828,6 @@ impl From<Cow<'_, OsStr>> for Box<OsStr> { impl From<Box<OsStr>> for OsString { /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or /// allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`OsStr`]: ../ffi/struct.OsStr.html fn from(boxed: Box<OsStr>) -> OsString { boxed.into_os_string() } @@ -876,9 +836,6 @@ impl From<Box<OsStr>> for OsString { #[stable(feature = "box_from_os_string", since = "1.20.0")] impl From<OsString> for Box<OsStr> { /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`OsString`]: ../ffi/struct.OsString.html fn from(s: OsString) -> Box<OsStr> { s.into_boxed_os_str() } @@ -895,9 +852,6 @@ impl Clone for Box<OsStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<OsString> for Arc<OsStr> { /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating. - /// - /// [`Arc`]: ../sync/struct.Arc.html - /// [`OsString`]: ../ffi/struct.OsString.html #[inline] fn from(s: OsString) -> Arc<OsStr> { let arc = s.inner.into_arc(); @@ -917,9 +871,6 @@ impl From<&OsStr> for Arc<OsStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<OsString> for Rc<OsStr> { /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating. - /// - /// [`Rc`]: ../rc/struct.Rc.html - /// [`OsString`]: ../ffi/struct.OsString.html #[inline] fn from(s: OsString) -> Rc<OsStr> { let rc = s.inner.into_rc(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index ff343625a19ed..c39989a60c92b 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1813,12 +1813,190 @@ mod type_keyword {} #[doc(keyword = "unsafe")] // -/// Code or interfaces whose [memory safety] cannot be verified by the type system. +/// Code or interfaces whose [memory safety] cannot be verified by the type +/// system. +/// +/// The `unsafe` keyword has two uses: to declare the existence of contracts the +/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a +/// programmer has checked that these contracts have been upheld (`unsafe {}` +/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually +/// exclusive, as can be seen in `unsafe fn`. +/// +/// # Unsafe abilities +/// +/// **No matter what, Safe Rust can't cause Undefined Behavior**. This is +/// referred to as [soundness]: a well-typed program actually has the desired +/// properties. The [Nomicon][nomicon-soundness] has a more detailed explanation +/// on the subject. +/// +/// To ensure soundness, Safe Rust is restricted enough that it can be +/// automatically checked. Sometimes, however, it is necessary to write code +/// that is correct for reasons which are too clever for the compiler to +/// understand. In those cases, you need to use Unsafe Rust. +/// +/// Here are the abilities Unsafe Rust has in addition to Safe Rust: +/// +/// - Dereference [raw pointers] +/// - Implement `unsafe` [`trait`]s +/// - Call `unsafe` functions +/// - Mutate [`static`]s (including [`extern`]al ones) +/// - Access fields of [`union`]s +/// +/// However, this extra power comes with extra responsibilities: it is now up to +/// you to ensure soundness. The `unsafe` keyword helps by clearly marking the +/// pieces of code that need to worry about this. +/// +/// ## The different meanings of `unsafe` +/// +/// Not all uses of `unsafe` are equivalent: some are here to mark the existence +/// of a contract the programmer must check, others are to say "I have checked +/// the contract, go ahead and do this". The following +/// [discussion on Rust Internals] has more in-depth explanations about this but +/// here is a summary of the main points: +/// +/// - `unsafe fn`: calling this function means abiding by a contract the +/// compiler cannot enforce. +/// - `unsafe trait`: implementing the [`trait`] means abiding by a +/// contract the compiler cannot enforce. +/// - `unsafe {}`: the contract necessary to call the operations inside the +/// block has been checked by the programmer and is guaranteed to be respected. +/// - `unsafe impl`: the contract necessary to implement the trait has been +/// checked by the programmer and is guaranteed to be respected. +/// +/// `unsafe fn` also acts like an `unsafe {}` block +/// around the code inside the function. This means it is not just a signal to +/// the caller, but also promises that the preconditions for the operations +/// inside the function are upheld. Mixing these two meanings can be confusing +/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when +/// making `unsafe` operations. +/// +/// See the [Rustnomicon] and the [Reference] for more informations. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// # Examples +/// +/// ## Marking elements as `unsafe` +/// +/// `unsafe` can be used on functions. Note that functions and statics declared +/// in [`extern`] blocks are implicitly marked as `unsafe` (but not functions +/// declared as `extern "something" fn ...`). Mutable statics are always unsafe, +/// wherever they are declared. Methods can also be declared as `unsafe`: +/// +/// ```rust +/// # #![allow(dead_code)] +/// static mut FOO: &str = "hello"; +/// +/// unsafe fn unsafe_fn() {} +/// +/// extern "C" { +/// fn unsafe_extern_fn(); +/// static BAR: *mut u32; +/// } +/// +/// trait SafeTraitWithUnsafeMethod { +/// unsafe fn unsafe_method(&self); +/// } +/// +/// struct S; +/// +/// impl S { +/// unsafe fn unsafe_method_on_struct() {} +/// } +/// ``` +/// +/// Traits can also be declared as `unsafe`: +/// +/// ```rust +/// unsafe trait UnsafeTrait {} +/// ``` /// +/// Since `unsafe fn` and `unsafe trait` indicate that there is a safety +/// contract that the compiler cannot enforce, documenting it is important. The +/// standard library has many examples of this, like the following which is an +/// extract from [`Vec::set_len`]. The `# Safety` section explains the contract +/// that must be fulfilled to safely call the function. +/// +/// ```rust,ignore (stub-to-show-doc-example) +/// /// Forces the length of the vector to `new_len`. +/// /// +/// /// This is a low-level operation that maintains none of the normal +/// /// invariants of the type. Normally changing the length of a vector +/// /// is done using one of the safe operations instead, such as +/// /// `truncate`, `resize`, `extend`, or `clear`. +/// /// +/// /// # Safety +/// /// +/// /// - `new_len` must be less than or equal to `capacity()`. +/// /// - The elements at `old_len..new_len` must be initialized. +/// pub unsafe fn set_len(&mut self, new_len: usize) +/// ``` +/// +/// ## Using `unsafe {}` blocks and `impl`s +/// +/// Performing `unsafe` operations requires an `unsafe {}` block: +/// +/// ```rust +/// # #![allow(dead_code)] +/// /// Dereference the given pointer. +/// /// +/// /// # Safety +/// /// +/// /// `ptr` must be aligned and must not be dangling. +/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 { +/// *ptr +/// } +/// +/// let a = 3; +/// let b = &a as *const _; +/// // SAFETY: `a` has not been dropped and references are always aligned, +/// // so `b` is a valid address. +/// unsafe { assert_eq!(*b, deref_unchecked(b)); }; +/// ``` +/// +/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This +/// makes a guarantee to other `unsafe` code that the implementation satisfies +/// the trait's safety contract. The [Send] and [Sync] traits are examples of +/// this behaviour in the standard library. +/// +/// ```rust +/// /// Implementors of this trait must guarantee an element is always +/// /// accessible with index 3. +/// unsafe trait ThreeIndexable<T> { +/// /// Returns a reference to the element with index 3 in `&self`. +/// fn three(&self) -> &T; +/// } +/// +/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe` +/// // because the implementor must abide by a contract the compiler cannot +/// // check but as a programmer we know there will always be a valid element +/// // at index 3 to access. +/// unsafe impl<T> ThreeIndexable<T> for [T; 4] { +/// fn three(&self) -> &T { +/// // SAFETY: implementing the trait means there always is an element +/// // with index 3 accessible. +/// unsafe { self.get_unchecked(3) } +/// } +/// } +/// +/// let a = [1, 2, 4, 8]; +/// assert_eq!(a.three(), &8); +/// ``` +/// +/// [`extern`]: keyword.extern.html +/// [`trait`]: keyword.trait.html +/// [`static`]: keyword.static.html +/// [`union`]: keyword.union.html +/// [`impl`]: keyword.impl.html +/// [Send]: marker/trait.Send.html +/// [Sync]: marker/trait.Sync.html +/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len +/// [raw pointers]: ../reference/types/pointer.html /// [memory safety]: ../book/ch19-01-unsafe-rust.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// [Rustnomicon]: ../nomicon/index.html +/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html +/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library +/// [Reference]: ../reference/unsafety.html +/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585 +/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696 mod unsafe_keyword {} #[doc(keyword = "use")] diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 8c8d1aadf48e2..4f751656e09c8 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -37,7 +37,7 @@ use crate::vec; /// assert_eq!(socket.port(), 8080); /// assert_eq!(socket.is_ipv4(), true); /// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub enum SocketAddr { /// An IPv4 socket address. @@ -597,6 +597,13 @@ impl fmt::Display for SocketAddr { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for SocketAddrV4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 2c0025bcba069..9d7b2b807636f 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -40,7 +40,7 @@ use crate::sys_common::{AsInner, FromInner}; /// assert_eq!(localhost_v4.is_ipv4(), true); /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub enum IpAddr { /// An IPv4 address. #[stable(feature = "ip_addr", since = "1.7.0")] @@ -802,6 +802,13 @@ impl fmt::Display for IpAddr { } } +#[stable(feature = "ip_addr", since = "1.7.0")] +impl fmt::Debug for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + #[stable(feature = "ip_from_ip", since = "1.16.0")] impl From<Ipv4Addr> for IpAddr { /// Copies this address to a new `IpAddr::V4`. diff --git a/library/std/src/os/raw/char.md b/library/std/src/os/raw/char.md index 9a55767d965a6..8256b725acfa3 100644 --- a/library/std/src/os/raw/char.md +++ b/library/std/src/os/raw/char.md @@ -5,7 +5,5 @@ Equivalent to C's `char` type. C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information. [C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types -[Rust's `char` type]: ../../primitive.char.html -[`CStr`]: ../../ffi/struct.CStr.html -[`i8`]: ../../primitive.i8.html -[`u8`]: ../../primitive.u8.html +[Rust's `char` type]: char +[`CStr`]: crate::ffi::CStr diff --git a/library/std/src/os/raw/double.md b/library/std/src/os/raw/double.md index 6818dada31793..57f4534829ec8 100644 --- a/library/std/src/os/raw/double.md +++ b/library/std/src/os/raw/double.md @@ -3,5 +3,4 @@ Equivalent to C's `double` type. This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard. [IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754 -[`float`]: type.c_float.html -[`f64`]: ../../primitive.f64.html +[`float`]: c_float diff --git a/library/std/src/os/raw/float.md b/library/std/src/os/raw/float.md index 57d1071d0da17..61e2abc05189d 100644 --- a/library/std/src/os/raw/float.md +++ b/library/std/src/os/raw/float.md @@ -3,4 +3,3 @@ Equivalent to C's `float` type. This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all. [IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754 -[`f32`]: ../../primitive.f32.html diff --git a/library/std/src/os/raw/int.md b/library/std/src/os/raw/int.md index a0d25fd21d89f..8062ff2307a95 100644 --- a/library/std/src/os/raw/int.md +++ b/library/std/src/os/raw/int.md @@ -2,6 +2,4 @@ Equivalent to C's `signed int` (`int`) type. This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example. -[`short`]: type.c_short.html -[`i32`]: ../../primitive.i32.html -[`i16`]: ../../primitive.i16.html +[`short`]: c_short diff --git a/library/std/src/os/raw/long.md b/library/std/src/os/raw/long.md index c620b402819fd..cc160783f78b7 100644 --- a/library/std/src/os/raw/long.md +++ b/library/std/src/os/raw/long.md @@ -2,6 +2,4 @@ Equivalent to C's `signed long` (`long`) type. This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`. -[`int`]: type.c_int.html -[`i32`]: ../../primitive.i32.html -[`i64`]: ../../primitive.i64.html +[`int`]: c_int diff --git a/library/std/src/os/raw/longlong.md b/library/std/src/os/raw/longlong.md index ab3d6436568df..49c61bd61f4ad 100644 --- a/library/std/src/os/raw/longlong.md +++ b/library/std/src/os/raw/longlong.md @@ -2,6 +2,4 @@ Equivalent to C's `signed long long` (`long long`) type. This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type. -[`long`]: type.c_int.html -[`i64`]: ../../primitive.i64.html -[`i128`]: ../../primitive.i128.html +[`long`]: c_int diff --git a/library/std/src/os/raw/schar.md b/library/std/src/os/raw/schar.md index 6aa8b1211d808..69879c9f17f4d 100644 --- a/library/std/src/os/raw/schar.md +++ b/library/std/src/os/raw/schar.md @@ -2,5 +2,4 @@ Equivalent to C's `signed char` type. This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`]. -[`char`]: type.c_char.html -[`i8`]: ../../primitive.i8.html +[`char`]: c_char diff --git a/library/std/src/os/raw/short.md b/library/std/src/os/raw/short.md index be92c6c106d59..3d1e53d1325f3 100644 --- a/library/std/src/os/raw/short.md +++ b/library/std/src/os/raw/short.md @@ -2,5 +2,4 @@ Equivalent to C's `signed short` (`short`) type. This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example. -[`char`]: type.c_char.html -[`i16`]: ../../primitive.i16.html +[`char`]: c_char diff --git a/library/std/src/os/raw/uchar.md b/library/std/src/os/raw/uchar.md index b6ca711f86934..b633bb7f8dacf 100644 --- a/library/std/src/os/raw/uchar.md +++ b/library/std/src/os/raw/uchar.md @@ -2,5 +2,4 @@ Equivalent to C's `unsigned char` type. This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`]. -[`char`]: type.c_char.html -[`u8`]: ../../primitive.u8.html +[`char`]: c_char diff --git a/library/std/src/os/raw/uint.md b/library/std/src/os/raw/uint.md index 6f7013a8ac18d..f3abea35937ab 100644 --- a/library/std/src/os/raw/uint.md +++ b/library/std/src/os/raw/uint.md @@ -2,6 +2,4 @@ Equivalent to C's `unsigned int` type. This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example. -[`int`]: type.c_int.html -[`u32`]: ../../primitive.u32.html -[`u16`]: ../../primitive.u16.html +[`int`]: c_int diff --git a/library/std/src/os/raw/ulong.md b/library/std/src/os/raw/ulong.md index c350395080e80..4ab304e657773 100644 --- a/library/std/src/os/raw/ulong.md +++ b/library/std/src/os/raw/ulong.md @@ -2,6 +2,4 @@ Equivalent to C's `unsigned long` type. This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`. -[`long`]: type.c_long.html -[`u32`]: ../../primitive.u32.html -[`u64`]: ../../primitive.u64.html +[`long`]: c_long diff --git a/library/std/src/os/raw/ulonglong.md b/library/std/src/os/raw/ulonglong.md index c41faf74c5c68..a27d70e17537d 100644 --- a/library/std/src/os/raw/ulonglong.md +++ b/library/std/src/os/raw/ulonglong.md @@ -2,6 +2,4 @@ Equivalent to C's `unsigned long long` type. This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type. -[`long long`]: type.c_longlong.html -[`u64`]: ../../primitive.u64.html -[`u128`]: ../../primitive.u128.html +[`long long`]: c_longlong diff --git a/library/std/src/os/raw/ushort.md b/library/std/src/os/raw/ushort.md index d364abb3c8e0c..6928e51b352c8 100644 --- a/library/std/src/os/raw/ushort.md +++ b/library/std/src/os/raw/ushort.md @@ -2,5 +2,4 @@ Equivalent to C's `unsigned short` type. This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`]. -[`short`]: type.c_short.html -[`u16`]: ../../primitive.u16.html +[`short`]: c_short diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4ba1940fd0ece..6d94fa9ebfe6d 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -84,25 +84,15 @@ //! assert_eq!(b"test", output.stdout.as_slice()); //! ``` //! -//! [`abort`]: fn.abort.html -//! [`exit`]: fn.exit.html +//! [`spawn`]: Command::spawn +//! [`output`]: Command::output //! -//! [`Command`]: struct.Command.html -//! [`spawn`]: struct.Command.html#method.spawn -//! [`output`]: struct.Command.html#method.output +//! [`stdout`]: Command::stdout +//! [`stdin`]: Command::stdin +//! [`stderr`]: Command::stderr //! -//! [`Child`]: struct.Child.html -//! [`ChildStdin`]: struct.ChildStdin.html -//! [`ChildStdout`]: struct.ChildStdout.html -//! [`ChildStderr`]: struct.ChildStderr.html -//! [`Stdio`]: struct.Stdio.html -//! -//! [`stdout`]: struct.Command.html#method.stdout -//! [`stdin`]: struct.Command.html#method.stdin -//! [`stderr`]: struct.Command.html#method.stderr -//! -//! [`Write`]: ../io/trait.Write.html -//! [`Read`]: ../io/trait.Read.html +//! [`Write`]: io::Write +//! [`Read`]: io::Read #![stable(feature = "process", since = "1.0.0")] @@ -130,7 +120,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// run, even after the `Child` handle to the child process has gone out of /// scope. /// -/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make +/// Calling [`wait`] (or other functions that wrap around it) will make /// the parent process wait until the child has actually exited before /// continuing. /// @@ -162,25 +152,44 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// assert!(ecode.success()); /// ``` /// -/// [`Command`]: struct.Command.html -/// [`Drop`]: ../../core/ops/trait.Drop.html -/// [`wait`]: #method.wait +/// [`wait`]: Child::wait #[stable(feature = "process", since = "1.0.0")] pub struct Child { handle: imp::Process, /// The handle for writing to the child's standard input (stdin), if it has - /// been captured. + /// been captured. To avoid partially moving + /// the `child` and thus blocking yourself from calling + /// functions on `child` while using `stdin`, + /// you might find it helpful: + /// + /// ```compile_fail,E0425 + /// let stdin = child.stdin.take().unwrap(); + /// ``` #[stable(feature = "process", since = "1.0.0")] pub stdin: Option<ChildStdin>, /// The handle for reading from the child's standard output (stdout), if it - /// has been captured. + /// has been captured. You might find it helpful to do + /// + /// ```compile_fail,E0425 + /// let stdout = child.stdout.take().unwrap(); + /// ``` + /// + /// to avoid partially moving the `child` and thus blocking yourself from calling + /// functions on `child` while using `stdout`. #[stable(feature = "process", since = "1.0.0")] pub stdout: Option<ChildStdout>, /// The handle for reading from the child's standard error (stderr), if it - /// has been captured. + /// has been captured. You might find it helpful to do + /// + /// ```compile_fail,E0425 + /// let stderr = child.stderr.take().unwrap(); + /// ``` + /// + /// to avoid partially moving the `child` and thus blocking yourself from calling + /// functions on `child` while using `stderr`. #[stable(feature = "process", since = "1.0.0")] pub stderr: Option<ChildStderr>, } @@ -227,9 +236,8 @@ impl fmt::Debug for Child { /// file handle will be closed. If the child process was blocked on input prior /// to being dropped, it will become unblocked after dropping. /// -/// [`Child`]: struct.Child.html -/// [`stdin`]: struct.Child.html#structfield.stdin -/// [dropped]: ../ops/trait.Drop.html +/// [`stdin`]: Child::stdin +/// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdin { inner: AnonPipe, @@ -286,9 +294,8 @@ impl fmt::Debug for ChildStdin { /// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s /// underlying file handle will be closed. /// -/// [`Child`]: struct.Child.html -/// [`stdout`]: struct.Child.html#structfield.stdout -/// [dropped]: ../ops/trait.Drop.html +/// [`stdout`]: Child::stdout +/// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdout { inner: AnonPipe, @@ -347,9 +354,8 @@ impl fmt::Debug for ChildStdout { /// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s /// underlying file handle will be closed. /// -/// [`Child`]: struct.Child.html -/// [`stderr`]: struct.Child.html#structfield.stderr -/// [dropped]: ../ops/trait.Drop.html +/// [`stderr`]: Child::stderr +/// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStderr { inner: AnonPipe, @@ -522,7 +528,7 @@ impl Command { /// /// To pass multiple arguments see [`args`]. /// - /// [`args`]: #method.args + /// [`args`]: Command::args /// /// # Examples /// @@ -547,7 +553,7 @@ impl Command { /// /// To pass a single argument see [`arg`]. /// - /// [`arg`]: #method.arg + /// [`arg`]: Command::arg /// /// # Examples /// @@ -700,7 +706,7 @@ impl Command { /// .expect("ls command failed to start"); /// ``` /// - /// [`canonicalize`]: ../fs/fn.canonicalize.html + /// [`canonicalize`]: crate::fs::canonicalize #[stable(feature = "process", since = "1.0.0")] pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command { self.inner.cwd(dir.as_ref().as_ref()); @@ -712,8 +718,8 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// [`inherit`]: struct.Stdio.html#method.inherit - /// [`piped`]: struct.Stdio.html#method.piped + /// [`inherit`]: Stdio::inherit + /// [`piped`]: Stdio::piped /// /// # Examples /// @@ -738,8 +744,8 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// [`inherit`]: struct.Stdio.html#method.inherit - /// [`piped`]: struct.Stdio.html#method.piped + /// [`inherit`]: Stdio::inherit + /// [`piped`]: Stdio::piped /// /// # Examples /// @@ -764,8 +770,8 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// [`inherit`]: struct.Stdio.html#method.inherit - /// [`piped`]: struct.Stdio.html#method.piped + /// [`inherit`]: Stdio::inherit + /// [`piped`]: Stdio::piped /// /// # Examples /// @@ -893,10 +899,8 @@ impl AsInnerMut<imp::Command> for Command { /// [`Command`], or the [`wait_with_output`] method of a [`Child`] /// process. /// -/// [`Command`]: struct.Command.html -/// [`Child`]: struct.Child.html -/// [`output`]: struct.Command.html#method.output -/// [`wait_with_output`]: struct.Child.html#method.wait_with_output +/// [`output`]: Command::output +/// [`wait_with_output`]: Child::wait_with_output #[derive(PartialEq, Eq, Clone)] #[stable(feature = "process", since = "1.0.0")] pub struct Output { @@ -939,10 +943,9 @@ impl fmt::Debug for Output { /// Describes what to do with a standard I/O stream for a child process when /// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`]. /// -/// [`stdin`]: struct.Command.html#method.stdin -/// [`stdout`]: struct.Command.html#method.stdout -/// [`stderr`]: struct.Command.html#method.stderr -/// [`Command`]: struct.Command.html +/// [`stdin`]: Command::stdin +/// [`stdout`]: Command::stdout +/// [`stderr`]: Command::stderr #[stable(feature = "process", since = "1.0.0")] pub struct Stdio(imp::Stdio); @@ -1206,10 +1209,8 @@ impl From<fs::File> for Stdio { /// status is exposed through the [`status`] method, or the [`wait`] method /// of a [`Child`] process. /// -/// [`Command`]: struct.Command.html -/// [`Child`]: struct.Child.html -/// [`status`]: struct.Command.html#method.status -/// [`wait`]: struct.Child.html#method.wait +/// [`status`]: Command::status +/// [`wait`]: Child::wait #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "process", since = "1.0.0")] pub struct ExitStatus(imp::ExitStatus); @@ -1294,8 +1295,8 @@ impl fmt::Display for ExitStatus { /// For the platform's canonical successful and unsuccessful codes, see /// the [`SUCCESS`] and [`FAILURE`] associated items. /// -/// [`SUCCESS`]: #associatedconstant.SUCCESS -/// [`FAILURE`]: #associatedconstant.FAILURE +/// [`SUCCESS`]: ExitCode::SUCCESS +/// [`FAILURE`]: ExitCode::FAILURE /// /// **Warning**: While various forms of this were discussed in [RFC #1937], /// it was ultimately cut from that RFC, and thus this type is more subject @@ -1349,9 +1350,9 @@ impl Child { /// } /// ``` /// - /// [`ErrorKind`]: ../io/enum.ErrorKind.html - /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput - /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other + /// [`ErrorKind`]: io::ErrorKind + /// [`InvalidInput`]: io::ErrorKind::InvalidInput + /// [`Other`]: io::ErrorKind::Other #[stable(feature = "process", since = "1.0.0")] pub fn kill(&mut self) -> io::Result<()> { self.handle.kill() @@ -1616,8 +1617,7 @@ pub fn exit(code: i32) -> ! { /// } /// ``` /// -/// [`panic!`]: ../../std/macro.panic.html -/// [panic hook]: ../../std/panic/fn.set_hook.html +/// [panic hook]: crate::panic::set_hook #[stable(feature = "process_abort", since = "1.17.0")] pub fn abort() -> ! { crate::sys::abort_internal(); diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs index 2c3d1e97df975..b65a88cb90e88 100644 --- a/src/librustc_ast/visit.rs +++ b/src/librustc_ast/visit.rs @@ -50,6 +50,13 @@ impl<'a> FnKind<'a> { } } + pub fn ident(&self) -> Option<&Ident> { + match self { + FnKind::Fn(_, ident, ..) => Some(ident), + _ => None, + } + } + pub fn decl(&self) -> &'a FnDecl { match self { FnKind::Fn(_, _, sig, _, _) => &sig.decl, diff --git a/src/librustc_error_codes/error_codes/E0752.md b/src/librustc_error_codes/error_codes/E0752.md index 86945f83b5524..9736da80c2b7b 100644 --- a/src/librustc_error_codes/error_codes/E0752.md +++ b/src/librustc_error_codes/error_codes/E0752.md @@ -1,11 +1,19 @@ -`fn main()` or the specified start function is not allowed to be -async. You might be seeing this error because your async runtime -library is not set up correctly. +The entry point of the program was marked as `async`. Erroneous code example: ```compile_fail,E0752 -async fn main() -> Result<i32, ()> { - Ok(1) +async fn main() -> Result<(), ()> { // error! + Ok(()) +} +``` + +`fn main()` or the specified start function is not allowed to be `async`. Not +having a correct async runtime library setup may cause this error. To fix it, +declare the entry point without `async`: + +``` +fn main() -> Result<(), ()> { // ok! + Ok(()) } ``` diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 7fbe5c409d3ce..4101f70b8206d 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -57,6 +57,12 @@ fn eval_body_using_ecx<'mir, 'tcx>( ecx.run()?; // Intern the result + // FIXME: since the DefId of a promoted is the DefId of its owner, this + // means that promoteds in statics are actually interned like statics! + // However, this is also currently crucial because we promote mutable + // non-empty slices in statics to extend their lifetime, and this + // ensures that they are put into a mutable allocation. + // For other kinds of promoteds in statics (like array initializers), this is rather silly. let intern_kind = match tcx.static_mutability(cid.instance.def_id()) { Some(m) => InternKind::Static(m), None if cid.promoted.is_some() => InternKind::Promoted, diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index dffbc969c21b8..6c8ee72bc66c2 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -312,7 +312,8 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>( let tcx = ecx.tcx; let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), - // FIXME: what about array lengths, array initializers? + // `Constant` includes array lengths. + // `Promoted` includes non-`Copy` array initializers and `rustc_args_required_const` arguments. InternKind::Constant | InternKind::Promoted => InternMode::ConstBase, }; diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index c056410570157..94637bae44a78 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -101,7 +101,7 @@ impl TempState { /// of a larger candidate. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Candidate { - /// Borrow of a constant temporary. + /// Borrow of a constant temporary, candidate for lifetime extension. Ref(Location), /// Promotion of the `x` in `[x; 32]`. diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index a7d3697405751..b3746ac2db2bd 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -7,6 +7,7 @@ use crate::{PathResult, PathSource, Segment}; use rustc_ast::ast::{self, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind}; use rustc_ast::util::lev_distance::find_best_match_for_name; +use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -175,16 +176,40 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let code = source.error_code(res.is_some()); let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code); + let is_assoc_fn = self.self_type_is_available(span); // Emit help message for fake-self from other languages (e.g., `this` in Javascript). - if ["this", "my"].contains(&&*item_str.as_str()) - && self.self_value_is_available(path[0].ident.span, span) - { + if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn { err.span_suggestion_short( span, "you might have meant to use `self` here instead", "self".to_string(), Applicability::MaybeIncorrect, ); + if !self.self_value_is_available(path[0].ident.span, span) { + if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) = + &self.diagnostic_metadata.current_function + { + let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) { + (param.span.shrink_to_lo(), "&self, ") + } else { + ( + self.r + .session + .source_map() + .span_through_char(*fn_span, '(') + .shrink_to_hi(), + "&self", + ) + }; + err.span_suggestion_verbose( + span, + "if you meant to use `self`, you are also missing a `self` receiver \ + argument", + sugg.to_string(), + Applicability::MaybeIncorrect, + ); + } + } } // Emit special messages for unresolved `Self` and `self`. @@ -213,7 +238,38 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) { err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters"); } else { - err.span_label(*span, "this function doesn't have a `self` parameter"); + let doesnt = if is_assoc_fn { + let (span, sugg) = fn_kind + .decl() + .inputs + .get(0) + .map(|p| (p.span.shrink_to_lo(), "&self, ")) + .unwrap_or_else(|| { + ( + self.r + .session + .source_map() + .span_through_char(*span, '(') + .shrink_to_hi(), + "&self", + ) + }); + err.span_suggestion_verbose( + span, + "add a `self` receiver parameter to make the associated `fn` a method", + sugg.to_string(), + Applicability::MaybeIncorrect, + ); + "doesn't" + } else { + "can't" + }; + if let Some(ident) = fn_kind.ident() { + err.span_label( + ident.span, + &format!("this function {} have a `self` parameter", doesnt), + ); + } } } return (err, Vec::new()); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2be100ae33662..3093ddbeaf1ae 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1623,6 +1623,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_bounds: &[hir::PolyTraitRef<'_>], lifetime: &hir::Lifetime, + borrowed: bool, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -1837,15 +1838,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(lifetime, None) } else { self.re_infer(None, span).unwrap_or_else(|| { - // FIXME: these can be redundant with E0106, but not always. - struct_span_err!( + let mut err = struct_span_err!( tcx.sess, span, E0228, "the lifetime bound for this object type cannot be deduced \ from context; please supply an explicit bound" - ) - .emit(); + ); + if borrowed { + // We will have already emitted an error E0106 complaining about a + // missing named lifetime in `&dyn Trait`, so we elide this one. + err.delay_as_bug(); + } else { + err.emit(); + } tcx.lifetimes.re_static }) } @@ -2873,6 +2879,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + self.ast_ty_to_ty_inner(ast_ty, false) + } + + /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait + /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. + fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> { debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind); let tcx = self.tcx(); @@ -2885,7 +2897,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!("ast_ty_to_ty: r={:?}", r); - let t = self.ast_ty_to_ty(&mt.ty); + let t = self.ast_ty_to_ty_inner(&mt.ty, true); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, @@ -2903,7 +2915,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { - self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) + self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); diff --git a/src/test/ui/error-codes/E0424.rs b/src/test/ui/error-codes/E0424.rs index 3c6a1d4f88f11..fa0c86ecf4894 100644 --- a/src/test/ui/error-codes/E0424.rs +++ b/src/test/ui/error-codes/E0424.rs @@ -6,6 +6,10 @@ impl Foo { fn foo() { self.bar(); //~ ERROR E0424 } + + fn baz(_: i32) { + self.bar(); //~ ERROR E0424 + } } fn main () { diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index 690a101496d73..9b8a29e827249 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -1,21 +1,37 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | -LL | / fn foo() { -LL | | self.bar(); - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | } - | |_____- this function doesn't have a `self` parameter +LL | fn foo() { + | --- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn foo(&self) { + | ^^^^^ + +error[E0424]: expected value, found module `self` + --> $DIR/E0424.rs:11:9 + | +LL | fn baz(_: i32) { + | --- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn baz(&self, _: i32) { + | ^^^^^^ error[E0424]: expected unit struct, unit variant or constant, found module `self` - --> $DIR/E0424.rs:12:9 + --> $DIR/E0424.rs:16:9 | -LL | / fn main () { -LL | | let self = "self"; - | | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed -LL | | } - | |_- this function doesn't have a `self` parameter +LL | fn main () { + | ---- this function can't have a `self` parameter +LL | let self = "self"; + | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0424`. diff --git a/src/test/ui/issues/issue-5099.rs b/src/test/ui/issues/issue-5099.rs index d00fff3280920..ee134835c37ed 100644 --- a/src/test/ui/issues/issue-5099.rs +++ b/src/test/ui/issues/issue-5099.rs @@ -1,3 +1,10 @@ -trait B < A > { fn a() -> A { this.a } } //~ ERROR cannot find value `this` in this scope +trait B <A> { + fn a() -> A { + this.a //~ ERROR cannot find value `this` in this scope + } + fn b(x: i32) { + this.b(x); //~ ERROR cannot find value `this` in this scope + } +} fn main() {} diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/issues/issue-5099.stderr index cc11db9c5eca6..b52fd28b2b575 100644 --- a/src/test/ui/issues/issue-5099.stderr +++ b/src/test/ui/issues/issue-5099.stderr @@ -1,9 +1,33 @@ error[E0425]: cannot find value `this` in this scope - --> $DIR/issue-5099.rs:1:31 + --> $DIR/issue-5099.rs:3:9 | -LL | trait B < A > { fn a() -> A { this.a } } - | ^^^^ not found in this scope +LL | this.a + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.a + | ^^^^ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn a(&self) -> A { + | ^^^^^ + +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-5099.rs:6:9 + | +LL | this.b(x); + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.b(x); + | ^^^^ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn b(&self, x: i32) { + | ^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index b687f0b0af0ad..0339daa0d6a18 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -70,14 +70,15 @@ LL | purr(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | -LL | / fn meow() { -LL | | if self.whiskers > 3 { - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | -LL | | println!("MEOW"); -LL | | } -LL | | } - | |___- this function doesn't have a `self` parameter +LL | fn meow() { + | ---- this function doesn't have a `self` parameter +LL | if self.whiskers > 3 { + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn meow(&self) { + | ^^^^^ error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -112,12 +113,10 @@ LL | purr_louder(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | -LL | / fn main() { -LL | | self += 1; - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | -LL | | } - | |_- this function doesn't have a `self` parameter +LL | fn main() { + | ---- this function can't have a `self` parameter +LL | self += 1; + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error: aborting due to 17 previous errors diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs index b09c1879d7015..fe88d105c78bf 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.rs +++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs @@ -25,8 +25,6 @@ thread_local! { //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier - //~| ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR the lifetime bound for this object type cannot be deduced from context } thread_local! { static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); @@ -39,8 +37,6 @@ thread_local! { //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier - //~| ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR the lifetime bound for this object type cannot be deduced from context } thread_local! { @@ -52,9 +48,7 @@ thread_local! { } thread_local! { static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - //~^ ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~^ ERROR wrong number of lifetime arguments: expected 2, found 1 //~| ERROR wrong number of lifetime arguments: expected 2, found 1 //~| ERROR wrong number of lifetime arguments: expected 2, found 1 //~| ERROR wrong number of lifetime arguments: expected 2, found 1 diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index 2630cf1affae6..9838ac72ad767 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -71,7 +71,7 @@ LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar<'static, 'static>>>>> = Ref | ^^^^^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:32:48 + --> $DIR/missing-lifetime-specifier.rs:30:48 | LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -83,7 +83,7 @@ LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:32:48 + --> $DIR/missing-lifetime-specifier.rs:30:48 | LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -95,7 +95,7 @@ LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:37:44 + --> $DIR/missing-lifetime-specifier.rs:35:44 | LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -107,7 +107,7 @@ LL | static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<i32>>>>> = RefCell: | ^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:37:49 + --> $DIR/missing-lifetime-specifier.rs:35:49 | LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -119,7 +119,7 @@ LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:37:44 + --> $DIR/missing-lifetime-specifier.rs:35:44 | LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -131,7 +131,7 @@ LL | static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<i32>>>>> = RefCell: | ^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:37:49 + --> $DIR/missing-lifetime-specifier.rs:35:49 | LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -143,7 +143,7 @@ LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:54:44 + --> $DIR/missing-lifetime-specifier.rs:50:44 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -155,7 +155,7 @@ LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = | ^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:54:44 + --> $DIR/missing-lifetime-specifier.rs:50:44 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -166,91 +166,55 @@ help: consider using the `'static` lifetime LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:23:45 - | -LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); - | ^^^ - -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:23:45 - | -LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); - | ^^^ - -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:37:45 - | -LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^ - -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:37:45 - | -LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^ - error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:54:45 - | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^^^^^^^^^^ - error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:54:45 - | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^^^^^^^^^^ - error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments -error: aborting due to 28 previous errors +error: aborting due to 22 previous errors -Some errors have detailed explanations: E0106, E0107, E0228. +Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`.