about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast_like.rs4
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs1
-rw-r--r--compiler/rustc_ast/src/token.rs5
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs5
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs1
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs52
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs15
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs8
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs29
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs21
-rw-r--r--src/bootstrap/builder.rs4
-rw-r--r--src/test/ui/auxiliary/empty-struct.rs9
-rw-r--r--src/test/ui/auxiliary/stability-cfg2.rs5
-rw-r--r--src/test/ui/auxiliary/weak-lang-items.rs22
-rw-r--r--src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs9
-rw-r--r--src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs3
-rw-r--r--src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs28
-rw-r--r--src/test/ui/empty/issue-37026.rs (renamed from src/test/ui/issues/issue-37026.rs)0
-rw-r--r--src/test/ui/empty/issue-37026.stderr (renamed from src/test/ui/issues/issue-37026.stderr)0
-rw-r--r--src/test/ui/empty/no-link.rs (renamed from src/test/ui/no-link.rs)0
-rw-r--r--src/test/ui/issues/auxiliary/empty-struct.rs9
-rw-r--r--src/test/ui/issues/issue-51244.rs4
-rw-r--r--src/test/ui/issues/issue-51244.stderr11
-rw-r--r--src/test/ui/macros/issue-95267.rs13
-rw-r--r--src/test/ui/panic-handler/weak-lang-item-2.rs (renamed from src/test/ui/weak-lang-item.rs)0
-rw-r--r--src/test/ui/regions/regions-enum-not-wf.rs39
-rw-r--r--src/test/ui/regions/regions-enum-not-wf.stderr28
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr22
-rw-r--r--src/test/ui/span/E0057.rs6
-rw-r--r--src/test/ui/span/E0057.stderr19
-rw-r--r--src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs (renamed from src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs)0
-rw-r--r--src/test/ui/structs/suggest-private-fields.rs (renamed from src/test/ui/suggestions/suggest-private-fields.rs)0
-rw-r--r--src/test/ui/structs/suggest-private-fields.stderr (renamed from src/test/ui/suggestions/suggest-private-fields.stderr)0
-rw-r--r--src/test/ui/suggestions/auxiliary/struct_field_privacy.rs9
-rw-r--r--src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs4
-rw-r--r--src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr22
-rw-r--r--src/test/ui/xcrate/xcrate-unit-struct-2.rs (renamed from src/test/ui/cross-crate/xcrate-unit-struct.rs)0
39 files changed, 118 insertions, 296 deletions
diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs
index 9a24158ba35..1a271b0adef 100644
--- a/compiler/rustc_ast/src/ast_like.rs
+++ b/compiler/rustc_ast/src/ast_like.rs
@@ -51,7 +51,6 @@ impl AstLike for crate::token::Nonterminal {
             | Nonterminal::NtMeta(_)
             | Nonterminal::NtPath(_)
             | Nonterminal::NtVis(_)
-            | Nonterminal::NtTT(_)
             | Nonterminal::NtBlock(_)
             | Nonterminal::NtIdent(..)
             | Nonterminal::NtLifetime(_) => &[],
@@ -67,7 +66,6 @@ impl AstLike for crate::token::Nonterminal {
             | Nonterminal::NtMeta(_)
             | Nonterminal::NtPath(_)
             | Nonterminal::NtVis(_)
-            | Nonterminal::NtTT(_)
             | Nonterminal::NtBlock(_)
             | Nonterminal::NtIdent(..)
             | Nonterminal::NtLifetime(_) => {}
@@ -84,7 +82,7 @@ impl AstLike for crate::token::Nonterminal {
             Nonterminal::NtPath(path) => path.tokens_mut(),
             Nonterminal::NtVis(vis) => vis.tokens_mut(),
             Nonterminal::NtBlock(block) => block.tokens_mut(),
-            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) | Nonterminal::NtTT(..) => None,
+            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
         }
     }
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 9d79fe53d5c..32621eb5f2f 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -787,7 +787,6 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
             visit_lazy_tts(tokens, vis);
         }
         token::NtPath(path) => vis.visit_path(path),
-        token::NtTT(tt) => visit_tt(tt, vis),
         token::NtVis(visib) => vis.visit_vis(visib),
     }
 }
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index c367573de8a..7df385873c1 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -6,7 +6,6 @@ pub use TokenKind::*;
 
 use crate::ast;
 use crate::ptr::P;
-use crate::tokenstream::TokenTree;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
@@ -680,7 +679,6 @@ pub enum Nonterminal {
     NtMeta(P<ast::AttrItem>),
     NtPath(ast::Path),
     NtVis(ast::Visibility),
-    NtTT(TokenTree),
 }
 
 // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -778,7 +776,6 @@ impl Nonterminal {
             NtMeta(attr_item) => attr_item.span(),
             NtPath(path) => path.span,
             NtVis(vis) => vis.span,
-            NtTT(tt) => tt.span(),
         }
     }
 }
@@ -790,7 +787,6 @@ impl PartialEq for Nonterminal {
                 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
             }
             (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
-            (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
             // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
             // correctly based on data from AST. This will prevent them from matching each other
             // in macros. The comparison will become possible only when each nonterminal has an
@@ -813,7 +809,6 @@ impl fmt::Debug for Nonterminal {
             NtLiteral(..) => f.pad("NtLiteral(..)"),
             NtMeta(..) => f.pad("NtMeta(..)"),
             NtPath(..) => f.pad("NtPath(..)"),
-            NtTT(..) => f.pad("NtTT(..)"),
             NtVis(..) => f.pad("NtVis(..)"),
             NtLifetime(..) => f.pad("NtLifetime(..)"),
         }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 8ba6a914c4a..aba0b6a7463 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -122,7 +122,10 @@ impl<'a> AstValidator<'a> {
             diag.note("only supported directly in conditions of `if` and `while` expressions");
             diag.note("as well as when nested within `&&` and parentheses in those conditions");
             if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
-                diag.span_note(span, "`||` operators are not allowed in let chain expressions");
+                diag.span_note(
+                    span,
+                    "`||` operators are not currently supported in let chain expressions",
+                );
             }
             diag.emit();
         } else {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index b2c62383fb6..719fd271093 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -714,7 +714,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
             token::NtLifetime(e) => e.to_string(),
             token::NtLiteral(ref e) => self.expr_to_string(e),
-            token::NtTT(ref tree) => self.tt_to_string(tree),
             token::NtVis(ref e) => self.vis_to_string(e),
         }
     }
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 5e97fc90320..5a6a2b2c57b 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -76,7 +76,7 @@ crate use ParseResult::*;
 use crate::mbe::{self, SequenceRepetition, TokenTree};
 
 use rustc_ast::token::{self, DocComment, Nonterminal, Token};
-use rustc_parse::parser::Parser;
+use rustc_parse::parser::{NtOrTt, Parser};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::MacroRulesNormalizedIdent;
 
@@ -275,7 +275,7 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
 }
 
 /// `NamedMatch` is a pattern-match result for a single metavar. All
-/// `MatchedNtNonTt`s in the `NamedMatch` have the same non-terminal type
+/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
 /// (expr, item, etc).
 ///
 /// The in-memory structure of a particular `NamedMatch` represents the match
@@ -306,17 +306,17 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
 /// ```rust
 /// MatchedSeq([
 ///   MatchedSeq([
-///     MatchedNtNonTt(a),
-///     MatchedNtNonTt(b),
-///     MatchedNtNonTt(c),
-///     MatchedNtNonTt(d),
+///     MatchedNonterminal(a),
+///     MatchedNonterminal(b),
+///     MatchedNonterminal(c),
+///     MatchedNonterminal(d),
 ///   ]),
 ///   MatchedSeq([
-///     MatchedNtNonTt(a),
-///     MatchedNtNonTt(b),
-///     MatchedNtNonTt(c),
-///     MatchedNtNonTt(d),
-///     MatchedNtNonTt(e),
+///     MatchedNonterminal(a),
+///     MatchedNonterminal(b),
+///     MatchedNonterminal(c),
+///     MatchedNonterminal(d),
+///     MatchedNonterminal(e),
 ///   ])
 /// ])
 /// ```
@@ -324,14 +324,11 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
 crate enum NamedMatch {
     MatchedSeq(Lrc<NamedMatchVec>),
 
-    // This variant should never hold an `NtTT`. `MatchedNtTt` should be used
-    // for that case.
-    MatchedNtNonTt(Lrc<Nonterminal>),
+    // A metavar match of type `tt`.
+    MatchedTokenTree(rustc_ast::tokenstream::TokenTree),
 
-    // `NtTT` is handled without any cloning when transcribing, unlike other
-    // nonterminals. Therefore, an `Lrc` isn't helpful and causes unnecessary
-    // allocations. Hence this separate variant.
-    MatchedNtTt(rustc_ast::tokenstream::TokenTree),
+    // A metavar match of any type other than `tt`.
+    MatchedNonterminal(Lrc<Nonterminal>),
 }
 
 /// Takes a slice of token trees `ms` representing a matcher which successfully matched input
@@ -519,13 +516,14 @@ impl<'tt> TtParser<'tt> {
                     }
 
                     TokenTree::Token(t) => {
-                        // Doc comments cannot appear in a matcher.
-                        debug_assert!(!matches!(t, Token { kind: DocComment(..), .. }));
-
-                        // If the token matches, we can just advance the parser. Otherwise, this
-                        // match hash failed, there is nothing to do, and hopefully another item in
-                        // `cur_items` will match.
-                        if token_name_eq(&t, token) {
+                        // If it's a doc comment, we just ignore it and move on to the next tt in
+                        // the matcher. If the token matches, we can just advance the parser.
+                        // Otherwise, this match has failed, there is nothing to do, and hopefully
+                        // another item in `cur_items` will match.
+                        if matches!(t, Token { kind: DocComment(..), .. }) {
+                            item.idx += 1;
+                            self.cur_items.push(item);
+                        } else if token_name_eq(&t, token) {
                             item.idx += 1;
                             self.next_items.push(item);
                         }
@@ -677,8 +675,8 @@ impl<'tt> TtParser<'tt> {
                             Ok(nt) => nt,
                         };
                         let m = match nt {
-                            Nonterminal::NtTT(tt) => MatchedNtTt(tt),
-                            _ => MatchedNtNonTt(Lrc::new(nt)),
+                            NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
+                            NtOrTt::Tt(tt) => MatchedTokenTree(tt),
                         };
                         item.push_match(match_cur, m);
                         item.idx += 1;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 7837de5c18d..10b2b9f07e2 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF
 use crate::mbe;
 use crate::mbe::macro_check;
 use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
-use crate::mbe::macro_parser::{MatchedNtTt, MatchedSeq};
+use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree};
 use crate::mbe::transcribe::transcribe;
 
 use rustc_ast as ast;
@@ -470,7 +470,7 @@ pub fn compile_declarative_macro(
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
-                if let MatchedNtTt(ref tt) = *m {
+                if let MatchedTokenTree(ref tt) = *m {
                     let mut tts = vec![];
                     mbe::quoted::parse(
                         tt.clone().into(),
@@ -495,7 +495,7 @@ pub fn compile_declarative_macro(
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
-                if let MatchedNtTt(ref tt) = *m {
+                if let MatchedTokenTree(ref tt) = *m {
                     let mut tts = vec![];
                     mbe::quoted::parse(
                         tt.clone().into(),
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 228ed04548d..cd016bfd8f4 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,8 +1,8 @@
 use crate::base::ExtCtxt;
-use crate::mbe::macro_parser::{MatchedNtNonTt, MatchedNtTt, MatchedSeq, NamedMatch};
+use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch};
 use crate::mbe::{self, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -234,17 +234,16 @@ pub(super) fn transcribe<'a>(
                 let ident = MacroRulesNormalizedIdent::new(orignal_ident);
                 if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
                     match cur_matched {
-                        MatchedNtTt(ref tt) => {
+                        MatchedTokenTree(ref tt) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
                             // without wrapping them into groups.
                             let token = tt.clone();
                             result.push(token.into());
                         }
-                        MatchedNtNonTt(ref nt) => {
+                        MatchedNonterminal(ref nt) => {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::None` to maintain parsing priorities.
                             // `Interpolated` is currently used for such groups in rustc parser.
-                            debug_assert!(!matches!(**nt, Nonterminal::NtTT(_)));
                             marker.visit_span(&mut sp);
                             let token = TokenTree::token(token::Interpolated(nt.clone()), sp);
                             result.push(token.into());
@@ -312,7 +311,7 @@ fn lookup_cur_matched<'a>(
         let mut matched = matched;
         for &(idx, _) in repeats {
             match matched {
-                MatchedNtTt(_) | MatchedNtNonTt(_) => break,
+                MatchedTokenTree(_) | MatchedNonterminal(_) => break,
                 MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(),
             }
         }
@@ -402,7 +401,7 @@ fn lockstep_iter_size(
             let name = MacroRulesNormalizedIdent::new(name);
             match lookup_cur_matched(name, interpolations, repeats) {
                 Some(matched) => match matched {
-                    MatchedNtTt(_) | MatchedNtNonTt(_) => LockstepIterSize::Unconstrained,
+                    MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
                     MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name),
                 },
                 _ => LockstepIterSize::Unconstrained,
@@ -449,7 +448,7 @@ fn count_repetitions<'a>(
         sp: &DelimSpan,
     ) -> PResult<'a, usize> {
         match matched {
-            MatchedNtTt(_) | MatchedNtNonTt(_) => {
+            MatchedTokenTree(_) | MatchedNonterminal(_) => {
                 if declared_lhs_depth == 0 {
                     return Err(cx.struct_span_err(
                         sp.entire(),
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 1118caf5075..28c2a63db27 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -290,7 +290,6 @@ pub fn nt_to_tokenstream(
         Nonterminal::NtMeta(ref attr) => convert_tokens(attr.tokens.as_ref()),
         Nonterminal::NtPath(ref path) => convert_tokens(path.tokens.as_ref()),
         Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()),
-        Nonterminal::NtTT(ref tt) => Some(tt.clone().into()),
         Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => {
             prepend_attrs(&expr.attrs, expr.tokens.as_ref())
         }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3a2f193d319..5d244ef9118 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -19,7 +19,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, DelimToken, Token, TokenKind};
+use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::AttributesData;
 use rustc_ast::tokenstream::{self, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
@@ -1507,3 +1507,9 @@ pub enum FlatToken {
     /// handling of replace ranges.
     Empty,
 }
+
+#[derive(Debug)]
+pub enum NtOrTt {
+    Nt(Nonterminal),
+    Tt(TokenTree),
+}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 40902fa1833..c105fbfaee0 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,12 +1,12 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token};
+use rustc_ast::token::{self, NonterminalKind, Token};
 use rustc_ast::AstLike;
 use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
 use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
+use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
     /// Checks whether a non-terminal may begin with a particular token.
@@ -85,7 +85,7 @@ impl<'a> Parser<'a> {
             NonterminalKind::Lifetime => match token.kind {
                 token::Lifetime(_) => true,
                 token::Interpolated(ref nt) => {
-                    matches!(**nt, token::NtLifetime(_) | token::NtTT(_))
+                    matches!(**nt, token::NtLifetime(_))
                 }
                 _ => false,
             },
@@ -96,7 +96,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
-    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
         // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
         // needs to have them force-captured here.
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
@@ -104,6 +104,8 @@ impl<'a> Parser<'a> {
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
         let mut nt = match kind {
+            // Note that TT is treated differently to all the others.
+            NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())),
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
                 Some(item) => token::NtItem(item),
                 None => {
@@ -124,9 +126,12 @@ impl<'a> Parser<'a> {
             NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
                 token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
-                    NonterminalKind::PatWithOr { .. } => {
-                        this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe)
-                    }
+                    NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
+                        None,
+                        RecoverComma::No,
+                        RecoverColon::No,
+                        CommaRecoveryMode::EitherTupleOrPipe,
+                    ),
                     _ => unreachable!(),
                 })?)
             }
@@ -139,9 +144,10 @@ impl<'a> Parser<'a> {
                 )
             }
 
-            NonterminalKind::Ty => {
-                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?)
-            }
+            NonterminalKind::Ty => token::NtTy(
+                self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?,
+            ),
+
             // this could be handled like a token, since it is one
             NonterminalKind::Ident
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
@@ -158,7 +164,6 @@ impl<'a> Parser<'a> {
                 self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?,
             ),
             NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
-            NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
             NonterminalKind::Vis => token::NtVis(
                 self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?,
             ),
@@ -183,7 +188,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        Ok(nt)
+        Ok(NtOrTt::Nt(nt))
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 038ba220608..c8ca51348cc 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -696,14 +696,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         ) = &bounded_ty.kind
         {
             // use this to verify that ident is a type param.
-            let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
-                None,
-                &Segment::from_path(path),
-                Namespace::TypeNS,
-                span,
-                true,
-                Finalize::No,
-            ) else {
+            let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
                 return false;
             };
             if !(matches!(
@@ -718,16 +711,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             return false;
         };
 
-        if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind {
+        let peeled_ty = ty.peel_refs();
+        if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind {
             // Confirm that the `SelfTy` is a type parameter.
-            let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
-                None,
-                &Segment::from_path(type_param_path),
-                Namespace::TypeNS,
-                span,
-                true,
-                Finalize::No,
-            ) else {
+            let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
                 return false;
             };
             if !(matches!(
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 32ccca8bcdd..e7511888114 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -231,10 +231,10 @@ impl StepDescription {
         }
 
         if !builder.config.exclude.is_empty() {
-            eprintln!(
+            builder.verbose(&format!(
                 "{:?} not skipped for {:?} -- not in {:?}",
                 pathset, self.name, builder.config.exclude
-            );
+            ));
         }
         false
     }
diff --git a/src/test/ui/auxiliary/empty-struct.rs b/src/test/ui/auxiliary/empty-struct.rs
deleted file mode 100644
index 3fb40f6bfa9..00000000000
--- a/src/test/ui/auxiliary/empty-struct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct XEmpty1 {}
-pub struct XEmpty2;
-pub struct XEmpty6();
-
-pub enum XE {
-    XEmpty3 {},
-    XEmpty4,
-    XEmpty5(),
-}
diff --git a/src/test/ui/auxiliary/stability-cfg2.rs b/src/test/ui/auxiliary/stability-cfg2.rs
deleted file mode 100644
index c995038e5a8..00000000000
--- a/src/test/ui/auxiliary/stability-cfg2.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags:--cfg foo
-
-#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))]
-#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
-#![feature(staged_api)]
diff --git a/src/test/ui/auxiliary/weak-lang-items.rs b/src/test/ui/auxiliary/weak-lang-items.rs
deleted file mode 100644
index 7a698cf76ae..00000000000
--- a/src/test/ui/auxiliary/weak-lang-items.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// no-prefer-dynamic
-
-// This aux-file will require the eh_personality function to be codegen'd, but
-// it hasn't been defined just yet. Make sure we don't explode.
-
-#![no_std]
-#![crate_type = "rlib"]
-
-struct A;
-
-impl core::ops::Drop for A {
-    fn drop(&mut self) {}
-}
-
-pub fn foo() {
-    let _a = A;
-    panic!("wut");
-}
-
-mod std {
-    pub use core::{option, fmt};
-}
diff --git a/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs b/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs
deleted file mode 100644
index dceec7e3ec1..00000000000
--- a/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct Foo {
-    pub x: isize
-}
-
-impl Foo {
-    pub fn new() -> Foo {
-        Foo { x: 3 }
-    }
-}
diff --git a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs b/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs
deleted file mode 100644
index 9d1e0742e3c..00000000000
--- a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub struct Au(pub isize);
diff --git a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs b/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
deleted file mode 100644
index 69ed498e7e1..00000000000
--- a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![crate_type = "lib"]
-
-// used by the rpass test
-
-#[derive(Copy, Clone)]
-pub struct Struct;
-
-#[derive(Copy, Clone)]
-pub enum Unit {
-    UnitVariant,
-    Argument(Struct)
-}
-
-#[derive(Copy, Clone)]
-pub struct TupleStruct(pub usize, pub &'static str);
-
-// used by the cfail test
-
-#[derive(Copy, Clone)]
-pub struct StructWithFields {
-    foo: isize,
-}
-
-#[derive(Copy, Clone)]
-pub enum EnumWithVariants {
-    EnumVariant,
-    EnumVariantArg(isize)
-}
diff --git a/src/test/ui/issues/issue-37026.rs b/src/test/ui/empty/issue-37026.rs
index fd678a717d0..fd678a717d0 100644
--- a/src/test/ui/issues/issue-37026.rs
+++ b/src/test/ui/empty/issue-37026.rs
diff --git a/src/test/ui/issues/issue-37026.stderr b/src/test/ui/empty/issue-37026.stderr
index 48a4a5bcad2..48a4a5bcad2 100644
--- a/src/test/ui/issues/issue-37026.stderr
+++ b/src/test/ui/empty/issue-37026.stderr
diff --git a/src/test/ui/no-link.rs b/src/test/ui/empty/no-link.rs
index c80e61b4511..c80e61b4511 100644
--- a/src/test/ui/no-link.rs
+++ b/src/test/ui/empty/no-link.rs
diff --git a/src/test/ui/issues/auxiliary/empty-struct.rs b/src/test/ui/issues/auxiliary/empty-struct.rs
deleted file mode 100644
index 3fb40f6bfa9..00000000000
--- a/src/test/ui/issues/auxiliary/empty-struct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct XEmpty1 {}
-pub struct XEmpty2;
-pub struct XEmpty6();
-
-pub enum XE {
-    XEmpty3 {},
-    XEmpty4,
-    XEmpty5(),
-}
diff --git a/src/test/ui/issues/issue-51244.rs b/src/test/ui/issues/issue-51244.rs
deleted file mode 100644
index d634b8bf800..00000000000
--- a/src/test/ui/issues/issue-51244.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let ref my_ref @ _ = 0;
-    *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
-}
diff --git a/src/test/ui/issues/issue-51244.stderr b/src/test/ui/issues/issue-51244.stderr
deleted file mode 100644
index 19f0223a357..00000000000
--- a/src/test/ui/issues/issue-51244.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
-  --> $DIR/issue-51244.rs:3:5
-   |
-LL |     let ref my_ref @ _ = 0;
-   |         -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
-LL |     *my_ref = 0;
-   |     ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/macros/issue-95267.rs b/src/test/ui/macros/issue-95267.rs
new file mode 100644
index 00000000000..4d59c7ea5e9
--- /dev/null
+++ b/src/test/ui/macros/issue-95267.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+// This is a valid macro. Commit 4 in #95159 broke things such that it failed
+// with a "missing tokens in macro arguments" error, as reported in #95267.
+macro_rules! f {
+    (
+        /// ab
+    ) => {};
+}
+
+fn main() {
+    f!();
+}
diff --git a/src/test/ui/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item-2.rs
index a429d8fabc7..a429d8fabc7 100644
--- a/src/test/ui/weak-lang-item.rs
+++ b/src/test/ui/panic-handler/weak-lang-item-2.rs
diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs
deleted file mode 100644
index 8b491ee4e30..00000000000
--- a/src/test/ui/regions/regions-enum-not-wf.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Various examples of structs whose fields are not well-formed.
-
-#![allow(dead_code)]
-
-trait Dummy<'a> {
-    type Out;
-}
-impl<'a, T> Dummy<'a> for T
-where
-    T: 'a,
-{
-    type Out = ();
-}
-type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
-
-enum Ref1<'a, T> {
-    Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
-}
-
-enum Ref2<'a, T> {
-    Ref2Variant1,
-    Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
-}
-
-enum RefOk<'a, T: 'a> {
-    RefOkVariant1(&'a T),
-}
-
-// This is now well formed. RFC 2093
-enum RefIndirect<'a, T> {
-    RefIndirectVariant1(isize, RefOk<'a, T>),
-}
-
-enum RefDouble<'a, 'b, T> {
-    RefDoubleVariant1(&'a RequireOutlives<'b, T>),
-    //~^ the parameter type `T` may not live long enough [E0309]
-}
-
-fn main() {}
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
deleted file mode 100644
index 553a3e71c16..00000000000
--- a/src/test/ui/regions/regions-enum-not-wf.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:17:18
-   |
-LL | enum Ref1<'a, T> {
-   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref1Variant1(RequireOutlives<'a, T>),
-   |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:22:25
-   |
-LL | enum Ref2<'a, T> {
-   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref2Variant1,
-LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:35:23
-   |
-LL | enum RefDouble<'a, 'b, T> {
-   |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index dd090a3a548..34f059248b6 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -62,7 +62,7 @@ LL |     if true || let 0 = 0 {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:47:13
    |
 LL |     if true || let 0 = 0 {}
@@ -76,7 +76,7 @@ LL |     if (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:48:14
    |
 LL |     if (true || let 0 = 0) {}
@@ -90,7 +90,7 @@ LL |     if true && (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:49:22
    |
 LL |     if true && (true || let 0 = 0) {}
@@ -104,7 +104,7 @@ LL |     if true || (true && let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:50:13
    |
 LL |     if true || (true && let 0 = 0) {}
@@ -244,7 +244,7 @@ LL |     while true || let 0 = 0 {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:111:16
    |
 LL |     while true || let 0 = 0 {}
@@ -258,7 +258,7 @@ LL |     while (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:112:17
    |
 LL |     while (true || let 0 = 0) {}
@@ -272,7 +272,7 @@ LL |     while true && (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:113:25
    |
 LL |     while true && (true || let 0 = 0) {}
@@ -286,7 +286,7 @@ LL |     while true || (true && let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:114:16
    |
 LL |     while true || (true && let 0 = 0) {}
@@ -426,7 +426,7 @@ LL |     true || let 0 = 0;
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:184:10
    |
 LL |     true || let 0 = 0;
@@ -440,7 +440,7 @@ LL |     (true || let 0 = 0);
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:185:11
    |
 LL |     (true || let 0 = 0);
@@ -454,7 +454,7 @@ LL |     true && (true || let 0 = 0);
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:186:19
    |
 LL |     true && (true || let 0 = 0);
diff --git a/src/test/ui/span/E0057.rs b/src/test/ui/span/E0057.rs
deleted file mode 100644
index 83f941f65b9..00000000000
--- a/src/test/ui/span/E0057.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let f = |x| x * 3;
-    let a = f(); //~ ERROR E0057
-    let b = f(4);
-    let c = f(2, 3); //~ ERROR E0057
-}
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
deleted file mode 100644
index 31579e28289..00000000000
--- a/src/test/ui/span/E0057.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0057]: this function takes 1 argument but 0 arguments were supplied
-  --> $DIR/E0057.rs:3:13
-   |
-LL |     let a = f();
-   |             ^-- supplied 0 arguments
-   |             |
-   |             expected 1 argument
-
-error[E0057]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/E0057.rs:5:13
-   |
-LL |     let c = f(2, 3);
-   |             ^ -  - supplied 2 arguments
-   |             |
-   |             expected 1 argument
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs
index eabffc16170..eabffc16170 100644
--- a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs
+++ b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs
diff --git a/src/test/ui/suggestions/suggest-private-fields.rs b/src/test/ui/structs/suggest-private-fields.rs
index 8267a82fe2a..8267a82fe2a 100644
--- a/src/test/ui/suggestions/suggest-private-fields.rs
+++ b/src/test/ui/structs/suggest-private-fields.rs
diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/structs/suggest-private-fields.stderr
index d628bd16208..d628bd16208 100644
--- a/src/test/ui/suggestions/suggest-private-fields.stderr
+++ b/src/test/ui/structs/suggest-private-fields.stderr
diff --git a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs b/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
deleted file mode 100644
index 9765af1a7f6..00000000000
--- a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct A {
-    a: isize,
-    pub b: isize,
-}
-
-pub struct B {
-    pub a: isize,
-    b: isize,
-}
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
index c66009fe24c..471a6b836b5 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
@@ -16,4 +16,8 @@ fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, f
 fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found
 }
 
+fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+//~^ ERROR expected trait, found struct
+//~| ERROR use of undeclared type `Unresolved`
+
 fn main() {}
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 38b2e5ae9b9..9ca446a0a89 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -1,3 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type `Unresolved`
+  --> $DIR/assoc_type_bound_with_struct.rs:19:31
+   |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+   |                               ^^^^^^^^^^ use of undeclared type `Unresolved`
+
 error[E0404]: expected trait, found struct `String`
   --> $DIR/assoc_type_bound_with_struct.rs:5:46
    |
@@ -78,6 +84,18 @@ help: a trait with a similar name exists
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
    |                                                         ~~~~~~~~
 
-error: aborting due to 4 previous errors
+error[E0404]: expected trait, found struct `String`
+  --> $DIR/assoc_type_bound_with_struct.rs:19:51
+   |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+   |                                                   ^^^^^^ help: a trait with a similar name exists: `ToString`
+   |
+  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
+   |
+LL | pub trait ToString {
+   | ------------------ similarly named trait `ToString` defined here
+
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0404`.
+Some errors have detailed explanations: E0404, E0433.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/cross-crate/xcrate-unit-struct.rs b/src/test/ui/xcrate/xcrate-unit-struct-2.rs
index 7aa3eb0d6c4..7aa3eb0d6c4 100644
--- a/src/test/ui/cross-crate/xcrate-unit-struct.rs
+++ b/src/test/ui/xcrate/xcrate-unit-struct-2.rs