about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs95
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs32
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs46
-rw-r--r--compiler/rustc_session/src/session.rs7
-rw-r--r--library/alloc/src/vec/mod.rs61
-rw-r--r--library/std/src/sys/unix/ext/process.rs4
-rw-r--r--src/bootstrap/builder/tests.rs3
-rw-r--r--src/librustdoc/formats/renderer.rs7
-rw-r--r--src/librustdoc/html/render/context.rs2
-rw-r--r--src/librustdoc/json/conversions.rs3
-rw-r--r--src/librustdoc/json/mod.rs6
-rw-r--r--src/test/assembly/asm/aarch64-modifiers.rs2
-rw-r--r--src/test/assembly/asm/aarch64-types.rs2
-rw-r--r--src/test/assembly/asm/arm-modifiers.rs2
-rw-r--r--src/test/assembly/asm/arm-types.rs2
-rw-r--r--src/test/assembly/asm/hexagon-types.rs2
-rw-r--r--src/test/assembly/asm/mips-types.rs2
-rw-r--r--src/test/assembly/asm/nvptx-types.rs2
-rw-r--r--src/test/assembly/asm/riscv-types.rs2
-rw-r--r--src/test/assembly/asm/wasm-types.rs2
-rw-r--r--src/test/assembly/asm/x86-modifiers.rs2
-rw-r--r--src/test/assembly/asm/x86-types.rs2
-rw-r--r--src/test/codegen/alloc-optimisation.rs2
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod.rs15
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs20
-rw-r--r--src/test/rustdoc-json/reexport/rename_private.rs14
-rw-r--r--src/test/ui/asm/const.rs2
-rw-r--r--src/test/ui/asm/inline-syntax.arm.stderr74
-rw-r--r--src/test/ui/asm/inline-syntax.rs25
-rw-r--r--src/test/ui/asm/inline-syntax.x86_64.stderr50
-rw-r--r--src/test/ui/asm/srcloc.rs2
-rw-r--r--src/test/ui/asm/sym.rs2
-rw-r--r--src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs10
-rw-r--r--src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr8
-rw-r--r--src/tools/jsondocck/Cargo.toml1
-rw-r--r--src/tools/jsondocck/src/cache.rs10
-rw-r--r--src/tools/jsondocck/src/main.rs20
39 files changed, 393 insertions, 159 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e5a7b7d9b60..9b0f310e3ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1220,6 +1220,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "fs-err"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcd1163ae48bda72a20ae26d66a04d3094135cadab911cff418ae5e33f253431"
+
+[[package]]
 name = "fs_extra"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1748,6 +1754,7 @@ checksum = "92c245af8786f6ac35f95ca14feca9119e71339aaab41e878e7cdd655c97e9e5"
 name = "jsondocck"
 version = "0.1.0"
 dependencies = [
+ "fs-err",
  "getopts",
  "jsonpath_lib",
  "lazy_static",
diff --git a/RELEASES.md b/RELEASES.md
index dfb21ed8380..3cd253afbcd 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -87,7 +87,7 @@ Cargo
 Rustdoc
 -------
 
-- [Rustdoc will now include documentation for methods available from `Deref` traits.][80653]
+- [Rustdoc will now include documentation for methods available from _nested_ `Deref` traits.][80653]
 - [You can now provide a `--default-theme` flag which sets the default theme to use for
   documentation.][79642]
 
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 8d8b3f4f6aa..e6afc81d039 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -7,11 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
 use rustc_parse::parser::Parser;
 use rustc_parse_format as parse;
-use rustc_span::{
-    symbol::{kw, sym, Symbol},
-    BytePos,
-};
+use rustc_session::lint;
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{InnerSpan, Span};
+use rustc_target::asm::InlineAsmArch;
 
 struct AsmArgs {
     templates: Vec<P<ast::Expr>>,
@@ -402,8 +401,6 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
     let mut line_spans = Vec::with_capacity(args.templates.len());
     let mut curarg = 0;
 
-    let default_dialect = ecx.sess.inline_asm_dialect();
-
     for template_expr in args.templates.into_iter() {
         if !template.is_empty() {
             template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
@@ -430,56 +427,36 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         let template_str = &template_str.as_str();
         let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
 
-        if let Some(snippet) = &template_snippet {
-            let snippet = snippet.trim_matches('"');
-            match default_dialect {
-                ast::LlvmAsmDialect::Intel => {
-                    if let Some(span) = check_syntax_directive(snippet, ".intel_syntax") {
-                        let span = template_span.from_inner(span);
-                        let mut err = ecx.struct_span_err(span, "intel syntax is the default syntax on this target, and trying to use this directive may cause issues");
-                        err.span_suggestion(
-                            span,
-                            "remove this assembler directive",
-                            "".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                        err.emit();
-                    }
-
-                    if let Some(span) = check_syntax_directive(snippet, ".att_syntax") {
-                        let span = template_span.from_inner(span);
-                        let mut err = ecx.struct_span_err(span, "using the .att_syntax directive may cause issues, use the att_syntax option instead");
-                        let asm_end = sp.hi() - BytePos(2);
-                        let suggestions = vec![
-                            (span, "".to_string()),
-                            (
-                                Span::new(asm_end, asm_end, sp.ctxt()),
-                                ", options(att_syntax)".to_string(),
-                            ),
-                        ];
-                        err.multipart_suggestion(
-                        "remove the assembler directive and replace it with options(att_syntax)",
-                        suggestions,
-                        Applicability::MachineApplicable,
-                    );
-                        err.emit();
+        if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch {
+            let find_span = |needle: &str| -> Span {
+                if let Some(snippet) = &template_snippet {
+                    if let Some(pos) = snippet.find(needle) {
+                        let end = pos
+                            + &snippet[pos..]
+                                .find(|c| matches!(c, '\n' | ';' | '\\' | '"'))
+                                .unwrap_or(snippet[pos..].len() - 1);
+                        let inner = InnerSpan::new(pos, end);
+                        return template_sp.from_inner(inner);
                     }
                 }
-                ast::LlvmAsmDialect::Att => {
-                    if let Some(span) = check_syntax_directive(snippet, ".att_syntax") {
-                        let span = template_span.from_inner(span);
-                        let mut err = ecx.struct_span_err(span, "att syntax is the default syntax on this target, and trying to use this directive may cause issues");
-                        err.span_suggestion(
-                            span,
-                            "remove this assembler directive",
-                            "".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                        err.emit();
-                    }
+                template_sp
+            };
 
-                    // Use of .intel_syntax is ignored
-                }
+            if template_str.contains(".intel_syntax") {
+                ecx.parse_sess().buffer_lint(
+                    lint::builtin::BAD_ASM_STYLE,
+                    find_span(".intel_syntax"),
+                    ecx.resolver.lint_node_id(ecx.current_expansion.id),
+                    "avoid using `.intel_syntax`, Intel syntax is the default",
+                );
+            }
+            if template_str.contains(".att_syntax") {
+                ecx.parse_sess().buffer_lint(
+                    lint::builtin::BAD_ASM_STYLE,
+                    find_span(".att_syntax"),
+                    ecx.resolver.lint_node_id(ecx.current_expansion.id),
+                    "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead",
+                );
             }
         }
 
@@ -690,15 +667,3 @@ pub fn expand_asm<'cx>(
         }
     }
 }
-
-fn check_syntax_directive<S: AsRef<str>>(piece: S, syntax: &str) -> Option<InnerSpan> {
-    let piece = piece.as_ref();
-    if let Some(idx) = piece.find(syntax) {
-        let end =
-            idx + &piece[idx..].find(|c| matches!(c, '\n' | ';')).unwrap_or(piece[idx..].len());
-        // Offset by one because these represent the span with the " removed
-        Some(InnerSpan::new(idx + 1, end + 1))
-    } else {
-        None
-    }
-}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 9b43c11f0f3..a97cac7e514 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -14,31 +14,31 @@ pub fn expand(
     ecx: &mut ExtCtxt<'_>,
     _span: Span,
     meta_item: &ast::MetaItem,
-    mut item: Annotatable,
+    item: Annotatable,
 ) -> Vec<Annotatable> {
     check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
 
-    let not_static = |item: Annotatable| {
+    let orig_item = item.clone();
+    let not_static = || {
         ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
-        vec![item]
+        vec![orig_item.clone()]
     };
-    let orig_item = item.clone();
-    let mut is_stmt = false;
 
     // Allow using `#[global_allocator]` on an item statement
-    if let Annotatable::Stmt(stmt) = &item {
-        if let StmtKind::Item(item_) = &stmt.kind {
-            item = Annotatable::Item(item_.clone());
-            is_stmt = true;
-        }
-    }
-
-    let item = match item {
+    // FIXME - if we get deref patterns, use them to reduce duplication here
+    let (item, is_stmt) = match &item {
         Annotatable::Item(item) => match item.kind {
-            ItemKind::Static(..) => item,
-            _ => return not_static(Annotatable::Item(item)),
+            ItemKind::Static(..) => (item, false),
+            _ => return not_static(),
+        },
+        Annotatable::Stmt(stmt) => match &stmt.kind {
+            StmtKind::Item(item_) => match item_.kind {
+                ItemKind::Static(..) => (item_, true),
+                _ => return not_static(),
+            },
+            _ => return not_static(),
         },
-        _ => return not_static(item),
+        _ => return not_static(),
     };
 
     // Generate a bunch of new items using the AllocFnFactory
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 005c4f9f6ea..cd4d01ddc05 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2487,6 +2487,52 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `bad_asm_style` lint detects the use of the `.intel_syntax` and
+    /// `.att_syntax` directives.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (fails on system llvm)
+    /// #![feature(asm)]
+    ///
+    /// fn main() {
+    ///     #[cfg(target_arch="x86_64")]
+    ///     unsafe {
+    ///         asm!(
+    ///             ".att_syntax",
+    ///             "movl {0}, {0}", in(reg) 0usize
+    ///         );
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    ///  warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+    ///  --> test.rs:7:14
+    ///   |
+    /// 7 |             ".att_syntax",
+    ///   |              ^^^^^^^^^^^
+    /// 8 |             "movq {0}, {0}", out(reg) _,
+    /// 9 |         );
+    ///   |         - help: add option: `, options(att_syntax)`
+    ///   |
+    ///   = note: `#[warn(bad_asm_style)]` on by default
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// On x86, `asm!` uses the intel assembly syntax by default. While this
+    /// can be switched using assembler directives like `.att_syntax`, using the
+    /// `att_syntax` option is recomended instead because it will also properly
+    /// prefix register placeholders with `%` as required by AT&T syntax.
+    pub BAD_ASM_STYLE,
+    Warn,
+    "incorrect use of inline assembly",
+}
+
+declare_lint! {
     /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe
     /// functions without an explicit unsafe block.
     ///
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a30b4ae9b97..ca9214c03a8 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -793,13 +793,6 @@ impl Session {
         }
     }
 
-    pub fn inline_asm_dialect(&self) -> rustc_ast::LlvmAsmDialect {
-        match self.asm_arch {
-            Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) => rustc_ast::LlvmAsmDialect::Intel,
-            _ => rustc_ast::LlvmAsmDialect::Att,
-        }
-    }
-
     pub fn relocation_model(&self) -> RelocModel {
         self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 135279874bb..ff93c772b5b 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2712,6 +2712,13 @@ impl<T, A: Allocator> AsMut<[T]> for Vec<T, A> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> From<&[T]> for Vec<T> {
+    /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]);
+    /// ```
     #[cfg(not(test))]
     fn from(s: &[T]) -> Vec<T> {
         s.to_vec()
@@ -2724,6 +2731,13 @@ impl<T: Clone> From<&[T]> for Vec<T> {
 
 #[stable(feature = "vec_from_mut", since = "1.19.0")]
 impl<T: Clone> From<&mut [T]> for Vec<T> {
+    /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]);
+    /// ```
     #[cfg(not(test))]
     fn from(s: &mut [T]) -> Vec<T> {
         s.to_vec()
@@ -2740,6 +2754,13 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
     fn from(s: [T; N]) -> Vec<T> {
         <[T]>::into_vec(box s)
     }
+    /// Allocate a `Vec<T>` and move `s`'s items into it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]);
+    /// ```
     #[cfg(test)]
     fn from(s: [T; N]) -> Vec<T> {
         crate::slice::into_vec(box s)
@@ -2751,6 +2772,20 @@ impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
 where
     [T]: ToOwned<Owned = Vec<T>>,
 {
+    /// Convert a clone-on-write slice into a vector.
+    ///
+    /// If `s` already owns a `Vec<T>`, it will be returned directly.
+    /// If `s` is borrowing a slice, a new `Vec<T>` will be allocated and
+    /// filled by cloning `s`'s items into it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use std::borrow::Cow;
+    /// let o: Cow<[i32]> = Cow::Owned(vec![1, 2, 3]);
+    /// let b: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]);
+    /// assert_eq!(Vec::from(o), Vec::from(b));
+    /// ```
     fn from(s: Cow<'a, [T]>) -> Vec<T> {
         s.into_owned()
     }
@@ -2760,6 +2795,15 @@ where
 #[cfg(not(test))]
 #[stable(feature = "vec_from_box", since = "1.18.0")]
 impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
+    /// Convert a boxed slice into a vector by transferring ownership of
+    /// the existing heap allocation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let b: Box<[i32]> = vec![1, 2, 3].into_boxed_slice();
+    /// assert_eq!(Vec::from(b), vec![1, 2, 3]);
+    /// ```
     fn from(s: Box<[T], A>) -> Self {
         let len = s.len();
         Self { buf: RawVec::from_box(s), len }
@@ -2770,6 +2814,16 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
 #[cfg(not(test))]
 #[stable(feature = "box_from_vec", since = "1.20.0")]
 impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
+    /// Convert a vector into a boxed slice.
+    ///
+    /// If `v` has excess capacity, its items will be moved into a
+    /// newly-allocated buffer with exactly the right capacity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Box::from(vec![1, 2, 3]), vec![1, 2, 3].into_boxed_slice());
+    /// ```
     fn from(v: Vec<T, A>) -> Self {
         v.into_boxed_slice()
     }
@@ -2777,6 +2831,13 @@ impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<&str> for Vec<u8> {
+    /// Allocate a `Vec<u8>` and fill it with a UTF-8 string.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Vec::from("123"), vec![b'1', b'2', b'3']);
+    /// ```
     fn from(s: &str) -> Vec<u8> {
         From::from(s.as_bytes())
     }
diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs
index 1276edc6af6..bc3bc0dcb0c 100644
--- a/library/std/src/sys/unix/ext/process.rs
+++ b/library/std/src/sys/unix/ext/process.rs
@@ -227,14 +227,14 @@ pub trait ExitStatusExt: Sealed {
     /// If the process was stopped by a signal, returns that signal.
     ///
     /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`.  This is only possible if the status came from
-    /// a `wait` system call which was passed `WUNTRACED`, was then converted into an `ExitStatus`.
+    /// a `wait` system call which was passed `WUNTRACED`, and was then converted into an `ExitStatus`.
     #[unstable(feature = "unix_process_wait_more", issue = "80695")]
     fn stopped_signal(&self) -> Option<i32>;
 
     /// Whether the process was continued from a stopped status.
     ///
     /// Ie, `WIFCONTINUED`.  This is only possible if the status came from a `wait` system call
-    /// which was passed `WCONTINUED`, was then converted into an `ExitStatus`.
+    /// which was passed `WCONTINUED`, and was then converted into an `ExitStatus`.
     #[unstable(feature = "unix_process_wait_more", issue = "80695")]
     fn continued(&self) -> bool;
 
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 885fcfff030..a881512e988 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -585,8 +585,11 @@ mod dist {
             rustfix_coverage: false,
             pass: None,
         };
+        // Make sure rustfmt binary not being found isn't an error.
+        config.channel = "beta".to_string();
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
+
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
         let a = TargetSelection::from_user("A");
 
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 9dcef3a20d6..4e0f3a4e3c3 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -13,6 +13,11 @@ crate trait FormatRenderer<'tcx>: Sized {
     /// Gives a description of the renderer. Used for performance profiling.
     fn descr() -> &'static str;
 
+    /// Whether to call `item` recursivly for modules
+    ///
+    /// This is true for html, and false for json. See #80664
+    const RUN_ON_MODULE: bool;
+
     /// Sets up any state required for the renderer. When this is called the cache has already been
     /// populated.
     fn init(
@@ -68,7 +73,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
 
     let unknown = Symbol::intern("<unknown item>");
     while let Some((mut cx, item)) = work.pop() {
-        if item.is_mod() {
+        if item.is_mod() && T::RUN_ON_MODULE {
             // modules are special because they add a namespace. We also need to
             // recurse into the items of the module as well.
             let name = item.name.as_ref().unwrap().to_string();
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 64d413a5f31..0ffb4d616da 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -290,6 +290,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         "html"
     }
 
+    const RUN_ON_MODULE: bool = true;
+
     fn init(
         mut krate: clean::Crate,
         options: RenderOptions,
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 7516fc1eaa1..c470dc57005 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -198,7 +198,8 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Sy
             bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(),
             default: t.map(|x| x.into_tcx(tcx)),
         },
-        StrippedItem(inner) => from_clean_item_kind(*inner, tcx, name),
+        // `convert_item` early returns `None` for striped items
+        StrippedItem(_) => unreachable!(),
         PrimitiveItem(_) | KeywordItem(_) => {
             panic!("{:?} is not supported for JSON output", item)
         }
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 6d18dbe67e4..db3a0c5ceb1 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -129,6 +129,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         "json"
     }
 
+    const RUN_ON_MODULE: bool = false;
+
     fn init(
         krate: clean::Crate,
         options: RenderOptions,
@@ -169,8 +171,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 e.impls = self.get_impls(id)
             }
             let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
+
             // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
-            // to make sure the items are unique.
+            // to make sure the items are unique. The main place this happens is when an item, is
+            // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
             if let Some(old_item) = removed {
                 assert_eq!(old_item, new_item);
             }
diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs
index 150997ee807..d4a44b17392 100644
--- a/src/test/assembly/asm/aarch64-modifiers.rs
+++ b/src/test/assembly/asm/aarch64-modifiers.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: -O
 // compile-flags: --target aarch64-unknown-linux-gnu
diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs
index 8dd1f3c873f..aa25562d323 100644
--- a/src/test/assembly/asm/aarch64-types.rs
+++ b/src/test/assembly/asm/aarch64-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target aarch64-unknown-linux-gnu
 // needs-llvm-components: aarch64
diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs
index ad4ab63f265..bb6cc1c9873 100644
--- a/src/test/assembly/asm/arm-modifiers.rs
+++ b/src/test/assembly/asm/arm-modifiers.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: -O
 // compile-flags: --target armv7-unknown-linux-gnueabihf
diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs
index 09901a7a39c..b16fde571af 100644
--- a/src/test/assembly/asm/arm-types.rs
+++ b/src/test/assembly/asm/arm-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target armv7-unknown-linux-gnueabihf
 // compile-flags: -C target-feature=+neon
diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs
index 95135a3e5dd..40352cdb4cd 100644
--- a/src/test/assembly/asm/hexagon-types.rs
+++ b/src/test/assembly/asm/hexagon-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target hexagon-unknown-linux-musl
 // needs-llvm-components: hexagon
diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs
index 04e840dc166..60cfebdd992 100644
--- a/src/test/assembly/asm/mips-types.rs
+++ b/src/test/assembly/asm/mips-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: mips32 mips64
 // assembly-output: emit-asm
 //[mips32] compile-flags: --target mips-unknown-linux-gnu
diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs
index 77fd5141357..75b6371fb70 100644
--- a/src/test/assembly/asm/nvptx-types.rs
+++ b/src/test/assembly/asm/nvptx-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target nvptx64-nvidia-cuda
 // compile-flags: --crate-type cdylib
diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs
index 47518cdcf16..1ba73fcac9d 100644
--- a/src/test/assembly/asm/riscv-types.rs
+++ b/src/test/assembly/asm/riscv-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: riscv64 riscv32
 // assembly-output: emit-asm
 //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
diff --git a/src/test/assembly/asm/wasm-types.rs b/src/test/assembly/asm/wasm-types.rs
index 94ca526222a..a071a850c22 100644
--- a/src/test/assembly/asm/wasm-types.rs
+++ b/src/test/assembly/asm/wasm-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // assembly-output: emit-asm
 // compile-flags: --target wasm32-unknown-unknown
 // compile-flags: --crate-type cdylib
diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs
index e538167cd46..da2dc51d69e 100644
--- a/src/test/assembly/asm/x86-modifiers.rs
+++ b/src/test/assembly/asm/x86-modifiers.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: x86_64 i686
 // assembly-output: emit-asm
 // compile-flags: -O
diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs
index f636f1f5296..e0190d3bdae 100644
--- a/src/test/assembly/asm/x86-types.rs
+++ b/src/test/assembly/asm/x86-types.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // revisions: x86_64 i686
 // assembly-output: emit-asm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs
index c3ffaeb9547..5b27f3f4545 100644
--- a/src/test/codegen/alloc-optimisation.rs
+++ b/src/test/codegen/alloc-optimisation.rs
@@ -1,5 +1,5 @@
 //
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // compile-flags: -O
 #![crate_type="lib"]
 
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
new file mode 100644
index 00000000000..e3cecbdd7ff
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
@@ -0,0 +1,15 @@
+#![feature(no_core)]
+#![no_core]
+
+mod foo {
+    // @set foo_id = in_root_and_mod.json "$.index[*][?(@.name=='Foo')].id"
+    pub struct Foo;
+}
+
+// @has - "$.index[*][?(@.name=='in_root_and_mod')].inner.items[*]" $foo_id
+pub use foo::Foo;
+
+pub mod bar {
+    // @has - "$.index[*][?(@.name=='bar')].inner.items[*]" $foo_id
+    pub use crate::foo::Foo;
+}
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
new file mode 100644
index 00000000000..2daadf7620c
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -0,0 +1,20 @@
+#![feature(no_core)]
+#![no_core]
+
+pub mod foo {
+    // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
+    // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
+    pub struct Bar;
+}
+
+// @set root_import_id = - "$.index[*][?(@.inner.source=='foo::Bar')].id"
+// @is - "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id
+// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
+pub use foo::Bar;
+
+pub mod baz {
+    // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
+    // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
+    // @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
+    pub use crate::foo::Bar;
+}
diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs
new file mode 100644
index 00000000000..fb8296f2337
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/rename_private.rs
@@ -0,0 +1,14 @@
+// edition:2018
+
+#![no_core]
+#![feature(no_core)]
+// @!has rename_private.json "$.index[*][?(@.name=='inner')]"
+mod inner {
+    // @!has - "$.index[*][?(@.name=='Public')]"
+    pub struct Public;
+}
+
+// @set newname_id = - "$.index[*][?(@.name=='NewName')].id"
+// @is - "$.index[*][?(@.name=='NewName')].kind" \"struct\"
+// @has - "$.index[*][?(@.name=='rename_private')].inner.items[*]" $newname_id
+pub use inner::Public as NewName;
diff --git a/src/test/ui/asm/const.rs b/src/test/ui/asm/const.rs
index e08da24f44a..22bc790713d 100644
--- a/src/test/ui/asm/const.rs
+++ b/src/test/ui/asm/const.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // only-x86_64
 // run-pass
 
diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr
index 78b85dfde33..56e6572fc67 100644
--- a/src/test/ui/asm/inline-syntax.arm.stderr
+++ b/src/test/ui/asm/inline-syntax.arm.stderr
@@ -1,14 +1,74 @@
-error: att syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:23:15
+error: unknown directive
+  --> $DIR/inline-syntax.rs:22:15
+   |
+LL |         asm!(".intel_syntax noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:25:15
+   |
+LL |         asm!(".intel_syntax aaa noprefix", "nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax aaa noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:28:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .att_syntax noprefix
+   |     ^
 
-error: att syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:26:15
+error: unknown directive
+  --> $DIR/inline-syntax.rs:31:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .att_syntax bbb noprefix
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:34:15
+   |
+LL |         asm!(".intel_syntax noprefix; nop");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     .intel_syntax noprefix; nop
+   |     ^
+
+error: unknown directive
+  --> $DIR/inline-syntax.rs:40:13
+   |
+LL |             .intel_syntax noprefix
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:13
+   |
+LL |             .intel_syntax noprefix
+   |             ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs
index 9048282456e..78dde5a58e1 100644
--- a/src/test/ui/asm/inline-syntax.rs
+++ b/src/test/ui/asm/inline-syntax.rs
@@ -1,9 +1,12 @@
 // needs-llvm-components: arm
 // revisions: x86_64 arm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] check-pass
 //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
+//[arm] build-fail
 
 #![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
 #![no_core]
 
 #[rustc_builtin_macro]
@@ -14,26 +17,30 @@ macro_rules! asm {
 #[lang = "sized"]
 trait Sized {}
 
-fn main() {
+pub fn main() {
     unsafe {
         asm!(".intel_syntax noprefix", "nop");
-        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.intel_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".intel_syntax aaa noprefix", "nop");
-        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.intel_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".att_syntax noprefix", "nop");
-        //[x86_64]~^ ERROR using the .att_syntax directive may cause issues
-        //[arm]~^^ att syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.att_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".att_syntax bbb noprefix", "nop");
-        //[x86_64]~^ ERROR using the .att_syntax directive may cause issues
-        //[arm]~^^ att syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.att_syntax`
+        //[arm]~^^ ERROR unknown directive
         asm!(".intel_syntax noprefix; nop");
-        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^ WARN avoid using `.intel_syntax`
+        //[arm]~^^ ERROR unknown directive
 
         asm!(
             r"
             .intel_syntax noprefix
             nop"
         );
-        //[x86_64]~^^^ ERROR intel syntax is the default syntax on this target
+        //[x86_64]~^^^ WARN avoid using `.intel_syntax`
+        //[arm]~^^^^ ERROR unknown directive
     }
 }
diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr
index 826657c98e1..5c03d3a002c 100644
--- a/src/test/ui/asm/inline-syntax.x86_64.stderr
+++ b/src/test/ui/asm/inline-syntax.x86_64.stderr
@@ -1,50 +1,40 @@
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:19:15
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:22:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(bad_asm_style)]` on by default
 
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:21:15
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:25:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: using the .att_syntax directive may cause issues, use the att_syntax option instead
-  --> $DIR/inline-syntax.rs:23:15
+warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+  --> $DIR/inline-syntax.rs:28:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the assembler directive and replace it with options(att_syntax)
-   |
-LL |         asm!("", "nop", options(att_syntax));
-   |              --       ^^^^^^^^^^^^^^^^^^^^^
 
-error: using the .att_syntax directive may cause issues, use the att_syntax option instead
-  --> $DIR/inline-syntax.rs:26:15
+warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+  --> $DIR/inline-syntax.rs:31:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the assembler directive and replace it with options(att_syntax)
-   |
-LL |         asm!("", "nop", options(att_syntax));
-   |              --       ^^^^^^^^^^^^^^^^^^^^^
 
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:29:15
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:34:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
-error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
-  --> $DIR/inline-syntax.rs:34:14
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:40:13
    |
-LL |               .intel_syntax noprefix
-   |  ______________^
-LL | |             nop"
-   | |_ help: remove this assembler directive
+LL |             .intel_syntax noprefix
+   |             ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+warning: 6 warnings emitted
 
diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs
index 1477e3dd566..26be3eae459 100644
--- a/src/test/ui/asm/srcloc.rs
+++ b/src/test/ui/asm/srcloc.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // only-x86_64
 // build-fail
 
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
index 9931697e412..58463a90944 100644
--- a/src/test/ui/asm/sym.rs
+++ b/src/test/ui/asm/sym.rs
@@ -1,4 +1,4 @@
-// no-system-llvm
+// min-llvm-version: 10.0.1
 // only-x86_64
 // only-linux
 // run-pass
diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs
new file mode 100644
index 00000000000..25adc5d2578
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #83469
+// Ensures that we recover from `#[global_alloc]` on an invalid
+// stmt without an ICE
+
+fn outer() {
+    #[global_allocator]
+    fn inner() {} //~ ERROR allocators must be statics
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr
new file mode 100644
index 00000000000..ec0e3c4c754
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr
@@ -0,0 +1,8 @@
+error: allocators must be statics
+  --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5
+   |
+LL |     fn inner() {}
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml
index 97052ef58d6..a6efc4c9a6b 100644
--- a/src/tools/jsondocck/Cargo.toml
+++ b/src/tools/jsondocck/Cargo.toml
@@ -12,3 +12,4 @@ lazy_static = "1.4"
 shlex = "0.1"
 serde = "1.0"
 serde_json = "1.0"
+fs-err = "2.5.0"
diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs
index 8a6a911321c..a188750c56a 100644
--- a/src/tools/jsondocck/src/cache.rs
+++ b/src/tools/jsondocck/src/cache.rs
@@ -1,8 +1,10 @@
 use crate::error::CkError;
 use serde_json::Value;
 use std::collections::HashMap;
+use std::io;
 use std::path::{Path, PathBuf};
-use std::{fs, io};
+
+use fs_err as fs;
 
 #[derive(Debug)]
 pub struct Cache {
@@ -31,7 +33,11 @@ impl Cache {
             self.last_path = Some(resolve.clone());
             resolve
         } else {
-            self.last_path.as_ref().unwrap().clone()
+            self.last_path
+                .as_ref()
+                // FIXME: Point to a line number
+                .expect("No last path set. Make sure to specify a full path before using `-`")
+                .clone()
         }
     }
 
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index bcb3f6922ef..216890d59ad 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -239,7 +239,20 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
             let val = cache.get_value(&command.args[0])?;
             let results = select(&val, &command.args[1]).unwrap();
             let pat = string_to_value(&command.args[2], cache);
-            results.len() == 1 && results[0] == pat.as_ref()
+            let is = results.len() == 1 && results[0] == pat.as_ref();
+            if !command.negated && !is {
+                return Err(CkError::FailedCheck(
+                    format!(
+                        "{} matched to {:?}, but expected {:?}",
+                        &command.args[1],
+                        results,
+                        pat.as_ref()
+                    ),
+                    command,
+                ));
+            } else {
+                is
+            }
         }
         CommandKind::Set => {
             // @set <name> = <path> <jsonpath>
@@ -299,7 +312,10 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
 
 fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> {
     if s.starts_with("$") {
-        Cow::Borrowed(&cache.variables[&s[1..]])
+        Cow::Borrowed(&cache.variables.get(&s[1..]).unwrap_or_else(|| {
+            // FIXME(adotinthevoid): Show line number
+            panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.variables)
+        }))
     } else {
         Cow::Owned(serde_json::from_str(s).unwrap())
     }