about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-15 15:24:54 +0000
committerbors <bors@rust-lang.org>2021-03-15 15:24:54 +0000
commit2ccf06302c08d7d4911aad40e66a9a3ee731c6f9 (patch)
tree407134d0127b6a7d759851a2a032f5b172ca845a
parent7a7bbdb3abfa72ca717ef54ffc4f307d0d44de67 (diff)
parent2816c110e01846dd737207f19ba3db11a20b887d (diff)
downloadrust-2ccf06302c08d7d4911aad40e66a9a3ee731c6f9.tar.gz
rust-2ccf06302c08d7d4911aad40e66a9a3ee731c6f9.zip
Auto merge of #83149 - Dylan-DPC:rollup-ov70c5v, r=Dylan-DPC
Rollup of 10 pull requests

Successful merges:

 - #82989 (Custom error on literal names from other languages)
 - #83054 (Validate rustc_layout_scalar_valid_range_{start,end} attributes)
 - #83098 (Find more invalid doc attributes)
 - #83108 (Remove unused `opt_local_def_id_to_hir_id` function)
 - #83110 (Fix typos in `library/core/src/ptr/mod.rs` and `library/std/src/sys_common/thread_local_dtor.rs`)
 - #83113 (Minor refactoring in try_index_step)
 - #83127 (Introduce `proc_macro_back_compat` lint, and emit for `time-macros-impl`)
 - #83132 (Don't encode file information for span with a dummy location)
 - #83141 (:arrow_up: rust-analyzer)
 - #83144 (Introduce `rustc_interface::interface::Config::parse_sess_created` callback)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs1
-rw-r--r--compiler/rustc_ast/src/token.rs50
-rw-r--r--compiler/rustc_driver/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs70
-rw-r--r--compiler/rustc_hir/src/definitions.rs5
-rw-r--r--compiler/rustc_interface/src/interface.rs13
-rw-r--r--compiler/rustc_lint/src/context.rs3
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs53
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs4
-rw-r--r--compiler/rustc_passes/Cargo.toml1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs147
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs26
-rw-r--r--compiler/rustc_typeck/src/check/place_op.rs10
-rw-r--r--library/core/src/ptr/mod.rs2
-rw-r--r--library/std/src/sys_common/thread_local_dtor.rs2
-rw-r--r--src/librustdoc/core.rs1
-rw-r--r--src/librustdoc/doctest.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-19371/foo.rs1
-rw-r--r--src/test/run-make/issue-83112-incr-test-moved-file/Makefile25
-rw-r--r--src/test/run-make/issue-83112-incr-test-moved-file/main.rs1
-rw-r--r--src/test/rustdoc-ui/doc-alias-crate-level.stderr2
-rw-r--r--src/test/rustdoc-ui/doc-attr.rs15
-rw-r--r--src/test/rustdoc-ui/doc-attr.stderr47
-rw-r--r--src/test/rustdoc-ui/doc-attr2.stderr4
-rw-r--r--src/test/ui/attributes/doc-attr.rs15
-rw-r--r--src/test/ui/attributes/doc-attr.stderr47
-rw-r--r--src/test/ui/attributes/doc-attr2.stderr4
-rw-r--r--src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs23
-rw-r--r--src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr31
-rw-r--r--src/test/ui/lint/recommend-literal.rs35
-rw-r--r--src/test/ui/lint/recommend-literal.stderr72
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs6
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr70
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout18
-rw-r--r--src/test/ui/rustdoc/doc-alias-crate-level.stderr2
-rw-r--r--src/test/ui/rustdoc/doc_keyword.stderr2
-rw-r--r--src/tools/clippy/src/driver.rs20
m---------src/tools/rust-analyzer32
42 files changed, 702 insertions, 174 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d2d5eae5f93..203d8acb5b4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4247,6 +4247,7 @@ name = "rustc_passes"
 version = "0.0.0"
 dependencies = [
  "rustc_ast",
+ "rustc_ast_pretty",
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 1e224dbf833..40b0cefd83a 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -120,6 +120,7 @@ impl NestedMetaItem {
 }
 
 impl Attribute {
+    #[inline]
     pub fn has_name(&self, name: Symbol) -> bool {
         match self.kind {
             AttrKind::Normal(ref item, _) => item.path == name,
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 71792acb37d..093f7f2668c 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -11,11 +11,9 @@ use crate::tokenstream::TokenTree;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_macros::HashStable_Generic;
-use rustc_span::hygiene::ExpnKind;
-use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, edition::Edition, FileName, RealFileName, Span, DUMMY_SP};
+use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::{fmt, mem};
 
@@ -813,52 +811,6 @@ impl Nonterminal {
         }
         false
     }
-
-    // See issue #74616 for details
-    pub fn ident_name_compatibility_hack(
-        &self,
-        orig_span: Span,
-        source_map: &SourceMap,
-    ) -> Option<(Ident, bool)> {
-        if let NtIdent(ident, is_raw) = self {
-            if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
-                let filename = source_map.span_to_filename(orig_span);
-                if let FileName::Real(RealFileName::Named(path)) = filename {
-                    let matches_prefix = |prefix, filename| {
-                        // Check for a path that ends with 'prefix*/src/<filename>'
-                        let mut iter = path.components().rev();
-                        iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
-                            && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
-                            && iter
-                                .next()
-                                .and_then(|p| p.as_os_str().to_str())
-                                .map_or(false, |p| p.starts_with(prefix))
-                    };
-
-                    if (macro_name == sym::impl_macros
-                        && matches_prefix("time-macros-impl", "lib.rs"))
-                        || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"))
-                    {
-                        let snippet = source_map.span_to_snippet(orig_span);
-                        if snippet.as_deref() == Ok("$name") {
-                            return Some((*ident, *is_raw));
-                        }
-                    }
-
-                    if macro_name == sym::tuple_from_req
-                        && (matches_prefix("actix-web", "extract.rs")
-                            || matches_prefix("actori-web", "extract.rs"))
-                    {
-                        let snippet = source_map.span_to_snippet(orig_span);
-                        if snippet.as_deref() == Ok("$T") {
-                            return Some((*ident, *is_raw));
-                        }
-                    }
-                }
-            }
-        }
-        None
-    }
 }
 
 impl PartialEq for Nonterminal {
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 79bb21b29fc..25a78041c00 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -215,6 +215,7 @@ fn run_compiler(
             diagnostic_output,
             stderr: None,
             lint_caps: Default::default(),
+            parse_sess_created: None,
             register_lints: None,
             override_queries: None,
             make_codegen_backend: make_codegen_backend.take().unwrap(),
@@ -298,6 +299,7 @@ fn run_compiler(
         diagnostic_output,
         stderr: None,
         lint_caps: Default::default(),
+        parse_sess_created: None,
         register_lints: None,
         override_queries: None,
         make_codegen_backend: make_codegen_backend.unwrap(),
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index b6195d3bbc4..837fad90580 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -2,16 +2,21 @@ use crate::base::ExtCtxt;
 
 use rustc_ast as ast;
 use rustc_ast::token;
+use rustc_ast::token::Nonterminal;
+use rustc_ast::token::NtIdent;
 use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens};
 use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::Diagnostic;
+use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
+use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
 use rustc_session::parse::ParseSess;
+use rustc_span::hygiene::ExpnKind;
 use rustc_span::symbol::{self, kw, sym, Symbol};
-use rustc_span::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
+use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span};
 
 use pm::bridge::{server, TokenTree};
 use pm::{Delimiter, Level, LineColumn, Spacing};
@@ -174,9 +179,7 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
             }
 
             Interpolated(nt) => {
-                if let Some((name, is_raw)) =
-                    nt.ident_name_compatibility_hack(span, sess.source_map())
-                {
+                if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, sess) {
                     TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
                 } else {
                     let stream = nt_to_tokenstream(&nt, sess, CanSynthesizeMissingTokens::No);
@@ -711,3 +714,62 @@ impl server::Span for Rustc<'_> {
         self.sess.source_map().span_to_snippet(span).ok()
     }
 }
+
+// See issue #74616 for details
+fn ident_name_compatibility_hack(
+    nt: &Nonterminal,
+    orig_span: Span,
+    sess: &ParseSess,
+) -> Option<(rustc_span::symbol::Ident, bool)> {
+    if let NtIdent(ident, is_raw) = nt {
+        if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
+            let source_map = sess.source_map();
+            let filename = source_map.span_to_filename(orig_span);
+            if let FileName::Real(RealFileName::Named(path)) = filename {
+                let matches_prefix = |prefix, filename| {
+                    // Check for a path that ends with 'prefix*/src/<filename>'
+                    let mut iter = path.components().rev();
+                    iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
+                        && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
+                        && iter
+                            .next()
+                            .and_then(|p| p.as_os_str().to_str())
+                            .map_or(false, |p| p.starts_with(prefix))
+                };
+
+                let time_macros_impl =
+                    macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs");
+                if time_macros_impl
+                    || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"))
+                {
+                    let snippet = source_map.span_to_snippet(orig_span);
+                    if snippet.as_deref() == Ok("$name") {
+                        if time_macros_impl {
+                            sess.buffer_lint_with_diagnostic(
+                                &PROC_MACRO_BACK_COMPAT,
+                                orig_span,
+                                ast::CRATE_NODE_ID,
+                                "using an old version of `time-macros-impl`",
+                                BuiltinLintDiagnostics::ProcMacroBackCompat(
+                                "the `time-macros-impl` crate will stop compiling in futures version of Rust. \
+                                Please update to the latest version of the `time` crate to avoid breakage".to_string())
+                            );
+                        }
+                        return Some((*ident, *is_raw));
+                    }
+                }
+
+                if macro_name == sym::tuple_from_req
+                    && (matches_prefix("actix-web", "extract.rs")
+                        || matches_prefix("actori-web", "extract.rs"))
+                {
+                    let snippet = source_map.span_to_snippet(orig_span);
+                    if snippet.as_deref() == Ok("$T") {
+                        return Some((*ident, *is_raw));
+                    }
+                }
+            }
+        }
+    }
+    None
+}
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index ac6a359ee57..3266dfac702 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -343,11 +343,6 @@ impl Definitions {
     }
 
     #[inline]
-    pub fn opt_local_def_id_to_hir_id(&self, id: LocalDefId) -> Option<hir::HirId> {
-        self.def_id_to_hir_id[id]
-    }
-
-    #[inline]
     pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefId> {
         self.hir_id_to_def_id.get(&hir_id).copied()
     }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 502e7155c2e..a1090ee316d 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -142,6 +142,9 @@ pub struct Config {
 
     pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
+    /// This is a callback from the driver that is called when [`ParseSess`] is created.
+    pub parse_sess_created: Option<Box<dyn FnOnce(&mut ParseSess) + Send>>,
+
     /// This is a callback from the driver that is called when we're registering lints;
     /// it is called during plugin registration when we have the LintStore in a non-shared state.
     ///
@@ -166,7 +169,7 @@ pub struct Config {
 
 pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R) -> R {
     let registry = &config.registry;
-    let (sess, codegen_backend) = util::create_session(
+    let (mut sess, codegen_backend) = util::create_session(
         config.opts,
         config.crate_cfg,
         config.diagnostic_output,
@@ -177,6 +180,14 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
         registry.clone(),
     );
 
+    if let Some(parse_sess_created) = config.parse_sess_created {
+        parse_sess_created(
+            &mut Lrc::get_mut(&mut sess)
+                .expect("create_session() should never share the returned session")
+                .parse_sess,
+        );
+    }
+
     let compiler = Compiler {
         sess,
         codegen_backend,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 7d5577cdca6..42ead89ca4f 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -670,6 +670,9 @@ pub trait LintContext: Sized {
                         json
                     );
                 }
+                BuiltinLintDiagnostics::ProcMacroBackCompat(note) => {
+                    db.note(&note);
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index af48f6c2a5d..005c4f9f6ea 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -6,7 +6,7 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use crate::{declare_lint, declare_lint_pass};
+use crate::{declare_lint, declare_lint_pass, FutureBreakage};
 use rustc_span::edition::Edition;
 
 declare_lint! {
@@ -2955,6 +2955,7 @@ declare_lint_pass! {
         SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
         DISJOINT_CAPTURE_DROP_REORDER,
         LEGACY_DERIVE_HELPERS,
+        PROC_MACRO_BACK_COMPAT,
     ]
 }
 
@@ -3082,3 +3083,53 @@ declare_lint! {
         edition: None,
     };
 }
+
+declare_lint! {
+    /// The `proc_macro_back_compat` lint detects uses of old versions of certain
+    /// proc-macro crates, which have hardcoded workarounds in the compiler.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs-dependency)
+    ///
+    /// use time_macros_impl::impl_macros;
+    /// struct Foo;
+    /// impl_macros!(Foo);
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// warning: using an old version of `time-macros-impl`
+    ///   ::: $DIR/group-compat-hack.rs:27:5
+    ///    |
+    /// LL |     impl_macros!(Foo);
+    ///    |     ------------------ in this macro invocation
+    ///    |
+    ///    = note: `#[warn(proc_macro_back_compat)]` on by default
+    ///    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    ///    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+    ///    = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
+    ///    = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Eventually, the backwards-compatibility hacks present in the compiler will be removed,
+    /// causing older versions of certain crates to stop compiling.
+    /// This is a [future-incompatible] lint to ease the transition to an error.
+    /// See [issue #83125] for more details.
+    ///
+    /// [issue #83125]: https://github.com/rust-lang/rust/issues/83125
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub PROC_MACRO_BACK_COMPAT,
+    Warn,
+    "detects usage of old versions of certain proc-macro crates",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #83125 <https://github.com/rust-lang/rust/issues/83125>",
+        edition: None,
+        future_breakage: Some(FutureBreakage {
+            date: None
+        })
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 4c7d3f6c8c0..400b367095e 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -266,6 +266,7 @@ pub enum BuiltinLintDiagnostics {
     PatternsInFnsWithoutBody(Span, Ident),
     LegacyDeriveHelpers(Span),
     ExternDepSpec(String, ExternDepSpec),
+    ProcMacroBackCompat(String),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 41ecffb9c56..9d00f0715a0 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -180,11 +180,6 @@ impl<'hir> Map<'hir> {
         self.tcx.definitions.local_def_id_to_hir_id(def_id)
     }
 
-    #[inline]
-    pub fn opt_local_def_id_to_hir_id(&self, def_id: LocalDefId) -> Option<HirId> {
-        self.tcx.definitions.opt_local_def_id_to_hir_id(def_id)
-    }
-
     pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
         self.tcx.definitions.iter_local_def_id()
     }
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index d0cd8a48f99..78193acc74a 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -1045,12 +1045,12 @@ where
     E: 'a + OpaqueEncoder,
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        if *self == DUMMY_SP {
+        let span_data = self.data();
+        if self.is_dummy() {
             TAG_PARTIAL_SPAN.encode(s)?;
-            return SyntaxContext::root().encode(s);
+            return span_data.ctxt.encode(s);
         }
 
-        let span_data = self.data();
         let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
         let partial_span = match &pos {
             Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 47f75825fb6..a2adbdddc40 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -427,7 +427,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.unit()
             }
             ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => {
-                debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
+                debug_assert_eq!(Category::of(&expr.kind), Some(Category::Place));
 
                 // Create a "fake" temporary variable so that we check that the
                 // value is Sized. Usually, this is caught in type checking, but
@@ -436,8 +436,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.local_decls.push(LocalDecl::new(expr.ty, expr.span));
                 }
 
-                debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
-
                 let place = unpack!(block = this.as_place(block, expr));
                 let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
                 this.cfg.push_assign(block, source_info, destination, rvalue);
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index c87799f1c2a..4069fb2127e 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -19,3 +19,4 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_lexer = { path = "../rustc_lexer" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c7b266f18bf..9c606f3e4d4 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -8,7 +8,7 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 
-use rustc_ast::{Attribute, LitKind, NestedMetaItem};
+use rustc_ast::{Attribute, Lit, LitKind, NestedMetaItem};
 use rustc_errors::{pluralize, struct_span_err};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -87,6 +87,10 @@ impl CheckAttrVisitor<'tcx> {
                 self.check_export_name(hir_id, &attr, span, target)
             } else if self.tcx.sess.check_name(attr, sym::rustc_args_required_const) {
                 self.check_rustc_args_required_const(&attr, span, target, item)
+            } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_start) {
+                self.check_rustc_layout_scalar_valid_range(&attr, span, target)
+            } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_end) {
+                self.check_rustc_layout_scalar_valid_range(&attr, span, target)
             } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) {
                 self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs)
             } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) {
@@ -520,7 +524,7 @@ impl CheckAttrVisitor<'tcx> {
                 .struct_span_err(
                     meta.span(),
                     &format!(
-                        "`#![doc({} = \"...\")]` isn't allowed as a crate level attribute",
+                        "`#![doc({} = \"...\")]` isn't allowed as a crate-level attribute",
                         attr_name,
                     ),
                 )
@@ -531,79 +535,97 @@ impl CheckAttrVisitor<'tcx> {
     }
 
     fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
-        if let Some(mi) = attr.meta() {
-            if let Some(list) = mi.meta_item_list() {
-                for meta in list {
-                    if meta.has_name(sym::alias) {
-                        if !self.check_attr_crate_level(meta, hir_id, "alias")
-                            || !self.check_doc_alias(meta, hir_id, target)
+        let mut is_valid = true;
+
+        if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) {
+            for meta in list {
+                if let Some(i_meta) = meta.meta_item() {
+                    match i_meta.name_or_empty() {
+                        sym::alias
+                            if !self.check_attr_crate_level(&meta, hir_id, "alias")
+                                || !self.check_doc_alias(&meta, hir_id, target) =>
                         {
-                            return false;
+                            is_valid = false
                         }
-                    } else if meta.has_name(sym::keyword) {
-                        if !self.check_attr_crate_level(meta, hir_id, "keyword")
-                            || !self.check_doc_keyword(meta, hir_id)
+
+                        sym::keyword
+                            if !self.check_attr_crate_level(&meta, hir_id, "keyword")
+                                || !self.check_doc_keyword(&meta, hir_id) =>
                         {
-                            return false;
+                            is_valid = false
                         }
-                    } else if meta.has_name(sym::test) {
-                        if CRATE_HIR_ID != hir_id {
+
+                        sym::test if CRATE_HIR_ID != hir_id => {
                             self.tcx.struct_span_lint_hir(
                                 INVALID_DOC_ATTRIBUTES,
                                 hir_id,
                                 meta.span(),
                                 |lint| {
                                     lint.build(
-                                        "`#![doc(test(...)]` is only allowed as a crate level attribute"
+                                        "`#![doc(test(...)]` is only allowed \
+                                         as a crate-level attribute",
                                     )
                                     .emit();
                                 },
                             );
-                            return false;
+                            is_valid = false;
                         }
-                    } else if let Some(i_meta) = meta.meta_item() {
-                        if ![
-                            sym::cfg,
-                            sym::hidden,
-                            sym::html_favicon_url,
-                            sym::html_logo_url,
-                            sym::html_no_source,
-                            sym::html_playground_url,
-                            sym::html_root_url,
-                            sym::include,
-                            sym::inline,
-                            sym::issue_tracker_base_url,
-                            sym::masked,
-                            sym::no_default_passes, // deprecated
-                            sym::no_inline,
-                            sym::passes,  // deprecated
-                            sym::plugins, // removed, but rustdoc warns about it itself
-                            sym::primitive,
-                            sym::spotlight,
-                            sym::test,
-                        ]
-                        .iter()
-                        .any(|m| i_meta.has_name(*m))
-                        {
+
+                        // no_default_passes: deprecated
+                        // passes: deprecated
+                        // plugins: removed, but rustdoc warns about it itself
+                        sym::alias
+                        | sym::cfg
+                        | sym::hidden
+                        | sym::html_favicon_url
+                        | sym::html_logo_url
+                        | sym::html_no_source
+                        | sym::html_playground_url
+                        | sym::html_root_url
+                        | sym::include
+                        | sym::inline
+                        | sym::issue_tracker_base_url
+                        | sym::keyword
+                        | sym::masked
+                        | sym::no_default_passes
+                        | sym::no_inline
+                        | sym::passes
+                        | sym::plugins
+                        | sym::primitive
+                        | sym::spotlight
+                        | sym::test => {}
+
+                        _ => {
                             self.tcx.struct_span_lint_hir(
                                 INVALID_DOC_ATTRIBUTES,
                                 hir_id,
                                 i_meta.span,
                                 |lint| {
-                                    lint.build(&format!(
+                                    let msg = format!(
                                         "unknown `doc` attribute `{}`",
-                                        i_meta.name_or_empty()
-                                    ))
-                                    .emit();
+                                        rustc_ast_pretty::pprust::path_to_string(&i_meta.path),
+                                    );
+                                    lint.build(&msg).emit();
                                 },
                             );
-                            return false;
+                            is_valid = false;
                         }
                     }
+                } else {
+                    self.tcx.struct_span_lint_hir(
+                        INVALID_DOC_ATTRIBUTES,
+                        hir_id,
+                        meta.span(),
+                        |lint| {
+                            lint.build(&format!("invalid `doc` attribute")).emit();
+                        },
+                    );
+                    is_valid = false;
                 }
             }
         }
-        true
+
+        is_valid
     }
 
     /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid.
@@ -807,6 +829,37 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
+    fn check_rustc_layout_scalar_valid_range(
+        &self,
+        attr: &Attribute,
+        span: &Span,
+        target: Target,
+    ) -> bool {
+        if target != Target::Struct {
+            self.tcx
+                .sess
+                .struct_span_err(attr.span, "attribute should be applied to a struct")
+                .span_label(*span, "not a struct")
+                .emit();
+            return false;
+        }
+
+        let list = match attr.meta_item_list() {
+            None => return false,
+            Some(it) => it,
+        };
+
+        if matches!(&list[..], &[NestedMetaItem::Literal(Lit { kind: LitKind::Int(..), .. })]) {
+            true
+        } else {
+            self.tcx
+                .sess
+                .struct_span_err(attr.span, "expected exactly one integer literal argument")
+                .emit();
+            false
+        }
+    }
+
     /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
     fn check_rustc_legacy_const_generics(
         &self,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e7b3d459766..e85d78db22c 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -563,6 +563,15 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         }
                     }
                 }
+            } else if err_code == &rustc_errors::error_code!(E0412) {
+                if let Some(correct) = Self::likely_rust_type(path) {
+                    err.span_suggestion(
+                        span,
+                        "perhaps you intended to use this type",
+                        correct.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
             }
         }
 
@@ -1243,6 +1252,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         }
     }
 
+    // Returns the name of the Rust type approximately corresponding to
+    // a type name in another programming language.
+    fn likely_rust_type(path: &[Segment]) -> Option<Symbol> {
+        let name = path[path.len() - 1].ident.as_str();
+        // Common Java types
+        Some(match &*name {
+            "byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes.
+            "short" => sym::i16,
+            "boolean" => sym::bool,
+            "int" => sym::i32,
+            "long" => sym::i64,
+            "float" => sym::f32,
+            "double" => sym::f64,
+            _ => return None,
+        })
+    }
+
     /// Only used in a specific case of type ascription suggestions
     fn get_colon_suggestion_span(&self, start: Span) -> Span {
         let sm = self.r.session.source_map();
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs
index 254e41706f9..5bd385107ca 100644
--- a/compiler/rustc_typeck/src/check/place_op.rs
+++ b/compiler/rustc_typeck/src/check/place_op.rs
@@ -103,9 +103,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let method =
                 self.try_overloaded_place_op(expr.span, self_ty, &[input_ty], PlaceOp::Index);
 
-            let result = method.map(|ok| {
+            if let Some(result) = method {
                 debug!("try_index_step: success, using overloaded indexing");
-                let method = self.register_infer_ok_obligations(ok);
+                let method = self.register_infer_ok_obligations(result);
 
                 let mut adjustments = self.adjust_steps(autoderef);
                 if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() {
@@ -128,10 +128,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.apply_adjustments(base_expr, adjustments);
 
                 self.write_method_call(expr.hir_id, method);
-                (input_ty, self.make_overloaded_place_return_type(method).ty)
-            });
-            if result.is_some() {
-                return result;
+
+                return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
             }
         }
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5026c48bdf4..5ac260fc883 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -512,7 +512,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
         let t = t.as_mut_ptr() as *mut u8;
 
         // SAFETY: As `i < len`, and as the caller must guarantee that `x` and `y` are valid
-        // for `len` bytes, `x + i` and `y + i` must be valid adresses, which fulfills the
+        // for `len` bytes, `x + i` and `y + i` must be valid addresses, which fulfills the
         // safety contract for `add`.
         //
         // Also, the caller must guarantee that `x` and `y` are valid for writes, properly aligned,
diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs
index 6f5ebf4a271..f9971fb6f21 100644
--- a/library/std/src/sys_common/thread_local_dtor.rs
+++ b/library/std/src/sys_common/thread_local_dtor.rs
@@ -1,6 +1,6 @@
 //! Thread-local destructor
 //!
-//! Besides thread-local "keys" (pointer-sized non-adressable thread-local store
+//! Besides thread-local "keys" (pointer-sized non-addressable thread-local store
 //! with an associated destructor), many platforms also provide thread-local
 //! destructors that are not associated with any particular data. These are
 //! often more efficient.
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index e9c32396e84..c5b5ab0f3d0 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -311,6 +311,7 @@ crate fn create_config(
         diagnostic_output: DiagnosticOutput::Default,
         stderr: None,
         lint_caps,
+        parse_sess_created: None,
         register_lints: Some(box crate::lint::register_lints),
         override_queries: Some(|_sess, providers, _external_providers| {
             // Most lints will require typechecking, so just don't run them.
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 64375964e70..80e2e23eadd 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -95,6 +95,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
         diagnostic_output: DiagnosticOutput::Default,
         stderr: None,
         lint_caps,
+        parse_sess_created: None,
         register_lints: Some(box crate::lint::register_lints),
         override_queries: None,
         make_codegen_backend: None,
diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs
index fdd7e8b24c5..4acabbb70ed 100644
--- a/src/test/run-make-fulldeps/issue-19371/foo.rs
+++ b/src/test/run-make-fulldeps/issue-19371/foo.rs
@@ -57,6 +57,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
         diagnostic_output: DiagnosticOutput::Default,
         stderr: None,
         lint_caps: Default::default(),
+        parse_sess_created: None,
         register_lints: None,
         override_queries: None,
         make_codegen_backend: None,
diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/Makefile b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
new file mode 100644
index 00000000000..76ecaba0f6a
--- /dev/null
+++ b/src/test/run-make/issue-83112-incr-test-moved-file/Makefile
@@ -0,0 +1,25 @@
+include ../../run-make-fulldeps/tools.mk
+
+# FIXME https://github.com/rust-lang/rust/issues/78911
+# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64)
+
+# Regression test for issue #83112
+# The generated test harness code contains spans with a dummy location,
+# but a non-dummy SyntaxContext. Previously, the incremental cache was encoding
+# these spans as a full span (with a source file index), instead of skipping
+# the encoding of the location information. If the file gest moved, the hash
+# of the span will be unchanged (since it has a dummy location), so the incr
+# cache would end up try to load a non-existent file using the previously
+# enccoded source file id.
+
+SRC=$(TMPDIR)/src
+INCR=$(TMPDIR)/incr
+
+all:
+	mkdir $(SRC)
+	mkdir $(SRC)/mydir
+	mkdir $(INCR)
+	cp main.rs $(SRC)/main.rs
+	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/main.rs
+	mv $(SRC)/main.rs $(SRC)/mydir/main.rs
+	$(RUSTC) --test -C incremental=$(INCR) $(SRC)/mydir/main.rs
diff --git a/src/test/run-make/issue-83112-incr-test-moved-file/main.rs b/src/test/run-make/issue-83112-incr-test-moved-file/main.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/src/test/run-make/issue-83112-incr-test-moved-file/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.stderr b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
index 9e746cba05f..fc8095e03ca 100644
--- a/src/test/rustdoc-ui/doc-alias-crate-level.stderr
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
@@ -4,7 +4,7 @@ error: '\'' character isn't allowed in `#[doc(alias = "...")]`
 LL | #[doc(alias = "shouldn't work!")]
    |               ^^^^^^^^^^^^^^^^^
 
-error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
+error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute
   --> $DIR/doc-alias-crate-level.rs:1:8
    |
 LL | #![doc(alias = "crate-level-not-working")]
diff --git a/src/test/rustdoc-ui/doc-attr.rs b/src/test/rustdoc-ui/doc-attr.rs
index 3a584112973..980d1c0e207 100644
--- a/src/test/rustdoc-ui/doc-attr.rs
+++ b/src/test/rustdoc-ui/doc-attr.rs
@@ -8,3 +8,18 @@
 //~^ ERROR unknown `doc` attribute
 //~^^ WARN
 pub fn foo() {}
+
+#[doc(123)]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+#[doc("hello", "bar")]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+//~| ERROR invalid `doc` attribute
+//~| WARN
+#[doc(foo::bar, crate::bar::baz = "bye")]
+//~^ ERROR unknown `doc` attribute
+//~| WARN
+//~| ERROR unknown `doc` attribute
+//~| WARN
+fn bar() {}
diff --git a/src/test/rustdoc-ui/doc-attr.stderr b/src/test/rustdoc-ui/doc-attr.stderr
index 21479d25fc2..cc2494c92e6 100644
--- a/src/test/rustdoc-ui/doc-attr.stderr
+++ b/src/test/rustdoc-ui/doc-attr.stderr
@@ -13,6 +13,51 @@ LL | #![deny(warnings)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:12:7
+   |
+LL | #[doc(123)]
+   |       ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:15:7
+   |
+LL | #[doc("hello", "bar")]
+   |       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:15:16
+   |
+LL | #[doc("hello", "bar")]
+   |                ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `foo::bar`
+  --> $DIR/doc-attr.rs:20:7
+   |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+   |       ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `crate::bar::baz`
+  --> $DIR/doc-attr.rs:20:17
+   |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
 error: unknown `doc` attribute `as_ptr`
   --> $DIR/doc-attr.rs:3:8
    |
@@ -22,5 +67,5 @@ LL | #![doc(as_ptr)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
-error: aborting due to 2 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/rustdoc-ui/doc-attr2.stderr b/src/test/rustdoc-ui/doc-attr2.stderr
index eeb2c2be085..643107318b9 100644
--- a/src/test/rustdoc-ui/doc-attr2.stderr
+++ b/src/test/rustdoc-ui/doc-attr2.stderr
@@ -1,4 +1,4 @@
-error: `#![doc(test(...)]` is only allowed as a crate level attribute
+error: `#![doc(test(...)]` is only allowed as a crate-level attribute
   --> $DIR/doc-attr2.rs:4:7
    |
 LL | #[doc(test(no_crate_inject))]
@@ -13,7 +13,7 @@ LL | #![deny(warnings)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
-error: `#![doc(test(...)]` is only allowed as a crate level attribute
+error: `#![doc(test(...)]` is only allowed as a crate-level attribute
   --> $DIR/doc-attr2.rs:9:12
    |
 LL |     #![doc(test(no_crate_inject))]
diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs
index 3a584112973..980d1c0e207 100644
--- a/src/test/ui/attributes/doc-attr.rs
+++ b/src/test/ui/attributes/doc-attr.rs
@@ -8,3 +8,18 @@
 //~^ ERROR unknown `doc` attribute
 //~^^ WARN
 pub fn foo() {}
+
+#[doc(123)]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+#[doc("hello", "bar")]
+//~^ ERROR invalid `doc` attribute
+//~| WARN
+//~| ERROR invalid `doc` attribute
+//~| WARN
+#[doc(foo::bar, crate::bar::baz = "bye")]
+//~^ ERROR unknown `doc` attribute
+//~| WARN
+//~| ERROR unknown `doc` attribute
+//~| WARN
+fn bar() {}
diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr
index 21479d25fc2..cc2494c92e6 100644
--- a/src/test/ui/attributes/doc-attr.stderr
+++ b/src/test/ui/attributes/doc-attr.stderr
@@ -13,6 +13,51 @@ LL | #![deny(warnings)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:12:7
+   |
+LL | #[doc(123)]
+   |       ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:15:7
+   |
+LL | #[doc("hello", "bar")]
+   |       ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: invalid `doc` attribute
+  --> $DIR/doc-attr.rs:15:16
+   |
+LL | #[doc("hello", "bar")]
+   |                ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `foo::bar`
+  --> $DIR/doc-attr.rs:20:7
+   |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+   |       ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc` attribute `crate::bar::baz`
+  --> $DIR/doc-attr.rs:20:17
+   |
+LL | #[doc(foo::bar, crate::bar::baz = "bye")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
 error: unknown `doc` attribute `as_ptr`
   --> $DIR/doc-attr.rs:3:8
    |
@@ -22,5 +67,5 @@ LL | #![doc(as_ptr)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
-error: aborting due to 2 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/attributes/doc-attr2.stderr b/src/test/ui/attributes/doc-attr2.stderr
index eeb2c2be085..643107318b9 100644
--- a/src/test/ui/attributes/doc-attr2.stderr
+++ b/src/test/ui/attributes/doc-attr2.stderr
@@ -1,4 +1,4 @@
-error: `#![doc(test(...)]` is only allowed as a crate level attribute
+error: `#![doc(test(...)]` is only allowed as a crate-level attribute
   --> $DIR/doc-attr2.rs:4:7
    |
 LL | #[doc(test(no_crate_inject))]
@@ -13,7 +13,7 @@ LL | #![deny(warnings)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
-error: `#![doc(test(...)]` is only allowed as a crate level attribute
+error: `#![doc(test(...)]` is only allowed as a crate-level attribute
   --> $DIR/doc-attr2.rs:9:12
    |
 LL |     #![doc(test(no_crate_inject))]
diff --git a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs
new file mode 100644
index 00000000000..25fe4be660b
--- /dev/null
+++ b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs
@@ -0,0 +1,23 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(u32::MAX)] //~ ERROR
+pub struct A(u32);
+
+#[rustc_layout_scalar_valid_range_end(1, 2)] //~ ERROR
+pub struct B(u8);
+
+#[rustc_layout_scalar_valid_range_end(a = "a")] //~ ERROR
+pub struct C(i32);
+
+#[rustc_layout_scalar_valid_range_end(1)] //~ ERROR
+enum E {
+    X = 1,
+    Y = 14,
+}
+
+fn main() {
+    let _ = A(0);
+    let _ = B(0);
+    let _ = C(0);
+    let _ = E::X;
+}
diff --git a/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
new file mode 100644
index 00000000000..7e95fedebdf
--- /dev/null
+++ b/src/test/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
@@ -0,0 +1,31 @@
+error: expected exactly one integer literal argument
+  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:3:1
+   |
+LL | #[rustc_layout_scalar_valid_range_start(u32::MAX)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected exactly one integer literal argument
+  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:6:1
+   |
+LL | #[rustc_layout_scalar_valid_range_end(1, 2)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected exactly one integer literal argument
+  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:9:1
+   |
+LL | #[rustc_layout_scalar_valid_range_end(a = "a")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute should be applied to a struct
+  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1
+   |
+LL |   #[rustc_layout_scalar_valid_range_end(1)]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / enum E {
+LL | |     X = 1,
+LL | |     Y = 14,
+LL | | }
+   | |_- not a struct
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/lint/recommend-literal.rs b/src/test/ui/lint/recommend-literal.rs
new file mode 100644
index 00000000000..f60d3d10dce
--- /dev/null
+++ b/src/test/ui/lint/recommend-literal.rs
@@ -0,0 +1,35 @@
+type Real = double;
+//~^ ERROR cannot find type `double` in this scope
+//~| HELP perhaps you intended to use this type
+
+fn main() {
+    let x: Real = 3.5;
+    let y: long = 74802374902374923;
+    //~^ ERROR cannot find type `long` in this scope
+    //~| HELP perhaps you intended to use this type
+}
+
+fn z(a: boolean) {
+    //~^ ERROR cannot find type `boolean` in this scope
+    //~| HELP perhaps you intended to use this type
+}
+
+fn a() -> byte {
+//~^ ERROR cannot find type `byte` in this scope
+//~| HELP perhaps you intended to use this type
+    3
+}
+
+struct Data { //~ HELP you might be missing a type parameter
+    width: float,
+    //~^ ERROR cannot find type `float` in this scope
+    //~| HELP perhaps you intended to use this type
+    depth: Option<int>,
+    //~^ ERROR cannot find type `int` in this scope
+    //~| HELP perhaps you intended to use this type
+}
+
+trait Stuff {}
+impl Stuff for short {}
+//~^ ERROR cannot find type `short` in this scope
+//~| HELP perhaps you intended to use this type
diff --git a/src/test/ui/lint/recommend-literal.stderr b/src/test/ui/lint/recommend-literal.stderr
new file mode 100644
index 00000000000..b01073b42b8
--- /dev/null
+++ b/src/test/ui/lint/recommend-literal.stderr
@@ -0,0 +1,72 @@
+error[E0412]: cannot find type `double` in this scope
+  --> $DIR/recommend-literal.rs:1:13
+   |
+LL | type Real = double;
+   |             ^^^^^^
+   |             |
+   |             not found in this scope
+   |             help: perhaps you intended to use this type: `f64`
+
+error[E0412]: cannot find type `long` in this scope
+  --> $DIR/recommend-literal.rs:7:12
+   |
+LL |     let y: long = 74802374902374923;
+   |            ^^^^
+   |            |
+   |            not found in this scope
+   |            help: perhaps you intended to use this type: `i64`
+
+error[E0412]: cannot find type `boolean` in this scope
+  --> $DIR/recommend-literal.rs:12:9
+   |
+LL | fn z(a: boolean) {
+   |         ^^^^^^^
+   |         |
+   |         not found in this scope
+   |         help: perhaps you intended to use this type: `bool`
+
+error[E0412]: cannot find type `byte` in this scope
+  --> $DIR/recommend-literal.rs:17:11
+   |
+LL | fn a() -> byte {
+   |           ^^^^
+   |           |
+   |           not found in this scope
+   |           help: perhaps you intended to use this type: `u8`
+
+error[E0412]: cannot find type `float` in this scope
+  --> $DIR/recommend-literal.rs:24:12
+   |
+LL |     width: float,
+   |            ^^^^^
+   |            |
+   |            not found in this scope
+   |            help: perhaps you intended to use this type: `f32`
+
+error[E0412]: cannot find type `int` in this scope
+  --> $DIR/recommend-literal.rs:27:19
+   |
+LL |     depth: Option<int>,
+   |                   ^^^ not found in this scope
+   |
+help: perhaps you intended to use this type
+   |
+LL |     depth: Option<i32>,
+   |                   ^^^
+help: you might be missing a type parameter
+   |
+LL | struct Data<int> {
+   |            ^^^^^
+
+error[E0412]: cannot find type `short` in this scope
+  --> $DIR/recommend-literal.rs:33:16
+   |
+LL | impl Stuff for short {}
+   |                ^^^^^
+   |                |
+   |                not found in this scope
+   |                help: perhaps you intended to use this type: `i16`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs
index 652fabf34ac..7f3f5e36f50 100644
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs
+++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs
@@ -24,7 +24,8 @@ mod no_version {
     }
 
     struct Foo;
-    impl_macros!(Foo);
+    impl_macros!(Foo); //~ WARN  using an old version
+                       //~| WARN this was previously
     arrays!(Foo);
     other!(Foo);
 }
@@ -40,7 +41,8 @@ mod with_version {
     }
 
     struct Foo;
-    impl_macros!(Foo);
+    impl_macros!(Foo); //~  WARN using an old version
+                       //~| WARN this was previously
     arrays!(Foo);
     other!(Foo);
 }
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
new file mode 100644
index 00000000000..9370440a635
--- /dev/null
+++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
@@ -0,0 +1,70 @@
+warning: using an old version of `time-macros-impl`
+  --> $DIR/time-macros-impl/src/lib.rs:5:32
+   |
+LL |         #[my_macro] struct One($name);
+   |                                ^^^^^
+   | 
+  ::: $DIR/group-compat-hack.rs:27:5
+   |
+LL |     impl_macros!(Foo);
+   |     ------------------ in this macro invocation
+   |
+   = note: `#[warn(proc_macro_back_compat)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: using an old version of `time-macros-impl`
+  --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
+   |
+LL |         #[my_macro] struct One($name);
+   |                                ^^^^^
+   | 
+  ::: $DIR/group-compat-hack.rs:44:5
+   |
+LL |     impl_macros!(Foo);
+   |     ------------------ in this macro invocation
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 2 warnings emitted
+
+Future incompatibility report: Future breakage date: None, diagnostic:
+warning: using an old version of `time-macros-impl`
+  --> $DIR/time-macros-impl/src/lib.rs:5:32
+   |
+LL |         #[my_macro] struct One($name);
+   |                                ^^^^^
+   | 
+  ::: $DIR/group-compat-hack.rs:27:5
+   |
+LL |     impl_macros!(Foo);
+   |     ------------------ in this macro invocation
+   |
+   = note: `#[warn(proc_macro_back_compat)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage date: None, diagnostic:
+warning: using an old version of `time-macros-impl`
+  --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
+   |
+LL |         #[my_macro] struct One($name);
+   |                                ^^^^^
+   | 
+  ::: $DIR/group-compat-hack.rs:44:5
+   |
+LL |     impl_macros!(Foo);
+   |     ------------------ in this macro invocation
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout
index c6b18ab674b..468cb511915 100644
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout
+++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout
@@ -1,10 +1,10 @@
 Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:43:18: 43:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:13: 44:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:38:25: 38:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:45:12: 45:15 (#0) }], span: $DIR/group-compat-hack.rs:38:38: 38:43 (#28) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38:45 (#28) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:52:21: 52:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:59:21: 59:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:66:21: 66:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:73:21: 73:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:30:12: 30:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:18: 44:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:46:13: 46:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:61:21: 61:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:68:21: 68:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
+Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:75:21: 75:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]
diff --git a/src/test/ui/rustdoc/doc-alias-crate-level.stderr b/src/test/ui/rustdoc/doc-alias-crate-level.stderr
index c0467514ae1..bd32609ade2 100644
--- a/src/test/ui/rustdoc/doc-alias-crate-level.stderr
+++ b/src/test/ui/rustdoc/doc-alias-crate-level.stderr
@@ -4,7 +4,7 @@ error: '\'' character isn't allowed in `#[doc(alias = "...")]`
 LL | #[doc(alias = "shouldn't work!")]
    |               ^^^^^^^^^^^^^^^^^
 
-error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
+error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute
   --> $DIR/doc-alias-crate-level.rs:5:8
    |
 LL | #![doc(alias = "not working!")]
diff --git a/src/test/ui/rustdoc/doc_keyword.stderr b/src/test/ui/rustdoc/doc_keyword.stderr
index d72a876163e..0679bb8c5a7 100644
--- a/src/test/ui/rustdoc/doc_keyword.stderr
+++ b/src/test/ui/rustdoc/doc_keyword.stderr
@@ -10,7 +10,7 @@ error: `#[doc(keyword = "...")]` can only be used on modules
 LL | #[doc(keyword = "hall")]
    |       ^^^^^^^^^^^^^^^^
 
-error: `#![doc(keyword = "...")]` isn't allowed as a crate level attribute
+error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute
   --> $DIR/doc_keyword.rs:4:8
    |
 LL | #![doc(keyword = "hello")]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 30272c9b800..b6aed862e89 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -15,7 +15,7 @@ extern crate rustc_session;
 extern crate rustc_span;
 
 use rustc_interface::interface;
-use rustc_session::Session;
+use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Symbol;
 use rustc_tools_util::VersionInfo;
 
@@ -63,8 +63,8 @@ fn test_arg_value() {
     assert_eq!(arg_value(args, "--foo", |_| true), None);
 }
 
-fn track_clippy_args(sess: &Session, args_env_var: &Option<String>) {
-    sess.parse_sess.env_depinfo.borrow_mut().insert((
+fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>) {
+    parse_sess.env_depinfo.get_mut().insert((
         Symbol::intern("CLIPPY_ARGS"),
         args_env_var.as_deref().map(Symbol::intern),
     ));
@@ -81,14 +81,9 @@ struct RustcCallbacks {
 
 impl rustc_driver::Callbacks for RustcCallbacks {
     fn config(&mut self, config: &mut interface::Config) {
-        let previous = config.register_lints.take();
         let clippy_args_var = self.clippy_args_var.take();
-        config.register_lints = Some(Box::new(move |sess, lint_store| {
-            if let Some(ref previous) = previous {
-                (previous)(sess, lint_store);
-            }
-
-            track_clippy_args(sess, &clippy_args_var);
+        config.parse_sess_created = Some(Box::new(move |parse_sess| {
+            track_clippy_args(parse_sess, &clippy_args_var);
         }));
     }
 }
@@ -101,6 +96,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
     fn config(&mut self, config: &mut interface::Config) {
         let previous = config.register_lints.take();
         let clippy_args_var = self.clippy_args_var.take();
+        config.parse_sess_created = Some(Box::new(move |parse_sess| {
+            track_clippy_args(parse_sess, &clippy_args_var);
+        }));
         config.register_lints = Some(Box::new(move |sess, mut lint_store| {
             // technically we're ~guaranteed that this is none but might as well call anything that
             // is there already. Certainly it can't hurt.
@@ -108,8 +106,6 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
                 (previous)(sess, lint_store);
             }
 
-            track_clippy_args(sess, &clippy_args_var);
-
             let conf = clippy_lints::read_conf(&[], &sess);
             clippy_lints::register_plugins(&mut lint_store, &sess, &conf);
             clippy_lints::register_pre_expansion_lints(&mut lint_store);
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject d54e1157b66017e4aae38328cd213286e39ca13
+Subproject 5ba7852cf153688d5b5035a9a2a2145aa7334d7