]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #75519 - ssomers:btree_splitpoint_cleanup, r=Mark-Simulacrum
authorTyler Mandry <tmandry@gmail.com>
Fri, 14 Aug 2020 21:47:01 +0000 (14:47 -0700)
committerGitHub <noreply@github.com>
Fri, 14 Aug 2020 21:47:01 +0000 (14:47 -0700)
BTreeMap: refactor splitpoint and move testing over to unit test

r? @Mark-Simulacrum

46 files changed:
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/node.rs
library/alloc/src/vec.rs
library/core/src/mem/manually_drop.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/str/mod.rs
library/std/Cargo.toml
library/std/src/ffi/c_str.rs
library/std/src/ffi/mod.rs
library/std/src/ffi/os_str.rs
library/std/src/keyword_docs.rs
library/std/src/net/addr.rs
library/std/src/net/ip.rs
library/std/src/process.rs
src/librustc_ast/visit.rs
src/librustc_codegen_llvm/coverageinfo/mod.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_ssa/back/symbol_export.rs
src/librustc_codegen_ssa/traits/coverageinfo.rs
src/librustc_error_codes/error_codes/E0752.md
src/librustc_mir/const_eval/eval_queries.rs
src/librustc_mir/interpret/intern.rs
src/librustc_mir/transform/add_retag.rs
src/librustc_mir/transform/deaggregator.rs
src/librustc_mir/transform/instrument_coverage.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/simplify_try.rs
src/librustc_mir/transform/uninhabited_enum_branching.rs
src/librustc_mir/transform/unreachable_prop.rs
src/librustc_resolve/late/diagnostics.rs
src/librustc_typeck/astconv.rs
src/rustllvm/CoverageMappingWrapper.cpp
src/test/run-make-fulldeps/instrument-coverage/Makefile
src/test/run-make-fulldeps/instrument-coverage/expected_export_coverage.json
src/test/run-make-fulldeps/instrument-coverage/filecheck-patterns.txt [new file with mode: 0644]
src/test/run-make-fulldeps/instrument-coverage/main.rs [deleted file]
src/test/run-make-fulldeps/instrument-coverage/testprog.rs [new file with mode: 0644]
src/test/run-make-fulldeps/instrument-coverage/typical_show_coverage.txt
src/test/ui/error-codes/E0424.rs
src/test/ui/error-codes/E0424.stderr
src/test/ui/issues/issue-5099.rs
src/test/ui/issues/issue-5099.stderr
src/test/ui/resolve/issue-2356.stderr
src/test/ui/suggestions/missing-lifetime-specifier.rs
src/test/ui/suggestions/missing-lifetime-specifier.stderr

index e7d243bfcb0f75d00c6c246026b3b508f0b86737..8e800f48c69de5786cc33b6ec2a7c7ddf5f4740c 100644 (file)
@@ -245,7 +245,7 @@ fn take(&mut self, key: &Q) -> Option<K> {
     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 @@ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut 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 @@ pub fn get_mut(&mut self) -> &mut 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,
index 5a6a71c5fb687a0725fad418f737f499eb2a0c90..acc2ae73572ba757aa801bafde1ae2e376efc2b5 100644 (file)
@@ -416,7 +416,7 @@ pub unsafe fn deallocate_and_ascend(
 impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
     /// Unsafely asserts to the compiler some static information about whether this
     /// node is a `Leaf` or an `Internal`.
-    unsafe fn cast_unchecked<NewType>(&mut self) -> NodeRef<marker::Mut<'_>, K, V, NewType> {
+    unsafe fn cast_unchecked<NewType>(self) -> NodeRef<marker::Mut<'a>, K, V, NewType> {
         NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
     }
 
@@ -724,7 +724,7 @@ fn clone(&self) -> Self {
 }
 
 impl<Node, Type> Handle<Node, Type> {
-    /// Retrieves the node that contains the edge of key/value pair this handle points to.
+    /// Retrieves the node that contains the edge or key/value pair this handle points to.
     pub fn into_node(self) -> Node {
         self.node
     }
@@ -1044,6 +1044,16 @@ pub fn into_kv(self) -> (&'a K, &'a V) {
 }
 
 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();
@@ -1108,7 +1118,7 @@ pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, R
     }
 
     /// Removes the key/value pair pointed to by this handle and returns it, along with the edge
-    /// between the now adjacent key/value pairs (if any) to the left and right of this handle.
+    /// that the key/value pair collapsed into.
     pub fn remove(
         mut self,
     ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
@@ -1166,7 +1176,7 @@ pub fn can_merge(&self) -> bool {
     /// to by this handle, and the node immediately to the right of this handle into one new
     /// child of the underlying node, returning an edge referencing that new child.
     ///
-    /// Assumes that this edge `.can_merge()`.
+    /// Panics unless this edge `.can_merge()`.
     pub fn merge(
         mut self,
     ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> {
@@ -1174,10 +1184,9 @@ pub fn merge(
         let self2 = unsafe { ptr::read(&self) };
         let mut left_node = self1.left_edge().descend();
         let left_len = left_node.len();
-        let mut right_node = self2.right_edge().descend();
+        let right_node = self2.right_edge().descend();
         let right_len = right_node.len();
 
-        // necessary for correctness, but in a private module
         assert!(left_len + right_len < CAPACITY);
 
         unsafe {
@@ -1208,28 +1217,25 @@ pub fn merge(
 
             (*left_node.as_leaf_mut()).len += right_len as u16 + 1;
 
-            let layout = if self.node.height > 1 {
+            if self.node.height > 1 {
+                // SAFETY: the height of the nodes being merged is one below the height
+                // of the node of this edge, thus above zero, so they are internal.
+                let mut left_node = left_node.cast_unchecked();
+                let right_node = right_node.cast_unchecked();
                 ptr::copy_nonoverlapping(
-                    right_node.cast_unchecked().as_internal().edges.as_ptr(),
-                    left_node
-                        .cast_unchecked()
-                        .as_internal_mut()
-                        .edges
-                        .as_mut_ptr()
-                        .add(left_len + 1),
+                    right_node.reborrow().as_internal().edges.as_ptr(),
+                    left_node.reborrow_mut().as_internal_mut().edges.as_mut_ptr().add(left_len + 1),
                     right_len + 1,
                 );
 
                 for i in left_len + 1..left_len + right_len + 2 {
-                    Handle::new_edge(left_node.cast_unchecked().reborrow_mut(), i)
-                        .correct_parent_link();
+                    Handle::new_edge(left_node.reborrow_mut(), i).correct_parent_link();
                 }
 
-                Layout::new::<InternalNode<K, V>>()
+                Global.dealloc(right_node.node.cast(), Layout::new::<InternalNode<K, V>>());
             } else {
-                Layout::new::<LeafNode<K, V>>()
-            };
-            Global.dealloc(right_node.node.cast(), layout);
+                Global.dealloc(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
+            }
 
             Handle::new_edge(self.node, self.idx)
         }
@@ -1242,8 +1248,8 @@ pub fn steal_left(&mut self) {
         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),
@@ -1259,8 +1265,8 @@ pub fn steal_right(&mut self) {
         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),
@@ -1288,7 +1294,7 @@ pub fn bulk_steal_left(&mut self, count: usize) {
                 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)
                 };
 
@@ -1345,7 +1351,7 @@ pub fn bulk_steal_right(&mut self, count: usize) {
                 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)
                 };
 
index de707a71a8c9e9c920e6947687d1142e84b1570a..8ca0a0883cb1679a538d203e3b8471e5c4f705d5 100644 (file)
@@ -2620,9 +2620,6 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
 ///
 /// 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 @@ fn drop(&mut self) {
 
 /// 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> {
index 920f5e9c0bd28521e732e3e5159862168fd1c807..e45aa86c0795a915d7f5b079e4189d8a7999e3a7 100644 (file)
@@ -56,9 +56,9 @@
 /// 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 @@ pub const fn into_inner(slot: ManuallyDrop<T>) -> 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>) {
index 027498d3911c8fcac38383ee5df5cb0add760480..d2d65fd2fa517027c365215f4e88c28e3dc98125 100644 (file)
@@ -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 @@ pub unsafe fn assume_init(self) -> T {
     /// to ensure that that data may indeed be duplicated.
     ///
     /// [inv]: #initialization-invariant
-    /// [`assume_init`]: #method.assume_init
+    /// [`assume_init`]: MaybeUninit::assume_init
     ///
     /// # Examples
     ///
index eac4741cd260ad483969d3dfdc70f9cb838f2c45..934f581f3faeb7575aa8f99726e22c69f51b50a2 100644 (file)
@@ -414,12 +414,13 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
-    // SAFETY: the caller must guarantee that the bytes `v`
-    // are valid UTF-8, thus the cast to `*const str` is safe.
-    // Also, the pointer dereference is safe because that pointer
-    // comes from a reference which is guaranteed to be valid for reads.
-    unsafe { &*(v as *const [u8] as *const str) }
+#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
+#[allow(unused_attributes)]
+#[allow_internal_unstable(const_fn_transmute)]
+pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
+    // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
+    // Also relies on `&str` and `&[u8]` having the same layout.
+    unsafe { mem::transmute(v) }
 }
 
 /// Converts a slice of bytes to a string slice without checking
@@ -2357,15 +2358,10 @@ pub fn is_char_boundary(&self, index: usize) -> bool {
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
     #[inline(always)]
     #[allow(unused_attributes)]
-    #[allow_internal_unstable(const_fn_union)]
+    #[allow_internal_unstable(const_fn_transmute)]
     pub const fn as_bytes(&self) -> &[u8] {
-        #[repr(C)]
-        union Slices<'a> {
-            str: &'a str,
-            slice: &'a [u8],
-        }
         // SAFETY: const sound because we transmute two types with the same layout
-        unsafe { Slices { str: self }.slice }
+        unsafe { mem::transmute(self) }
     }
 
     /// Converts a mutable string slice to a mutable byte slice.
index fc07fa77b85e7660cebdd53a9e24d30cae5c5ff7..ef0ef415b4cbab4bbc00d7dbf5e8b86b00c627fd 100644 (file)
@@ -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" }
index da25a0ede729d1fd3c66b1819fda6e91d17aa3bb..11b3f22503e83c6c6c8a474efb6519e94884ebd5 100644 (file)
@@ -1,3 +1,4 @@
+#![deny(unsafe_op_in_unsafe_fn)]
 use crate::ascii;
 use crate::borrow::{Borrow, Cow};
 use crate::cmp::Ordering;
 /// 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 @@
 /// [`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
 /// 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
 ///
 /// 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 CStr {
 /// 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 @@ pub fn as_bytes(&self) -> &[u8] {
     ///
     /// 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 @@ pub fn into_bytes(self) -> Vec<u8> {
 
 /// 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 @@ fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
     /// 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 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> 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 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> 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 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> 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 @@ pub fn into_raw(self) -> *mut c_char {
     ///
     /// On failure, ownership of the original `CString` is returned.
     ///
-    /// [`String`]: ../string/struct.String.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -608,10 +574,8 @@ pub fn into_bytes(self) -> Vec<u8> {
         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 @@ pub fn into_bytes_with_nul(self) -> Vec<u8> {
     /// 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 @@ pub fn as_bytes(&self) -> &[u8] {
         &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 @@ pub fn as_bytes_with_nul(&self) -> &[u8] {
 
     /// Extracts a [`CStr`] slice containing the entire string.
     ///
-    /// [`CStr`]: struct.CStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -693,8 +651,6 @@ pub fn as_c_str(&self) -> &CStr {
 
     /// Converts this `CString` into a boxed [`CStr`].
     ///
-    /// [`CStr`]: struct.CStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -711,8 +667,6 @@ pub fn into_boxed_c_str(self) -> Box<CStr> {
     }
 
     /// 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 @@ fn into_inner(self) -> Box<[u8]> {
         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 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
         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 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
     ///
     /// # 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 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
     /// );
     /// ```
     ///
-    /// 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 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
     /// // 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 @@ fn from(cow: Cow<'_, CStr>) -> 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 @@ fn from(s: Box<CStr>) -> 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 @@ fn clone(&self) -> Self {
 #[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 @@ fn from(s: &'a CString) -> 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 @@ fn from(s: &CStr) -> 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 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 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     #[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 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     ///
     /// 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 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     /// }
     /// ```
     ///
-    /// 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 @@ pub fn to_bytes(&self) -> &[u8] {
 
     /// 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 @@ pub fn to_bytes_with_nul(&self) -> &[u8] {
     /// 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 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
     /// [`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 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
 
     /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
     ///
-    /// [`Box`]: ../boxed/struct.Box.html
-    /// [`CString`]: struct.CString.html
-    ///
     /// # Examples
     ///
     /// ```
index f442d7fde1a5e9464fe0e6116e2dc204930cce39..0184495eecf09ffdf59ca11148b34f41f974acd1 100644 (file)
@@ -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.
 //!
 //! 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")]
 
index d1eaf3c583f2d4b5a0ced796d64aec3576eaf263..262d39d98ee2ecc66790141c9cb2b11fe3b96162 100644 (file)
 /// 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.
 ///
 /// 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 @@ pub fn new() -> OsString {
 
     /// Converts to an [`OsStr`] slice.
     ///
-    /// [`OsStr`]: struct.OsStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -145,8 +132,6 @@ pub fn as_os_str(&self) -> &OsStr {
     ///
     /// On failure, ownership of the original `OsString` is returned.
     ///
-    /// [`String`]: ../../std/string/struct.String.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -163,7 +148,7 @@ pub fn into_string(self) -> Result<String, OsString> {
 
     /// Extends the string with the given [`&OsStr`] slice.
     ///
-    /// [`&OsStr`]: struct.OsStr.html
+    /// [`&OsStr`]: OsStr
     ///
     /// # Examples
     ///
@@ -333,8 +318,6 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
 
     /// 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 @@ fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
     ///
     /// This conversion may entail doing a check for UTF-8 validity.
     ///
-    /// [`&str`]: ../../std/primitive.str.html
+    /// [`&str`]: str
     ///
     /// # Examples
     ///
@@ -564,9 +545,7 @@ pub fn to_str(&self) -> Option<&str> {
     /// 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 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
 
     /// Copies the slice into an owned [`OsString`].
     ///
-    /// [`OsString`]: struct.OsString.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -662,9 +639,6 @@ pub fn is_empty(&self) -> bool {
     /// 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 @@ pub fn len(&self) -> usize {
     }
 
     /// 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 @@ fn bytes(&self) -> &[u8] {
     /// 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 @@ pub fn make_ascii_lowercase(&mut self) {
     /// 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 @@ pub fn make_ascii_uppercase(&mut self) {
     /// 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 @@ pub fn to_ascii_lowercase(&self) -> OsString {
     /// 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 @@ fn from(cow: Cow<'_, OsStr>) -> 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 @@ fn from(boxed: Box<OsStr>) -> 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 @@ fn clone(&self) -> Self {
 #[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 @@ fn from(s: &OsStr) -> 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();
index ff343625a19ed75932bf944f9e9cd57f394aa1e1..c39989a60c92b5c62d4615de8c46192064f45963 100644 (file)
@@ -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")]
index 8c8d1aadf48e2076b8e685ce434daffb45883091..4f751656e09c82d8d348345840f8ace30006d18d 100644 (file)
@@ -37,7 +37,7 @@
 /// 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+#[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 {
index 2c0025bcba069ea16e370713977e3e6b059fdc57..9d7b2b807636f9568072dcf3f0397d052b185b68 100644 (file)
@@ -40,7 +40,7 @@
 /// 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 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+#[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`.
index 4ba1940fd0ece193521b01b3a57b13c7405c9f17..6d94fa9ebfe6d7316dd5149e7c0068a249f42ab7 100644 (file)
 //! 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")]
 
 /// 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.
 ///
 /// 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// 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 @@ pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
     ///
     /// To pass multiple arguments see [`args`].
     ///
-    /// [`args`]: #method.args
+    /// [`args`]: Command::args
     ///
     /// # Examples
     ///
@@ -547,7 +553,7 @@ pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
     ///
     /// To pass a single argument see [`arg`].
     ///
-    /// [`arg`]: #method.arg
+    /// [`arg`]: Command::arg
     ///
     /// # Examples
     ///
@@ -700,7 +706,7 @@ pub fn env_clear(&mut self) -> &mut 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 @@ pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut 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 @@ pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut 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 @@ pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut 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 @@ fn as_inner_mut(&mut self) -> &mut imp::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 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// 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 @@ fn from(file: fs::File) -> 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// 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();
index 2c3d1e97df97574bb932723c861c6dd7c603a94e..b65a88cb90e88501721432cced016e00185e3cef 100644 (file)
@@ -50,6 +50,13 @@ pub fn header(&self) -> Option<&'a FnHeader> {
         }
     }
 
+    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,
index 90831f0bcfbeebe6ce2c4f15d549b6e57ae80985..da567293d7be08905430cee69e23bf8e21c5a347 100644 (file)
@@ -8,7 +8,7 @@
 use log::debug;
 use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage, Region};
 use rustc_codegen_ssa::traits::{
-    BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, StaticMethods,
+    BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods,
 };
 use rustc_data_structures::fx::FxHashMap;
 use rustc_llvm::RustString;
@@ -44,6 +44,16 @@ fn coverageinfo_finalize(&self) {
 }
 
 impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
+    /// Calls llvm::createPGOFuncNameVar() with the given function instance's mangled function name.
+    /// The LLVM API returns an llvm::GlobalVariable containing the function name, with the specific
+    /// variable name and linkage required by LLVM InstrProf source-based coverage instrumentation.
+    fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value {
+        let llfn = self.cx.get_fn(instance);
+        let mangled_fn_name = CString::new(self.tcx.symbol_name(instance).name)
+            .expect("error converting function name to C string");
+        unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) }
+    }
+
     fn add_counter_region(
         &mut self,
         instance: Instance<'tcx>,
index dfd5104a31f6d0ae735aba57aa8c84b476f0b85b..14aec1ff5e19e66e633f8e1115692ecc75fa3023 100644 (file)
@@ -215,19 +215,19 @@ fn codegen_intrinsic_call(
                 self.call(llfn, &[], None)
             }
             sym::count_code_region => {
-                let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
-                let mangled_fn = tcx.symbol_name(caller_instance);
-                let (mangled_fn_name, _len_val) = self.const_str(Symbol::intern(mangled_fn.name));
-                let num_counters = self.const_u32(coverageinfo.num_counters);
                 use coverage::count_code_region_args::*;
+                let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
+
+                let fn_name = self.create_pgo_func_name_var(caller_instance);
                 let hash = args[FUNCTION_SOURCE_HASH].immediate();
+                let num_counters = self.const_u32(coverageinfo.num_counters);
                 let index = args[COUNTER_ID].immediate();
                 debug!(
                     "translating Rust intrinsic `count_code_region()` to LLVM intrinsic: \
-                    instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
-                    mangled_fn.name, hash, num_counters, index,
+                    instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
+                    fn_name, hash, num_counters, index,
                 );
-                self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
+                self.instrprof_increment(fn_name, hash, num_counters, index)
             }
             sym::va_start => self.va_start(args[0].immediate()),
             sym::va_end => self.va_end(args[0].immediate()),
index f094ad868947fa32242c0a699ca98d73f31b7231..63b0aa64bd3d8dca8029397c0393b7e5cb5c76f0 100644 (file)
@@ -1786,6 +1786,8 @@ pub fn LLVMRustCoverageWriteMappingToBuffer(
         BufferOut: &RustString,
     );
 
+    pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char)
+    -> &'a Value;
     pub fn LLVMRustCoverageComputeHash(Name: *const c_char) -> u64;
 
     #[allow(improper_ctypes)]
index 7d742e7a7afd2b35a613fb20f1b9569f2133507b..e7c789ad210267e5fb9c7a9a3f5bb4603dd5d314 100644 (file)
@@ -190,7 +190,9 @@ fn exported_symbols_provider_local(
         }
     }
 
-    if tcx.sess.opts.cg.profile_generate.enabled() {
+    if tcx.sess.opts.debugging_opts.instrument_coverage
+        || tcx.sess.opts.cg.profile_generate.enabled()
+    {
         // These are weak symbols that point to the profile version and the
         // profile name, which need to be treated as exported so LTO doesn't nix
         // them.
@@ -203,17 +205,6 @@ fn exported_symbols_provider_local(
         }));
     }
 
-    if tcx.sess.opts.debugging_opts.instrument_coverage {
-        // Similar to PGO profiling, preserve symbols used by LLVM InstrProf coverage profiling.
-        const COVERAGE_WEAK_SYMBOLS: [&str; 3] =
-            ["__llvm_profile_filename", "__llvm_coverage_mapping", "__llvm_covmap"];
-
-        symbols.extend(COVERAGE_WEAK_SYMBOLS.iter().map(|sym| {
-            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
-            (exported_symbol, SymbolExportLevel::C)
-        }));
-    }
-
     if tcx.sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::MEMORY) {
         // Similar to profiling, preserve weak msan symbol during LTO.
         const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"];
index 2b5878f46bc43bfc7540b45468f6657e5c7e07ee..5602599b0c25b579aaaef4fb560344444dd7504f 100644 (file)
@@ -7,6 +7,8 @@ pub trait CoverageInfoMethods: BackendTypes {
 }
 
 pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
+    fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value;
+
     fn add_counter_region(
         &mut self,
         instance: Instance<'tcx>,
index 86945f83b55240a30af21ecd8c5460a666dbbb80..9736da80c2b7b178396f85e680e7ff358a15215c 100644 (file)
@@ -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(())
 }
 ```
index 7fbe5c409d3ce283f0a694a86a9f4d4551c21130..4101f70b8206dbaacda90a9940e8e35b54168fe5 100644 (file)
@@ -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,
index dffbc969c21b8c645158e7ba7850e59d29df5bb6..6c8ee72bc66c2e01e65435a34df0ceeb13fb7eb8 100644 (file)
@@ -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,
     };
 
index baa3e5e1581c5c2f2f90652690de56cf5c16a6da..324289166b9fb0c913929dadcc63863979d8d44c 100644 (file)
@@ -86,12 +86,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
                 .skip(1)
                 .take(arg_count)
                 .map(|(local, _)| Place::from(local))
-                .filter(needs_retag)
-                .collect::<Vec<_>>();
+                .filter(needs_retag);
             // Emit their retags.
             basic_blocks[START_BLOCK].statements.splice(
                 0..0,
-                places.into_iter().map(|place| Statement {
+                places.map(|place| Statement {
                     source_info,
                     kind: StatementKind::Retag(RetagKind::FnEntry, box (place)),
                 }),
@@ -101,29 +100,24 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
         // PART 2
         // Retag return values of functions.  Also escape-to-raw the argument of `drop`.
         // We collect the return destinations because we cannot mutate while iterating.
-        let mut returns: Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new();
-        for block_data in basic_blocks.iter_mut() {
-            match block_data.terminator().kind {
-                TerminatorKind::Call { ref destination, .. } => {
-                    // Remember the return destination for later
-                    if let Some(ref destination) = destination {
-                        if needs_retag(&destination.0) {
-                            returns.push((
-                                block_data.terminator().source_info,
-                                destination.0,
-                                destination.1,
-                            ));
-                        }
+        let returns = basic_blocks
+            .iter_mut()
+            .filter_map(|block_data| {
+                match block_data.terminator().kind {
+                    TerminatorKind::Call { destination: Some(ref destination), .. }
+                        if needs_retag(&destination.0) =>
+                    {
+                        // Remember the return destination for later
+                        Some((block_data.terminator().source_info, destination.0, destination.1))
                     }
-                }
-                TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
+
                     // `Drop` is also a call, but it doesn't return anything so we are good.
-                }
-                _ => {
+                    TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None,
                     // Not a block ending in a Call -> ignore.
+                    _ => None,
                 }
-            }
-        }
+            })
+            .collect::<Vec<_>>();
         // Now we go over the returns we collected to retag the return values.
         for (source_info, dest_place, dest_block) in returns {
             basic_blocks[dest_block].statements.insert(
index 2de701284e3f5815dfd7e7a9df876c1a84c78e71..66989a902447d6076071f0936672459dc276f4e9 100644 (file)
@@ -12,26 +12,24 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<
         for bb in basic_blocks {
             bb.expand_statements(|stmt| {
                 // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
-                if let StatementKind::Assign(box (_, ref rhs)) = stmt.kind {
-                    if let Rvalue::Aggregate(ref kind, _) = *rhs {
-                        // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
-                        if let AggregateKind::Array(_) = **kind {
-                            return None;
-                        }
-                    } else {
+                match stmt.kind {
+                    // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
+                    StatementKind::Assign(box (
+                        _,
+                        Rvalue::Aggregate(box AggregateKind::Array(_), _),
+                    )) => {
                         return None;
                     }
-                } else {
-                    return None;
+                    StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {}
+                    _ => return None,
                 }
 
                 let stmt = stmt.replace_nop();
                 let source_info = stmt.source_info;
                 let (lhs, kind, operands) = match stmt.kind {
-                    StatementKind::Assign(box (lhs, rvalue)) => match rvalue {
-                        Rvalue::Aggregate(kind, operands) => (lhs, kind, operands),
-                        _ => bug!(),
-                    },
+                    StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) => {
+                        (lhs, kind, operands)
+                    }
                     _ => bug!(),
                 };
 
index 5b2954dd5b0a3e08ebf228722ed6d056f35d9631..500d66ece0676312e08461c17b9e24e11f515446 100644 (file)
@@ -295,6 +295,21 @@ fn inject_call(
 
         let (file_name, start_line, start_col, end_line, end_col) = self.code_region(&span);
 
+        // FIXME(richkadel): Note that `const_str()` results in the creation of an `Allocation` to
+        // hold one copy of each unique filename. It looks like that `Allocation` may translate into
+        // the creation of an `@alloc` in LLVM IR that is never actually used by runtime code.
+        //
+        // Example LLVM IR:
+        //
+        // @alloc4 = private unnamed_addr constant <{ [43 x i8] }> \
+        //   <{ [43 x i8] c"C:\\msys64\\home\\richkadel\\rust\\rust_basic.rs" }>, align 1
+        //
+        // Can I flag the alloc as something not to be added to codegen? Or somehow remove it before
+        // it gets added to the LLVM IR? Do we need some kind of reference counting to know it's
+        // not used by any runtime code?
+        //
+        // This question is moot if I convert the Call Terminators to Statements, I believe:
+        // https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Implement.20LLVM-compatible.20source-based.20cod.20compiler-team.23278/near/206731748
         args.push(self.const_str(&file_name, inject_at));
         args.push(self.const_u32(start_line, inject_at));
         args.push(self.const_u32(start_col, inject_at));
index c0564105701575f20c9c00150f3be4d61ce602f9..94637bae44a7806cce8d6c3b9157890ebd74f512 100644 (file)
@@ -101,7 +101,7 @@ pub fn is_promotable(&self) -> bool {
 /// 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]`.
index 02896d7de357ff40524e740a303f75264bec4232..84082edd1933f61ec858fe2abba005a3ede99ec9 100644 (file)
@@ -246,12 +246,14 @@ fn find_storage_live_dead_stmts_for_local<'tcx>(
         tmp_assigned_vars.insert(*r);
     }
 
-    let mut dbg_info_to_adjust = Vec::new();
-    for (i, var_info) in debug_info.iter().enumerate() {
-        if tmp_assigned_vars.contains(var_info.place.local) {
-            dbg_info_to_adjust.push(i);
-        }
-    }
+    let dbg_info_to_adjust: Vec<_> =
+        debug_info
+            .iter()
+            .enumerate()
+            .filter_map(|(i, var_info)| {
+                if tmp_assigned_vars.contains(var_info.place.local) { Some(i) } else { None }
+            })
+            .collect();
 
     Some(ArmIdentityInfo {
         local_temp_0: local_tmp_s0,
@@ -461,14 +463,14 @@ fn match_get_variant_field<'tcx>(
     stmt: &Statement<'tcx>,
 ) -> Option<(Local, Local, VarField<'tcx>, &'tcx List<PlaceElem<'tcx>>)> {
     match &stmt.kind {
-        StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from {
-            Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)) => {
-                let local_into = place_into.as_local()?;
-                let (local_from, vf) = match_variant_field_place(*pf)?;
-                Some((local_into, local_from, vf, pf.projection))
-            }
-            _ => None,
-        },
+        StatementKind::Assign(box (
+            place_into,
+            Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)),
+        )) => {
+            let local_into = place_into.as_local()?;
+            let (local_from, vf) = match_variant_field_place(*pf)?;
+            Some((local_into, local_from, vf, pf.projection))
+        }
         _ => None,
     }
 }
@@ -479,14 +481,11 @@ fn match_get_variant_field<'tcx>(
 /// ```
 fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
     match &stmt.kind {
-        StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into {
-            Rvalue::Use(Operand::Move(place_into)) => {
-                let local_into = place_into.as_local()?;
-                let (local_from, vf) = match_variant_field_place(*place_from)?;
-                Some((local_into, local_from, vf))
-            }
-            _ => None,
-        },
+        StatementKind::Assign(box (place_from, Rvalue::Use(Operand::Move(place_into)))) => {
+            let local_into = place_into.as_local()?;
+            let (local_from, vf) = match_variant_field_place(*place_from)?;
+            Some((local_into, local_from, vf))
+        }
         _ => None,
     }
 }
index e3b182b88492f10e81f5b2e7430dd3c3a6114452..4cca4d223c0cb6dd7c2f6cff5e71b762b549012b 100644 (file)
@@ -99,26 +99,18 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
             if let TerminatorKind::SwitchInt { values, targets, .. } =
                 &mut body.basic_blocks_mut()[bb].terminator_mut().kind
             {
-                let vals = &*values;
-                let zipped = vals.iter().zip(targets.iter());
-
-                let mut matched_values = Vec::with_capacity(allowed_variants.len());
-                let mut matched_targets = Vec::with_capacity(allowed_variants.len() + 1);
-
-                for (val, target) in zipped {
-                    if allowed_variants.contains(val) {
-                        matched_values.push(*val);
-                        matched_targets.push(*target);
-                    } else {
-                        trace!("eliminating {:?} -> {:?}", val, target);
-                    }
-                }
-
-                // handle the "otherwise" branch
-                matched_targets.push(targets.pop().unwrap());
-
-                *values = matched_values.into();
-                *targets = matched_targets;
+                // take otherwise out early
+                let otherwise = targets.pop().unwrap();
+                assert_eq!(targets.len(), values.len());
+                let mut i = 0;
+                targets.retain(|_| {
+                    let keep = allowed_variants.contains(&values[i]);
+                    i += 1;
+                    keep
+                });
+                targets.push(otherwise);
+
+                values.to_mut().retain(|var| allowed_variants.contains(var));
             } else {
                 unreachable!()
             }
index d9f2259030ff5b0b05ee715e8687b7405259bcb1..fa362c66fb2897a02661f19e2a50486830f1021e 100644 (file)
@@ -67,18 +67,13 @@ fn remove_successors<F>(
 where
     F: Fn(BasicBlock) -> bool,
 {
-    match *terminator_kind {
-        TerminatorKind::Goto { target } if predicate(target) => Some(TerminatorKind::Unreachable),
+    let terminator = match *terminator_kind {
+        TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable,
         TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
             let original_targets_len = targets.len();
             let (otherwise, targets) = targets.split_last().unwrap();
-            let retained = values
-                .iter()
-                .zip(targets.iter())
-                .filter(|(_, &t)| !predicate(t))
-                .collect::<Vec<_>>();
-            let mut values = retained.iter().map(|&(v, _)| *v).collect::<Vec<_>>();
-            let mut targets = retained.iter().map(|&(_, d)| *d).collect::<Vec<_>>();
+            let (mut values, mut targets): (Vec<_>, Vec<_>) =
+                values.iter().zip(targets.iter()).filter(|(_, &t)| !predicate(t)).unzip();
 
             if !predicate(*otherwise) {
                 targets.push(*otherwise);
@@ -89,20 +84,21 @@ fn remove_successors<F>(
             let retained_targets_len = targets.len();
 
             if targets.is_empty() {
-                Some(TerminatorKind::Unreachable)
+                TerminatorKind::Unreachable
             } else if targets.len() == 1 {
-                Some(TerminatorKind::Goto { target: targets[0] })
+                TerminatorKind::Goto { target: targets[0] }
             } else if original_targets_len != retained_targets_len {
-                Some(TerminatorKind::SwitchInt {
+                TerminatorKind::SwitchInt {
                     discr: discr.clone(),
                     switch_ty,
                     values: Cow::from(values),
                     targets,
-                })
+                }
             } else {
-                None
+                return None;
             }
         }
-        _ => None,
-    }
+        _ => return None,
+    };
+    Some(terminator)
 }
index a7d3697405751782b82f579613424af3a6ae6351..b3746ac2db2bdd36b863d322bed176933e9b7633 100644 (file)
@@ -7,6 +7,7 @@
 
 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 @@ pub(crate) fn smart_resolve_report_errors(
         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 @@ pub(crate) fn smart_resolve_report_errors(
                 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());
index 2be100ae33662174e16a127c54c18e04a0e580ef..3093ddbeaf1ae05de8418b436a00ff5dd51e31b3 100644 (file)
@@ -1623,6 +1623,7 @@ fn conv_object_ty_poly_trait_ref(
         span: Span,
         trait_bounds: &[hir::PolyTraitRef<'_>],
         lifetime: &hir::Lifetime,
+        borrowed: bool,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
 
@@ -1837,15 +1838,20 @@ fn conv_object_ty_poly_trait_ref(
                     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 @@ pub fn res_to_ty(
     /// 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 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
             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 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
                 ))
             }
             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);
index 7c8481540aae41d259bd79eaa99be4b45634a040..4d15e31df15a3edbe90d443e8833e47b2e1bb65f 100644 (file)
@@ -38,6 +38,11 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   CoverageMappingWriter.write(OS);
 }
 
+extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
+  StringRef FuncNameRef(FuncName);
+  return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
+}
+
 extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
   StringRef NameRef(Name);
   return IndexedInstrProf::ComputeHash(NameRef);
index df47305b547a82e7070dd9f126b65b68e1ea1ef8..4392cfec080dcb0fdcef38d0de01feb6d3ccc6df 100644 (file)
 
 # FIXME(richkadel): Debug the following problem, and reenable on Windows (by
 # removing the `# ignore-msvc` directive above). The current implementation
-# generates a segfault when running the instrumented `main` executable,
-# after the `main` program code executes, but before the process terminates.
-# This most likely points to a problem generating the LLVM "main.profraw"
+# generates a segfault when running the instrumented `testprog` executable,
+# after the `main()` function completes, but before the process terminates.
+# This most likely points to a problem generating the LLVM "testprog.profraw"
 # file.
 
 -include ../tools.mk
 
+UNAME = $(shell uname)
+
+ifeq ($(UNAME),Darwin)
+       INSTR_PROF_DATA_SUFFIX=,regular,live_support
+       DATA_SECTION_PREFIX=__DATA,
+       LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+else
+       INSTR_PROF_DATA_SUFFIX=
+       DATA_SECTION_PREFIX=
+       LLVM_COV_SECTION_PREFIX=
+endif
+
 # This test makes sure that LLVM coverage maps are genereated in LLVM IR.
 
 COMMON_FLAGS=-Zinstrument-coverage
 
 all:
        # Compile the test program with instrumentation, and also generate LLVM IR
-       $(RUSTC) $(COMMON_FLAGS) main.rs
+       $(RUSTC) $(COMMON_FLAGS) testprog.rs \
+                       --emit=link,llvm-ir
+
+       # check the LLVM IR
+ifdef IS_WIN32
+       cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt \
+                       -check-prefixes=CHECK,WIN32 \
+                       -DPRIVATE_GLOBAL="internal global" \
+                       -DINSTR_PROF_DATA=".lprfd$$M" \
+                       -DINSTR_PROF_NAME=".lprfn$$M" \
+                       -DINSTR_PROF_CNTS=".lprfc$$M" \
+                       -DINSTR_PROF_VALS=".lprfv$$M" \
+                       -DINSTR_PROF_VNODES=".lprfnd$$M" \
+                       -DINSTR_PROF_COVMAP=".lcovmap$$M" \
+                       -DINSTR_PROF_ORDERFILE=".lorderfile$$M"
+else
+       cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt \
+                       -check-prefixes=CHECK \
+                       -DPRIVATE_GLOBAL="private global" \
+                       -DINSTR_PROF_DATA="$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)" \
+                       -DINSTR_PROF_NAME="$(DATA_SECTION_PREFIX)__llvm_prf_names" \
+                       -DINSTR_PROF_CNTS="$(DATA_SECTION_PREFIX)__llvm_prf_cnts" \
+                       -DINSTR_PROF_VALS="$(DATA_SECTION_PREFIX)__llvm_prf_vals" \
+                       -DINSTR_PROF_VNODES="$(DATA_SECTION_PREFIX)__llvm_prf_vnds" \
+                       -DINSTR_PROF_COVMAP="$(LLVM_COV_SECTION_PREFIX)__llvm_covmap" \
+                       -DINSTR_PROF_ORDERFILE="$(DATA_SECTION_PREFIX)__llvm_orderfile"
+endif
 
        # Run it in order to generate some profiling data,
        # with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
        # output the coverage stats for this run.
-       LLVM_PROFILE_FILE="$(TMPDIR)"/main.profraw \
-         $(call RUN,main)
+       LLVM_PROFILE_FILE="$(TMPDIR)"/testprog.profraw \
+                       $(call RUN,testprog)
 
        # Postprocess the profiling data so it can be used by the llvm-cov tool
        "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
-         "$(TMPDIR)"/main.profraw \
-               -o "$(TMPDIR)"/main.profdata
+                       "$(TMPDIR)"/testprog.profraw \
+                       -o "$(TMPDIR)"/testprog.profdata
 
        # Generate a coverage report using `llvm-cov show`. The output ordering
        # can be non-deterministic, so ignore the return status. If the test fails
        # when comparing the JSON `export`, the `show` output may be useful when
        # debugging.
        "$(LLVM_BIN_DIR)"/llvm-cov show \
-         --Xdemangler="$(RUST_DEMANGLER)" \
-         --show-line-counts-or-regions \
-         --instr-profile="$(TMPDIR)"/main.profdata \
-               $(call BIN,"$(TMPDIR)"/main) \
+                       --Xdemangler="$(RUST_DEMANGLER)" \
+                       --show-line-counts-or-regions \
+                       --instr-profile="$(TMPDIR)"/testprog.profdata \
+                       $(call BIN,"$(TMPDIR)"/testprog) \
                > "$(TMPDIR)"/actual_show_coverage.txt
 
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/actual_show_coverage.txt typical_show_coverage.txt
+else
        # Compare the show coverage output
        $(DIFF) typical_show_coverage.txt "$(TMPDIR)"/actual_show_coverage.txt || \
-         >&2 echo 'diff failed for `llvm-cov show` (might not be an error)'
+               >&2 echo 'diff failed for `llvm-cov show` (might not be an error)'
+endif
 
        # Generate a coverage report in JSON, using `llvm-cov export`, and fail if
        # there are differences from the expected output.
        "$(LLVM_BIN_DIR)"/llvm-cov export \
-         --summary-only \
-         --instr-profile="$(TMPDIR)"/main.profdata \
-               $(call BIN,"$(TMPDIR)"/main) \
+                       --summary-only \
+                       --instr-profile="$(TMPDIR)"/testprog.profdata \
+                       $(call BIN,"$(TMPDIR)"/testprog) \
                | "$(PYTHON)" prettify_json.py \
                > "$(TMPDIR)"/actual_export_coverage.json
 
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/actual_export_coverage.json expected_export_coverage.json
+else
        # Check that the exported JSON coverage data matches what we expect
        $(DIFF) expected_export_coverage.json "$(TMPDIR)"/actual_export_coverage.json
+endif
index 9d739a89114e2c37f359977e4ca0fb6e9e09df92..5881cf4b7dbbc6eefa64b4f83e9a26b17e1bb830 100644 (file)
@@ -3,7 +3,7 @@
     {
       "files": [
         {
-          "filename": "main.rs",
+          "filename": "testprog.rs",
           "summary": {
             "functions": {
               "count": 7,
diff --git a/src/test/run-make-fulldeps/instrument-coverage/filecheck-patterns.txt b/src/test/run-make-fulldeps/instrument-coverage/filecheck-patterns.txt
new file mode 100644 (file)
index 0000000..5a7cc9a
--- /dev/null
@@ -0,0 +1,51 @@
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Zinstrument-coverage.
+
+WIN32:      $__llvm_profile_runtime_user = comdat any
+
+CHECK:      @__llvm_coverage_mapping = internal constant
+CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
+
+WIN32:      @__llvm_profile_runtime = external global i32
+
+CHECK:      @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]]
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8
+
+CHECK:      @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]]
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+CHECK-SAME: ()* @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called to i8*),
+CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8
+
+CHECK:      @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]]
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8
+
+CHECK:      @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]]
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main,
+CHECK-SAME: ()* @_R{{[a-zA-Z0-9_]+}}testprog4main to i8*),
+CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8
+
+CHECK:      @__llvm_prf_nm = private constant
+CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK:      @llvm.used = appending global
+CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
+WIN32-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)
+CHECK-SAME: i8* bitcast ({ {{.*}} }* @__profd__R{{[a-zA-Z0-9_]*}}testprog4main to i8*)
+CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0)
+CHECK-SAME: section "llvm.metadata"
+
+CHECK:      define hidden { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT: start:
+CHECK-NOT:  bb{{[0-9]+}}:
+CHECK:      %pgocount = load i64, i64* getelementptr inbounds
+CHECK-SAME: * @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK:      declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WIN32:      define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WIN32-NEXT: %1 = load i32, i32* @__llvm_profile_runtime
+WIN32-NEXT: ret i32 %1
+WIN32-NEXT: }
+
+CHECK:      attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WIN32:      attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
\ No newline at end of file
diff --git a/src/test/run-make-fulldeps/instrument-coverage/main.rs b/src/test/run-make-fulldeps/instrument-coverage/main.rs
deleted file mode 100644 (file)
index 358c256..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-pub fn will_be_called() -> &'static str {
-    let val = "called";
-    println!("{}", val);
-    val
-}
-
-pub fn will_not_be_called() -> bool {
-    println!("should not have been called");
-    false
-}
-
-pub fn print<T>(left: &str, value: T, right: &str)
-where
-    T: std::fmt::Display,
-{
-    println!("{}{}{}", left, value, right);
-}
-
-pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
-where
-    F: FnOnce(&T)
-{
-    if should_wrap {
-        wrapper(&inner)
-    }
-}
-
-fn main() {
-    let less = 1;
-    let more = 100;
-
-    if less < more {
-        wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
-        wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
-    } else {
-        wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
-    }
-}
diff --git a/src/test/run-make-fulldeps/instrument-coverage/testprog.rs b/src/test/run-make-fulldeps/instrument-coverage/testprog.rs
new file mode 100644 (file)
index 0000000..358c256
--- /dev/null
@@ -0,0 +1,38 @@
+pub fn will_be_called() -> &'static str {
+    let val = "called";
+    println!("{}", val);
+    val
+}
+
+pub fn will_not_be_called() -> bool {
+    println!("should not have been called");
+    false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+    T: std::fmt::Display,
+{
+    println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+    F: FnOnce(&T)
+{
+    if should_wrap {
+        wrapper(&inner)
+    }
+}
+
+fn main() {
+    let less = 1;
+    let more = 100;
+
+    if less < more {
+        wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+        wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+    } else {
+        wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+    }
+}
index 9c593d0809d484ce3dfc1cf934148496b1ce8b07..ae123afff04000652fa3feee1e539d007bf267a4 100644 (file)
    25|      2|    }
    26|      2|}
   ------------------
-  | main[317d481089b8c8fe]::wrap_with::<main[317d481089b8c8fe]::main::{closure#0}, &str>:
+  | testprog[317d481089b8c8fe]::wrap_with::<testprog[317d481089b8c8fe]::main::{closure#0}, &str>:
   |   22|      1|{
   |   23|      1|    if should_wrap {
   |   24|      1|        wrapper(&inner)
   |   25|      1|    }
   |   26|      1|}
   ------------------
-  | main[317d481089b8c8fe]::wrap_with::<main[317d481089b8c8fe]::main::{closure#1}, &str>:
+  | testprog[317d481089b8c8fe]::wrap_with::<testprog[317d481089b8c8fe]::main::{closure#1}, &str>:
   |   22|      1|{
   |   23|      1|    if should_wrap {
   |   24|      1|        wrapper(&inner)
index 3c6a1d4f88f1153b60c1dd5bba8962b163393d06..fa0c86ecf489423b8e1b67d765fb1ff8e2e87a99 100644 (file)
@@ -6,6 +6,10 @@ fn bar(self) {}
     fn foo() {
         self.bar(); //~ ERROR E0424
     }
+
+    fn baz(_: i32) {
+        self.bar(); //~ ERROR E0424
+    }
 }
 
 fn main () {
index 690a101496d7325eee1265c9b532fa6c37ec0e1e..9b8a29e8272492e64d8f513ec95b46b85d0d6d9b 100644 (file)
@@ -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`.
index d00fff32809206b285a178d948abe48eec69342f..ee134835c37ed14eae101b077ee613c0dc68ee13 100644 (file)
@@ -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() {}
index cc11db9c5eca62dab03f485c58572d80ec9ab679..b52fd28b2b575a9490700fbce875b36175f6f9ef 100644 (file)
@@ -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`.
index b687f0b0af0ad90f60c98d9d0a6f44e182055bbf..0339daa0d6a18c0018937304bf45bf51dd9629be 100644 (file)
@@ -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
 
index b09c1879d701599092a3fa1e5e1d96817a317f85..fe88d105c78bf19f697db21bb7c47be77cb1a4df 100644 (file)
@@ -25,8 +25,6 @@ trait Tar<'t, 'k, I> {}
     //~| 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 @@ trait Tar<'t, 'k, I> {}
     //~| 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 @@ trait Tar<'t, 'k, I> {}
 }
 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
index 2630cf1affae6be7531a36b9d6aa44f8048b9766..9838ac72ad7675f9b3906f4bf736a138c45fca32 100644 (file)
@@ -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`.