about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-02 20:00:51 +0000
committerbors <bors@rust-lang.org>2021-07-02 20:00:51 +0000
commit798baebde1fe77e5a660490ec64e727a5d79970d (patch)
tree271df8bcac32ffd8ffd2d52d4a56f0094cecdcbf
parent2545459bff0aae43288e2e17bff0d332c49a6353 (diff)
parent1b136323dcd219241bf8b8949f50992a83b28954 (diff)
downloadrust-798baebde1fe77e5a660490ec64e727a5d79970d.tar.gz
rust-798baebde1fe77e5a660490ec64e727a5d79970d.zip
Auto merge of #86817 - JohnTitor:rollup-rcysc95, r=JohnTitor
Rollup of 7 pull requests

Successful merges:

 - #84029 (add `track_path::path` fn for usage in `proc_macro`s)
 - #85001 (Merge `sys_common::bytestring` back into `os_str_bytes`)
 - #86308 (Docs: clarify that certain intrinsics are not unsafe)
 - #86796 (Add a regression test for issue-70703)
 - #86803 (Remove & from Command::args calls in documentation)
 - #86807 (Fix double import in wasm thread )
 - #86813 (Add a help message to `unused_doc_comments` lint)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs4
-rw-r--r--compiler/rustc_interface/src/passes.rs16
-rw-r--r--compiler/rustc_lint/src/builtin.rs15
-rw-r--r--compiler/rustc_session/src/parse.rs3
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs4
-rw-r--r--library/core/src/intrinsics.rs165
-rw-r--r--library/proc_macro/src/bridge/mod.rs1
-rw-r--r--library/proc_macro/src/lib.rs14
-rw-r--r--library/std/src/process.rs4
-rw-r--r--library/std/src/sys/wasm/atomics/thread.rs1
-rw-r--r--library/std/src/sys_common/bytestring.rs26
-rw-r--r--library/std/src/sys_common/bytestring/tests.rs19
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/os_str_bytes.rs22
-rw-r--r--library/std/src/sys_common/os_str_bytes/tests.rs10
-rw-r--r--src/test/run-make/track-path-dep-info/Makefile13
-rw-r--r--src/test/run-make/track-path-dep-info/emojis.txt1
-rw-r--r--src/test/run-make/track-path-dep-info/macro_def.rs11
-rw-r--r--src/test/run-make/track-path-dep-info/macro_use.rs6
-rw-r--r--src/test/ui/inference/issue-70703.rs26
-rw-r--r--src/test/ui/unused/unused-doc-comments-edge-cases.rs29
-rw-r--r--src/test/ui/unused/unused-doc-comments-edge-cases.stderr61
-rw-r--r--src/test/ui/unused/useless-comment.stderr16
23 files changed, 410 insertions, 58 deletions
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 92315c4d4f6..1d73002710d 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -411,6 +411,10 @@ impl server::FreeFunctions for Rustc<'_> {
     fn track_env_var(&mut self, var: &str, value: Option<&str>) {
         self.sess.env_depinfo.borrow_mut().insert((Symbol::intern(var), value.map(Symbol::intern)));
     }
+
+    fn track_path(&mut self, path: &str) {
+        self.sess.file_depinfo.borrow_mut().insert(Symbol::intern(path));
+    }
 }
 
 impl server::TokenStream for Rustc<'_> {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 9ea1f88b43f..c0f7ea8df49 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -28,18 +28,18 @@ use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
 use rustc_query_impl::Queries as TcxQueries;
 use rustc_resolve::{Resolver, ResolverArenas};
+use rustc_serialize::json;
 use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode};
 use rustc_session::lint;
 use rustc_session::output::{filename_for_input, filename_for_metadata};
 use rustc_session::search_paths::PathKind;
 use rustc_session::Session;
 use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::FileName;
 use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
-use tracing::{info, warn};
-
-use rustc_serialize::json;
 use tempfile::Builder as TempFileBuilder;
+use tracing::{info, warn};
 
 use std::any::Any;
 use std::cell::RefCell;
@@ -594,6 +594,16 @@ fn write_out_deps(
             .map(|fmap| escape_dep_filename(&fmap.name.prefer_local().to_string()))
             .collect();
 
+        // Account for explicitly marked-to-track files
+        // (e.g. accessed in proc macros).
+        let file_depinfo = sess.parse_sess.file_depinfo.borrow();
+        let extra_tracked_files = file_depinfo.iter().map(|path_sym| {
+            let path = PathBuf::from(&*path_sym.as_str());
+            let file = FileName::from(path);
+            escape_dep_filename(&file.prefer_local().to_string())
+        });
+        files.extend(extra_tracked_files);
+
         if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend {
             files.push(backend.to_string());
         }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 65695fc03de..b303f55cf77 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -984,13 +984,16 @@ impl EarlyLintPass for DeprecatedAttr {
 }
 
 fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) {
+    use rustc_ast::token::CommentKind;
+
     let mut attrs = attrs.iter().peekable();
 
     // Accumulate a single span for sugared doc comments.
     let mut sugared_span: Option<Span> = None;
 
     while let Some(attr) = attrs.next() {
-        if attr.is_doc_comment() {
+        let is_doc_comment = attr.is_doc_comment();
+        if is_doc_comment {
             sugared_span =
                 Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi())));
         }
@@ -1001,13 +1004,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
 
         let span = sugared_span.take().unwrap_or(attr.span);
 
-        if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) {
+        if is_doc_comment || cx.sess().check_name(attr, sym::doc) {
             cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
                 let mut err = lint.build("unused doc comment");
                 err.span_label(
                     node_span,
                     format!("rustdoc does not generate documentation for {}", node_kind),
                 );
+                match attr.kind {
+                    AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
+                        err.help("use `//` for a plain comment");
+                    }
+                    AttrKind::DocComment(CommentKind::Block, _) => {
+                        err.help("use `/* */` for a plain comment");
+                    }
+                }
                 err.emit();
             });
         }
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 7b7878e9c7f..226fde2343a 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -133,6 +133,8 @@ pub struct ParseSess {
     pub reached_eof: Lock<bool>,
     /// Environment variables accessed during the build and their values when they exist.
     pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>,
+    /// File paths accessed during the build.
+    pub file_depinfo: Lock<FxHashSet<Symbol>>,
     /// All the type ascriptions expressions that have had a suggestion for likely path typo.
     pub type_ascription_path_suggestions: Lock<FxHashSet<Span>>,
     /// Whether cfg(version) should treat the current release as incomplete
@@ -165,6 +167,7 @@ impl ParseSess {
             symbol_gallery: SymbolGallery::default(),
             reached_eof: Lock::new(false),
             env_depinfo: Default::default(),
+            file_depinfo: Default::default(),
             type_ascription_path_suggestions: Default::default(),
             assume_incomplete_release: false,
             proc_macro_quoted_spans: Default::default(),
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index a56aefcef9c..882d5d54b7c 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -65,6 +65,10 @@ fn equate_intrinsic_type<'tcx>(
 /// Returns the unsafety of the given intrinsic.
 pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
     match intrinsic {
+        // When adding a new intrinsic to this list,
+        // it's usually worth updating that intrinsic's documentation
+        // to note that it's safe to call, since
+        // safe extern fns are otherwise unprecedented.
         sym::abort
         | sym::size_of
         | sym::min_align_of
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index baa0952c8bb..b4311bbe5f4 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -712,6 +712,11 @@ extern "rust-intrinsic" {
 
     /// Aborts the execution of the process.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// A more user-friendly and stable version of this operation is
     /// [`std::process::abort`](../../std/process/fn.abort.html).
     pub fn abort() -> !;
@@ -745,6 +750,11 @@ extern "rust-intrinsic" {
     ///
     /// Any use other than with `if` statements will probably not have an effect.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_likely", issue = "none")]
     pub fn likely(b: bool) -> bool;
@@ -754,6 +764,11 @@ extern "rust-intrinsic" {
     ///
     /// Any use other than with `if` statements will probably not have an effect.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_likely", issue = "none")]
     pub fn unlikely(b: bool) -> bool;
@@ -765,6 +780,11 @@ extern "rust-intrinsic" {
 
     /// The size of a type in bytes.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// More specifically, this is the offset in bytes between successive
     /// items of the same type, including alignment padding.
     ///
@@ -774,6 +794,11 @@ extern "rust-intrinsic" {
 
     /// The minimum alignment of a type.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::mem::align_of`].
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
@@ -796,6 +821,11 @@ extern "rust-intrinsic" {
 
     /// Gets a static string slice containing the name of a type.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::any::type_name`].
     #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
     pub fn type_name<T: ?Sized>() -> &'static str;
@@ -804,6 +834,11 @@ extern "rust-intrinsic" {
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
     #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
@@ -829,6 +864,11 @@ extern "rust-intrinsic" {
 
     /// Gets a reference to a static `Location` indicating where it was called.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// Consider using [`core::panic::Location::caller`] instead.
     #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
@@ -837,6 +877,11 @@ extern "rust-intrinsic" {
     ///
     /// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
     /// `ManuallyDrop` instead.
+    ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
     pub fn forget<T: ?Sized>(_: T);
 
@@ -1090,6 +1135,11 @@ extern "rust-intrinsic" {
     /// If the actual type neither requires drop glue nor implements
     /// `Copy`, then the return value of this function is unspecified.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
     #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
     pub fn needs_drop<T>() -> bool;
@@ -1310,21 +1360,41 @@ extern "rust-intrinsic" {
 
     /// Returns the minimum of two `f32` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f32::min`]
     pub fn minnumf32(x: f32, y: f32) -> f32;
     /// Returns the minimum of two `f64` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f64::min`]
     pub fn minnumf64(x: f64, y: f64) -> f64;
     /// Returns the maximum of two `f32` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f32::max`]
     pub fn maxnumf32(x: f32, y: f32) -> f32;
     /// Returns the maximum of two `f64` values.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is
     /// [`f64::max`]
     pub fn maxnumf64(x: f64, y: f64) -> f64;
@@ -1438,6 +1508,11 @@ extern "rust-intrinsic" {
 
     /// Returns the number of bits set in an integer type `T`
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `count_ones` method. For example,
     /// [`u32::count_ones`]
@@ -1446,6 +1521,11 @@ extern "rust-intrinsic" {
 
     /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `leading_zeros` method. For example,
     /// [`u32::leading_zeros`]
@@ -1497,6 +1577,11 @@ extern "rust-intrinsic" {
 
     /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `trailing_zeros` method. For example,
     /// [`u32::trailing_zeros`]
@@ -1548,6 +1633,11 @@ extern "rust-intrinsic" {
 
     /// Reverses the bytes in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `swap_bytes` method. For example,
     /// [`u32::swap_bytes`]
@@ -1556,6 +1646,11 @@ extern "rust-intrinsic" {
 
     /// Reverses the bits in an integer type `T`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `reverse_bits` method. For example,
     /// [`u32::reverse_bits`]
@@ -1564,6 +1659,11 @@ extern "rust-intrinsic" {
 
     /// Performs checked integer addition.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_add` method. For example,
     /// [`u32::overflowing_add`]
@@ -1572,6 +1672,11 @@ extern "rust-intrinsic" {
 
     /// Performs checked integer subtraction
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_sub` method. For example,
     /// [`u32::overflowing_sub`]
@@ -1580,6 +1685,11 @@ extern "rust-intrinsic" {
 
     /// Performs checked integer multiplication
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_mul` method. For example,
     /// [`u32::overflowing_mul`]
@@ -1649,6 +1759,11 @@ extern "rust-intrinsic" {
 
     /// Performs rotate left.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
     /// [`u32::rotate_left`]
@@ -1657,6 +1772,11 @@ extern "rust-intrinsic" {
 
     /// Performs rotate right.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_right` method. For example,
     /// [`u32::rotate_right`]
@@ -1665,6 +1785,11 @@ extern "rust-intrinsic" {
 
     /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`u32::wrapping_add`]
@@ -1672,6 +1797,11 @@ extern "rust-intrinsic" {
     pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`u32::wrapping_sub`]
@@ -1679,6 +1809,11 @@ extern "rust-intrinsic" {
     pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`u32::wrapping_mul`]
@@ -1687,6 +1822,11 @@ extern "rust-intrinsic" {
 
     /// Computes `a + b`, saturating at numeric bounds.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`u32::saturating_add`]
@@ -1694,6 +1834,11 @@ extern "rust-intrinsic" {
     pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
     /// Computes `a - b`, saturating at numeric bounds.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
     /// [`u32::saturating_sub`]
@@ -1703,6 +1848,11 @@ extern "rust-intrinsic" {
     /// Returns the value of the discriminant for the variant in 'v';
     /// if `T` has no discriminant, returns `0`.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The stabilized version of this intrinsic is [`core::mem::discriminant`].
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
@@ -1710,6 +1860,11 @@ extern "rust-intrinsic" {
     /// Returns the number of variants of the type `T` cast to a `usize`;
     /// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
     ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
+    ///
     /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
     pub fn variant_count<T>() -> usize;
@@ -1732,10 +1887,20 @@ extern "rust-intrinsic" {
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// See documentation of `<*const T>::guaranteed_eq` for details.
+    ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
 
     /// See documentation of `<*const T>::guaranteed_ne` for details.
+    ///
+    /// Note that, unlike most intrinsics, this is safe to call;
+    /// it does not require an `unsafe` block.
+    /// Therefore, implementations must not require the user to uphold
+    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
 
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index a2953b68564..b968d44fe48 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -55,6 +55,7 @@ macro_rules! with_api {
             FreeFunctions {
                 fn drop($self: $S::FreeFunctions);
                 fn track_env_var(var: &str, value: Option<&str>);
+                fn track_path(path: &str);
             },
             TokenStream {
                 fn drop($self: $S::TokenStream);
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 9b155db6d7b..53fd58a29d8 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -1234,3 +1234,17 @@ pub mod tracked_env {
         value
     }
 }
+
+/// Tracked access to additional files.
+#[unstable(feature = "track_path", issue = "73921")]
+pub mod tracked_path {
+
+    /// Track a file explicitly.
+    ///
+    /// Commonly used for tracking asset preprocessing.
+    #[unstable(feature = "track_path", issue = "73921")]
+    pub fn path<P: AsRef<str>>(path: P) {
+        let path: &str = path.as_ref();
+        crate::bridge::client::FreeFunctions::track_path(path);
+    }
+}
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index e6f8b9cfcc7..b46d3dfc1e7 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -452,7 +452,7 @@ impl fmt::Debug for ChildStderr {
 ///
 /// let output = if cfg!(target_os = "windows") {
 ///     Command::new("cmd")
-///             .args(&["/C", "echo hello"])
+///             .args(["/C", "echo hello"])
 ///             .output()
 ///             .expect("failed to execute process")
 /// } else {
@@ -609,7 +609,7 @@ impl Command {
     /// use std::process::Command;
     ///
     /// Command::new("ls")
-    ///         .args(&["-l", "-a"])
+    ///         .args(["-l", "-a"])
     ///         .spawn()
     ///         .expect("ls command failed to start");
     /// ```
diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs
index 09714835104..a66ab083757 100644
--- a/library/std/src/sys/wasm/atomics/thread.rs
+++ b/library/std/src/sys/wasm/atomics/thread.rs
@@ -1,4 +1,3 @@
-use super::unsupported;
 use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZeroUsize;
diff --git a/library/std/src/sys_common/bytestring.rs b/library/std/src/sys_common/bytestring.rs
deleted file mode 100644
index 97fba60c271..00000000000
--- a/library/std/src/sys_common/bytestring.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#![allow(dead_code)]
-
-#[cfg(test)]
-mod tests;
-
-use crate::fmt::{Formatter, Result, Write};
-use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
-
-pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result {
-    // Writes out a valid unicode string with the correct escape sequences
-    fn write_str_escaped(f: &mut Formatter<'_>, s: &str) -> Result {
-        for c in s.chars().flat_map(|c| c.escape_debug()) {
-            f.write_char(c)?
-        }
-        Ok(())
-    }
-
-    f.write_str("\"")?;
-    for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(slice).chunks() {
-        write_str_escaped(f, valid)?;
-        for b in broken {
-            write!(f, "\\x{:02X}", b)?;
-        }
-    }
-    f.write_str("\"")
-}
diff --git a/library/std/src/sys_common/bytestring/tests.rs b/library/std/src/sys_common/bytestring/tests.rs
deleted file mode 100644
index 1685f087d18..00000000000
--- a/library/std/src/sys_common/bytestring/tests.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use super::*;
-use crate::fmt::{Debug, Formatter, Result};
-
-#[test]
-fn smoke() {
-    struct Helper<'a>(&'a [u8]);
-
-    impl Debug for Helper<'_> {
-        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-            debug_fmt_bytestring(self.0, f)
-        }
-    }
-
-    let input = b"\xF0hello,\tworld";
-    let expected = r#""\xF0hello,\tworld""#;
-    let output = format!("{:?}", Helper(input));
-
-    assert!(output == expected);
-}
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 1a9caa22c92..db83bad60d8 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -21,7 +21,6 @@
 mod tests;
 
 pub mod backtrace;
-pub mod bytestring;
 pub mod condvar;
 pub mod fs;
 pub mod io;
diff --git a/library/std/src/sys_common/os_str_bytes.rs b/library/std/src/sys_common/os_str_bytes.rs
index 470f401a6d2..569600470db 100644
--- a/library/std/src/sys_common/os_str_bytes.rs
+++ b/library/std/src/sys_common/os_str_bytes.rs
@@ -2,16 +2,18 @@
 //! systems: just a `Vec<u8>`/`[u8]`.
 
 use crate::borrow::Cow;
-
 use crate::fmt;
+use crate::fmt::Write;
 use crate::mem;
 use crate::rc::Rc;
 use crate::str;
 use crate::sync::Arc;
-use crate::sys_common::bytestring::debug_fmt_bytestring;
 use crate::sys_common::{AsInner, IntoInner};
 
-use core::str::lossy::Utf8Lossy;
+use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
+
+#[cfg(test)]
+mod tests;
 
 #[derive(Hash)]
 #[repr(transparent)]
@@ -26,7 +28,19 @@ pub struct Slice {
 
 impl fmt::Debug for Slice {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        debug_fmt_bytestring(&self.inner, formatter)
+        // Writes out a valid unicode string with the correct escape sequences
+
+        formatter.write_str("\"")?;
+        for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(&self.inner).chunks() {
+            for c in valid.chars().flat_map(|c| c.escape_debug()) {
+                formatter.write_char(c)?
+            }
+
+            for b in broken {
+                write!(formatter, "\\x{:02X}", b)?;
+            }
+        }
+        formatter.write_str("\"")
     }
 }
 
diff --git a/library/std/src/sys_common/os_str_bytes/tests.rs b/library/std/src/sys_common/os_str_bytes/tests.rs
new file mode 100644
index 00000000000..37967378155
--- /dev/null
+++ b/library/std/src/sys_common/os_str_bytes/tests.rs
@@ -0,0 +1,10 @@
+use super::*;
+
+#[test]
+fn slice_debug_output() {
+    let input = Slice::from_u8_slice(b"\xF0hello,\tworld");
+    let expected = r#""\xF0hello,\tworld""#;
+    let output = format!("{:?}", input);
+
+    assert_eq!(output, expected);
+}
diff --git a/src/test/run-make/track-path-dep-info/Makefile b/src/test/run-make/track-path-dep-info/Makefile
new file mode 100644
index 00000000000..465d3744789
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/Makefile
@@ -0,0 +1,13 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC`
+# instead of hardcoding them everywhere they're needed.
+ifeq ($(IS_MUSL_HOST),1)
+ADDITIONAL_ARGS := $(RUSTFLAGS)
+endif
+
+all:
+	# Proc macro
+	$(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs
+	EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs
+	$(CGREP) "emojis.txt:" < $(TMPDIR)/macro_use.d
diff --git a/src/test/run-make/track-path-dep-info/emojis.txt b/src/test/run-make/track-path-dep-info/emojis.txt
new file mode 100644
index 00000000000..e1a728461f3
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/emojis.txt
@@ -0,0 +1 @@
+👾👾👾👾👾👾
diff --git a/src/test/run-make/track-path-dep-info/macro_def.rs b/src/test/run-make/track-path-dep-info/macro_def.rs
new file mode 100644
index 00000000000..8777ce21f8b
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/macro_def.rs
@@ -0,0 +1,11 @@
+#![feature(track_path)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn access_tracked_paths(_: TokenStream) -> TokenStream {
+    tracked_path::path("emojis.txt");
+    TokenStream::new()
+}
diff --git a/src/test/run-make/track-path-dep-info/macro_use.rs b/src/test/run-make/track-path-dep-info/macro_use.rs
new file mode 100644
index 00000000000..3c49fd05dd9
--- /dev/null
+++ b/src/test/run-make/track-path-dep-info/macro_use.rs
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate macro_def;
+
+access_tracked_paths!();
+
+fn main() {}
diff --git a/src/test/ui/inference/issue-70703.rs b/src/test/ui/inference/issue-70703.rs
new file mode 100644
index 00000000000..d90498e96ea
--- /dev/null
+++ b/src/test/ui/inference/issue-70703.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+trait Factory {
+    type Product;
+}
+
+impl Factory for () {
+    type Product = ();
+}
+
+trait ProductConsumer<P> {
+    fn consume(self, product: P);
+}
+
+impl<P> ProductConsumer<P> for () {
+    fn consume(self, _: P) {}
+}
+
+fn make_product_consumer<F: Factory>(_: F) -> impl ProductConsumer<F::Product> {
+    ()
+}
+
+fn main() {
+    let consumer = make_product_consumer(());
+    consumer.consume(());
+}
diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.rs b/src/test/ui/unused/unused-doc-comments-edge-cases.rs
new file mode 100644
index 00000000000..fd9baf8c6b9
--- /dev/null
+++ b/src/test/ui/unused/unused-doc-comments-edge-cases.rs
@@ -0,0 +1,29 @@
+#![deny(unused_doc_comments)]
+
+fn doc_comment_on_match_arms(num: u8) -> bool {
+    match num {
+        3 => true,
+        /// useless doc comment
+        //~^ ERROR: unused doc comment
+        _ => false,
+    }
+}
+
+fn doc_comment_between_if_else(num: u8) -> bool {
+    if num == 3 {
+        true //~ ERROR: mismatched types
+    }
+    /// useless doc comment
+    else { //~ ERROR: expected expression, found keyword `else`
+        false
+    }
+}
+
+fn doc_comment_on_expr(num: u8) -> bool {
+    /// useless doc comment
+    //~^ ERROR: attributes on expressions are experimental
+    //~| ERROR: unused doc comment
+    num == 3
+}
+
+fn main() {}
diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr
new file mode 100644
index 00000000000..14db5f64b0c
--- /dev/null
+++ b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr
@@ -0,0 +1,61 @@
+error: expected expression, found keyword `else`
+  --> $DIR/unused-doc-comments-edge-cases.rs:17:5
+   |
+LL |     else {
+   |     ^^^^ expected expression
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+   |
+LL |     /// useless doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+   = help: `///` is for documentation comments. For a plain comment, use `//`.
+
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:6:9
+   |
+LL |         /// useless doc comment
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL |         _ => false,
+   |         ---------- rustdoc does not generate documentation for match arms
+   |
+note: the lint level is defined here
+  --> $DIR/unused-doc-comments-edge-cases.rs:1:9
+   |
+LL | #![deny(unused_doc_comments)]
+   |         ^^^^^^^^^^^^^^^^^^^
+   = help: use `//` for a plain comment
+
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+   |
+LL |     /// useless doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     num == 3
+   |     --- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
+
+error[E0308]: mismatched types
+  --> $DIR/unused-doc-comments-edge-cases.rs:14:9
+   |
+LL | /     if num == 3 {
+LL | |         true
+   | |         ^^^^ expected `()`, found `bool`
+LL | |     }
+   | |_____- expected this to be `()`
+   |
+help: you might have meant to return this value
+   |
+LL |         return true;
+   |         ^^^^^^     ^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unused/useless-comment.stderr b/src/test/ui/unused/useless-comment.stderr
index 5a0af8db7c5..0054426fb1e 100644
--- a/src/test/ui/unused/useless-comment.stderr
+++ b/src/test/ui/unused/useless-comment.stderr
@@ -26,6 +26,8 @@ LL |     /// a
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     let x = 12;
    |     ----------- rustdoc does not generate documentation for statements
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:16:5
@@ -40,6 +42,8 @@ LL | |         1 => {},
 LL | |         _ => {}
 LL | |     }
    | |_____- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:20:9
@@ -48,6 +52,8 @@ LL |         /// c
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |         1 => {},
    |         ------- rustdoc does not generate documentation for match arms
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:25:5
@@ -56,6 +62,8 @@ LL |     /// foo
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |     unsafe {}
    |     --------- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:28:5
@@ -65,6 +73,8 @@ LL |     #[doc = "foo"]
 LL |     #[doc = "bar"]
 LL |     3;
    |     - rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:29:5
@@ -73,12 +83,16 @@ LL |     #[doc = "bar"]
    |     ^^^^^^^^^^^^^^
 LL |     3;
    |     - rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:35:13
    |
 LL |     let x = /** comment */ 47;
    |             ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
+   |
+   = help: use `/* */` for a plain comment
 
 error: unused doc comment
   --> $DIR/useless-comment.rs:37:5
@@ -89,6 +103,8 @@ LL | /     {
 LL | |
 LL | |     }
    | |_____- rustdoc does not generate documentation for expressions
+   |
+   = help: use `//` for a plain comment
 
 error: aborting due to 10 previous errors