about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs21
-rw-r--r--src/test/incremental/const-generics/hash-tyvid-regression-1.rs1
-rw-r--r--src/test/rustdoc-json/nested.rs13
-rw-r--r--src/test/rustdoc-json/reexport/glob_extern.rs9
-rw-r--r--src/test/rustdoc-json/reexport/glob_private.rs9
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs4
-rw-r--r--src/test/rustdoc-json/reexport/macro.rs6
-rw-r--r--src/test/rustdoc-json/reexport/private_twice_one_inline.rs18
-rw-r--r--src/test/rustdoc-json/reexport/private_two_names.rs14
-rw-r--r--src/test/rustdoc-json/reexport/rename_public.rs6
-rw-r--r--src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs16
-rw-r--r--src/test/rustdoc-json/reexport/simple_private.rs4
-rw-r--r--src/test/rustdoc-json/reexport/simple_public.rs6
-rw-r--r--src/test/rustdoc-json/type/fn_lifetime.rs3
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr9
-rw-r--r--src/test/ui/iterators/issue-28098.rs2
-rw-r--r--src/test/ui/iterators/issue-28098.stderr28
-rw-r--r--src/test/ui/on-unimplemented/multiple-impls.rs3
-rw-r--r--src/test/ui/on-unimplemented/multiple-impls.stderr39
-rw-r--r--src/test/ui/on-unimplemented/on-impl.rs1
-rw-r--r--src/test/ui/on-unimplemented/on-impl.stderr11
-rw-r--r--src/test/ui/suggestions/return-cycle-2.rs14
-rw-r--r--src/test/ui/suggestions/return-cycle-2.stderr12
-rw-r--r--src/test/ui/suggestions/return-cycle.rs14
-rw-r--r--src/test/ui/suggestions/return-cycle.stderr12
-rw-r--r--src/test/ui/unsized/issue-30355.stderr9
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/octal_escapes.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs10
-rw-r--r--src/tools/jsondocck/src/main.rs42
-rw-r--r--src/tools/rustfmt/src/expr.rs8
-rw-r--r--src/tools/rustfmt/src/parse/session.rs52
39 files changed, 249 insertions, 159 deletions
diff --git a/src/doc/book b/src/doc/book
-Subproject 36383b4da21dbd0a0781473bc8ad7ef0ed1b675
+Subproject 42ca0ef484fcc8437a0682cee23abe4b7c407d5
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject c55611dd6c58bdeb52423b5c52fd0f3c93615ba
+Subproject 6038be9d37d7251c966b486154af621d1794d7a
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 8d1e4dccf71114ff56f328f671f2026d8e6b62a
+Subproject 8e6aa3448515a0654e347b5e2510f1d4bc4d5a6
diff --git a/src/doc/reference b/src/doc/reference
-Subproject f3d3953bf3b158d596c96d55ce5366f9f3f972e
+Subproject e647eb102890e8927f488bea12672b079eff8d9
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject ee342dc91e1ba1bb1e1f1318f84bbe3bfac0479
+Subproject 03301f8ae55fa6f20f7ea152a517598e6db2cdb
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 04f3cf0bb2f5a6ee2bfc4b1a6a6cd8c11d1c553
+Subproject d3daa1f28e169087becbc5e2b49ac91ca0405a4
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 0172ef5700b..381ac7a5dee 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -1,7 +1,8 @@
 //! Validates syntax inside Rust code blocks (\`\`\`rust).
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_errors::{
-    emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle, LintDiagnosticBuilder,
+    emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
+    LazyFallbackBundle, LintDiagnosticBuilder,
 };
 use rustc_parse::parse_stream_from_source_str;
 use rustc_session::parse::ParseSess;
@@ -181,6 +182,16 @@ struct BufferEmitter {
     fallback_bundle: LazyFallbackBundle,
 }
 
+impl Translate for BufferEmitter {
+    fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
+        None
+    }
+
+    fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
+        &**self.fallback_bundle
+    }
+}
+
 impl Emitter for BufferEmitter {
     fn emit_diagnostic(&mut self, diag: &Diagnostic) {
         let mut buffer = self.buffer.borrow_mut();
@@ -194,12 +205,4 @@ impl Emitter for BufferEmitter {
     fn source_map(&self) -> Option<&Lrc<SourceMap>> {
         None
     }
-
-    fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
-        None
-    }
-
-    fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
-        &**self.fallback_bundle
-    }
 }
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs
index 5ff7b19d894..53358b183cb 100644
--- a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs
+++ b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs
@@ -9,7 +9,6 @@ where
     use std::convert::TryFrom;
     <[T; N.get()]>::try_from(())
     //~^ error: the trait bound
-    //~| error: the trait bound
     //~| error: mismatched types
 }
 
diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs
index b0e717d8a86..9ff1f60c0d5 100644
--- a/src/test/rustdoc-json/nested.rs
+++ b/src/test/rustdoc-json/nested.rs
@@ -4,27 +4,28 @@
 // @is nested.json "$.crate_version" \"1.0.0\"
 // @is - "$.index[*][?(@.name=='nested')].kind" \"module\"
 // @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true
-// @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1
+
+// @set l1_id = - "$.index[*][?(@.name=='l1')].id"
+// @ismany - "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id
 
 // @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\"
 // @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false
-// @count - "$.index[*][?(@.name=='l1')].inner.items[*]" 2
 pub mod l1 {
-
     // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\"
     // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false
-    // @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1
     // @set l3_id = - "$.index[*][?(@.name=='l3')].id"
-    // @has - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id
     pub mod l3 {
 
         // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\"
         // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
         // @set l4_id = - "$.index[*][?(@.name=='L4')].id"
-        // @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
+        // @ismany - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
         pub struct L4;
     }
     // @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\"
     // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false
+    // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id
+    // @set l4_use_id = - "$.index[*][?(@.inner.source=='l3::L4')].id"
     pub use l3::L4;
 }
+// @ismany - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id
diff --git a/src/test/rustdoc-json/reexport/glob_extern.rs b/src/test/rustdoc-json/reexport/glob_extern.rs
index ba1cfd8a0b5..4fe25904423 100644
--- a/src/test/rustdoc-json/reexport/glob_extern.rs
+++ b/src/test/rustdoc-json/reexport/glob_extern.rs
@@ -4,15 +4,20 @@
 #![feature(no_core)]
 
 // @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"module\"
-// @is glob_extern.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+// @is - "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
 mod mod1 {
     extern "C" {
-        // @has - "$.index[*][?(@.name=='public_fn')].id"
+        // @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id"
         pub fn public_fn();
         // @!has - "$.index[*][?(@.name=='private_fn')]"
         fn private_fn();
     }
+    // @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id
+    // @set mod1_id = - "$.index[*][?(@.name=='mod1')].id"
 }
 
 // @is - "$.index[*][?(@.kind=='import')].inner.glob" true
+// @is - "$.index[*][?(@.kind=='import')].inner.id" $mod1_id
+// @set use_id = - "$.index[*][?(@.kind=='import')].id"
+// @ismany - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id
 pub use mod1::*;
diff --git a/src/test/rustdoc-json/reexport/glob_private.rs b/src/test/rustdoc-json/reexport/glob_private.rs
index e6a44748c25..04460a817f1 100644
--- a/src/test/rustdoc-json/reexport/glob_private.rs
+++ b/src/test/rustdoc-json/reexport/glob_private.rs
@@ -16,7 +16,7 @@ mod mod1 {
         struct Mod2Private;
     }
 
-    // @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')]"
+    // @set mod2_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id"
     pub use self::mod2::*;
 
     // @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id"
@@ -25,8 +25,9 @@ mod mod1 {
     struct Mod1Private;
 }
 
-// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')]"
+// @set mod1_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id"
 pub use mod1::*;
 
-// @has - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
-// @has - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id
+// @ismany - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
+// @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id
+// @ismany - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id
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
index 2daadf7620c..09302ee3acb 100644
--- a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -3,7 +3,7 @@
 
 pub mod foo {
     // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
-    // @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
+    // @ismany - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
     pub struct Bar;
 }
 
@@ -15,6 +15,6 @@ 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
+    // @ismany - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
     pub use crate::foo::Bar;
 }
diff --git a/src/test/rustdoc-json/reexport/macro.rs b/src/test/rustdoc-json/reexport/macro.rs
index b86614ffbad..0959736f309 100644
--- a/src/test/rustdoc-json/reexport/macro.rs
+++ b/src/test/rustdoc-json/reexport/macro.rs
@@ -3,15 +3,13 @@
 #![no_core]
 #![feature(no_core)]
 
-// @count macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" 2
-
 // @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id"
-// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id
 #[macro_export]
 macro_rules! repro {
     () => {};
 }
 
 // @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id"
-// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro2_id
 pub use crate::repro as repro2;
+
+// @ismany macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id
diff --git a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs
index 327b0f45fdd..a76d352b28b 100644
--- a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -1,18 +1,28 @@
 // aux-build:pub-struct.rs
+// ignore-tidy-linelength
 
-// Test for the ICE in rust/83057
-// Am external type re-exported with different attributes shouldn't cause an error
+// Test for the ICE in https://github.com/rust-lang/rust/issues/83057
+// An external type re-exported with different attributes shouldn't cause an error
 
 #![no_core]
 #![feature(no_core)]
 
 extern crate pub_struct as foo;
-
 #[doc(inline)]
+
+// @set crate_use_id = private_twice_one_inline.json "$.index[*][?(@.docs=='Hack A')].id"
+// @set foo_id = - "$.index[*][?(@.docs=='Hack A')].inner.id"
+/// Hack A
 pub use foo::Foo;
 
+// @set bar_id = - "$.index[*][?(@.name=='bar')].id"
 pub mod bar {
+    // @is - "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id
+    // @set bar_use_id = - "$.index[*][?(@.docs=='Hack B')].id"
+    // @ismany - "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id
+    /// Hack B
     pub use foo::Foo;
 }
 
-// @count private_twice_one_inline.json "$.index[*][?(@.kind=='import')]" 2
+// @ismany - "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id
+// @ismany - "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id
diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs
index 36d6a50d385..cd8212cf344 100644
--- a/src/test/rustdoc-json/reexport/private_two_names.rs
+++ b/src/test/rustdoc-json/reexport/private_two_names.rs
@@ -1,4 +1,6 @@
-// Test for the ICE in rust/83720
+// ignore-tidy-linelength
+
+// Test for the ICE in https://github.com/rust-lang/rust/issues/83720
 // A pub-in-private type re-exported under two different names shouldn't cause an error
 
 #![no_core]
@@ -7,11 +9,15 @@
 // @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"module\"
 // @is private_two_names.json "$.index[*][?(@.name=='style')].inner.is_stripped" "true"
 mod style {
-    // @has - "$.index[*](?(@.name=='Color'))"
+    // @set color_struct_id = - "$.index[*][?(@.kind=='struct' && @.name=='Color')].id"
     pub struct Color;
 }
 
-// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')]"
+// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id
+// @set color_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id"
 pub use style::Color;
-// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')]"
+// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id
+// @set colour_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id"
 pub use style::Color as Colour;
+
+// @ismany - "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id
diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs
index 2dd438d2230..d41556974b4 100644
--- a/src/test/rustdoc-json/reexport/rename_public.rs
+++ b/src/test/rustdoc-json/reexport/rename_public.rs
@@ -4,14 +4,14 @@
 #![feature(no_core)]
 
 // @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id"
-// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id
 pub mod inner {
     // @set public_id = - "$.index[*][?(@.name=='Public')].id"
-    // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
     pub struct Public;
 }
 // @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id"
 // @!has - "$.index[*][?(@.inner.name=='Public')]"
-// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id
 // @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\"
 pub use inner::Public as NewName;
+
+// @ismany - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id
diff --git a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index eedddd6a7bb..1d76c7e139b 100644
--- a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 // Regression test for <https://github.com/rust-lang/rust/issues/97432>.
 
 #![feature(no_core)]
@@ -5,11 +7,17 @@
 #![no_core]
 
 // @has same_type_reexported_more_than_once.json
-// @has - "$.index[*][?(@.name=='Trait')]"
-pub use inner::Trait;
-// @has - "$.index[*].inner[?(@.name=='Reexport')].id"
-pub use inner::Trait as Reexport;
 
 mod inner {
+    // @set trait_id = - "$.index[*][?(@.name=='Trait')].id"
     pub trait Trait {}
 }
+
+// @set export_id = - "$.index[*][?(@.inner.name=='Trait')].id"
+// @is - "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id
+pub use inner::Trait;
+// @set reexport_id = - "$.index[*][?(@.inner.name=='Reexport')].id"
+// @is - "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id
+pub use inner::Trait as Reexport;
+
+// @ismany - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id
diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs
index 5ec13e403ae..55523bcd1de 100644
--- a/src/test/rustdoc-json/reexport/simple_private.rs
+++ b/src/test/rustdoc-json/reexport/simple_private.rs
@@ -10,6 +10,8 @@ mod inner {
 }
 
 // @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
+// @set use_id = - "$.index[*][?(@.kind=='import')].id"
 pub use inner::Public;
 
-// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
+// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
+// @ismany - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id
diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs
index 2e4de301f6f..a3156a2b33a 100644
--- a/src/test/rustdoc-json/reexport/simple_public.rs
+++ b/src/test/rustdoc-json/reexport/simple_public.rs
@@ -4,15 +4,15 @@
 #![feature(no_core)]
 
 // @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id"
-// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $inner_id
 pub mod inner {
 
     // @set public_id = - "$.index[*][?(@.name=='Public')].id"
-    // @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
     pub struct Public;
 }
 
 // @set import_id = - "$.index[*][?(@.inner.name=='Public')].id"
-// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id
 // @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\"
 pub use inner::Public;
+
+// @ismany - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id
diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs
index e0d1e9649a0..fd49a0890c0 100644
--- a/src/test/rustdoc-json/type/fn_lifetime.rs
+++ b/src/test/rustdoc-json/type/fn_lifetime.rs
@@ -2,8 +2,7 @@
 
 // @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"
 
-// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1
-// @is    - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
+// @ismany    - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
 // @has   - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
 // @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
 // @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
index c37d469890c..66f1ab72692 100644
--- a/src/test/ui/associated-types/associated-types-path-2.stderr
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -33,7 +33,9 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:29:14
    |
 LL |     f1(2u32, 4u32);
-   |              ^^^^ the trait `Foo` is not implemented for `u32`
+   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Foo` is implemented for `i32`
 
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
index 0f7520ef7f8..0557340f792 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -15,11 +15,16 @@ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known
   --> $DIR/feature-gate-unsized_fn_params.rs:24:9
    |
 LL |     foo(*x);
-   |         ^^ doesn't have a size known at compile-time
+   |     --- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
-   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     foo(&*x);
+   |         +
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/iterators/issue-28098.rs b/src/test/ui/iterators/issue-28098.rs
index 62a90d90d12..c4addaccefc 100644
--- a/src/test/ui/iterators/issue-28098.rs
+++ b/src/test/ui/iterators/issue-28098.rs
@@ -1,7 +1,6 @@
 fn main() {
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
-    //~| ERROR `()` is not an iterator
 
     for _ in false {}
     //~^ ERROR `bool` is not an iterator
@@ -17,7 +16,6 @@ pub fn other() {
 
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
-    //~| ERROR `()` is not an iterator
 
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
diff --git a/src/test/ui/iterators/issue-28098.stderr b/src/test/ui/iterators/issue-28098.stderr
index 3beb9929244..e7128248f93 100644
--- a/src/test/ui/iterators/issue-28098.stderr
+++ b/src/test/ui/iterators/issue-28098.stderr
@@ -9,7 +9,7 @@ LL |     let _ = Iterator::next(&mut ());
    = help: the trait `Iterator` is not implemented for `()`
 
 error[E0277]: `bool` is not an iterator
-  --> $DIR/issue-28098.rs:6:14
+  --> $DIR/issue-28098.rs:5:14
    |
 LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
@@ -18,7 +18,7 @@ LL |     for _ in false {}
    = note: required because of the requirements on the impl of `IntoIterator` for `bool`
 
 error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:9:28
+  --> $DIR/issue-28098.rs:8:28
    |
 LL |     let _ = Iterator::next(&mut ());
    |             -------------- ^^^^^^^ `()` is not an iterator
@@ -28,15 +28,7 @@ LL |     let _ = Iterator::next(&mut ());
    = help: the trait `Iterator` is not implemented for `()`
 
 error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:2:13
-   |
-LL |     let _ = Iterator::next(&mut ());
-   |             ^^^^^^^^^^^^^^ `()` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `()`
-
-error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:18:28
+  --> $DIR/issue-28098.rs:17:28
    |
 LL |     let _ = Iterator::next(&mut ());
    |             -------------- ^^^^^^^ `()` is not an iterator
@@ -46,7 +38,7 @@ LL |     let _ = Iterator::next(&mut ());
    = help: the trait `Iterator` is not implemented for `()`
 
 error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:22:28
+  --> $DIR/issue-28098.rs:20:28
    |
 LL |     let _ = Iterator::next(&mut ());
    |             -------------- ^^^^^^^ `()` is not an iterator
@@ -56,7 +48,7 @@ LL |     let _ = Iterator::next(&mut ());
    = help: the trait `Iterator` is not implemented for `()`
 
 error[E0277]: `bool` is not an iterator
-  --> $DIR/issue-28098.rs:25:14
+  --> $DIR/issue-28098.rs:23:14
    |
 LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
@@ -64,14 +56,6 @@ LL |     for _ in false {}
    = help: the trait `Iterator` is not implemented for `bool`
    = note: required because of the requirements on the impl of `IntoIterator` for `bool`
 
-error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:18:13
-   |
-LL |     let _ = Iterator::next(&mut ());
-   |             ^^^^^^^^^^^^^^ `()` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `()`
-
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs
index b74957ebcd4..79c40f650db 100644
--- a/src/test/ui/on-unimplemented/multiple-impls.rs
+++ b/src/test/ui/on-unimplemented/multiple-impls.rs
@@ -32,11 +32,8 @@ impl Index<Bar<usize>> for [i32] {
 fn main() {
     Index::index(&[] as &[i32], 2u32);
     //~^ ERROR E0277
-    //~| ERROR E0277
     Index::index(&[] as &[i32], Foo(2u32));
     //~^ ERROR E0277
-    //~| ERROR E0277
     Index::index(&[] as &[i32], Bar(2u32));
     //~^ ERROR E0277
-    //~| ERROR E0277
 }
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr
index 06e1a222af8..6e3601d7bf4 100644
--- a/src/test/ui/on-unimplemented/multiple-impls.stderr
+++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -12,7 +12,7 @@ LL |     Index::index(&[] as &[i32], 2u32);
              <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:36:18
+  --> $DIR/multiple-impls.rs:35:18
    |
 LL |     Index::index(&[] as &[i32], Foo(2u32));
    |     ------------ ^^^^^^^^^^^^^ on impl for Foo
@@ -25,7 +25,7 @@ LL |     Index::index(&[] as &[i32], Foo(2u32));
              <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:39:18
+  --> $DIR/multiple-impls.rs:37:18
    |
 LL |     Index::index(&[] as &[i32], Bar(2u32));
    |     ------------ ^^^^^^^^^^^^^ on impl for Bar
@@ -37,39 +37,6 @@ LL |     Index::index(&[] as &[i32], Bar(2u32));
              <[i32] as Index<Bar<usize>>>
              <[i32] as Index<Foo<usize>>>
 
-error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
-  --> $DIR/multiple-impls.rs:33:5
-   |
-LL |     Index::index(&[] as &[i32], 2u32);
-   |     ^^^^^^^^^^^^ trait message
-   |
-   = help: the trait `Index<u32>` is not implemented for `[i32]`
-   = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Bar<usize>>>
-             <[i32] as Index<Foo<usize>>>
-
-error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:36:5
-   |
-LL |     Index::index(&[] as &[i32], Foo(2u32));
-   |     ^^^^^^^^^^^^ on impl for Foo
-   |
-   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
-   = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Bar<usize>>>
-             <[i32] as Index<Foo<usize>>>
-
-error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:39:5
-   |
-LL |     Index::index(&[] as &[i32], Bar(2u32));
-   |     ^^^^^^^^^^^^ on impl for Bar
-   |
-   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
-   = help: the following other types implement trait `Index<Idx>`:
-             <[i32] as Index<Bar<usize>>>
-             <[i32] as Index<Foo<usize>>>
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs
index ab3e67d01fe..b03e1f7c6a8 100644
--- a/src/test/ui/on-unimplemented/on-impl.rs
+++ b/src/test/ui/on-unimplemented/on-impl.rs
@@ -21,5 +21,4 @@ impl Index<usize> for [i32] {
 fn main() {
     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
     //~^ ERROR E0277
-    //~| ERROR E0277
 }
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr
index 769a3d77a57..396c062cfe2 100644
--- a/src/test/ui/on-unimplemented/on-impl.stderr
+++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -9,15 +9,6 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
 
-error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
-  --> $DIR/on-impl.rs:22:5
-   |
-LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
-   |     ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
-   |
-   = help: the trait `Index<u32>` is not implemented for `[i32]`
-   = help: the trait `Index<usize>` is implemented for `[i32]`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/return-cycle-2.rs b/src/test/ui/suggestions/return-cycle-2.rs
new file mode 100644
index 00000000000..d6d24be1b8d
--- /dev/null
+++ b/src/test/ui/suggestions/return-cycle-2.rs
@@ -0,0 +1,14 @@
+use std::marker::PhantomData;
+
+struct Token<T>(PhantomData<T>);
+
+impl<T> Token<T> {
+    fn as_ref(_: i32, _: i32) -> _ {
+        //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+        //~| NOTE not allowed in type signatures
+        //~| HELP replace with the correct return type
+        Token(PhantomData::<&T>)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-cycle-2.stderr b/src/test/ui/suggestions/return-cycle-2.stderr
new file mode 100644
index 00000000000..3a1a0f7f4f5
--- /dev/null
+++ b/src/test/ui/suggestions/return-cycle-2.stderr
@@ -0,0 +1,12 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/return-cycle-2.rs:6:34
+   |
+LL |     fn as_ref(_: i32, _: i32) -> _ {
+   |                                  ^
+   |                                  |
+   |                                  not allowed in type signatures
+   |                                  help: replace with the correct return type: `Token<&'static T>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/suggestions/return-cycle.rs b/src/test/ui/suggestions/return-cycle.rs
new file mode 100644
index 00000000000..60b80e35a20
--- /dev/null
+++ b/src/test/ui/suggestions/return-cycle.rs
@@ -0,0 +1,14 @@
+use std::marker::PhantomData;
+
+struct Token<T>(PhantomData<T>);
+
+impl<T> Token<T> {
+    fn new() -> _ {
+        //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+        //~| NOTE not allowed in type signatures
+        //~| HELP replace with the correct return type
+        Token(PhantomData::<()>)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/return-cycle.stderr b/src/test/ui/suggestions/return-cycle.stderr
new file mode 100644
index 00000000000..63fa9e04087
--- /dev/null
+++ b/src/test/ui/suggestions/return-cycle.stderr
@@ -0,0 +1,12 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/return-cycle.rs:6:17
+   |
+LL |     fn new() -> _ {
+   |                 ^
+   |                 |
+   |                 not allowed in type signatures
+   |                 help: replace with the correct return type: `Token<()>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr
index 71bbdf5dec7..d7af558eef4 100644
--- a/src/test/ui/unsized/issue-30355.stderr
+++ b/src/test/ui/unsized/issue-30355.stderr
@@ -2,11 +2,16 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/issue-30355.rs:5:8
    |
 LL |     &X(*Y)
-   |        ^^ doesn't have a size known at compile-time
+   |      - ^^ doesn't have a size known at compile-time
+   |      |
+   |      required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[u8]`
-   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     &X(&*Y)
+   |        +
 
 error: aborting due to previous error
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject efd4ca3dc0b89929dc8c5f5c023d25978d76cb6
+Subproject 9809f8ff33c2b998919fd0432c626f0f7323697
diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
index 6ad6837f0e3..bffbf20b4d2 100644
--- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs
+++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
@@ -57,10 +57,10 @@ impl EarlyLintPass for OctalEscapes {
         }
 
         if let ExprKind::Lit(lit) = &expr.kind {
-            if matches!(lit.token.kind, LitKind::Str) {
-                check_lit(cx, &lit.token, lit.span, true);
-            } else if matches!(lit.token.kind, LitKind::ByteStr) {
-                check_lit(cx, &lit.token, lit.span, false);
+            if matches!(lit.token_lit.kind, LitKind::Str) {
+                check_lit(cx, &lit.token_lit, lit.span, true);
+            } else if matches!(lit.token_lit.kind, LitKind::ByteStr) {
+                check_lit(cx, &lit.token_lit, lit.span, false);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 32718200c0b..fa2383066f3 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -589,12 +589,12 @@ impl Write {
                 },
             };
 
-            let replacement: String = match lit.token.kind {
+            let replacement: String = match lit.token_lit.kind {
                 LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => {
-                    lit.token.symbol.as_str().replace('{', "{{").replace('}', "}}")
+                    lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
                 },
                 LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => {
-                    lit.token.symbol.as_str().replace('{', "{{").replace('}', "}}")
+                    lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
                 },
                 LitKind::StrRaw(_)
                 | LitKind::Str
@@ -603,7 +603,7 @@ impl Write {
                 | LitKind::Integer
                 | LitKind::Float
                 | LitKind::Err => continue,
-                LitKind::Byte | LitKind::Char => match lit.token.symbol.as_str() {
+                LitKind::Byte | LitKind::Char => match lit.token_lit.symbol.as_str() {
                     "\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"",
                     "\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue,
                     "\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\",
@@ -614,7 +614,7 @@ impl Write {
                     x => x,
                 }
                 .into(),
-                LitKind::Bool => lit.token.symbol.as_str().deref().into(),
+                LitKind::Bool => lit.token_lit.symbol.as_str().deref().into(),
             };
 
             if !fmt_spans.is_empty() {
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index c4462466646..022f7eb8e02 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -50,6 +50,7 @@ pub enum CommandKind {
     Has,
     Count,
     Is,
+    IsMany,
     Set,
 }
 
@@ -57,6 +58,7 @@ impl CommandKind {
     fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool {
         let count = match self {
             CommandKind::Has => (1..=3).contains(&args.len()),
+            CommandKind::IsMany => args.len() >= 3,
             CommandKind::Count | CommandKind::Is => 3 == args.len(),
             CommandKind::Set => 4 == args.len(),
         };
@@ -89,6 +91,7 @@ impl fmt::Display for CommandKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let text = match self {
             CommandKind::Has => "has",
+            CommandKind::IsMany => "ismany",
             CommandKind::Count => "count",
             CommandKind::Is => "is",
             CommandKind::Set => "set",
@@ -137,6 +140,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
             "has" => CommandKind::Has,
             "count" => CommandKind::Count,
             "is" => CommandKind::Is,
+            "ismany" => CommandKind::IsMany,
             "set" => CommandKind::Set,
             _ => {
                 print_err(&format!("Unrecognized command name `@{}`", cmd), lineno);
@@ -227,6 +231,44 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                 _ => unreachable!(),
             }
         }
+        CommandKind::IsMany => {
+            // @ismany <path> <jsonpath> <value>...
+            let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] {
+                (path, query, values)
+            } else {
+                unreachable!("Checked in CommandKind::validate")
+            };
+            let val = cache.get_value(path)?;
+            let got_values = select(&val, &query).unwrap();
+            assert!(!command.negated, "`@!ismany` is not supported");
+
+            // Serde json doesn't implement Ord or Hash for Value, so we must
+            // use a Vec here. While in theory that makes setwize equality
+            // O(n^2), in practice n will never be large enought to matter.
+            let expected_values =
+                values.iter().map(|v| string_to_value(v, cache)).collect::<Vec<_>>();
+            if expected_values.len() != got_values.len() {
+                return Err(CkError::FailedCheck(
+                    format!(
+                        "Expected {} values, but `{}` matched to {} values ({:?})",
+                        expected_values.len(),
+                        query,
+                        got_values.len(),
+                        got_values
+                    ),
+                    command,
+                ));
+            };
+            for got_value in got_values {
+                if !expected_values.iter().any(|exp| &**exp == got_value) {
+                    return Err(CkError::FailedCheck(
+                        format!("`{}` has match {:?}, which was not expected", query, got_value),
+                        command,
+                    ));
+                }
+            }
+            true
+        }
         CommandKind::Count => {
             // @count <path> <jsonpath> <count> = Check that the jsonpath matches exactly [count] times
             assert_eq!(command.args.len(), 3);
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index a7b73ba78c5..3105882e2d3 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -79,7 +79,7 @@ pub(crate) fn format_expr(
             if let Some(expr_rw) = rewrite_literal(context, l, shape) {
                 Some(expr_rw)
             } else {
-                if let LitKind::StrRaw(_) = l.token.kind {
+                if let LitKind::StrRaw(_) = l.token_lit.kind {
                     Some(context.snippet(l.span).trim().into())
                 } else {
                     None
@@ -1226,7 +1226,7 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) ->
 
 fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option<String> {
     let span = lit.span;
-    let symbol = lit.token.symbol.as_str();
+    let symbol = lit.token_lit.symbol.as_str();
 
     if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
         let hex_lit = match context.config.hex_literal_case() {
@@ -1239,7 +1239,9 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -
                 format!(
                     "0x{}{}",
                     hex_lit,
-                    lit.token.suffix.map_or(String::new(), |s| s.to_string())
+                    lit.token_lit
+                        .suffix
+                        .map_or(String::new(), |s| s.to_string())
                 ),
                 context.config.max_width(),
                 shape,
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 23db5421910..6efeee98fea 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_data_structures::sync::{Lrc, Send};
 use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::translation::Translate;
 use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
 use rustc_session::parse::ParseSess as RawParseSess;
 use rustc_span::{
@@ -28,19 +29,24 @@ pub(crate) struct ParseSess {
 /// Emitter which discards every error.
 struct SilentEmitter;
 
-impl Emitter for SilentEmitter {
-    fn source_map(&self) -> Option<&Lrc<SourceMap>> {
-        None
-    }
-    fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
+impl Translate for SilentEmitter {
     fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
         None
     }
+
     fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
         panic!("silent emitter attempted to translate a diagnostic");
     }
 }
 
+impl Emitter for SilentEmitter {
+    fn source_map(&self) -> Option<&Lrc<SourceMap>> {
+        None
+    }
+
+    fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
+}
+
 fn silent_emitter() -> Box<dyn Emitter + Send> {
     Box::new(SilentEmitter {})
 }
@@ -62,10 +68,21 @@ impl SilentOnIgnoredFilesEmitter {
     }
 }
 
+impl Translate for SilentOnIgnoredFilesEmitter {
+    fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
+        self.emitter.fluent_bundle()
+    }
+
+    fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
+        self.emitter.fallback_fluent_bundle()
+    }
+}
+
 impl Emitter for SilentOnIgnoredFilesEmitter {
     fn source_map(&self) -> Option<&Lrc<SourceMap>> {
         None
     }
+
     fn emit_diagnostic(&mut self, db: &Diagnostic) {
         if db.level() == DiagnosticLevel::Fatal {
             return self.handle_non_ignoreable_error(db);
@@ -88,14 +105,6 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
         }
         self.handle_non_ignoreable_error(db);
     }
-
-    fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
-        self.emitter.fluent_bundle()
-    }
-
-    fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
-        self.emitter.fallback_fluent_bundle()
-    }
 }
 
 fn default_handler(
@@ -340,19 +349,24 @@ mod tests {
             num_emitted_errors: Lrc<AtomicU32>,
         }
 
+        impl Translate for TestEmitter {
+            fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
+                None
+            }
+
+            fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
+                panic!("test emitter attempted to translate a diagnostic");
+            }
+        }
+
         impl Emitter for TestEmitter {
             fn source_map(&self) -> Option<&Lrc<SourceMap>> {
                 None
             }
+
             fn emit_diagnostic(&mut self, _db: &Diagnostic) {
                 self.num_emitted_errors.fetch_add(1, Ordering::Release);
             }
-            fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
-                None
-            }
-            fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
-                panic!("test emitter attempted to translate a diagnostic");
-            }
         }
 
         fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic {