From 08ee5f5e63afe3e6a3d852932484c506d0eaee87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 18 Jan 2025 23:40:27 +0000 Subject: [PATCH 001/158] Do not ICE on default_field_value const with lifetimes Fix #135649. --- .../rustc_borrowck/src/universal_regions.rs | 6 ++++- .../do-not-ice-on-invalid-lifetime.rs | 6 +++++ .../do-not-ice-on-invalid-lifetime.stderr | 23 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs create mode 100644 tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 26af86c0cdd4..b25f449079a7 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -21,6 +21,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Diag; use rustc_hir::BodyOwnerKind; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; @@ -603,7 +604,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => { let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); - if self.mir_def.to_def_id() == typeck_root_def_id { + if self.mir_def.to_def_id() == typeck_root_def_id + // Do not ICE when checking default_field_values consts with lifetimes (#135649) + && DefKind::Field != tcx.def_kind(tcx.parent(typeck_root_def_id)) + { let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args); DefiningTy::Const(self.mir_def.to_def_id(), args) diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs new file mode 100644 index 000000000000..71d90ddd935f --- /dev/null +++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.rs @@ -0,0 +1,6 @@ +#![feature(default_field_values)] +struct A<'a> { //~ ERROR lifetime parameter `'a` is never used + x: Vec = Vec::new(), //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr new file mode 100644 index 000000000000..20b9afe80cdc --- /dev/null +++ b/tests/ui/structs/default-field-values/do-not-ice-on-invalid-lifetime.stderr @@ -0,0 +1,23 @@ +error[E0106]: missing lifetime specifier + --> $DIR/do-not-ice-on-invalid-lifetime.rs:3:12 + | +LL | x: Vec = Vec::new(), + | ^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | x: Vec> = Vec::new(), + | ++++ + +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/do-not-ice-on-invalid-lifetime.rs:2:10 + | +LL | struct A<'a> { + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0106, E0392. +For more information about an error, try `rustc --explain E0106`. From ee6b5cff4f0e43961be2ad932938200aef7825e4 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 7 Jan 2025 22:57:40 +0100 Subject: [PATCH 002/158] Make Pat::Range's start and end Option --- .../crates/hir-def/src/expr_store.rs | 10 ++-- .../crates/hir-def/src/expr_store/lower.rs | 46 +++++++++++++------ .../crates/hir-def/src/expr_store/pretty.rs | 4 +- .../rust-analyzer/crates/hir-def/src/hir.rs | 4 +- .../crates/hir-ty/src/diagnostics/expr.rs | 4 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 6 ++- 6 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 9df6eaade757..5ff6a7ffe566 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -112,9 +112,9 @@ pub struct ExpressionStoreSourceMap { // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected). expr_map: FxHashMap, - expr_map_back: ArenaMap, + expr_map_back: ArenaMap, - pat_map: FxHashMap, + pat_map: FxHashMap, pat_map_back: ArenaMap, label_map: FxHashMap, @@ -606,12 +606,12 @@ impl Index for ExpressionStore { impl ExpressionStoreSourceMap { pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result { match id { - ExprOrPatId::ExprId(id) => self.expr_syntax(id).map(|it| it.map(AstPtr::wrap_left)), + ExprOrPatId::ExprId(id) => self.expr_syntax(id), ExprOrPatId::PatId(id) => self.pat_syntax(id), } } - pub fn expr_syntax(&self, expr: ExprId) -> Result { + pub fn expr_syntax(&self, expr: ExprId) -> Result { self.expr_map_back.get(expr).cloned().ok_or(SyntheticSyntax) } @@ -633,7 +633,7 @@ impl ExpressionStoreSourceMap { self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax) } - pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { + pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { self.pat_map.get(&node.map(AstPtr::new)).cloned() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 88f770da02a4..d2715ac8760b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1784,23 +1784,32 @@ impl ExprCollector<'_> { self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { this.collect_pat_opt(expanded_pat, binding_list) }); - self.source_map.pat_map.insert(src, pat); + self.source_map.pat_map.insert(src, pat.into()); return pat; } None => Pat::Missing, }, // FIXME: implement in a way that also builds source map and calculates assoc resolutions in type inference. ast::Pat::RangePat(p) => { - let mut range_part_lower = |p: Option| { - p.and_then(|it| match &it { - ast::Pat::LiteralPat(it) => { - Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) + let mut range_part_lower = |p: Option| -> Option { + p.and_then(|it| { + let ptr = PatPtr::new(&it); + match &it { + ast::Pat::LiteralPat(it) => { + // Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) + Some(self.alloc_expr_from_pat( + Expr::Literal(pat_literal_to_hir(it)?.0), + ptr, + )) + } + pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { + // let subpat = self.collect_pat(pat.clone(), binding_list); + // Some(Box::new(LiteralOrConst::Const(subpat))) + // TODO + Some(self.missing_expr()) + } + _ => None, } - pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { - let subpat = self.collect_pat(pat.clone(), binding_list); - Some(Box::new(LiteralOrConst::Const(subpat))) - } - _ => None, }) }; let start = range_part_lower(p.start()); @@ -1863,7 +1872,7 @@ impl ExprCollector<'_> { } }); if let Some(pat) = pat.left() { - self.source_map.pat_map.insert(src, pat); + self.source_map.pat_map.insert(src, pat.into()); } pat } @@ -2490,7 +2499,7 @@ impl ExprCollector<'_> { fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId { let src = self.expander.in_file(ptr); let id = self.store.exprs.alloc(expr); - self.source_map.expr_map_back.insert(id, src); + self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_left)); self.source_map.expr_map.insert(src, id.into()); id } @@ -2502,7 +2511,7 @@ impl ExprCollector<'_> { fn alloc_expr_desugared_with_ptr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId { let src = self.expander.in_file(ptr); let id = self.store.exprs.alloc(expr); - self.source_map.expr_map_back.insert(id, src); + self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_left)); // We intentionally don't fill this as it could overwrite a non-desugared entry // self.source_map.expr_map.insert(src, id); id @@ -2526,11 +2535,20 @@ impl ExprCollector<'_> { self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_left)); id } + + fn alloc_expr_from_pat(&mut self, expr: Expr, ptr: PatPtr) -> ExprId { + let src = self.expander.in_file(ptr); + let id = self.body.exprs.alloc(expr); + self.source_map.pat_map.insert(src, id.into()); + self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_right)); + id + } + fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let src = self.expander.in_file(ptr); let id = self.store.pats.alloc(pat); self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_right)); - self.source_map.pat_map.insert(src, id); + self.source_map.pat_map.insert(src, id.into()); id } // FIXME: desugared pats don't have ptr, that's wrong and should be fixed somehow. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index 6a0b1e519790..c28cfb24529c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -656,11 +656,11 @@ impl Printer<'_> { } Pat::Range { start, end } => { if let Some(start) = start { - self.print_literal_or_const(start); + self.print_expr(*start); } w!(self, "..="); if let Some(end) = end { - self.print_literal_or_const(end); + self.print_expr(*end); } } Pat::Slice { prefix, slice, suffix } => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 0dcddf162b2f..a964512beb2d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -571,8 +571,8 @@ pub enum Pat { ellipsis: bool, }, Range { - start: Option>, - end: Option>, + start: Option, + end: Option, }, Slice { prefix: Box<[PatId]>, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 0b5f1319243f..59aaf85164a0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -440,7 +440,9 @@ impl ExprValidator { return; }; let root = source_ptr.file_syntax(db.upcast()); - let ast::Expr::IfExpr(if_expr) = source_ptr.value.to_node(&root) else { + let either::Left(ast::Expr::IfExpr(if_expr)) = + source_ptr.value.to_node(&root) + else { return; }; let mut top_if_expr = if_expr; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 2ffea34c85a1..d78d15288adc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -234,10 +234,12 @@ impl MirLowerCtx<'_> { }; if mode == MatchingMode::Check { if let Some(start) = start { - add_check(start, BinOp::Le)?; + // TODO + // add_check(start, BinOp::Le)?; } if let Some(end) = end { - add_check(end, BinOp::Ge)?; + // TODO + // add_check(end, BinOp::Ge)?; } } (current, current_else) From 31a56851449d0e8a65991d2e2a0ae637d5779d9c Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 8 Jan 2025 00:26:47 +0100 Subject: [PATCH 003/158] Make higher levels adapt Bodys exprs having ExprOrPatId values --- .../crates/hir/src/diagnostics.rs | 35 ++++++++++--------- .../crates/hir/src/has_source.rs | 4 +-- src/tools/rust-analyzer/crates/hir/src/lib.rs | 7 ++-- .../crates/hir/src/semantics/source_to_def.rs | 2 +- .../crates/hir/src/source_analyzer.rs | 2 +- .../src/handlers/mismatched_arg_count.rs | 2 +- .../src/handlers/unresolved_field.rs | 7 ++-- .../src/handlers/unresolved_method.rs | 6 ++-- 8 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 64e982c42d7f..9a5e50af0790 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -6,6 +6,7 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_def::{ + body::ExprOrPatPtr, hir::ExprOrPatId, path::{hir_segment_to_ast_segment, ModPath}, type_ref::TypesSourceMap, @@ -115,14 +116,14 @@ diagnostics![ #[derive(Debug)] pub struct BreakOutsideOfLoop { - pub expr: InFile>, + pub expr: InFile>>, pub is_break: bool, pub bad_value_break: bool, } #[derive(Debug)] pub struct TypedHole { - pub expr: InFile>, + pub expr: InFile>>, pub expected: Type, } @@ -234,13 +235,13 @@ pub struct MismatchedTupleStructPatArgCount { #[derive(Debug)] pub struct ExpectedFunction { - pub call: InFile>, + pub call: InFile>>, pub found: Type, } #[derive(Debug)] pub struct UnresolvedField { - pub expr: InFile>, + pub expr: InFile>>, pub receiver: Type, pub name: Name, pub method_with_same_name_exists: bool, @@ -248,7 +249,7 @@ pub struct UnresolvedField { #[derive(Debug)] pub struct UnresolvedMethodCall { - pub expr: InFile>, + pub expr: InFile>>, pub receiver: Type, pub name: Name, pub field_with_same_name: Option, @@ -267,7 +268,7 @@ pub struct UnresolvedIdent { #[derive(Debug)] pub struct PrivateField { - pub expr: InFile>, + pub expr: InFile>>, pub field: Field, } @@ -302,7 +303,7 @@ pub struct ReplaceFilterMapNextWithFindMap { #[derive(Debug)] pub struct MismatchedArgCount { - pub call_expr: InFile>, + pub call_expr: InFile, pub expected: usize, pub found: usize, } @@ -395,13 +396,13 @@ pub struct RemoveUnnecessaryElse { #[derive(Debug)] pub struct CastToUnsized { - pub expr: InFile>, + pub expr: InFile>>, pub cast_ty: Type, } #[derive(Debug)] pub struct InvalidCast { - pub expr: InFile>, + pub expr: InFile>>, pub error: CastError, pub expr_ty: Type, pub cast_ty: Type, @@ -428,9 +429,7 @@ impl AnyDiagnostic { .collect(); let record = match record { - Either::Left(record_expr) => { - source_map.expr_syntax(record_expr).ok()?.map(AstPtr::wrap_left) - } + Either::Left(record_expr) => source_map.expr_syntax(record_expr).ok()?, Either::Right(record_pat) => source_map.pat_syntax(record_pat).ok()?, }; let file = record.file_id; @@ -474,7 +473,7 @@ impl AnyDiagnostic { return Some( ReplaceFilterMapNextWithFindMap { file: next_source_ptr.file_id, - next_expr: next_source_ptr.value, + next_expr: next_source_ptr.value.cast()?, } .into(), ); @@ -484,7 +483,9 @@ impl AnyDiagnostic { match source_map.expr_syntax(match_expr) { Ok(source_ptr) => { let root = source_ptr.file_syntax(db.upcast()); - if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) { + if let Either::Left(ast::Expr::MatchExpr(match_expr)) = + &source_ptr.value.to_node(&root) + { match match_expr.expr() { Some(scrut_expr) if match_expr.match_arm_list().is_some() => { return Some( @@ -561,7 +562,7 @@ impl AnyDiagnostic { let pat_syntax = |pat| source_map.pat_syntax(pat).inspect_err(|_| stdx::never!("synthetic syntax")).ok(); let expr_or_pat_syntax = |id| match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(|it| it.map(AstPtr::wrap_left)), + ExprOrPatId::ExprId(expr) => expr_syntax(expr), ExprOrPatId::PatId(pat) => pat_syntax(pat), }; Some(match d { @@ -633,7 +634,7 @@ impl AnyDiagnostic { &InferenceDiagnostic::UnresolvedIdent { id } => { let node = match id { ExprOrPatId::ExprId(id) => match source_map.expr_syntax(id) { - Ok(syntax) => syntax.map(|it| (it.wrap_left(), None)), + Ok(syntax) => syntax.map(|it| (it, None)), Err(SyntheticSyntax) => source_map .format_args_implicit_capture(id)? .map(|(node, range)| (node.wrap_left(), Some(range))), @@ -652,7 +653,7 @@ impl AnyDiagnostic { } &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { let expr_or_pat = match pat { - ExprOrPatId::ExprId(expr) => expr_syntax(expr)?.map(AstPtr::wrap_left), + ExprOrPatId::ExprId(expr) => expr_syntax(expr)?, ExprOrPatId::PatId(pat) => { let InFile { file_id, value } = pat_syntax(pat)?; diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index 82c90ac30101..a34b4980832c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -248,7 +248,7 @@ impl HasSource for Param { let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?; let root = db.parse_or_expand(file_id); match value.to_node(&root) { - ast::Expr::ClosureExpr(it) => it + Either::Left(ast::Expr::ClosureExpr(it)) => it .param_list()? .params() .nth(self.idx) @@ -301,7 +301,7 @@ impl HasSource for InlineAsmOperand { let root = src.file_syntax(db.upcast()); return src .map(|ast| match ast.to_node(&root) { - ast::Expr::AsmExpr(asm) => asm + Either::Left(ast::Expr::AsmExpr(asm)) => asm .asm_pieces() .filter_map(|it| match it { ast::AsmPiece::AsmOperandNamed(it) => Some(it), diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 56090bc6b605..26b2819913e2 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1957,7 +1957,7 @@ impl DefWithBody { ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right), }; let expr_or_pat = match expr_or_pat { - Ok(Either::Left(expr)) => expr.map(AstPtr::wrap_left), + Ok(Either::Left(expr)) => expr, Ok(Either::Right(InFile { file_id, value: pat })) => { // cast from Either -> Either<_, Pat> let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else { @@ -4592,10 +4592,7 @@ impl CaptureUsages { match span { mir::MirSpan::ExprId(expr) => { if let Ok(expr) = source_map.expr_syntax(expr) { - result.push(CaptureUsageSource { - is_ref, - source: expr.map(AstPtr::wrap_left), - }) + result.push(CaptureUsageSource { is_ref, source: expr }) } } mir::MirSpan::PatId(pat) => { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 3c9e7065c41d..29d3736bae72 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -352,7 +352,7 @@ impl SourceToDefCtx<'_, '_> { let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; // the pattern could resolve to a constant, verify that this is not the case - if let crate::Pat::Bind { id, .. } = body[pat_id] { + if let crate::Pat::Bind { id, .. } = body[pat_id.as_pat()?] { Some((container, id)) } else { None diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index ca239826d4fc..cf756c679750 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -142,7 +142,7 @@ impl SourceAnalyzer { fn pat_id(&self, pat: &ast::Pat) -> Option { // FIXME: macros, see `expr_id` let src = InFile { file_id: self.file_id, value: pat }; - self.body_source_map()?.node_pat(src) + self.body_source_map()?.node_pat(src).and_then(ExprOrPatId::as_pat) } fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 7126617cdeed..0520bb3fe9b9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -40,7 +40,7 @@ pub(crate) fn mismatched_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0107"), message, - invalid_args_range(ctx, d.call_expr.map(AstPtr::wrap_left), d.expected, d.found), + invalid_args_range(ctx, d.call_expr, d.expected, d.found), ) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 4accd181ca43..dfb03eee732a 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -1,5 +1,6 @@ use std::iter; +use either::Either; use hir::{db::ExpandDatabase, Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union}; use ide_db::text_edit::TextEdit; use ide_db::{ @@ -41,7 +42,7 @@ pub(crate) fn unresolved_field( ), adjusted_display_range(ctx, d.expr, &|expr| { Some( - match expr { + match expr.left()? { ast::Expr::MethodCallExpr(it) => it.name_ref(), ast::Expr::FieldExpr(it) => it.name_ref(), _ => None, @@ -72,7 +73,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option, d: &hir::UnresolvedField) -> Option { // Get the FileRange of the invalid field access let root = ctx.sema.db.parse_or_expand(d.expr.file_id); - let expr = d.expr.value.to_node(&root); + let expr = d.expr.value.to_node(&root).left()?; let error_range = ctx.sema.original_range_opt(expr.syntax())?; let field_name = d.name.as_str(); @@ -263,7 +264,7 @@ fn record_field_layout( // FIXME: We should fill out the call here, move the cursor and trigger signature help fn method_fix( ctx: &DiagnosticsContext<'_>, - expr_ptr: &InFile>, + expr_ptr: &InFile>>, ) -> Option { let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 4ab649cc1628..dd1b593e8f6e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -35,7 +35,7 @@ pub(crate) fn unresolved_method( ), adjusted_display_range(ctx, d.expr, &|expr| { Some( - match expr { + match expr.left()? { ast::Expr::MethodCallExpr(it) => it.name_ref(), ast::Expr::FieldExpr(it) => it.name_ref(), _ => None, @@ -85,7 +85,7 @@ fn field_fix( let expr_ptr = &d.expr; let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); - let (file_id, range) = match expr { + let (file_id, range) = match expr.left()? { ast::Expr::MethodCallExpr(mcall) => { let FileRange { range, file_id } = ctx.sema.original_range_opt(mcall.receiver()?.syntax())?; @@ -117,7 +117,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) - let expr_ptr = &d.expr; let root = db.parse_or_expand(expr_ptr.file_id); - let expr: ast::Expr = expr_ptr.value.to_node(&root); + let expr: ast::Expr = expr_ptr.value.to_node(&root).left()?; let call = ast::MethodCallExpr::cast(expr.syntax().clone())?; let range = InFile::new(expr_ptr.file_id, call.syntax().text_range()) From 8a18dce223a84e32dff217a0ba641576203600be Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 8 Jan 2025 00:48:25 +0100 Subject: [PATCH 004/158] Add a test to monitor whats going on --- .../crates/hir-def/src/expr_store/lower.rs | 17 +++++--- .../crates/hir-def/src/expr_store/tests.rs | 43 +++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index d2715ac8760b..3f3beb21858c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -44,8 +44,8 @@ use crate::{ FormatPlaceholder, FormatSign, FormatTrait, }, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, - Expr, ExprId, Item, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability, - OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement, + Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId, + RecordFieldPat, RecordLitField, Statement, }, item_scope::BuiltinShadowMode, lang_item::LangItem, @@ -1802,10 +1802,15 @@ impl ExprCollector<'_> { ptr, )) } - pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { - // let subpat = self.collect_pat(pat.clone(), binding_list); - // Some(Box::new(LiteralOrConst::Const(subpat))) - // TODO + ast::Pat::IdentPat(_) => Some(self.missing_expr()), + ast::Pat::PathPat(p) => { + if let Some(path) = p.path() { + if let Some(parsed) = self.parse_path(path) { + return Some( + self.alloc_expr_from_pat(Expr::Path(parsed), ptr), + ); + } + } Some(self.missing_expr()) } _ => None, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 9bf1ddb47938..5ce9a67f9b6c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -460,3 +460,46 @@ async fn foo(a: (), b: i32) -> u32 { expect!["fn foo(�: (), �: i32) -> impl ::core::future::Future:: �"] .assert_eq(&printed); } + +fn abc() { + let (db, body, owner) = lower( + r#" +pub const L: i32 = 6; +mod x { + pub const R: i32 = 100; +} +const fn f(x: i32) -> i32 { + match x { + -1..=5 => x * 10, + L..=x::R => x * 100, + _ => x, + } +}"#, + ); + + for (pat_id, pat) in body.pats.iter() { + match pat { + Pat::Range { start, end } => { + let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); + eprintln!("RANGE {}", pretty); + + if let Some(start) = start { + eprintln!("START"); + let expr = body.exprs[*start].clone(); + dbg!(expr); + } else { + eprintln!("START is None"); + } + + if let Some(end) = end { + eprintln!("END"); + let expr = body.exprs[*end].clone(); + dbg!(expr); + } else { + eprintln!("END is None"); + } + } + _ => {} + } + } +} From d694b2086ce3f60591220ea1ef31b9bdd5738fea Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 22 Jan 2025 19:01:56 +0200 Subject: [PATCH 005/158] Make `rust-analyzer.files.excludeDirs` work, actually I have no idea what the original writer of the code thought but the logic just seems backwards. We should not exclude a file/directory if it is equal to an include! This also meant that we had to add a `root == path` check so this stuff will actually work, which in turn meant excludes (of root files) no longer worked... Also rename if to `rust-analyzer.files.exclude`, because it can exclude files as well. --- .../crates/rust-analyzer/src/config.rs | 8 ++--- .../rust-analyzer/tests/slow-tests/main.rs | 36 ++++++++++++++++++- .../crates/vfs-notify/src/lib.rs | 5 +-- .../docs/book/src/configuration_generated.md | 4 +-- .../rust-analyzer/editors/code/package.json | 4 +-- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 7656c07c9485..daddeae13aa4 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -84,10 +84,10 @@ config_data! { completion_snippets_custom: FxHashMap = Config::completion_snippets_default(), - /// These directories will be ignored by rust-analyzer. They are + /// These paths (file/directories) will be ignored by rust-analyzer. They are /// relative to the workspace root, and globs are not supported. You may /// also need to add the folders to Code's `files.watcherExclude`. - files_excludeDirs: Vec = vec![], + files_exclude | files_excludeDirs: Vec = vec![], @@ -1787,7 +1787,7 @@ impl Config { fn discovered_projects(&self) -> Vec { let exclude_dirs: Vec<_> = - self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect(); + self.files_exclude().iter().map(|p| self.root_path.join(p)).collect(); let mut projects = vec![]; for fs_proj in &self.discovered_projects_from_filesystem { @@ -1909,7 +1909,7 @@ impl Config { } _ => FilesWatcher::Server, }, - exclude: self.files_excludeDirs().iter().map(|it| self.root_path.join(it)).collect(), + exclude: self.files_exclude().iter().map(|it| self.root_path.join(it)).collect(), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 2b3c0a47a220..5ad28d0b909e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1372,6 +1372,40 @@ pub fn foo() {} name = "bar" version = "0.0.0" +[dependencies] +foo = { path = "../foo" } + +//- /bar/src/lib.rs +"#, + ) + .root("foo") + .root("bar") + .root("baz") + .with_config(json!({ + "files": { + "exclude": ["foo"] + } + })) + .server() + .wait_until_workspace_is_loaded(); + + server.request::(Default::default(), json!([])); + + let server = Project::with_fixture( + r#" +//- /foo/Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /foo/src/lib.rs +pub fn foo() {} + +//- /bar/Cargo.toml +[package] +name = "bar" +version = "0.0.0" + //- /bar/src/lib.rs pub fn bar() {} @@ -1388,7 +1422,7 @@ version = "0.0.0" .root("baz") .with_config(json!({ "files": { - "excludeDirs": ["foo", "bar"] + "exclude": ["foo", "bar"] } })) .server() diff --git a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs index 0ae8b7baf464..320033417640 100644 --- a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs +++ b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs @@ -280,8 +280,9 @@ impl NotifyActor { return false; } - root == path - || dirs.exclude.iter().chain(&dirs.include).all(|it| it != path) + // We want to filter out subdirectories that are roots themselves, because they will be visited separately. + dirs.exclude.iter().all(|it| it != path) + && (root == path || dirs.include.iter().all(|it| it != path)) }); let files = walkdir.filter_map(|it| it.ok()).filter_map(|entry| { diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index 49eb7248898e..a7f54289b964 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -470,9 +470,9 @@ The warnings will be indicated by a blue squiggly underline in code and a blue icon in the `Problems Panel`. -**rust-analyzer.files.excludeDirs** (default: []) +**rust-analyzer.files.exclude** (default: []) - These directories will be ignored by rust-analyzer. They are + These paths (file/directories) will be ignored by rust-analyzer. They are relative to the workspace root, and globs are not supported. You may also need to add the folders to Code's `files.watcherExclude`. diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 57f4254b6899..5db8ca52a587 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -1473,8 +1473,8 @@ { "title": "files", "properties": { - "rust-analyzer.files.excludeDirs": { - "markdownDescription": "These directories will be ignored by rust-analyzer. They are\nrelative to the workspace root, and globs are not supported. You may\nalso need to add the folders to Code's `files.watcherExclude`.", + "rust-analyzer.files.exclude": { + "markdownDescription": "These paths (file/directories) will be ignored by rust-analyzer. They are\nrelative to the workspace root, and globs are not supported. You may\nalso need to add the folders to Code's `files.watcherExclude`.", "default": [], "type": "array", "items": { From cee2df27b7a1ae72cecad3d1d4d16911db1e596d Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 23:07:05 +0200 Subject: [PATCH 006/158] Refactor `TyLoweringContext::substs_from_args_and_bindings()` to always take a `GenericDefId` --- .../rust-analyzer/crates/hir-ty/src/infer.rs | 3 +- .../rust-analyzer/crates/hir-ty/src/lower.rs | 42 ++++++++----------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 617ebba8811e..cf6905a0b28f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1625,8 +1625,7 @@ impl<'a> InferenceContext<'a> { None => path.segments().last().unwrap(), Some(n) => path.segments().get(path.segments().len() - n - 1).unwrap(), }; - let substs = - ctx.substs_from_path_segment(resolved_seg, Some(it.into()), true, None); + let substs = ctx.substs_from_path_segment(resolved_seg, it.into(), true, None); drop(ctx); let ty = self.db.ty(it.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index db13e1fd3543..595929a8f41b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -592,7 +592,7 @@ impl<'a> TyLoweringContext<'a> { // this point (`trait_ref.substitution`). let substitution = self.substs_from_path_segment( segment, - Some(associated_ty.into()), + associated_ty.into(), false, None, ); @@ -1007,7 +1007,7 @@ impl<'a> TyLoweringContext<'a> { // that method to optionally take parent `Substitution` as we already know them at // this point (`t.substitution`). let substs = - self.substs_from_path_segment(segment, Some(associated_ty.into()), false, None); + self.substs_from_path_segment(segment, associated_ty.into(), false, None); let len_self = crate::generics::generics(self.db.upcast(), associated_ty.into()).len_self(); @@ -1037,9 +1037,9 @@ impl<'a> TyLoweringContext<'a> { infer_args: bool, ) -> Ty { let generic_def = match typeable { - TyDefId::BuiltinType(_) => None, - TyDefId::AdtId(it) => Some(it.into()), - TyDefId::TypeAliasId(it) => Some(it.into()), + TyDefId::BuiltinType(builtin) => return TyBuilder::builtin(builtin), + TyDefId::AdtId(it) => it.into(), + TyDefId::TypeAliasId(it) => it.into(), }; let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); self.db.ty(typeable).substitute(Interner, &substs) @@ -1058,11 +1058,11 @@ impl<'a> TyLoweringContext<'a> { ) -> Substitution { let last = path.segments().last(); let (segment, generic_def) = match resolved { - ValueTyDefId::FunctionId(it) => (last, Some(it.into())), - ValueTyDefId::StructId(it) => (last, Some(it.into())), - ValueTyDefId::UnionId(it) => (last, Some(it.into())), - ValueTyDefId::ConstId(it) => (last, Some(it.into())), - ValueTyDefId::StaticId(_) => (last, None), + ValueTyDefId::FunctionId(it) => (last, it.into()), + ValueTyDefId::StructId(it) => (last, it.into()), + ValueTyDefId::UnionId(it) => (last, it.into()), + ValueTyDefId::ConstId(it) => (last, it.into()), + ValueTyDefId::StaticId(_) => return Substitution::empty(Interner), ValueTyDefId::EnumVariantId(var) => { // the generic args for an enum variant may be either specified // on the segment referring to the enum, or on the segment @@ -1075,23 +1075,17 @@ impl<'a> TyLoweringContext<'a> { Some(segment) if segment.args_and_bindings.is_some() => Some(segment), _ => last, }; - (segment, Some(var.lookup(self.db.upcast()).parent.into())) + (segment, var.lookup(self.db.upcast()).parent.into()) } }; - if let Some(segment) = segment { - self.substs_from_path_segment(segment, generic_def, infer_args, None) - } else if let Some(generic_def) = generic_def { - // lang item - self.substs_from_args_and_bindings(None, Some(generic_def), infer_args, None) - } else { - Substitution::empty(Interner) - } + let args_and_bindings = segment.and_then(|it| it.args_and_bindings); + self.substs_from_args_and_bindings(args_and_bindings, generic_def, infer_args, None) } pub(super) fn substs_from_path_segment( &mut self, segment: PathSegment<'_>, - def: Option, + def: GenericDefId, infer_args: bool, explicit_self_ty: Option, ) -> Substitution { @@ -1106,12 +1100,10 @@ impl<'a> TyLoweringContext<'a> { fn substs_from_args_and_bindings( &mut self, args_and_bindings: Option<&GenericArgs>, - def: Option, + def: GenericDefId, infer_args: bool, explicit_self_ty: Option, ) -> Substitution { - let Some(def) = def else { return Substitution::empty(Interner) }; - // Order is // - Optional Self parameter // - Lifetime parameters @@ -1317,7 +1309,7 @@ impl<'a> TyLoweringContext<'a> { resolved: TraitId, explicit_self_ty: Ty, ) -> Substitution { - self.substs_from_path_segment(segment, Some(resolved.into()), false, Some(explicit_self_ty)) + self.substs_from_path_segment(segment, resolved.into(), false, Some(explicit_self_ty)) } pub(crate) fn lower_where_predicate<'b>( @@ -1445,7 +1437,7 @@ impl<'a> TyLoweringContext<'a> { let substitution = self.substs_from_path_segment( // FIXME: This is hack. We shouldn't really build `PathSegment` directly. PathSegment { name: &binding.name, args_and_bindings: binding.args.as_ref() }, - Some(associated_ty.into()), + associated_ty.into(), false, // this is not relevant Some(super_trait_ref.self_type_parameter(Interner)), ); From 54ad31b5b885bfcec5fd7d470ed03c0718656cac Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 23:07:35 +0200 Subject: [PATCH 007/158] Fix incorrect terminology Lifetimes are elided in function signatures, and inferred in bodies. --- src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 86e5afdb5092..ab3c039ece37 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -2132,8 +2132,8 @@ impl InferenceContext<'_> { for kind_id in def_generics.iter_self_id().take(self_params) { let arg = args.peek(); let arg = match (kind_id, arg) { - // Lifetimes can be elided. - // Once we have implemented lifetime elision correctly, + // Lifetimes can be inferred. + // Once we have implemented lifetime inference correctly, // this should be handled in a proper way. ( GenericParamId::LifetimeParamId(_), From 66599f1dd5ade8f87cfeca3b2334649820c659d9 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 23:07:48 +0200 Subject: [PATCH 008/158] Remove a no-longer-correct FIXME --- src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs index 7fe196cdbb59..dac04307b740 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs @@ -26,7 +26,6 @@ pub enum GenericArgsProhibitedReason { Static, /// When there is a generic enum, within the expression `Enum::Variant`, /// either `Enum` or `Variant` are allowed to have generic arguments, but not both. - // FIXME: This is not used now but it should be. EnumVariant, } From c7e331bfb8d131d52278785e2fe8338010020eb0 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 17:53:52 +0200 Subject: [PATCH 009/158] Do not include excluded files even when the client opens them This require a pretty big modification, because this is a new kind of file: exists - but ignore it. --- .../crates/load-cargo/src/lib.rs | 4 +- .../crates/rust-analyzer/src/config.rs | 6 +- .../crates/rust-analyzer/src/global_state.rs | 25 ++- .../src/handlers/notification.rs | 16 +- .../rust-analyzer/src/handlers/request.rs | 170 ++++++++++-------- .../src/integrated_benchmarks.rs | 14 +- .../crates/rust-analyzer/src/lib.rs | 11 ++ .../rust-analyzer/src/lsp/from_proto.rs | 30 ++-- .../crates/rust-analyzer/src/main_loop.rs | 31 ++-- .../crates/rust-analyzer/src/reload.rs | 4 +- src/tools/rust-analyzer/crates/vfs/src/lib.rs | 27 ++- 11 files changed, 217 insertions(+), 121 deletions(-) diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 5654c04a5928..67ee9d111997 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -94,7 +94,9 @@ pub fn load_workspace( let contents = loader.load_sync(path); let path = vfs::VfsPath::from(path.to_path_buf()); vfs.set_file_contents(path.clone(), contents); - vfs.file_id(&path) + vfs.file_id(&path).and_then(|(file_id, excluded)| { + (excluded == vfs::FileExcluded::No).then_some(file_id) + }) }, extra_env, ); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index daddeae13aa4..758f60dc3e43 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1909,10 +1909,14 @@ impl Config { } _ => FilesWatcher::Server, }, - exclude: self.files_exclude().iter().map(|it| self.root_path.join(it)).collect(), + exclude: self.excluded().collect(), } } + pub fn excluded(&self) -> impl Iterator + use<'_> { + self.files_exclude().iter().map(|it| self.root_path.join(it)) + } + pub fn notifications(&self) -> NotificationsConfig { NotificationsConfig { cargo_toml_not_found: self.notifications_cargoTomlNotFound().to_owned(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index b52f64aaacec..70105cda006b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -650,7 +650,8 @@ impl GlobalStateSnapshot { RwLockReadGuard::map(self.vfs.read(), |(it, _)| it) } - pub(crate) fn url_to_file_id(&self, url: &Url) -> anyhow::Result { + /// Returns `None` if the file was excluded. + pub(crate) fn url_to_file_id(&self, url: &Url) -> anyhow::Result> { url_to_file_id(&self.vfs_read(), url) } @@ -658,7 +659,8 @@ impl GlobalStateSnapshot { file_id_to_url(&self.vfs_read(), id) } - pub(crate) fn vfs_path_to_file_id(&self, vfs_path: &VfsPath) -> anyhow::Result { + /// Returns `None` if the file was excluded. + pub(crate) fn vfs_path_to_file_id(&self, vfs_path: &VfsPath) -> anyhow::Result> { vfs_path_to_file_id(&self.vfs_read(), vfs_path) } @@ -750,14 +752,21 @@ pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url { url_from_abs_path(path) } -pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result { +/// Returns `None` if the file was excluded. +pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result> { let path = from_proto::vfs_path(url)?; - let res = vfs.file_id(&path).ok_or_else(|| anyhow::format_err!("file not found: {path}"))?; - Ok(res) + vfs_path_to_file_id(vfs, &path) } -pub(crate) fn vfs_path_to_file_id(vfs: &vfs::Vfs, vfs_path: &VfsPath) -> anyhow::Result { - let res = +/// Returns `None` if the file was excluded. +pub(crate) fn vfs_path_to_file_id( + vfs: &vfs::Vfs, + vfs_path: &VfsPath, +) -> anyhow::Result> { + let (file_id, excluded) = vfs.file_id(vfs_path).ok_or_else(|| anyhow::format_err!("file not found: {vfs_path}"))?; - Ok(res) + match excluded { + vfs::FileExcluded::Yes => Ok(None), + vfs::FileExcluded::No => Ok(Some(file_id)), + } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index 48856d19e155..55344a4d6ac6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -22,6 +22,7 @@ use crate::{ mem_docs::DocumentData, reload, target_spec::TargetSpec, + try_default, }; pub(crate) fn handle_cancel(state: &mut GlobalState, params: CancelParams) -> anyhow::Result<()> { @@ -74,6 +75,14 @@ pub(crate) fn handle_did_open_text_document( tracing::error!("duplicate DidOpenTextDocument: {}", path); } + if let Some(abs_path) = path.as_path() { + if state.config.excluded().any(|excluded| abs_path.starts_with(&excluded)) { + tracing::trace!("opened excluded file {abs_path}"); + state.vfs.write().0.insert_excluded_file(path); + return Ok(()); + } + } + let contents = params.text_document.text.into_bytes(); state.vfs.write().0.set_file_contents(path, Some(contents)); if state.config.discover_workspace_config().is_some() { @@ -127,7 +136,8 @@ pub(crate) fn handle_did_close_text_document( tracing::error!("orphan DidCloseTextDocument: {}", path); } - if let Some(file_id) = state.vfs.read().0.file_id(&path) { + // Clear diagnostics also for excluded files, just in case. + if let Some((file_id, _)) = state.vfs.read().0.file_id(&path) { state.diagnostics.clear_native_for(file_id); } @@ -146,7 +156,7 @@ pub(crate) fn handle_did_save_text_document( ) -> anyhow::Result<()> { if let Ok(vfs_path) = from_proto::vfs_path(¶ms.text_document.uri) { let snap = state.snapshot(); - let file_id = snap.vfs_path_to_file_id(&vfs_path)?; + let file_id = try_default!(snap.vfs_path_to_file_id(&vfs_path)?); let sr = snap.analysis.source_root_id(file_id)?; if state.config.script_rebuild_on_save(Some(sr)) && state.build_deps_changed { @@ -290,7 +300,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { let _p = tracing::info_span!("run_flycheck").entered(); let file_id = state.vfs.read().0.file_id(&vfs_path); - if let Some(file_id) = file_id { + if let Some((file_id, vfs::FileExcluded::No)) = file_id { let world = state.snapshot(); let invocation_strategy_once = state.config.flycheck(None).invocation_strategy_once(); let may_flycheck_workspace = state.config.flycheck_workspace(None); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index ed028f1d37b6..a3cb8c9be61f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -53,6 +53,7 @@ use crate::{ }, target_spec::{CargoTargetSpec, TargetSpec}, test_runner::{CargoTestHandle, TestTarget}, + try_default, }; pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { @@ -83,7 +84,8 @@ pub(crate) fn handle_analyzer_status( let mut file_id = None; if let Some(tdi) = params.text_document { match from_proto::file_id(&snap, &tdi.uri) { - Ok(it) => file_id = Some(it), + Ok(Some(it)) => file_id = Some(it), + Ok(None) => {} Err(_) => format_to!(buf, "file {} not found in vfs", tdi.uri), } } @@ -141,7 +143,7 @@ pub(crate) fn handle_view_syntax_tree( params: lsp_ext::ViewSyntaxTreeParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_view_syntax_tree").entered(); - let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let res = snap.analysis.view_syntax_tree(id)?; Ok(res) } @@ -151,7 +153,7 @@ pub(crate) fn handle_view_hir( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_view_hir").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let res = snap.analysis.view_hir(position)?; Ok(res) } @@ -161,7 +163,7 @@ pub(crate) fn handle_view_mir( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_view_mir").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let res = snap.analysis.view_mir(position)?; Ok(res) } @@ -171,7 +173,7 @@ pub(crate) fn handle_interpret_function( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_interpret_function").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let res = snap.analysis.interpret_function(position)?; Ok(res) } @@ -180,7 +182,7 @@ pub(crate) fn handle_view_file_text( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentIdentifier, ) -> anyhow::Result { - let file_id = from_proto::file_id(&snap, ¶ms.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.uri)?); Ok(snap.analysis.file_text(file_id)?.to_string()) } @@ -189,7 +191,7 @@ pub(crate) fn handle_view_item_tree( params: lsp_ext::ViewItemTreeParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_view_item_tree").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let res = snap.analysis.view_item_tree(file_id)?; Ok(res) } @@ -315,7 +317,7 @@ pub(crate) fn handle_expand_macro( params: lsp_ext::ExpandMacroParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_expand_macro").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; let offset = from_proto::offset(&line_index, params.position)?; @@ -328,7 +330,7 @@ pub(crate) fn handle_selection_range( params: lsp_types::SelectionRangeParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_selection_range").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; let res: anyhow::Result> = params .positions @@ -371,7 +373,7 @@ pub(crate) fn handle_matching_brace( params: lsp_ext::MatchingBraceParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_matching_brace").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; params .positions @@ -395,7 +397,7 @@ pub(crate) fn handle_join_lines( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_join_lines").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let config = snap.config.join_lines(); let line_index = snap.file_line_index(file_id)?; @@ -419,7 +421,7 @@ pub(crate) fn handle_on_enter( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_on_enter").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let edit = match snap.analysis.on_enter(position)? { None => return Ok(None), Some(it) => it, @@ -439,7 +441,8 @@ pub(crate) fn handle_on_type_formatting( return Ok(None); } - let mut position = from_proto::file_position(&snap, params.text_document_position)?; + let mut position = + try_default!(from_proto::file_position(&snap, params.text_document_position)?); let line_index = snap.file_line_index(position.file_id)?; // in `ide`, the `on_type` invariant is that @@ -465,32 +468,33 @@ pub(crate) fn handle_on_type_formatting( Ok(Some(change)) } +pub(crate) fn empty_diagnostic_report() -> lsp_types::DocumentDiagnosticReportResult { + lsp_types::DocumentDiagnosticReportResult::Report(lsp_types::DocumentDiagnosticReport::Full( + lsp_types::RelatedFullDocumentDiagnosticReport { + related_documents: None, + full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { + result_id: Some("rust-analyzer".to_owned()), + items: vec![], + }, + }, + )) +} + pub(crate) fn handle_document_diagnostics( snap: GlobalStateSnapshot, params: lsp_types::DocumentDiagnosticParams, ) -> anyhow::Result { - let empty = || { - lsp_types::DocumentDiagnosticReportResult::Report( - lsp_types::DocumentDiagnosticReport::Full( - lsp_types::RelatedFullDocumentDiagnosticReport { - related_documents: None, - full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { - result_id: Some("rust-analyzer".to_owned()), - items: vec![], - }, - }, - ), - ) + let file_id = match from_proto::file_id(&snap, ¶ms.text_document.uri)? { + Some(it) => it, + None => return Ok(empty_diagnostic_report()), }; - - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let source_root = snap.analysis.source_root_id(file_id)?; if !snap.analysis.is_local_source_root(source_root)? { - return Ok(empty()); + return Ok(empty_diagnostic_report()); } let config = snap.config.diagnostics(Some(source_root)); if !config.enabled { - return Ok(empty()); + return Ok(empty_diagnostic_report()); } let line_index = snap.file_line_index(file_id)?; let supports_related = snap.config.text_document_diagnostic_related_document_support(); @@ -546,7 +550,7 @@ pub(crate) fn handle_document_symbol( params: lsp_types::DocumentSymbolParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_document_symbol").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; let mut parents: Vec<(lsp_types::DocumentSymbol, Option)> = Vec::new(); @@ -760,7 +764,7 @@ pub(crate) fn handle_will_rename_files( } }) .filter_map(|(file_id, new_name)| { - snap.analysis.will_rename_file(file_id, &new_name).ok()? + snap.analysis.will_rename_file(file_id?, &new_name).ok()? }) .collect(); @@ -782,7 +786,8 @@ pub(crate) fn handle_goto_definition( params: lsp_types::GotoDefinitionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_definition").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params)?; + let position = + try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); let nav_info = match snap.analysis.goto_definition(position)? { None => return Ok(None), Some(it) => it, @@ -797,7 +802,10 @@ pub(crate) fn handle_goto_declaration( params: lsp_types::request::GotoDeclarationParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_declaration").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params.clone())?; + let position = try_default!(from_proto::file_position( + &snap, + params.text_document_position_params.clone() + )?); let nav_info = match snap.analysis.goto_declaration(position)? { None => return handle_goto_definition(snap, params), Some(it) => it, @@ -812,7 +820,8 @@ pub(crate) fn handle_goto_implementation( params: lsp_types::request::GotoImplementationParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_implementation").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params)?; + let position = + try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); let nav_info = match snap.analysis.goto_implementation(position)? { None => return Ok(None), Some(it) => it, @@ -827,7 +836,8 @@ pub(crate) fn handle_goto_type_definition( params: lsp_types::request::GotoTypeDefinitionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_goto_type_definition").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params)?; + let position = + try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); let nav_info = match snap.analysis.goto_type_definition(position)? { None => return Ok(None), Some(it) => it, @@ -880,7 +890,7 @@ pub(crate) fn handle_parent_module( } // check if invoked at the crate root - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let crate_id = match snap.analysis.crates_for(file_id)?.first() { Some(&crate_id) => crate_id, None => return Ok(None), @@ -904,7 +914,7 @@ pub(crate) fn handle_parent_module( } // locate parent module by semantics - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let navs = snap.analysis.parent_module(position)?; let res = to_proto::goto_definition_response(&snap, None, navs)?; Ok(Some(res)) @@ -915,7 +925,7 @@ pub(crate) fn handle_runnables( params: lsp_ext::RunnablesParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_runnables").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let source_root = snap.analysis.source_root_id(file_id).ok(); let line_index = snap.file_line_index(file_id)?; let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok()); @@ -1035,7 +1045,7 @@ pub(crate) fn handle_related_tests( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_related_tests").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let tests = snap.analysis.related_tests(position, None)?; let mut res = Vec::new(); @@ -1053,7 +1063,8 @@ pub(crate) fn handle_completion( lsp_types::CompletionParams { text_document_position, context,.. }: lsp_types::CompletionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_completion").entered(); - let mut position = from_proto::file_position(&snap, text_document_position.clone())?; + let mut position = + try_default!(from_proto::file_position(&snap, text_document_position.clone())?); let line_index = snap.file_line_index(position.file_id)?; let completion_trigger_character = context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next()); @@ -1102,7 +1113,8 @@ pub(crate) fn handle_completion_resolve( let resolve_data: lsp_ext::CompletionResolveData = serde_json::from_value(data)?; - let file_id = from_proto::file_id(&snap, &resolve_data.position.text_document.uri)?; + let file_id = from_proto::file_id(&snap, &resolve_data.position.text_document.uri)? + .expect("we never provide completions for excluded files"); let line_index = snap.file_line_index(file_id)?; // FIXME: We should fix up the position when retrying the cancelled request instead let Ok(offset) = from_proto::offset(&line_index, resolve_data.position.position) else { @@ -1185,7 +1197,7 @@ pub(crate) fn handle_folding_range( params: FoldingRangeParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_folding_range").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let folds = snap.analysis.folding_ranges(file_id)?; let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; @@ -1202,7 +1214,8 @@ pub(crate) fn handle_signature_help( params: lsp_types::SignatureHelpParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_signature_help").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params)?; + let position = + try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); let help = match snap.analysis.signature_help(position)? { Some(it) => it, None => return Ok(None), @@ -1221,7 +1234,7 @@ pub(crate) fn handle_hover( PositionOrRange::Position(position) => Range::new(position, position), PositionOrRange::Range(range) => range, }; - let file_range = from_proto::file_range(&snap, ¶ms.text_document, range)?; + let file_range = try_default!(from_proto::file_range(&snap, ¶ms.text_document, range)?); let hover = snap.config.hover(); let info = match snap.analysis.hover(&hover, file_range)? { @@ -1255,7 +1268,7 @@ pub(crate) fn handle_prepare_rename( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_prepare_rename").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?; @@ -1269,7 +1282,7 @@ pub(crate) fn handle_rename( params: RenameParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_rename").entered(); - let position = from_proto::file_position(&snap, params.text_document_position)?; + let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?); let mut change = snap.analysis.rename(position, ¶ms.new_name)?.map_err(to_proto::rename_error)?; @@ -1304,7 +1317,7 @@ pub(crate) fn handle_references( params: lsp_types::ReferenceParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_references").entered(); - let position = from_proto::file_position(&snap, params.text_document_position)?; + let position = try_default!(from_proto::file_position(&snap, params.text_document_position)?); let exclude_imports = snap.config.find_all_refs_exclude_imports(); let exclude_tests = snap.config.find_all_refs_exclude_tests(); @@ -1375,9 +1388,9 @@ pub(crate) fn handle_code_action( return Ok(None); } - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; - let frange = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; + let frange = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?); let source_root = snap.analysis.source_root_id(file_id)?; let mut assists_config = snap.config.assist(Some(source_root)); @@ -1455,7 +1468,8 @@ pub(crate) fn handle_code_action_resolve( return Err(invalid_params_error("code action without data".to_owned()).into()); }; - let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)?; + let file_id = from_proto::file_id(&snap, ¶ms.code_action_params.text_document.uri)? + .expect("we never provide code actions for excluded files"); if snap.file_version(file_id) != params.version { return Err(invalid_params_error("stale code action".to_owned()).into()); } @@ -1551,7 +1565,7 @@ pub(crate) fn handle_code_lens( return Ok(Some(Vec::default())); } - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let target_spec = TargetSpec::for_file(&snap, file_id)?; let annotations = snap.analysis.annotations( @@ -1613,7 +1627,8 @@ pub(crate) fn handle_document_highlight( params: lsp_types::DocumentHighlightParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_document_highlight").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params)?; + let position = + try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); let line_index = snap.file_line_index(position.file_id)?; let source_root = snap.analysis.source_root_id(position.file_id)?; @@ -1639,12 +1654,12 @@ pub(crate) fn handle_ssr( params: lsp_ext::SsrParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_ssr").entered(); - let selections = params + let selections = try_default!(params .selections .iter() .map(|range| from_proto::file_range(&snap, ¶ms.position.text_document, *range)) - .collect::, _>>()?; - let position = from_proto::file_position(&snap, params.position)?; + .collect::>, _>>()?); + let position = try_default!(from_proto::file_position(&snap, params.position)?); let source_change = snap.analysis.structural_search_replace( ¶ms.query, params.parse_only, @@ -1660,11 +1675,11 @@ pub(crate) fn handle_inlay_hints( ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_inlay_hints").entered(); let document_uri = ¶ms.text_document.uri; - let FileRange { file_id, range } = from_proto::file_range( + let FileRange { file_id, range } = try_default!(from_proto::file_range( &snap, &TextDocumentIdentifier::new(document_uri.to_owned()), params.range, - )?; + )?); let line_index = snap.file_line_index(file_id)?; let range = TextRange::new( range.start().min(line_index.index.len()), @@ -1744,7 +1759,8 @@ pub(crate) fn handle_call_hierarchy_prepare( params: CallHierarchyPrepareParams, ) -> anyhow::Result>> { let _p = tracing::info_span!("handle_call_hierarchy_prepare").entered(); - let position = from_proto::file_position(&snap, params.text_document_position_params)?; + let position = + try_default!(from_proto::file_position(&snap, params.text_document_position_params)?); let nav_info = match snap.analysis.call_hierarchy(position)? { None => return Ok(None), @@ -1769,7 +1785,7 @@ pub(crate) fn handle_call_hierarchy_incoming( let item = params.item; let doc = TextDocumentIdentifier::new(item.uri); - let frange = from_proto::file_range(&snap, &doc, item.selection_range)?; + let frange = try_default!(from_proto::file_range(&snap, &doc, item.selection_range)?); let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; let config = snap.config.call_hierarchy(); @@ -1807,7 +1823,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( let item = params.item; let doc = TextDocumentIdentifier::new(item.uri); - let frange = from_proto::file_range(&snap, &doc, item.selection_range)?; + let frange = try_default!(from_proto::file_range(&snap, &doc, item.selection_range)?); let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; let line_index = snap.file_line_index(fpos.file_id)?; @@ -1842,7 +1858,7 @@ pub(crate) fn handle_semantic_tokens_full( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_semantic_tokens_full").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; @@ -1872,7 +1888,7 @@ pub(crate) fn handle_semantic_tokens_full_delta( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_semantic_tokens_full_delta").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let text = snap.analysis.file_text(file_id)?; let line_index = snap.file_line_index(file_id)?; @@ -1915,7 +1931,7 @@ pub(crate) fn handle_semantic_tokens_range( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_semantic_tokens_range").entered(); - let frange = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; + let frange = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?); let text = snap.analysis.file_text(frange.file_id)?; let line_index = snap.file_line_index(frange.file_id)?; @@ -1940,7 +1956,7 @@ pub(crate) fn handle_open_docs( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { let _p = tracing::info_span!("handle_open_docs").entered(); - let position = from_proto::file_position(&snap, params)?; + let position = try_default!(from_proto::file_position(&snap, params)?); let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind { ProjectWorkspaceKind::Cargo { cargo, .. } @@ -1982,7 +1998,7 @@ pub(crate) fn handle_open_cargo_toml( params: lsp_ext::OpenCargoTomlParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_open_cargo_toml").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let cargo_spec = match TargetSpec::for_file(&snap, file_id)? { Some(TargetSpec::Cargo(it)) => it, @@ -2000,8 +2016,8 @@ pub(crate) fn handle_move_item( params: lsp_ext::MoveItemParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_move_item").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; - let range = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); + let range = try_default!(from_proto::file_range(&snap, ¶ms.text_document, params.range)?); let direction = match params.direction { lsp_ext::MoveItemDirection::Up => ide::Direction::Up, @@ -2022,7 +2038,7 @@ pub(crate) fn handle_view_recursive_memory_layout( params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { let _p = tracing::info_span!("handle_view_recursive_memory_layout").entered(); - let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let file_id = try_default!(from_proto::file_id(&snap, ¶ms.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; let offset = from_proto::offset(&line_index, params.position)?; @@ -2210,7 +2226,7 @@ fn run_rustfmt( text_document: TextDocumentIdentifier, range: Option, ) -> anyhow::Result>> { - let file_id = from_proto::file_id(snap, &text_document.uri)?; + let file_id = try_default!(from_proto::file_id(snap, &text_document.uri)?); let file = snap.analysis.file_text(file_id)?; // Determine the edition of the crate the file belongs to (if there's multiple, we pick the @@ -2275,7 +2291,7 @@ fn run_rustfmt( .into()); } - let frange = from_proto::file_range(snap, &text_document, range)?; + let frange = try_default!(from_proto::file_range(snap, &text_document, range)?); let start_line = line_index.index.line_col(frange.range.start()).line; let end_line = line_index.index.line_col(frange.range.end()).line; @@ -2416,15 +2432,15 @@ pub(crate) fn internal_testing_fetch_config( state: GlobalStateSnapshot, params: InternalTestingFetchConfigParams, ) -> anyhow::Result> { - let source_root = params - .text_document - .map(|it| { + let source_root = match params.text_document { + Some(it) => Some( state .analysis - .source_root_id(from_proto::file_id(&state, &it.uri)?) - .map_err(anyhow::Error::from) - }) - .transpose()?; + .source_root_id(try_default!(from_proto::file_id(&state, &it.uri)?)) + .map_err(anyhow::Error::from)?, + ), + None => None, + }; Ok(Some(match params.config { InternalTestingFetchConfigOption::AssistEmitMustUse => { InternalTestingFetchConfigResponse::AssistEmitMustUse( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 5cdc51a1c199..c6aa8ba17077 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -25,6 +25,14 @@ use vfs::{AbsPathBuf, VfsPath}; use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; +#[track_caller] +fn file_id(vfs: &vfs::Vfs, path: &VfsPath) -> vfs::FileId { + match vfs.file_id(path) { + Some((file_id, vfs::FileExcluded::No)) => file_id, + None | Some((_, vfs::FileExcluded::Yes)) => panic!("can't find virtual file for {path}"), + } +} + #[test] fn integrated_highlighting_benchmark() { if std::env::var("RUN_SLOW_BENCHES").is_err() { @@ -62,7 +70,7 @@ fn integrated_highlighting_benchmark() { let file_id = { let file = workspace_to_load.join(file); let path = VfsPath::from(AbsPathBuf::assert(file)); - vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) + file_id(&vfs, &path) }; { @@ -130,7 +138,7 @@ fn integrated_completion_benchmark() { let file_id = { let file = workspace_to_load.join(file); let path = VfsPath::from(AbsPathBuf::assert(file)); - vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) + file_id(&vfs, &path) }; // kick off parsing and index population @@ -324,7 +332,7 @@ fn integrated_diagnostics_benchmark() { let file_id = { let file = workspace_to_load.join(file); let path = VfsPath::from(AbsPathBuf::assert(file)); - vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) + file_id(&vfs, &path) }; let diagnostics_config = DiagnosticsConfig { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index 1221f7c7012e..27d6225cdb7e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -173,3 +173,14 @@ fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8; hasher.finalize() } + +#[doc(hidden)] +macro_rules! try_default_ { + ($it:expr $(,)?) => { + match $it { + Some(it) => it, + None => return Ok(Default::default()), + } + }; +} +pub(crate) use try_default_ as try_default; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs index 47e9961cf13f..6375a1a054b7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs @@ -9,7 +9,7 @@ use vfs::AbsPathBuf; use crate::{ global_state::GlobalStateSnapshot, line_index::{LineIndex, PositionEncoding}, - lsp_ext, + lsp_ext, try_default, }; pub(crate) fn abs_path(url: &lsp_types::Url) -> anyhow::Result { @@ -61,37 +61,44 @@ pub(crate) fn text_range( } } -pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> anyhow::Result { +/// Returns `None` if the file was excluded. +pub(crate) fn file_id( + snap: &GlobalStateSnapshot, + url: &lsp_types::Url, +) -> anyhow::Result> { snap.url_to_file_id(url) } +/// Returns `None` if the file was excluded. pub(crate) fn file_position( snap: &GlobalStateSnapshot, tdpp: lsp_types::TextDocumentPositionParams, -) -> anyhow::Result { - let file_id = file_id(snap, &tdpp.text_document.uri)?; +) -> anyhow::Result> { + let file_id = try_default!(file_id(snap, &tdpp.text_document.uri)?); let line_index = snap.file_line_index(file_id)?; let offset = offset(&line_index, tdpp.position)?; - Ok(FilePosition { file_id, offset }) + Ok(Some(FilePosition { file_id, offset })) } +/// Returns `None` if the file was excluded. pub(crate) fn file_range( snap: &GlobalStateSnapshot, text_document_identifier: &lsp_types::TextDocumentIdentifier, range: lsp_types::Range, -) -> anyhow::Result { +) -> anyhow::Result> { file_range_uri(snap, &text_document_identifier.uri, range) } +/// Returns `None` if the file was excluded. pub(crate) fn file_range_uri( snap: &GlobalStateSnapshot, document: &lsp_types::Url, range: lsp_types::Range, -) -> anyhow::Result { - let file_id = file_id(snap, document)?; +) -> anyhow::Result> { + let file_id = try_default!(file_id(snap, document)?); let line_index = snap.file_line_index(file_id)?; let range = text_range(&line_index, range)?; - Ok(FileRange { file_id, range }) + Ok(Some(FileRange { file_id, range })) } pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option { @@ -108,6 +115,7 @@ pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option Some(assist_kind) } +/// Returns `None` if the file was excluded. pub(crate) fn annotation( snap: &GlobalStateSnapshot, range: lsp_types::Range, @@ -121,7 +129,7 @@ pub(crate) fn annotation( return Ok(None); } let pos @ FilePosition { file_id, .. } = - file_position(snap, params.text_document_position_params)?; + try_default!(file_position(snap, params.text_document_position_params)?); let line_index = snap.file_line_index(file_id)?; Ok(Annotation { @@ -133,7 +141,7 @@ pub(crate) fn annotation( if snap.url_file_version(¶ms.text_document.uri) != Some(data.version) { return Ok(None); } - let pos @ FilePosition { file_id, .. } = file_position(snap, params)?; + let pos @ FilePosition { file_id, .. } = try_default!(file_position(snap, params)?); let line_index = snap.file_line_index(file_id)?; Ok(Annotation { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index ebc65373b522..f5d9469f2622 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -27,7 +27,10 @@ use crate::{ FetchWorkspaceResponse, GlobalState, }, hack_recover_crate_name, - handlers::dispatch::{NotificationDispatcher, RequestDispatcher}, + handlers::{ + dispatch::{NotificationDispatcher, RequestDispatcher}, + request::empty_diagnostic_report, + }, lsp::{ from_proto, to_proto, utils::{notification_is, Progress}, @@ -548,6 +551,9 @@ impl GlobalState { self.mem_docs .iter() .map(|path| vfs.file_id(path).unwrap()) + .filter_map(|(file_id, excluded)| { + (excluded == vfs::FileExcluded::No).then_some(file_id) + }) .filter(|&file_id| { let source_root = db.file_source_root(file_id); // Only publish diagnostics for files in the workspace, not from crates.io deps @@ -632,6 +638,9 @@ impl GlobalState { .mem_docs .iter() .map(|path| self.vfs.read().0.file_id(path).unwrap()) + .filter_map(|(file_id, excluded)| { + (excluded == vfs::FileExcluded::No).then_some(file_id) + }) .filter(|&file_id| { let source_root = db.file_source_root(file_id); !db.source_root(source_root).is_library @@ -879,7 +888,10 @@ impl GlobalState { self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| { let _p = tracing::info_span!("GlobalState::check_if_indexed").entered(); tracing::debug!(?uri, "handling uri"); - let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId"); + let Some(id) = from_proto::file_id(&snap, &uri).expect("unable to get FileId") + else { + return; + }; if let Ok(crates) = &snap.analysis.crates_for(id) { if crates.is_empty() { if snap.config.discover_workspace_config().is_some() { @@ -987,13 +999,14 @@ impl GlobalState { ); for diag in diagnostics { match url_to_file_id(&self.vfs.read().0, &diag.url) { - Ok(file_id) => self.diagnostics.add_check_diagnostic( + Ok(Some(file_id)) => self.diagnostics.add_check_diagnostic( id, &package_id, file_id, diag.diagnostic, diag.fix, ), + Ok(None) => {} Err(err) => { error!( "flycheck {id}: File with cargo diagnostic not found in VFS: {}", @@ -1115,17 +1128,7 @@ impl GlobalState { .on_latency_sensitive::(handlers::handle_semantic_tokens_range) // FIXME: Some of these NO_RETRY could be retries if the file they are interested didn't change. // All other request handlers - .on_with_vfs_default::(handlers::handle_document_diagnostics, || lsp_types::DocumentDiagnosticReportResult::Report( - lsp_types::DocumentDiagnosticReport::Full( - lsp_types::RelatedFullDocumentDiagnosticReport { - related_documents: None, - full_document_diagnostic_report: lsp_types::FullDocumentDiagnosticReport { - result_id: Some("rust-analyzer".to_owned()), - items: vec![], - }, - }, - ), - ), || lsp_server::ResponseError { + .on_with_vfs_default::(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError { code: lsp_server::ErrorCode::ServerCancelled as i32, message: "server cancelled the request".to_owned(), data: serde_json::to_value(lsp_types::DiagnosticServerCancellationData { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index d18e57704774..e3c003dbf8b1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -705,7 +705,9 @@ impl GlobalState { let load = |path: &AbsPath| { let vfs_path = vfs::VfsPath::from(path.to_path_buf()); self.crate_graph_file_dependencies.insert(vfs_path.clone()); - vfs.file_id(&vfs_path) + vfs.file_id(&vfs_path).and_then(|(file_id, excluded)| { + (excluded == vfs::FileExcluded::No).then_some(file_id) + }) }; ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load) diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs index a26444e9ea23..3feca512e55a 100644 --- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs +++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs @@ -100,6 +100,9 @@ pub enum FileState { Exists(u64), /// The file is deleted. Deleted, + /// The file was specifically excluded by the user. We still include excluded files + /// when they're opened (without their contents). + Excluded, } /// Changed file in the [`Vfs`]. @@ -164,10 +167,22 @@ pub enum ChangeKind { Delete, } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum FileExcluded { + Yes, + No, +} + impl Vfs { /// Id of the given path if it exists in the `Vfs` and is not deleted. - pub fn file_id(&self, path: &VfsPath) -> Option { - self.interner.get(path).filter(|&it| matches!(self.get(it), FileState::Exists(_))) + pub fn file_id(&self, path: &VfsPath) -> Option<(FileId, FileExcluded)> { + let file_id = self.interner.get(path)?; + let file_state = self.get(file_id); + match file_state { + FileState::Exists(_) => Some((file_id, FileExcluded::No)), + FileState::Deleted => None, + FileState::Excluded => Some((file_id, FileExcluded::Yes)), + } } /// File path corresponding to the given `file_id`. @@ -216,6 +231,7 @@ impl Vfs { } Change::Modify(v, new_hash) } + (FileState::Excluded, _) => return false, }; let mut set_data = |change_kind| { @@ -297,6 +313,13 @@ impl Vfs { fn get(&self, file_id: FileId) -> FileState { self.data[file_id.0 as usize] } + + /// We cannot ignore excluded files, because this will lead to errors when the client + /// requests semantic information for them, so we instead mark them specially. + pub fn insert_excluded_file(&mut self, path: VfsPath) { + let file_id = self.alloc_file_id(path); + self.data[file_id.0 as usize] = FileState::Excluded; + } } impl fmt::Debug for Vfs { From 720101002876ad6043735004b9ae20600a989fe8 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 8 Feb 2025 02:38:41 +0900 Subject: [PATCH 010/158] fix: Apply adjustments to proper expr when invoking `CoerceMany` --- .../rust-analyzer/crates/hir-ty/src/infer.rs | 24 +++++++++++- .../crates/hir-ty/src/infer/coerce.rs | 38 ++++++++++++++++--- .../crates/hir-ty/src/mir/eval/tests.rs | 33 ++++++++++++++++ .../crates/hir-ty/src/tests/coercion.rs | 3 +- 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 617ebba8811e..9f20117bf14f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1239,7 +1239,29 @@ impl<'a> InferenceContext<'a> { } fn write_expr_adj(&mut self, expr: ExprId, adjustments: Vec) { - self.result.expr_adjustments.insert(expr, adjustments); + if adjustments.is_empty() { + return; + } + match self.result.expr_adjustments.entry(expr) { + std::collections::hash_map::Entry::Occupied(mut entry) => { + match (&mut entry.get_mut()[..], &adjustments[..]) { + ( + [Adjustment { kind: Adjust::NeverToAny, target }], + [.., Adjustment { target: new_target, .. }], + ) => { + // NeverToAny coercion can target any type, so instead of adding a new + // adjustment on top we can change the target. + *target = new_target.clone(); + } + _ => { + *entry.get_mut() = adjustments; + } + } + } + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(adjustments); + } + } } fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs index d40816ba8ced..b490a31f68fa 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs @@ -163,10 +163,27 @@ impl CoerceMany { // type is a type variable and the new one is `!`, trying it the other // way around first would mean we make the type variable `!`, instead of // just marking it as possibly diverging. - if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes) { - self.final_ty = Some(res); - } else if let Ok(res) = ctx.coerce(expr, &self.merged_ty(), &expr_ty, CoerceNever::Yes) { + // + // - [Comment from rustc](https://github.com/rust-lang/rust/blob/5ff18d0eaefd1bd9ab8ec33dab2404a44e7631ed/compiler/rustc_hir_typeck/src/coercion.rs#L1334-L1335) + // First try to coerce the new expression to the type of the previous ones, + // but only if the new expression has no coercion already applied to it. + if expr.is_none_or(|expr| !ctx.result.expr_adjustments.contains_key(&expr)) { + if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes) { + self.final_ty = Some(res); + if let Some(expr) = expr { + self.expressions.push(expr); + } + return; + } + } + + if let Ok((adjustments, res)) = + ctx.coerce_inner(&self.merged_ty(), &expr_ty, CoerceNever::Yes) + { self.final_ty = Some(res); + for &e in &self.expressions { + ctx.write_expr_adj(e, adjustments.clone()); + } } else { match cause { CoercionCause::Expr(id) => { @@ -244,14 +261,23 @@ impl InferenceContext<'_> { // between places and values. coerce_never: CoerceNever, ) -> Result { - let from_ty = self.resolve_ty_shallow(from_ty); - let to_ty = self.resolve_ty_shallow(to_ty); - let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty, coerce_never)?; + let (adjustments, ty) = self.coerce_inner(from_ty, to_ty, coerce_never)?; if let Some(expr) = expr { self.write_expr_adj(expr, adjustments); } Ok(ty) } + + fn coerce_inner( + &mut self, + from_ty: &Ty, + to_ty: &Ty, + coerce_never: CoerceNever, + ) -> Result<(Vec, Ty), TypeError> { + let from_ty = self.resolve_ty_shallow(from_ty); + let to_ty = self.resolve_ty_shallow(to_ty); + self.table.coerce(&from_ty, &to_ty, coerce_never) + } } impl InferenceTable<'_> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index f1e86daea233..9625ae5f88ed 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -912,3 +912,36 @@ fn main() { "", ); } + +#[test] +fn regression_19021() { + check_pass( + r#" +//- minicore: deref +use core::ops::Deref; + +#[lang = "owned_box"] +struct Box(T); + +impl Deref for Box { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Foo; + +fn main() { + let x = Box(Foo); + let y = &Foo; + + || match x { + ref x => x, + _ => y, + }; +} +"#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs index 7992f1feeeb1..7e7c1f835c78 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs @@ -185,11 +185,10 @@ fn test() { let t = &mut 1; let x = match 1 { 1 => t as *mut i32, + //^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer) 2 => t as &i32, //^^^^^^^^^ expected *mut i32, got &'? i32 _ => t as *const i32, - // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer) - }; x; //^ type: *const i32 From 01794a4973c6e9b41af78cebd2f8adf9cdb36f9f Mon Sep 17 00:00:00 2001 From: Julian Eager Date: Sat, 8 Feb 2025 01:39:07 +0800 Subject: [PATCH 011/158] simplify panic_context --- .../crates/stdx/src/panic_context.rs | 56 +++++++++---------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs index 4ec74c0742aa..a35d50b78dfb 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs @@ -1,48 +1,44 @@ //! A micro-crate to enhance panic messages with context info. -//! -//! FIXME: upstream to ? use std::{cell::RefCell, panic, sync::Once}; -pub fn enter(context: String) -> PanicContext { - static ONCE: Once = Once::new(); - ONCE.call_once(PanicContext::init); - - with_ctx(|ctx| ctx.push(context)); - PanicContext { _priv: () } -} - +/// Dummy for leveraging RAII cleanup to pop frames. #[must_use] pub struct PanicContext { + // prevent arbitrary construction _priv: (), } -impl PanicContext { - #[allow(clippy::print_stderr)] - fn init() { - let default_hook = panic::take_hook(); - #[allow(deprecated)] - let hook = move |panic_info: &panic::PanicInfo<'_>| { - with_ctx(|ctx| { - if !ctx.is_empty() { - eprintln!("Panic context:"); - for frame in ctx.iter() { - eprintln!("> {frame}\n"); - } - } - default_hook(panic_info); - }); - }; - panic::set_hook(Box::new(hook)); - } -} - impl Drop for PanicContext { fn drop(&mut self) { with_ctx(|ctx| assert!(ctx.pop().is_some())); } } +pub fn enter(frame: String) -> PanicContext { + #[allow(clippy::print_stderr)] + fn set_hook() { + let default_hook = panic::take_hook(); + panic::set_hook(Box::new(move |panic_info| { + with_ctx(|ctx| { + if !ctx.is_empty() { + eprintln!("Panic context:"); + for frame in ctx.iter() { + eprintln!("> {frame}\n"); + } + } + }); + default_hook(panic_info); + })); + } + + static SET_HOOK: Once = Once::new(); + SET_HOOK.call_once(set_hook); + + with_ctx(|ctx| ctx.push(frame)); + PanicContext { _priv: () } +} + fn with_ctx(f: impl FnOnce(&mut Vec)) { thread_local! { static CTX: RefCell> = const { RefCell::new(Vec::new()) }; From 050c63a054bf29dbfc6161fb1ec12d89a319a87e Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 19 Jan 2025 23:58:49 +0100 Subject: [PATCH 012/158] Lower ast::Ident to hir::Path when lowering RangePats --- .../crates/hir-def/src/expr_store/lower.rs | 35 ++++---- .../crates/hir-def/src/expr_store/pretty.rs | 12 +-- .../crates/hir-def/src/expr_store/tests.rs | 88 ++++++++++++++++++- .../rust-analyzer/crates/hir-def/src/hir.rs | 14 +++ .../crates/hir-ty/src/mir/lower.rs | 29 +++--- .../hir-ty/src/mir/lower/pattern_matching.rs | 10 +-- .../rust-analyzer/crates/hir/src/semantics.rs | 1 + .../crates/hir/src/semantics/source_to_def.rs | 2 +- .../rust-analyzer/crates/ide-db/src/defs.rs | 6 +- 9 files changed, 139 insertions(+), 58 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 3f3beb21858c..e4fcf949d914 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1795,24 +1795,27 @@ impl ExprCollector<'_> { p.and_then(|it| { let ptr = PatPtr::new(&it); match &it { - ast::Pat::LiteralPat(it) => { - // Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) - Some(self.alloc_expr_from_pat( - Expr::Literal(pat_literal_to_hir(it)?.0), - ptr, - )) - } - ast::Pat::IdentPat(_) => Some(self.missing_expr()), - ast::Pat::PathPat(p) => { - if let Some(path) = p.path() { - if let Some(parsed) = self.parse_path(path) { - return Some( - self.alloc_expr_from_pat(Expr::Path(parsed), ptr), - ); - } + ast::Pat::LiteralPat(it) => Some(self.alloc_expr_from_pat( + Expr::Literal(pat_literal_to_hir(it)?.0), + ptr, + )), + ast::Pat::IdentPat(ident) => { + if ident.is_simple_ident() { + return ident + .name() + .and_then(|name| Some(name.as_name())) + .and_then(|hir_name| Some(Path::from(hir_name))) + .and_then(|path| { + Some(self.alloc_expr_from_pat(Expr::Path(path), ptr)) + }); } - Some(self.missing_expr()) + + None } + ast::Pat::PathPat(p) => p + .path() + .and_then(|path| self.parse_path(path)) + .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)), _ => None, } }) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index c28cfb24529c..82ad756dc2c6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -6,10 +6,7 @@ use itertools::Itertools; use span::Edition; use crate::{ - hir::{ - Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability, - Statement, - }, + hir::{Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement}, pretty::{print_generic_args, print_path, print_type_ref}, }; @@ -757,13 +754,6 @@ impl Printer<'_> { } } - fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) { - match literal_or_const { - LiteralOrConst::Literal(l) => self.print_literal(l), - LiteralOrConst::Const(c) => self.print_pat(*c), - } - } - fn print_literal(&mut self, literal: &Literal) { match literal { Literal::String(it) => w!(self, "{:?}", it), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 5ce9a67f9b6c..893645604418 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -1,10 +1,12 @@ mod block; +use base_db::Upcast; use expect_test::{expect, Expect}; use la_arena::RawIdx; use test_fixture::WithFixture; +use tracing::Instrument; -use crate::{test_db::TestDB, ModuleDefId}; +use crate::{db::InternDatabase, test_db::TestDB, ModuleDefId}; use super::*; @@ -446,7 +448,6 @@ fn foo() { ); } -#[test] fn skip_skips_body() { let (db, body, owner) = lower( r#" @@ -461,7 +462,45 @@ async fn foo(a: (), b: i32) -> u32 { .assert_eq(&printed); } -fn abc() { +fn test1() { + let (db, body, owner) = lower( + r#" +pub const L: i32 = 6; +mod x { + pub const R: i32 = 100; +} +const fn f(x: i32) -> i32 { + match x { + L..=x::R => x * 100, + -1..=5 => x * 10, + _ => x, + } +}"#, + ); + + let pat = body + .pats + .iter() + .find_map(|pat| { + if let Pat::Range { .. } = pat.1 { + return Some(pat.1); + } + + None + }) + .unwrap(); + + match pat { + Pat::Range { start, end } => { + dbg!(&body.exprs[start.unwrap()]); + dbg!(&body.exprs[end.unwrap()]); + } + _ => {} + } +} + +#[test] +fn test2() { let (db, body, owner) = lower( r#" pub const L: i32 = 6; @@ -471,7 +510,7 @@ mod x { const fn f(x: i32) -> i32 { match x { -1..=5 => x * 10, - L..=x::R => x * 100, + ::std::i32::MIN..=x::R => x * 100, _ => x, } }"#, @@ -503,3 +542,44 @@ const fn f(x: i32) -> i32 { } } } + +#[test] +fn test3() { + let (db, body, owner) = lower( + r#" +const A: u32 = 0; + +fn bar(v: u32) { + match v { + 0..=A => {} + _ => {} + } +}"#, + ); + + for (pat_id, pat) in body.pats.iter() { + match pat { + Pat::Range { start, end } => { + let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); + eprintln!("RANGE {}", pretty); + + if let Some(start) = start { + eprintln!("START"); + let expr = body.exprs[*start].clone(); + dbg!(expr); + } else { + eprintln!("START is None"); + } + + if let Some(end) = end { + eprintln!("END"); + let expr = body.exprs[*end].clone(); + dbg!(expr); + } else { + eprintln!("END is None"); + } + } + _ => {} + } + } +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index a964512beb2d..6aca610a9387 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -55,12 +55,26 @@ impl ExprOrPatId { } } + pub fn is_expr(&self) -> bool { + match self { + Self::ExprId(_) => true, + _ => false, + } + } + pub fn as_pat(self) -> Option { match self { Self::PatId(v) => Some(v), _ => None, } } + + pub fn is_pat(&self) -> bool { + match self { + Self::PatId(_) => true, + _ => false, + } + } } stdx::impl_from!(ExprId, PatId for ExprOrPatId); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index cc6ed122af4b..69b3b9c02a0c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -8,8 +8,8 @@ use hir_def::{ data::adt::{StructKind, VariantData}, expr_store::{Body, HygieneId}, hir::{ - ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, - LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, + ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm, + Pat, PatId, RecordFieldPat, RecordLitField, }, lang_item::{LangItem, LangItemTarget}, path::Path, @@ -1358,20 +1358,10 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(()) } - fn lower_literal_or_const_to_operand( - &mut self, - ty: Ty, - loc: &LiteralOrConst, - ) -> Result { - match loc { - LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l), - LiteralOrConst::Const(c) => { - let c = match &self.body.pats[*c] { - Pat::Path(p) => p, - _ => not_supported!( - "only `char` and numeric types are allowed in range patterns" - ), - }; + fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result { + match dbg!(&self.body.exprs[*loc]) { + Expr::Literal(l) => self.lower_literal_to_operand(ty, l), + Expr::Path(c) => { let edition = self.edition(); let unresolved_name = || MirLowerError::unresolved_path(self.db, c, edition, &self.body.types); @@ -1379,7 +1369,7 @@ impl<'ctx> MirLowerCtx<'ctx> { .resolver .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT) .ok_or_else(unresolved_name)?; - match pr { + dbg!(match dbg!(pr) { ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) @@ -1390,7 +1380,10 @@ impl<'ctx> MirLowerCtx<'ctx> { ResolveValueResult::Partial(_, _, _) => { not_supported!("associated constants in range pattern") } - } + }) + } + _ => { + not_supported!("only `char` and numeric types are allowed in range patterns"); } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index d78d15288adc..289175feefb1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -1,6 +1,6 @@ //! MIR lowering for patterns -use hir_def::{hir::LiteralOrConst, AssocItemId}; +use hir_def::{hir::ExprId, AssocItemId}; use crate::{ mir::{ @@ -207,7 +207,7 @@ impl MirLowerCtx<'_> { )? } Pat::Range { start, end } => { - let mut add_check = |l: &LiteralOrConst, binop| -> Result<()> { + let mut add_check = |l: &ExprId, binop| -> Result<()> { let lv = self.lower_literal_or_const_to_operand(self.infer[pattern].clone(), l)?; let else_target = *current_else.get_or_insert_with(|| self.new_basic_block()); @@ -234,12 +234,10 @@ impl MirLowerCtx<'_> { }; if mode == MatchingMode::Check { if let Some(start) = start { - // TODO - // add_check(start, BinOp::Le)?; + add_check(start, BinOp::Le)?; } if let Some(end) = end { - // TODO - // add_check(end, BinOp::Ge)?; + add_check(end, BinOp::Ge)?; } } (current, current_else) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 882a27182f01..90c6e7e7b3b4 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1640,6 +1640,7 @@ impl<'db> SemanticsImpl<'db> { } pub fn to_def(&self, src: &T) -> Option { + dbg!(std::any::type_name::()); let src = self.find_file(src.syntax()).with_value(src); T::to_def(self, src) } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 29d3736bae72..227a60bee242 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -347,7 +347,7 @@ impl SourceToDefCtx<'_, '_> { &mut self, src: InFile<&ast::IdentPat>, ) -> Option<(DefWithBodyId, BindingId)> { - let container = self.find_pat_or_label_container(src.syntax_ref())?; + let container = dbg!(self.find_pat_or_label_container(src.syntax_ref()))?; let (body, source_map) = self.db.body_with_source_map(container); let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index bad536080567..c45cb4294f0d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -20,6 +20,7 @@ use hir::{ }; use span::Edition; use stdx::{format_to, impl_from}; +use syntax::ToSmolStr; use syntax::{ ast::{self, AstNode}, match_ast, SyntaxKind, SyntaxNode, SyntaxToken, @@ -365,6 +366,7 @@ impl IdentClass { sema: &Semantics<'_, RootDatabase>, node: &SyntaxNode, ) -> Option { + dbg!(&node.to_smolstr()); match_ast! { match node { ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass), @@ -521,7 +523,7 @@ impl NameClass { let definition = match_ast! { match parent { ast::Item(it) => classify_item(sema, it)?, - ast::IdentPat(it) => return classify_ident_pat(sema, it), + ast::IdentPat(it) => return dbg!(classify_ident_pat(sema, it)), ast::Rename(it) => classify_rename(sema, it)?, ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?), ast::RecordField(it) => Definition::Field(sema.to_def(&it)?), @@ -574,7 +576,7 @@ impl NameClass { return Some(NameClass::ConstReference(Definition::from(def))); } - let local = sema.to_def(&ident_pat)?; + let local = dbg!(sema.to_def(&ident_pat))?; let pat_parent = ident_pat.syntax().parent(); if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) { if record_pat_field.name_ref().is_none() { From e402c8cd7e2a0f108f10a9718c28f76afe06d6e6 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 18:53:37 +0100 Subject: [PATCH 013/158] make SourceAnalyzer::pat_id return ExprOrPatId Not all patterns are mapped to Pats. As such, it was necessary to change the ret type Option to Option --- .../crates/hir-def/src/expr_store/tests.rs | 5 +-- .../crates/hir/src/source_analyzer.rs | 32 ++++++++++--------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 893645604418..73eed744715d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -1,12 +1,9 @@ mod block; -use base_db::Upcast; +use crate::{test_db::TestDB, ModuleDefId}; use expect_test::{expect, Expect}; use la_arena::RawIdx; use test_fixture::WithFixture; -use tracing::Instrument; - -use crate::{db::InternDatabase, test_db::TestDB, ModuleDefId}; use super::*; diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index cf756c679750..06fcebad65d1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -18,7 +18,7 @@ use hir_def::{ scope::{ExprScopes, ScopeId}, Body, BodySourceMap, HygieneId, }, - hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId}, + hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lang_item::LangItem, lower::LowerCtx, nameres::MacroSubNs, @@ -139,15 +139,15 @@ impl SourceAnalyzer { sm.node_expr(src.as_ref()) } - fn pat_id(&self, pat: &ast::Pat) -> Option { + fn pat_id(&self, pat: &ast::Pat) -> Option { // FIXME: macros, see `expr_id` let src = InFile { file_id: self.file_id, value: pat }; - self.body_source_map()?.node_pat(src).and_then(ExprOrPatId::as_pat) + self.body_source_map()?.node_pat(src) } fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; - if let Pat::Bind { id, .. } = self.body()?.pats[pat_id] { + if let Pat::Bind { id, .. } = self.body()?.pats[pat_id.as_pat()?] { Some(id) } else { None @@ -212,8 +212,10 @@ impl SourceAnalyzer { ) -> Option<(Type, Option)> { let pat_id = self.pat_id(pat)?; let infer = self.infer.as_ref()?; - let coerced = - infer.pat_adjustments.get(&pat_id).and_then(|adjusts| adjusts.last().cloned()); + let coerced = infer + .pat_adjustments + .get(&pat_id.as_pat()?) + .and_then(|adjusts| adjusts.last().cloned()); let ty = infer[pat_id].clone(); let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) @@ -248,7 +250,7 @@ impl SourceAnalyzer { ) -> Option { let id = self.pat_id(&pat.clone().into())?; let infer = self.infer.as_ref()?; - infer.binding_modes.get(id).map(|bm| match bm { + infer.binding_modes.get(id.as_pat()?).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { @@ -266,7 +268,7 @@ impl SourceAnalyzer { Some( infer .pat_adjustments - .get(&pat_id)? + .get(&pat_id.as_pat()?)? .iter() .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone())) .collect(), @@ -649,10 +651,10 @@ impl SourceAnalyzer { let field_name = field.field_name()?.as_name(); let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let pat_id = self.pat_id(&record_pat.into())?; - let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?; + let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id.as_pat()?)?; let variant_data = variant.variant_data(db.upcast()); let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; - let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?; + let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); Some(( @@ -684,7 +686,7 @@ impl SourceAnalyzer { ) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; let body = self.body()?; - let path = match &body[pat_id] { + let path = match &body[pat_id.as_pat()?] { Pat::Path(path) => path, _ => return None, }; @@ -783,7 +785,7 @@ impl SourceAnalyzer { prefer_value_ns = true; } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) { let pat_id = self.pat_id(&path_pat.into())?; - if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id) { + if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id.as_pat()?) { let (assoc, subst) = match assoc { AssocItemId::ConstId(const_id) => { let (konst, subst) = @@ -807,7 +809,7 @@ impl SourceAnalyzer { return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst))); } if let Some(VariantId::EnumVariantId(variant)) = - infer.variant_resolution_for_pat(pat_id) + infer.variant_resolution_for_pat(pat_id.as_pat()?) { return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None)); } @@ -824,7 +826,7 @@ impl SourceAnalyzer { || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from); if let Some(pat) = record_pat.or_else(tuple_struct_pat) { let pat_id = self.pat_id(&pat)?; - let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id); + let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?); if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat { return Some(( PathResolution::Def(ModuleDef::Variant(variant.into())), @@ -1043,7 +1045,7 @@ impl SourceAnalyzer { let body = self.body()?; let infer = self.infer.as_ref()?; - let pat_id = self.pat_id(&pattern.clone().into())?; + let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?; let substs = infer.type_of_pat[pat_id].as_adt()?.1; let (variant, missing_fields, _exhaustive) = From 3e9633b4611ec61b81611963dde154508192e8b3 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 19:21:41 +0100 Subject: [PATCH 014/158] resolve_bind_pat_to_const does not early return if expr --- .../crates/hir-def/src/expr_store/tests.rs | 114 +++--------------- .../crates/hir/src/source_analyzer.rs | 15 ++- 2 files changed, 29 insertions(+), 100 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 73eed744715d..b84043af687f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -1,6 +1,6 @@ mod block; -use crate::{test_db::TestDB, ModuleDefId}; +use crate::{hir::MatchArm, test_db::TestDB, ModuleDefId}; use expect_test::{expect, Expect}; use la_arena::RawIdx; use test_fixture::WithFixture; @@ -459,8 +459,9 @@ async fn foo(a: (), b: i32) -> u32 { .assert_eq(&printed); } -fn test1() { - let (db, body, owner) = lower( +#[test] +fn range_bounds_are_hir_exprs() { + let (_, body, _) = lower( r#" pub const L: i32 = 6; mod x { @@ -468,115 +469,34 @@ mod x { } const fn f(x: i32) -> i32 { match x { - L..=x::R => x * 100, -1..=5 => x * 10, + L..=x::R => x * 100, _ => x, } }"#, ); - let pat = body - .pats + let mtch_arms = body + .exprs .iter() - .find_map(|pat| { - if let Pat::Range { .. } = pat.1 { - return Some(pat.1); + .find_map(|(_, expr)| { + if let Expr::Match { arms, .. } = expr { + return Some(arms); } None }) .unwrap(); - match pat { + let MatchArm { pat, .. } = mtch_arms[1]; + match body.pats[pat] { Pat::Range { start, end } => { - dbg!(&body.exprs[start.unwrap()]); - dbg!(&body.exprs[end.unwrap()]); + let hir_start = &body.exprs[start.unwrap()]; + let hir_end = &body.exprs[end.unwrap()]; + + assert!(matches!(hir_start, Expr::Path { .. })); + assert!(matches!(hir_end, Expr::Path { .. })); } _ => {} } } - -#[test] -fn test2() { - let (db, body, owner) = lower( - r#" -pub const L: i32 = 6; -mod x { - pub const R: i32 = 100; -} -const fn f(x: i32) -> i32 { - match x { - -1..=5 => x * 10, - ::std::i32::MIN..=x::R => x * 100, - _ => x, - } -}"#, - ); - - for (pat_id, pat) in body.pats.iter() { - match pat { - Pat::Range { start, end } => { - let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); - eprintln!("RANGE {}", pretty); - - if let Some(start) = start { - eprintln!("START"); - let expr = body.exprs[*start].clone(); - dbg!(expr); - } else { - eprintln!("START is None"); - } - - if let Some(end) = end { - eprintln!("END"); - let expr = body.exprs[*end].clone(); - dbg!(expr); - } else { - eprintln!("END is None"); - } - } - _ => {} - } - } -} - -#[test] -fn test3() { - let (db, body, owner) = lower( - r#" -const A: u32 = 0; - -fn bar(v: u32) { - match v { - 0..=A => {} - _ => {} - } -}"#, - ); - - for (pat_id, pat) in body.pats.iter() { - match pat { - Pat::Range { start, end } => { - let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); - eprintln!("RANGE {}", pretty); - - if let Some(start) = start { - eprintln!("START"); - let expr = body.exprs[*start].clone(); - dbg!(expr); - } else { - eprintln!("START is None"); - } - - if let Some(end) = end { - eprintln!("END"); - let expr = body.exprs[*end].clone(); - dbg!(expr); - } else { - eprintln!("END is None"); - } - } - _ => {} - } - } -} diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 06fcebad65d1..8a1e4fba6b70 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -686,10 +686,19 @@ impl SourceAnalyzer { ) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; let body = self.body()?; - let path = match &body[pat_id.as_pat()?] { - Pat::Path(path) => path, - _ => return None, + + let path = if pat_id.is_pat() { + match &body[pat_id.as_pat()?] { + Pat::Path(path) => path, + _ => return None, + } + } else { + match &body[pat_id.as_expr()?] { + Expr::Path(path) => path, + _ => return None, + } }; + let res = resolve_hir_path(db, &self.resolver, path, HygieneId::ROOT, TypesMap::EMPTY)?; match res { PathResolution::Def(def) => Some(def), From 0d544cf622f8bfcfc7c324a4ff5709e27604726b Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 19:30:41 +0100 Subject: [PATCH 015/158] Remove dbg lines --- src/tools/rust-analyzer/crates/hir/src/semantics.rs | 1 - src/tools/rust-analyzer/crates/ide-db/src/defs.rs | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 90c6e7e7b3b4..882a27182f01 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1640,7 +1640,6 @@ impl<'db> SemanticsImpl<'db> { } pub fn to_def(&self, src: &T) -> Option { - dbg!(std::any::type_name::()); let src = self.find_file(src.syntax()).with_value(src); T::to_def(self, src) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index c45cb4294f0d..bad536080567 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -20,7 +20,6 @@ use hir::{ }; use span::Edition; use stdx::{format_to, impl_from}; -use syntax::ToSmolStr; use syntax::{ ast::{self, AstNode}, match_ast, SyntaxKind, SyntaxNode, SyntaxToken, @@ -366,7 +365,6 @@ impl IdentClass { sema: &Semantics<'_, RootDatabase>, node: &SyntaxNode, ) -> Option { - dbg!(&node.to_smolstr()); match_ast! { match node { ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass), @@ -523,7 +521,7 @@ impl NameClass { let definition = match_ast! { match parent { ast::Item(it) => classify_item(sema, it)?, - ast::IdentPat(it) => return dbg!(classify_ident_pat(sema, it)), + ast::IdentPat(it) => return classify_ident_pat(sema, it), ast::Rename(it) => classify_rename(sema, it)?, ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?), ast::RecordField(it) => Definition::Field(sema.to_def(&it)?), @@ -576,7 +574,7 @@ impl NameClass { return Some(NameClass::ConstReference(Definition::from(def))); } - let local = dbg!(sema.to_def(&ident_pat))?; + let local = sema.to_def(&ident_pat)?; let pat_parent = ident_pat.syntax().parent(); if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) { if record_pat_field.name_ref().is_none() { From fcc796829e0cbd189af0e29f283fb433a148ad11 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 21:14:16 +0100 Subject: [PATCH 016/158] Remove fixme and add a missing test attribute --- src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs | 1 - src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index e4fcf949d914..2be7b9963bb6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1789,7 +1789,6 @@ impl ExprCollector<'_> { } None => Pat::Missing, }, - // FIXME: implement in a way that also builds source map and calculates assoc resolutions in type inference. ast::Pat::RangePat(p) => { let mut range_part_lower = |p: Option| -> Option { p.and_then(|it| { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index b84043af687f..16bf46d3e3f9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -445,6 +445,7 @@ fn foo() { ); } +#[test] fn skip_skips_body() { let (db, body, owner) = lower( r#" From bf2f2c4d71915a9b98d64e75c31264665a0399a7 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 23:22:39 +0100 Subject: [PATCH 017/158] Fix clippy errors --- .../crates/hir-def/src/expr_store/lower.rs | 8 ++++---- src/tools/rust-analyzer/crates/hir-def/src/hir.rs | 10 ++-------- src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs | 6 +++--- .../crates/hir/src/semantics/source_to_def.rs | 2 +- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 2be7b9963bb6..95dd1e53ae78 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1802,10 +1802,10 @@ impl ExprCollector<'_> { if ident.is_simple_ident() { return ident .name() - .and_then(|name| Some(name.as_name())) - .and_then(|hir_name| Some(Path::from(hir_name))) - .and_then(|path| { - Some(self.alloc_expr_from_pat(Expr::Path(path), ptr)) + .map(|name| name.as_name()) + .map(Path::from) + .map(|path| { + self.alloc_expr_from_pat(Expr::Path(path), ptr) }); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 6aca610a9387..494644d8eff9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -56,10 +56,7 @@ impl ExprOrPatId { } pub fn is_expr(&self) -> bool { - match self { - Self::ExprId(_) => true, - _ => false, - } + matches!(self, Self::ExprId(_)) } pub fn as_pat(self) -> Option { @@ -70,10 +67,7 @@ impl ExprOrPatId { } pub fn is_pat(&self) -> bool { - match self { - Self::PatId(_) => true, - _ => false, - } + matches!(self, Self::PatId(_)) } } stdx::impl_from!(ExprId, PatId for ExprOrPatId); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 69b3b9c02a0c..f3f564459dea 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1359,7 +1359,7 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result { - match dbg!(&self.body.exprs[*loc]) { + match &self.body.exprs[*loc] { Expr::Literal(l) => self.lower_literal_to_operand(ty, l), Expr::Path(c) => { let edition = self.edition(); @@ -1369,7 +1369,7 @@ impl<'ctx> MirLowerCtx<'ctx> { .resolver .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT) .ok_or_else(unresolved_name)?; - dbg!(match dbg!(pr) { + match pr { ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) @@ -1380,7 +1380,7 @@ impl<'ctx> MirLowerCtx<'ctx> { ResolveValueResult::Partial(_, _, _) => { not_supported!("associated constants in range pattern") } - }) + } } _ => { not_supported!("only `char` and numeric types are allowed in range patterns"); diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 227a60bee242..29d3736bae72 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -347,7 +347,7 @@ impl SourceToDefCtx<'_, '_> { &mut self, src: InFile<&ast::IdentPat>, ) -> Option<(DefWithBodyId, BindingId)> { - let container = dbg!(self.find_pat_or_label_container(src.syntax_ref()))?; + let container = self.find_pat_or_label_container(src.syntax_ref())?; let (body, source_map) = self.db.body_with_source_map(container); let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; From bc5f61c76914aa192c04e8c5ecfff07dd37adf11 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 3 Feb 2025 12:07:52 +0100 Subject: [PATCH 018/158] Check if PatPtr resolves to ExprId --- .../crates/hir-def/src/expr_store/lower.rs | 22 ++++------ .../crates/hir/src/diagnostics.rs | 30 ++++++------- src/tools/rust-analyzer/crates/hir/src/lib.rs | 2 +- .../crates/hir/src/source_analyzer.rs | 43 +++++++++++-------- 4 files changed, 49 insertions(+), 48 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 95dd1e53ae78..6e505a6b1126 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1798,23 +1798,17 @@ impl ExprCollector<'_> { Expr::Literal(pat_literal_to_hir(it)?.0), ptr, )), - ast::Pat::IdentPat(ident) => { - if ident.is_simple_ident() { - return ident - .name() - .map(|name| name.as_name()) - .map(Path::from) - .map(|path| { - self.alloc_expr_from_pat(Expr::Path(path), ptr) - }); - } - - None - } + ast::Pat::IdentPat(ident) if ident.is_simple_ident() => ident + .name() + .map(|name| name.as_name()) + .map(Path::from) + .map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)), ast::Pat::PathPat(p) => p .path() .and_then(|path| self.parse_path(path)) .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)), + // We only need to handle literal, ident (if bare) and path patterns here, + // as any other pattern as a range pattern operand is semantically invalid. _ => None, } }) @@ -2545,7 +2539,7 @@ impl ExprCollector<'_> { fn alloc_expr_from_pat(&mut self, expr: Expr, ptr: PatPtr) -> ExprId { let src = self.expander.in_file(ptr); - let id = self.body.exprs.alloc(expr); + let id = self.store.exprs.alloc(expr); self.source_map.pat_map.insert(src, id.into()); self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_right)); id diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 9a5e50af0790..5876529df96a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -6,7 +6,7 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_def::{ - body::ExprOrPatPtr, + expr_store::ExprOrPatPtr, hir::ExprOrPatId, path::{hir_segment_to_ast_segment, ModPath}, type_ref::TypesSourceMap, @@ -116,14 +116,14 @@ diagnostics![ #[derive(Debug)] pub struct BreakOutsideOfLoop { - pub expr: InFile>>, + pub expr: InFile, pub is_break: bool, pub bad_value_break: bool, } #[derive(Debug)] pub struct TypedHole { - pub expr: InFile>>, + pub expr: InFile, pub expected: Type, } @@ -222,26 +222,26 @@ pub struct NoSuchField { #[derive(Debug)] pub struct PrivateAssocItem { - pub expr_or_pat: InFile>>, + pub expr_or_pat: InFile, pub item: AssocItem, } #[derive(Debug)] pub struct MismatchedTupleStructPatArgCount { - pub expr_or_pat: InFile>>, + pub expr_or_pat: InFile, pub expected: usize, pub found: usize, } #[derive(Debug)] pub struct ExpectedFunction { - pub call: InFile>>, + pub call: InFile, pub found: Type, } #[derive(Debug)] pub struct UnresolvedField { - pub expr: InFile>>, + pub expr: InFile, pub receiver: Type, pub name: Name, pub method_with_same_name_exists: bool, @@ -249,7 +249,7 @@ pub struct UnresolvedField { #[derive(Debug)] pub struct UnresolvedMethodCall { - pub expr: InFile>>, + pub expr: InFile, pub receiver: Type, pub name: Name, pub field_with_same_name: Option, @@ -258,17 +258,17 @@ pub struct UnresolvedMethodCall { #[derive(Debug)] pub struct UnresolvedAssocItem { - pub expr_or_pat: InFile>>, + pub expr_or_pat: InFile, } #[derive(Debug)] pub struct UnresolvedIdent { - pub node: InFile<(AstPtr>, Option)>, + pub node: InFile<(ExprOrPatPtr, Option)>, } #[derive(Debug)] pub struct PrivateField { - pub expr: InFile>>, + pub expr: InFile, pub field: Field, } @@ -281,7 +281,7 @@ pub enum UnsafeLint { #[derive(Debug)] pub struct MissingUnsafe { - pub node: InFile>>, + pub node: InFile, pub lint: UnsafeLint, pub reason: UnsafetyReason, } @@ -322,7 +322,7 @@ pub struct NonExhaustiveLet { #[derive(Debug)] pub struct TypeMismatch { - pub expr_or_pat: InFile>>, + pub expr_or_pat: InFile, pub expected: Type, pub actual: Type, } @@ -396,13 +396,13 @@ pub struct RemoveUnnecessaryElse { #[derive(Debug)] pub struct CastToUnsized { - pub expr: InFile>>, + pub expr: InFile, pub cast_ty: Type, } #[derive(Debug)] pub struct InvalidCast { - pub expr: InFile>>, + pub expr: InFile, pub error: CastError, pub expr_ty: Type, pub cast_ty: Type, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 26b2819913e2..8b8203acb146 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2003,7 +2003,7 @@ impl DefWithBody { match source_map.expr_syntax(node) { Ok(node) => acc.push( MissingUnsafe { - node: node.map(|it| it.wrap_left()), + node, lint: UnsafeLint::DeprecatedSafe2024, reason: UnsafetyReason::UnsafeFnCall, } diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 8a1e4fba6b70..9e7f2c194807 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -210,13 +210,20 @@ impl SourceAnalyzer { db: &dyn HirDatabase, pat: &ast::Pat, ) -> Option<(Type, Option)> { - let pat_id = self.pat_id(pat)?; + let expr_or_pat_id = self.pat_id(pat)?; let infer = self.infer.as_ref()?; - let coerced = infer - .pat_adjustments - .get(&pat_id.as_pat()?) - .and_then(|adjusts| adjusts.last().cloned()); - let ty = infer[pat_id].clone(); + let coerced = match expr_or_pat_id { + ExprOrPatId::ExprId(idx) => infer + .expr_adjustments + .get(&idx) + .and_then(|adjusts| adjusts.last().cloned()) + .map(|adjust| adjust.target), + ExprOrPatId::PatId(idx) => { + infer.pat_adjustments.get(&idx).and_then(|adjusts| adjusts.last().cloned()) + } + }; + + let ty = infer[expr_or_pat_id].clone(); let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) } @@ -684,19 +691,18 @@ impl SourceAnalyzer { db: &dyn HirDatabase, pat: &ast::IdentPat, ) -> Option { - let pat_id = self.pat_id(&pat.clone().into())?; + let expr_or_pat_id = self.pat_id(&pat.clone().into())?; let body = self.body()?; - let path = if pat_id.is_pat() { - match &body[pat_id.as_pat()?] { - Pat::Path(path) => path, - _ => return None, - } - } else { - match &body[pat_id.as_expr()?] { + let path = match expr_or_pat_id { + ExprOrPatId::ExprId(idx) => match &body[idx] { Expr::Path(path) => path, _ => return None, - } + }, + ExprOrPatId::PatId(idx) => match &body[idx] { + Pat::Path(path) => path, + _ => return None, + }, }; let res = resolve_hir_path(db, &self.resolver, path, HygieneId::ROOT, TypesMap::EMPTY)?; @@ -793,8 +799,9 @@ impl SourceAnalyzer { } prefer_value_ns = true; } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) { - let pat_id = self.pat_id(&path_pat.into())?; - if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id.as_pat()?) { + let expr_or_pat_id = self.pat_id(&path_pat.into())?; + if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_or_pat_id) + { let (assoc, subst) = match assoc { AssocItemId::ConstId(const_id) => { let (konst, subst) = @@ -818,7 +825,7 @@ impl SourceAnalyzer { return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst))); } if let Some(VariantId::EnumVariantId(variant)) = - infer.variant_resolution_for_pat(pat_id.as_pat()?) + infer.variant_resolution_for_expr_or_pat(expr_or_pat_id) { return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None)); } From 9bd9bcf4964ee3eeed2bbb99567619c8fb3d70d6 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Feb 2025 14:12:00 -0500 Subject: [PATCH 019/158] fix off-by-one error --- .../rust-analyzer/.github/workflows/ci.yaml | 6 +- .../rust-analyzer/src/handlers/request.rs | 3 +- .../rust-analyzer/tests/slow-tests/main.rs | 74 ++++++++++++++++++- 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index ec33009239c4..81b55712d7f3 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -64,7 +64,11 @@ jobs: run: | rustup update --no-self-update ${{ env.RUST_CHANNEL }} rustup default ${{ env.RUST_CHANNEL }} - rustup component add --toolchain ${{ env.RUST_CHANNEL }} rustfmt rust-src + rustup component add --toolchain ${{ env.RUST_CHANNEL }} rust-src + # We always use a nightly rustfmt, regardless of channel, because we need + # --file-lines. + rustup toolchain add nightly --profile minimal + rustup component add --toolchain nightly rustfmt # https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json - name: Install Rust Problem Matcher if: matrix.os == 'ubuntu-latest' diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index ed028f1d37b6..37e4a4940ba7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -2284,7 +2284,8 @@ fn run_rustfmt( cmd.arg( json!([{ "file": "stdin", - "range": [start_line, end_line] + // LineCol is 0-based, but rustfmt is 1-based. + "range": [start_line + 1, end_line + 1] }]) .to_string(), ); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 2b3c0a47a220..7f95641746e9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -21,12 +21,14 @@ use lsp_types::{ notification::DidOpenTextDocument, request::{ CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest, - InlayHintRequest, InlayHintResolveRequest, WillRenameFiles, WorkspaceSymbolRequest, + InlayHintRequest, InlayHintResolveRequest, RangeFormatting, WillRenameFiles, + WorkspaceSymbolRequest, }, CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, - DocumentFormattingParams, FileRename, FormattingOptions, GotoDefinitionParams, HoverParams, - InlayHint, InlayHintLabel, InlayHintParams, PartialResultParams, Position, Range, - RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, WorkDoneProgressParams, + DocumentFormattingParams, DocumentRangeFormattingParams, FileRename, FormattingOptions, + GotoDefinitionParams, HoverParams, InlayHint, InlayHintLabel, InlayHintParams, + PartialResultParams, Position, Range, RenameFilesParams, TextDocumentItem, + TextDocumentPositionParams, WorkDoneProgressParams, }; use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams}; use serde_json::json; @@ -660,6 +662,70 @@ fn main() {} ); } +#[test] +fn test_format_document_range() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +fn main() { + let unit_offsets_cache = collect(dwarf.units ()) ?; +} +"#, + ) + .with_config(serde_json::json!({ + "rustfmt": { + "overrideCommand": [ "rustfmt", "+nightly", ], + "rangeFormatting": { "enable": true } + }, + })) + .server() + .wait_until_workspace_is_loaded(); + + server.request::( + DocumentRangeFormattingParams { + range: Range { + end: Position { line: 1, character: 0 }, + start: Position { line: 1, character: 0 }, + }, + text_document: server.doc_id("src/lib.rs"), + options: FormattingOptions { + tab_size: 4, + insert_spaces: false, + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, + properties: HashMap::new(), + }, + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([ + { + "newText": "", + "range": { + "start": { "character": 48, "line": 1 }, + "end": { "character": 50, "line": 1 }, + }, + }, + { + "newText": "", + "range": { + "start": { "character": 53, "line": 1 }, + "end": { "character": 55, "line": 1 }, + }, + } + ]), + ); +} + #[test] fn test_missing_module_code_action() { if skip_slow_tests() { From d2459e5c1ef0c24582f8b84ae150204d9ab2d1f8 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Feb 2025 14:12:21 -0500 Subject: [PATCH 020/158] fix target dir test --- .../rust-analyzer/crates/rust-analyzer/src/config.rs | 4 +++- src/tools/rust-analyzer/crates/test-utils/src/lib.rs | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e915e55722bb..2e9bb8c08e2f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -3798,8 +3798,10 @@ mod tests { (config, _, _) = config.apply_change(change); assert_eq!(config.cargo_targetDir(None), &Some(TargetDirectory::UseSubdirectory(true))); + let target = + Utf8PathBuf::from(std::env::var("CARGO_TARGET_DIR").unwrap_or("target".to_owned())); assert!( - matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("target/rust-analyzer"))) + matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(target.join("rust-analyzer"))) ); } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/lib.rs b/src/tools/rust-analyzer/crates/test-utils/src/lib.rs index 36be9937d3fe..e7279fa1f661 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/lib.rs @@ -396,12 +396,19 @@ pub fn skip_slow_tests() -> bool { if should_skip { eprintln!("ignoring slow test"); } else { - let path = project_root().join("./target/.slow_tests_cookie"); + let path = target_dir().join(".slow_tests_cookie"); fs::write(path, ".").unwrap(); } should_skip } +pub fn target_dir() -> Utf8PathBuf { + match std::env::var("CARGO_TARGET_DIR") { + Ok(target) => Utf8PathBuf::from(target), + Err(_) => project_root().join("target"), + } +} + /// Returns the path to the root directory of `rust-analyzer` project. pub fn project_root() -> Utf8PathBuf { let dir = env!("CARGO_MANIFEST_DIR"); From b5ad702c621ca92a2a24088b6fb2e7fcf30638e9 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 10 Feb 2025 01:28:28 +0200 Subject: [PATCH 021/158] Censor cfg_attr for attribute macros This is not documented (and I discovered that from experimenting and looking at the compiler's source code), but cfg_attrs *on the same level* as the attribute macro should be processed before it is expanded. cfg_attrs *below* should not (and this is contrary to what happens with derive macros, where both should be processed). --- .../src/macro_expansion_tests/proc_macros.rs | 20 ++++++- .../crates/hir-expand/src/cfg_process.rs | 56 +++++++++++-------- .../crates/test-fixture/src/lib.rs | 44 ++++++++++++++- 3 files changed, 96 insertions(+), 24 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index 70e3e1ed4e9c..a43c0eb9d70b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -5,7 +5,7 @@ //! in-memory macros. use expect_test::expect; -use crate::macro_expansion_tests::check; +use crate::macro_expansion_tests::{check, check_errors}; #[test] fn attribute_macro_attr_censoring() { @@ -216,3 +216,21 @@ struct S; #[doc = "doc attr"] struct S;"##]], ); } + +#[test] +fn cfg_evaluated_before_attr_macros() { + check_errors( + r#" +//- proc_macros: disallow_cfg + +use proc_macros::disallow_cfg; + +#[disallow_cfg] #[cfg(false)] fn foo() {} +// True cfg are kept. +// #[disallow_cfg] #[cfg(true)] fn bar() {} +#[disallow_cfg] #[cfg_attr(false, inline)] fn baz() {} +#[disallow_cfg] #[cfg_attr(true, inline)] fn qux() {} + "#, + expect![[r#""#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs index 01a3103af82d..626a82ae08ea 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs @@ -201,9 +201,6 @@ pub(crate) fn process_cfg_attrs( MacroDefKind::BuiltInAttr(_, expander) => expander.is_derive(), _ => false, }; - if !is_derive { - return None; - } let mut remove = FxHashSet::default(); let item = ast::Item::cast(node.clone())?; @@ -220,28 +217,43 @@ pub(crate) fn process_cfg_attrs( } } } - match item { - ast::Item::Struct(it) => match it.field_list()? { - ast::FieldList::RecordFieldList(fields) => { - process_has_attrs_with_possible_comma(db, fields.fields(), loc.krate, &mut remove)?; + + if is_derive { + // Only derives get their code cfg-clean, normal attribute macros process only the cfg at their level + // (cfg_attr is handled above, cfg is handled in the def map). + match item { + ast::Item::Struct(it) => match it.field_list()? { + ast::FieldList::RecordFieldList(fields) => { + process_has_attrs_with_possible_comma( + db, + fields.fields(), + loc.krate, + &mut remove, + )?; + } + ast::FieldList::TupleFieldList(fields) => { + process_has_attrs_with_possible_comma( + db, + fields.fields(), + loc.krate, + &mut remove, + )?; + } + }, + ast::Item::Enum(it) => { + process_enum(db, it.variant_list()?, loc.krate, &mut remove)?; } - ast::FieldList::TupleFieldList(fields) => { - process_has_attrs_with_possible_comma(db, fields.fields(), loc.krate, &mut remove)?; + ast::Item::Union(it) => { + process_has_attrs_with_possible_comma( + db, + it.record_field_list()?.fields(), + loc.krate, + &mut remove, + )?; } - }, - ast::Item::Enum(it) => { - process_enum(db, it.variant_list()?, loc.krate, &mut remove)?; + // FIXME: Implement for other items if necessary. As we do not support #[cfg_eval] yet, we do not need to implement it for now + _ => {} } - ast::Item::Union(it) => { - process_has_attrs_with_possible_comma( - db, - it.record_field_list()?.fields(), - loc.krate, - &mut remove, - )?; - } - // FIXME: Implement for other items if necessary. As we do not support #[cfg_eval] yet, we do not need to implement it for now - _ => {} } Some(remove) } diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index ca596583590a..613f27c7958b 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -17,7 +17,7 @@ use hir_expand::{ tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter}, FileRange, }; -use intern::Symbol; +use intern::{sym, Symbol}; use rustc_hash::FxHashMap; use span::{Edition, EditionedFileId, FileId, Span}; use stdx::itertools::Itertools; @@ -511,6 +511,21 @@ pub fn issue_18898(_attr: TokenStream, input: TokenStream) -> TokenStream { disabled: false, }, ), + ( + r#" +#[proc_macro_attribute] +pub fn disallow_cfg(_attr: TokenStream, input: TokenStream) -> TokenStream { + input +} +"# + .into(), + ProcMacro { + name: Symbol::intern("disallow_cfg"), + kind: ProcMacroKind::Attr, + expander: sync::Arc::new(DisallowCfgProcMacroExpander), + disabled: false, + }, + ), ]) } @@ -865,3 +880,30 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander { }) } } + +// Reads ident type within string quotes, for issue #17479. +#[derive(Debug)] +struct DisallowCfgProcMacroExpander; +impl ProcMacroExpander for DisallowCfgProcMacroExpander { + fn expand( + &self, + subtree: &TopSubtree, + _: Option<&TopSubtree>, + _: &Env, + _: Span, + _: Span, + _: Span, + _: Option, + ) -> Result { + for tt in subtree.token_trees().flat_tokens() { + if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt { + if ident.sym == sym::cfg || ident.sym == sym::cfg_attr { + return Err(ProcMacroExpansionError::Panic( + "cfg or cfg_attr found in DisallowCfgProcMacroExpander".to_owned(), + )); + } + } + } + Ok(subtree.clone()) + } +} From ef8574aa0463c513a2b77a62b339f73fa8e5e9e0 Mon Sep 17 00:00:00 2001 From: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com> Date: Mon, 10 Feb 2025 10:50:11 +0900 Subject: [PATCH 022/158] Shadowing BuiltinType by Module Signed-off-by: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com> --- .../crates/hir/src/source_analyzer.rs | 39 ++++++++++++++++++- .../crates/ide/src/goto_definition.rs | 34 ++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 23e7518883b5..c687e2d8a0cf 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -866,7 +866,8 @@ impl SourceAnalyzer { // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are // trying to resolve foo::bar. - if path.parent_path().is_some() { + if let Some(parent_path) = path.parent_path() { + let parent_hir_path = Path::from_src(&mut ctx, parent_path); return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &types_map) { None if meta_path.is_some() => path .first_segment() @@ -876,6 +877,42 @@ impl SourceAnalyzer { .map(PathResolution::ToolModule) }) .map(|it| (it, None)), + // Case the type name conflict with use module, + // e.g. + // ``` + // use std::str; + // fn main() { + // str::from_utf8(); // as module std::str + // str::len(); // as primitive type str + // str::no_exist_item(); // as primitive type str + // } + // ``` + Some(it) if matches!(it, PathResolution::Def(ModuleDef::BuiltinType(_))) => { + if let (Some(mod_path), Some(parent_hir_path)) = + (hir_path.mod_path(), parent_hir_path) + { + if let Some(ModuleDefId::ModuleId(id)) = self + .resolver + .resolve_module_path_in_items(db.upcast(), mod_path) + .take_types() + { + let parent_hir_name = + parent_hir_path.segments().get(1).map(|it| it.name); + let module = crate::Module { id }; + if module + .scope(db, None) + .into_iter() + .any(|(name, _)| Some(&name) == parent_hir_name) + { + return Some(( + PathResolution::Def(ModuleDef::Module(module)), + None, + )); + }; + } + } + Some((it, None)) + } // FIXME: We do not show substitutions for parts of path, because this is really complex // due to the interactions with associated items of `impl`s and associated items of associated // types. diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index bdafb701ff53..60a904233a9a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -3290,4 +3290,38 @@ fn main() { "#, ); } + + #[test] + fn shadow_builtin_type_by_module() { + check( + r#" +mod Foo{ +pub mod str { + // ^^^ + pub fn foo() {} +} +} + +fn main() { + use Foo::str; + let s = st$0r::foo(); +} +"#, + ); + } + + #[test] + fn not_goto_module_because_str_is_builtin_type() { + check( + r#" +mod str { +pub fn foo() {} +} + +fn main() { + let s = st$0r::f(); +} +"#, + ); + } } From 8f8e1c6f08ec25ea42b74c44b0a5c93fffb84610 Mon Sep 17 00:00:00 2001 From: austaras Date: Sun, 9 Feb 2025 20:40:41 +0800 Subject: [PATCH 023/158] pass struct fields to chalk --- .../crates/hir-ty/src/chalk_db.rs | 20 +++++++-------- .../crates/hir-ty/src/tests/coercion.rs | 25 ++++++++++++++++--- .../crates/hir-ty/src/tests/traits.rs | 12 ++++----- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index c8ff6cba3dd1..6d4753ea3898 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -768,23 +768,21 @@ pub(crate) fn adt_datum_query( phantom_data, }; - // this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it - let _variant_id_to_fields = |id: VariantId| { + let variant_id_to_fields = |id: VariantId| { let variant_data = &id.variant_data(db.upcast()); - let fields = if variant_data.fields().is_empty() { + let fields = if variant_data.fields().is_empty() || bound_vars_subst.is_empty(Interner) { vec![] } else { - let field_types = db.field_types(id); - variant_data - .fields() - .iter() - .map(|(idx, _)| field_types[idx].clone().substitute(Interner, &bound_vars_subst)) - .filter(|it| !it.contains_unknown()) - .collect() + // HACK: provide full struct type info slows down rust-analyzer by quite a bit unfortunately, + // so we trick chalk into thinking that our struct impl Unsize + if let Some(ty) = bound_vars_subst.at(Interner, 0).ty(Interner) { + vec![ty.clone()] + } else { + vec![] + } }; rust_ir::AdtVariantDatum { fields } }; - let variant_id_to_fields = |_: VariantId| rust_ir::AdtVariantDatum { fields: vec![] }; let (kind, variants) = match adt_id { hir_def::AdtId::StructId(id) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs index 7992f1feeeb1..a5978d905b11 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs @@ -536,7 +536,7 @@ fn test() { #[test] fn coerce_unsize_generic() { - check( + check_no_mismatches( r#" //- minicore: coerce_unsized struct Foo { t: T }; @@ -544,9 +544,7 @@ struct Bar(Foo); fn test() { let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; - //^^^^^^^^^^^^^^^^^^^^^ expected &'? Foo<[usize]>, got &'? Foo<[i32; 3]> let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); - //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &'? Bar<[usize]>, got &'? Bar<[i32; 3]> } "#, ); @@ -958,3 +956,24 @@ fn f() { "#, ); } + +#[test] +fn coerce_nested_unsized_struct() { + check_types( + r#" +//- minicore: fn, coerce_unsized, dispatch_from_dyn, sized +use core::marker::Unsize; + +struct Foo(T); + +fn need(_: &Foo i32>) { +} + +fn test() { + let callback = |x| x; + //^ i32 + need(&Foo(callback)); +} +"#, + ) +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index dda7bfb2baf9..f0eb41b1ce72 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -4694,21 +4694,21 @@ fn f() { Struct::::IS_SEND; //^^^^^^^^^^^^^^^^^^^^Yes Struct::::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^{unknown} Struct::<*const T>::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown} Enum::::IS_SEND; //^^^^^^^^^^^^^^^^^^Yes Enum::::IS_SEND; - //^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^{unknown} Enum::<*const T>::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^^^^^^{unknown} Union::::IS_SEND; //^^^^^^^^^^^^^^^^^^^Yes Union::::IS_SEND; - //^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^{unknown} Union::<*const T>::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown} PhantomData::::IS_SEND; //^^^^^^^^^^^^^^^^^^^^^^^^^Yes PhantomData::::IS_SEND; From e1c6eade1619e2b84b39d61811407afc1f82fd12 Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 9 Feb 2025 04:11:23 -0800 Subject: [PATCH 024/158] move pattern migration setup/emitting to a separate module --- compiler/rustc_mir_build/src/errors.rs | 3 - .../src/thir/pattern/migration.rs | 87 +++++++++++++++++++ .../rustc_mir_build/src/thir/pattern/mod.rs | 75 ++++------------ 3 files changed, 104 insertions(+), 61 deletions(-) create mode 100644 compiler/rustc_mir_build/src/thir/pattern/migration.rs diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 07bdc59756aa..9f8b52165ab9 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1113,9 +1113,6 @@ pub(crate) struct Rust2024IncompatiblePatSugg { pub(crate) suggestion: Vec<(Span, String)>, pub(crate) ref_pattern_count: usize, pub(crate) binding_mode_count: usize, - /// Internal state: the ref-mutability of the default binding mode at the subpattern being - /// lowered, with the span where it was introduced. `None` for a by-value default mode. - pub(crate) default_mode_span: Option<(Span, ty::Mutability)>, /// Labels for where incompatibility-causing by-ref default binding modes were introduced. pub(crate) default_mode_labels: FxIndexMap, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs new file mode 100644 index 000000000000..be1ebd57d118 --- /dev/null +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -0,0 +1,87 @@ +//! Automatic migration of Rust 2021 patterns to a form valid in both Editions 2021 and 2024. + +use rustc_data_structures::fx::FxIndexMap; +use rustc_errors::MultiSpan; +use rustc_hir::HirId; +use rustc_lint as lint; +use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt}; +use rustc_span::Span; + +use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg}; +use crate::fluent_generated as fluent; + +/// For patterns flagged for migration during HIR typeck, this handles constructing and emitting +/// a diagnostic suggestion. +pub(super) struct PatMigration<'a> { + pub(super) suggestion: Vec<(Span, String)>, + pub(super) ref_pattern_count: usize, + pub(super) binding_mode_count: usize, + /// Internal state: the ref-mutability of the default binding mode at the subpattern being + /// lowered, with the span where it was introduced. `None` for a by-value default mode. + pub(super) default_mode_span: Option<(Span, ty::Mutability)>, + /// Labels for where incompatibility-causing by-ref default binding modes were introduced. + // FIXME(ref_pat_eat_one_layer_2024_structural): To track the default binding mode, we duplicate + // logic from HIR typeck (in order to avoid needing to store all changes to the dbm in + // TypeckResults). Since the default binding mode acts differently under this feature gate, the + // labels will be wrong. + pub(super) default_mode_labels: FxIndexMap, + /// Information collected from typeck, including spans for subpatterns invalid in Rust 2024. + pub(super) info: &'a Rust2024IncompatiblePatInfo, +} + +impl<'a> PatMigration<'a> { + pub(super) fn new(info: &'a Rust2024IncompatiblePatInfo) -> Self { + PatMigration { + suggestion: Vec::new(), + ref_pattern_count: 0, + binding_mode_count: 0, + default_mode_span: None, + default_mode_labels: Default::default(), + info, + } + } + + /// On Rust 2024, this emits a hard error. On earlier Editions, this emits the + /// future-incompatibility lint `rust_2024_incompatible_pat`. + pub(super) fn emit<'tcx>(self, tcx: TyCtxt<'tcx>, pat_id: HirId) { + let mut spans = + MultiSpan::from_spans(self.info.primary_labels.iter().map(|(span, _)| *span).collect()); + for (span, label) in self.info.primary_labels.iter() { + spans.push_span_label(*span, label.clone()); + } + let sugg = Rust2024IncompatiblePatSugg { + suggest_eliding_modes: self.info.suggest_eliding_modes, + suggestion: self.suggestion, + ref_pattern_count: self.ref_pattern_count, + binding_mode_count: self.binding_mode_count, + default_mode_labels: self.default_mode_labels, + }; + // If a relevant span is from at least edition 2024, this is a hard error. + let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); + if is_hard_error { + let mut err = + tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); + if let Some(info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { + // provide the same reference link as the lint + err.note(format!("for more information, see {}", info.reference)); + } + err.arg("bad_modifiers", self.info.bad_modifiers); + err.arg("bad_ref_pats", self.info.bad_ref_pats); + err.arg("is_hard_error", true); + err.subdiagnostic(sugg); + err.emit(); + } else { + tcx.emit_node_span_lint( + lint::builtin::RUST_2024_INCOMPATIBLE_PAT, + pat_id, + spans, + Rust2024IncompatiblePat { + sugg, + bad_modifiers: self.info.bad_modifiers, + bad_ref_pats: self.info.bad_ref_pats, + is_hard_error, + }, + ); + } + } +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 83fef7b0de6f..5535ac9bd636 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -2,18 +2,17 @@ mod check_match; mod const_to_pat; +mod migration; use std::cmp::Ordering; use std::sync::Arc; use rustc_abi::{FieldIdx, Integer}; -use rustc_errors::MultiSpan; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd}; use rustc_index::Idx; -use rustc_lint as lint; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, @@ -26,8 +25,8 @@ use rustc_span::{ErrorGuaranteed, Span}; use tracing::{debug, instrument}; pub(crate) use self::check_match::check_match; +use self::migration::PatMigration; use crate::errors::*; -use crate::fluent_generated as fluent; struct PatCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -35,7 +34,7 @@ struct PatCtxt<'a, 'tcx> { typeck_results: &'a ty::TypeckResults<'tcx>, /// Used by the Rust 2024 migration lint. - rust_2024_migration_suggestion: Option, + rust_2024_migration: Option>, } pub(super) fn pat_from_hir<'a, 'tcx>( @@ -44,59 +43,19 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box> { - let migration_info = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id); let mut pcx = PatCtxt { tcx, typing_env, typeck_results, - rust_2024_migration_suggestion: migration_info.and_then(|info| { - Some(Rust2024IncompatiblePatSugg { - suggest_eliding_modes: info.suggest_eliding_modes, - suggestion: Vec::new(), - ref_pattern_count: 0, - binding_mode_count: 0, - default_mode_span: None, - default_mode_labels: Default::default(), - }) - }), + rust_2024_migration: typeck_results + .rust_2024_migration_desugared_pats() + .get(pat.hir_id) + .map(PatMigration::new), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); - if let Some(info) = migration_info - && let Some(sugg) = pcx.rust_2024_migration_suggestion - { - let mut spans = - MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect()); - for (span, label) in &info.primary_labels { - spans.push_span_label(*span, label.clone()); - } - // If a relevant span is from at least edition 2024, this is a hard error. - let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); - if is_hard_error { - let mut err = - tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); - if let Some(lint_info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { - // provide the same reference link as the lint - err.note(format!("for more information, see {}", lint_info.reference)); - } - err.arg("bad_modifiers", info.bad_modifiers); - err.arg("bad_ref_pats", info.bad_ref_pats); - err.arg("is_hard_error", true); - err.subdiagnostic(sugg); - err.emit(); - } else { - tcx.emit_node_span_lint( - lint::builtin::RUST_2024_INCOMPATIBLE_PAT, - pat.hir_id, - spans, - Rust2024IncompatiblePat { - sugg, - bad_modifiers: info.bad_modifiers, - bad_ref_pats: info.bad_ref_pats, - is_hard_error, - }, - ); - } + if let Some(m) = pcx.rust_2024_migration { + m.emit(tcx, pat.hir_id); } result } @@ -107,7 +66,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); let mut opt_old_mode_span = None; - if let Some(s) = &mut self.rust_2024_migration_suggestion + if let Some(s) = &mut self.rust_2024_migration && !adjustments.is_empty() { let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { @@ -117,7 +76,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { mutbl }); - if !s.suggest_eliding_modes { + if !s.info.suggest_eliding_modes { let suggestion_str: String = implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect(); s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); @@ -169,7 +128,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }) }); - if let Some(s) = &mut self.rust_2024_migration_suggestion + if let Some(s) = &mut self.rust_2024_migration && let Some(old_mode_span) = opt_old_mode_span { s.default_mode_span = old_mode_span; @@ -368,7 +327,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Ref(subpattern, _) => { // Track the default binding mode for the Rust 2024 migration suggestion. - let old_mode_span = self.rust_2024_migration_suggestion.as_mut().and_then(|s| { + let old_mode_span = self.rust_2024_migration.as_mut().and_then(|s| { if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span { // If this eats a by-ref default binding mode, label the binding mode. s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); @@ -376,7 +335,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { s.default_mode_span.take() }); let subpattern = self.lower_pattern(subpattern); - if let Some(s) = &mut self.rust_2024_migration_suggestion { + if let Some(s) = &mut self.rust_2024_migration { s.default_mode_span = old_mode_span; } PatKind::Deref { subpattern } @@ -408,19 +367,19 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .get(pat.hir_id) .expect("missing binding mode"); - if let Some(s) = &mut self.rust_2024_migration_suggestion { + if let Some(s) = &mut self.rust_2024_migration { if explicit_ba != hir::BindingMode::NONE && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span { // If this overrides a by-ref default binding mode, label the binding mode. s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); // If our suggestion is to elide redundnt modes, this will be one of them. - if s.suggest_eliding_modes { + if s.info.suggest_eliding_modes { s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new())); s.binding_mode_count += 1; } } - if !s.suggest_eliding_modes + if !s.info.suggest_eliding_modes && explicit_ba.0 == ByRef::No && let ByRef::Yes(mutbl) = mode.0 { From f1c287f45bace992857b0a9c850da6f1a849a6f7 Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 9 Feb 2025 07:11:08 -0800 Subject: [PATCH 025/158] move pattern migration internals to the `migration` module --- .../src/thir/pattern/migration.rs | 113 ++++++++++++++++-- .../rustc_mir_build/src/thir/pattern/mod.rs | 67 ++--------- 2 files changed, 114 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs index be1ebd57d118..bd7787b643d5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/migration.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -2,10 +2,11 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::MultiSpan; -use rustc_hir::HirId; +use rustc_hir::{BindingMode, ByRef, HirId, Mutability}; use rustc_lint as lint; -use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt}; -use rustc_span::Span; +use rustc_middle::span_bug; +use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt}; +use rustc_span::{Ident, Span}; use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg}; use crate::fluent_generated as fluent; @@ -13,20 +14,20 @@ use crate::fluent_generated as fluent; /// For patterns flagged for migration during HIR typeck, this handles constructing and emitting /// a diagnostic suggestion. pub(super) struct PatMigration<'a> { - pub(super) suggestion: Vec<(Span, String)>, - pub(super) ref_pattern_count: usize, - pub(super) binding_mode_count: usize, + suggestion: Vec<(Span, String)>, + ref_pattern_count: usize, + binding_mode_count: usize, /// Internal state: the ref-mutability of the default binding mode at the subpattern being /// lowered, with the span where it was introduced. `None` for a by-value default mode. - pub(super) default_mode_span: Option<(Span, ty::Mutability)>, + default_mode_span: Option<(Span, ty::Mutability)>, /// Labels for where incompatibility-causing by-ref default binding modes were introduced. // FIXME(ref_pat_eat_one_layer_2024_structural): To track the default binding mode, we duplicate // logic from HIR typeck (in order to avoid needing to store all changes to the dbm in // TypeckResults). Since the default binding mode acts differently under this feature gate, the // labels will be wrong. - pub(super) default_mode_labels: FxIndexMap, + default_mode_labels: FxIndexMap, /// Information collected from typeck, including spans for subpatterns invalid in Rust 2024. - pub(super) info: &'a Rust2024IncompatiblePatInfo, + info: &'a Rust2024IncompatiblePatInfo, } impl<'a> PatMigration<'a> { @@ -84,4 +85,98 @@ impl<'a> PatMigration<'a> { ); } } + + /// Tracks when we're lowering a pattern that implicitly dereferences the scrutinee. + /// This should only be called when the pattern type adjustments list `adjustments` is + /// non-empty. Returns the prior default binding mode; this should be followed by a call to + /// [`PatMigration::leave_ref`] to restore it when we leave the pattern. + pub(super) fn visit_implicit_derefs<'tcx>( + &mut self, + pat_span: Span, + adjustments: &[Ty<'tcx>], + ) -> Option<(Span, Mutability)> { + let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { + let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { + span_bug!(pat_span, "pattern implicitly dereferences a non-ref type"); + }; + mutbl + }); + + if !self.info.suggest_eliding_modes { + // If we can't fix the pattern by eliding modifiers, we'll need to make the pattern + // fully explicit. i.e. we'll need to suggest reference patterns for this. + let suggestion_str: String = + implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect(); + self.suggestion.push((pat_span.shrink_to_lo(), suggestion_str)); + self.ref_pattern_count += adjustments.len(); + } + + // Remember if this changed the default binding mode, in case we want to label it. + let min_mutbl = implicit_deref_mutbls.min().unwrap(); + if self.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) { + // This changes the default binding mode to `ref` or `ref mut`. Return the old mode so + // it can be reinstated when we leave the pattern. + self.default_mode_span.replace((pat_span, min_mutbl)) + } else { + // This does not change the default binding mode; it was already `ref` or `ref mut`. + self.default_mode_span + } + } + + /// Tracks the default binding mode when we're lowering a `&` or `&mut` pattern. + /// Returns the prior default binding mode; this should be followed by a call to + /// [`PatMigration::leave_ref`] to restore it when we leave the pattern. + pub(super) fn visit_explicit_deref(&mut self) -> Option<(Span, Mutability)> { + if let Some((default_mode_span, default_ref_mutbl)) = self.default_mode_span { + // If this eats a by-ref default binding mode, label the binding mode. + self.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + } + // Set the default binding mode to by-value and return the old default binding mode so it + // can be reinstated when we leave the pattern. + self.default_mode_span.take() + } + + /// Restores the default binding mode after lowering a pattern that could change it. + /// This should follow a call to either [`PatMigration::visit_explicit_deref`] or + /// [`PatMigration::visit_implicit_derefs`]. + pub(super) fn leave_ref(&mut self, old_mode_span: Option<(Span, Mutability)>) { + self.default_mode_span = old_mode_span + } + + /// Determines if a binding is relevant to the diagnostic and adjusts the notes/suggestion if + /// so. Bindings are relevant if they have a modifier under a by-ref default mode (invalid in + /// Rust 2024) or if we need to suggest a binding modifier for them. + pub(super) fn visit_binding( + &mut self, + pat_span: Span, + mode: BindingMode, + explicit_ba: BindingMode, + ident: Ident, + ) { + if explicit_ba != BindingMode::NONE + && let Some((default_mode_span, default_ref_mutbl)) = self.default_mode_span + { + // If this overrides a by-ref default binding mode, label the binding mode. + self.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + // If our suggestion is to elide redundnt modes, this will be one of them. + if self.info.suggest_eliding_modes { + self.suggestion.push((pat_span.with_hi(ident.span.lo()), String::new())); + self.binding_mode_count += 1; + } + } + if !self.info.suggest_eliding_modes + && explicit_ba.0 == ByRef::No + && let ByRef::Yes(mutbl) = mode.0 + { + // If we can't fix the pattern by eliding modifiers, we'll need to make the pattern + // fully explicit. i.e. we'll need to suggest reference patterns for this. + let sugg_str = match mutbl { + Mutability::Not => "ref ", + Mutability::Mut => "ref mut ", + }; + self.suggestion + .push((pat_span.with_lo(ident.span.lo()).shrink_to_lo(), sugg_str.to_owned())); + self.binding_mode_count += 1; + } + } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 5535ac9bd636..5734eb1a0d81 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer}; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd}; +use rustc_hir::{self as hir, RangeEnd}; use rustc_index::Idx; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ @@ -65,31 +65,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let adjustments: &[Ty<'tcx>] = self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); + // Track the default binding mode for the Rust 2024 migration suggestion. let mut opt_old_mode_span = None; if let Some(s) = &mut self.rust_2024_migration && !adjustments.is_empty() { - let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { - let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { - span_bug!(pat.span, "pattern implicitly dereferences a non-ref type"); - }; - mutbl - }); - - if !s.info.suggest_eliding_modes { - let suggestion_str: String = - implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect(); - s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); - s.ref_pattern_count += adjustments.len(); - } - - // Remember if this changed the default binding mode, in case we want to label it. - let min_mutbl = implicit_deref_mutbls.min().unwrap(); - if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) { - opt_old_mode_span = Some(s.default_mode_span); - s.default_mode_span = Some((pat.span, min_mutbl)); - } - }; + opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments); + } // When implicit dereferences have been inserted in this pattern, the unadjusted lowered // pattern has the type that results *after* dereferencing. For example, in this code: @@ -129,9 +111,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }); if let Some(s) = &mut self.rust_2024_migration - && let Some(old_mode_span) = opt_old_mode_span + && !adjustments.is_empty() { - s.default_mode_span = old_mode_span; + s.leave_ref(opt_old_mode_span); } adjusted_pat @@ -327,16 +309,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Ref(subpattern, _) => { // Track the default binding mode for the Rust 2024 migration suggestion. - let old_mode_span = self.rust_2024_migration.as_mut().and_then(|s| { - if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span { - // If this eats a by-ref default binding mode, label the binding mode. - s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); - } - s.default_mode_span.take() - }); + let opt_old_mode_span = + self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref()); let subpattern = self.lower_pattern(subpattern); if let Some(s) = &mut self.rust_2024_migration { - s.default_mode_span = old_mode_span; + s.leave_ref(opt_old_mode_span); } PatKind::Deref { subpattern } } @@ -368,31 +345,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .expect("missing binding mode"); if let Some(s) = &mut self.rust_2024_migration { - if explicit_ba != hir::BindingMode::NONE - && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span - { - // If this overrides a by-ref default binding mode, label the binding mode. - s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); - // If our suggestion is to elide redundnt modes, this will be one of them. - if s.info.suggest_eliding_modes { - s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new())); - s.binding_mode_count += 1; - } - } - if !s.info.suggest_eliding_modes - && explicit_ba.0 == ByRef::No - && let ByRef::Yes(mutbl) = mode.0 - { - let sugg_str = match mutbl { - Mutability::Not => "ref ", - Mutability::Mut => "ref mut ", - }; - s.suggestion.push(( - pat.span.with_lo(ident.span.lo()).shrink_to_lo(), - sugg_str.to_owned(), - )); - s.binding_mode_count += 1; - } + s.visit_binding(pat.span, mode, explicit_ba, ident); } // A ref x pattern is the same node used for x, and as such it has From 724b85ef11213e128985a22c073c7373d80fd792 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 10 Feb 2025 15:47:31 +0200 Subject: [PATCH 026/158] Fix postfix completions inside macros Previously the receiver text was taken directly from the AST, which in macros is missing trivia, leading to corruption (or just unintended replacement of user code). Now we upmap the range, and extract the original file text in it. --- .../ide-completion/src/completions/postfix.rs | 91 +++++++++++++------ 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index 2c39a8fdfed7..28e2853096e0 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -2,17 +2,18 @@ mod format_like; -use hir::ItemInNs; -use ide_db::text_edit::TextEdit; +use base_db::SourceDatabase; +use hir::{ItemInNs, Semantics}; use ide_db::{ documentation::{Documentation, HasDocs}, imports::insert_use::ImportScope, + text_edit::TextEdit, ty_filter::TryEnum, - SnippetCap, + RootDatabase, SnippetCap, }; use stdx::never; use syntax::{ - ast::{self, make, AstNode, AstToken}, + ast::{self, AstNode, AstToken}, SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR}, TextRange, TextSize, }; @@ -48,7 +49,8 @@ pub(crate) fn complete_postfix( }; let expr_ctx = &dot_access.ctx; - let receiver_text = get_receiver_text(dot_receiver, receiver_is_ambiguous_float_literal); + let receiver_text = + get_receiver_text(&ctx.sema, dot_receiver, receiver_is_ambiguous_float_literal); let cap = match ctx.config.snippet_cap { Some(it) => it, @@ -172,13 +174,15 @@ pub(crate) fn complete_postfix( // The rest of the postfix completions create an expression that moves an argument, // so it's better to consider references now to avoid breaking the compilation - let (dot_receiver, node_to_replace_with) = include_references(dot_receiver); - let receiver_text = - get_receiver_text(&node_to_replace_with, receiver_is_ambiguous_float_literal); - let postfix_snippet = match build_postfix_snippet_builder(ctx, cap, &dot_receiver) { - Some(it) => it, - None => return, - }; + let (dot_receiver_including_refs, prefix) = include_references(dot_receiver); + let mut receiver_text = + get_receiver_text(&ctx.sema, dot_receiver, receiver_is_ambiguous_float_literal); + receiver_text.insert_str(0, &prefix); + let postfix_snippet = + match build_postfix_snippet_builder(ctx, cap, &dot_receiver_including_refs) { + Some(it) => it, + None => return, + }; if !ctx.config.snippets.is_empty() { add_custom_postfix_completions(acc, ctx, &postfix_snippet, &receiver_text); @@ -222,7 +226,7 @@ pub(crate) fn complete_postfix( postfix_snippet("call", "function(expr)", &format!("${{1}}({receiver_text})")) .add_to(acc, ctx.db); - if let Some(parent) = dot_receiver.syntax().parent().and_then(|p| p.parent()) { + if let Some(parent) = dot_receiver_including_refs.syntax().parent().and_then(|p| p.parent()) { if matches!(parent.kind(), STMT_LIST | EXPR_STMT) { postfix_snippet("let", "let", &format!("let $0 = {receiver_text};")) .add_to(acc, ctx.db); @@ -231,9 +235,9 @@ pub(crate) fn complete_postfix( } } - if let ast::Expr::Literal(literal) = dot_receiver.clone() { + if let ast::Expr::Literal(literal) = dot_receiver_including_refs.clone() { if let Some(literal_text) = ast::String::cast(literal.token()) { - add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text); + add_format_like_completions(acc, ctx, &dot_receiver_including_refs, cap, &literal_text); } } @@ -260,14 +264,20 @@ pub(crate) fn complete_postfix( } } -fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String { - let mut text = if receiver_is_ambiguous_float_literal { - let text = receiver.syntax().text(); - let without_dot = ..text.len() - TextSize::of('.'); - text.slice(without_dot).to_string() - } else { - receiver.to_string() +fn get_receiver_text( + sema: &Semantics<'_, RootDatabase>, + receiver: &ast::Expr, + receiver_is_ambiguous_float_literal: bool, +) -> String { + // Do not just call `receiver.to_string()`, as that will mess up whitespaces inside macros. + let Some(mut range) = sema.original_range_opt(receiver.syntax()) else { + return receiver.to_string(); }; + if receiver_is_ambiguous_float_literal { + range.range = TextRange::at(range.range.start(), range.range.len() - TextSize::of('.')) + } + let file_text = sema.db.file_text(range.file_id.file_id()); + let mut text = file_text[range.range].to_owned(); // The receiver texts should be interpreted as-is, as they are expected to be // normal Rust expressions. @@ -284,7 +294,7 @@ fn escape_snippet_bits(text: &mut String) { stdx::replace(text, '$', "\\$"); } -fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) { +fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) { let mut resulting_element = initial_element.clone(); while let Some(field_expr) = resulting_element.syntax().parent().and_then(ast::FieldExpr::cast) @@ -292,7 +302,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) { resulting_element = ast::Expr::from(field_expr); } - let mut new_element_opt = initial_element.clone(); + let mut prefix = String::new(); while let Some(parent_deref_element) = resulting_element.syntax().parent().and_then(ast::PrefixExpr::cast) @@ -303,7 +313,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) { resulting_element = ast::Expr::from(parent_deref_element); - new_element_opt = make::expr_prefix(syntax::T![*], new_element_opt).into(); + prefix.insert(0, '*'); } if let Some(first_ref_expr) = resulting_element.syntax().parent().and_then(ast::RefExpr::cast) { @@ -317,7 +327,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) { let exclusive = parent_ref_element.mut_token().is_some(); resulting_element = ast::Expr::from(parent_ref_element); - new_element_opt = make::expr_ref(new_element_opt, exclusive); + prefix.insert_str(0, if exclusive { "&mut " } else { "&" }); } } else { // If we do not find any ref expressions, restore @@ -325,7 +335,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) { resulting_element = initial_element.clone(); } - (resulting_element, new_element_opt) + (resulting_element, prefix) } fn build_postfix_snippet_builder<'ctx>( @@ -901,4 +911,31 @@ fn main() { "#, ); } + + #[test] + fn inside_macro() { + check_edit( + "box", + r#" +macro_rules! assert { + ( $it:expr $(,)? ) => { $it }; +} + +fn foo() { + let a = true; + assert!(if a == false { true } else { false }.$0); +} + "#, + r#" +macro_rules! assert { + ( $it:expr $(,)? ) => { $it }; +} + +fn foo() { + let a = true; + assert!(Box::new(if a == false { true } else { false })); +} + "#, + ); + } } From 0dd7aad8c323630a728b7595914f1c09fbac142d Mon Sep 17 00:00:00 2001 From: Josh Rotenberg Date: Mon, 10 Feb 2025 15:14:00 -0800 Subject: [PATCH 027/158] add xtask codegen command as well --- src/tools/rust-analyzer/docs/book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/book/README.md b/src/tools/rust-analyzer/docs/book/README.md index a9d10df66435..043524b2341b 100644 --- a/src/tools/rust-analyzer/docs/book/README.md +++ b/src/tools/rust-analyzer/docs/book/README.md @@ -26,4 +26,4 @@ Start with the mdbook [User Guide](https://rust-lang.github.io/mdBook/guide/inst Four sections are generated dynamically: assists, configuration, diagnostics and features. Their content is found in the `generated.md` files of the respective book section, for example `src/configuration_generated.md`, and are included in the book via mdbook's [include](https://rust-lang.github.io/mdBook/format/mdbook.html#including-files) functionality. Generated files can be rebuilt by running the various -test cases that generate them, or by simply running all of the `rust-analyzer` tests with `cargo test`. +test cases that generate them, or by simply running all of the `rust-analyzer` tests with `cargo test` and `cargo xtask codegen`. From 7c68345e1b4ab3ca838bb8e8548253b029824da8 Mon Sep 17 00:00:00 2001 From: Josh Rotenberg Date: Mon, 10 Feb 2025 15:20:51 -0800 Subject: [PATCH 028/158] fix mdbook paths --- src/tools/rust-analyzer/docs/book/book.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/book.toml b/src/tools/rust-analyzer/docs/book/book.toml index ba3c1dede5db..a6f6a6ed784d 100644 --- a/src/tools/rust-analyzer/docs/book/book.toml +++ b/src/tools/rust-analyzer/docs/book/book.toml @@ -9,10 +9,10 @@ title = "rust-analyzer" edition = "2021" [output.html] -edit-url-template = "https://github.com/rust-lang/rust-analyzer/edit/master/manual/{path}" -git-repository-url = "https://github.com/rust-lang/rust-analyzer/tree/master/manual" +edit-url-template = "https://github.com/rust-lang/rust-analyzer/edit/master/docs/book/{path}" +git-repository-url = "https://github.com/rust-lang/rust-analyzer/tree/master/docs/book" mathjax-support = true -site-url = "/manual/" +site-url = "/book/" [output.html.playground] editable = true From b4014deb7e444aa6ea19ad5039040fda6f60b9cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 05:37:54 +0000 Subject: [PATCH 029/158] Bump esbuild from 0.18.12 to 0.25.0 in /editors/code Bumps [esbuild](https://github.com/evanw/esbuild) from 0.18.12 to 0.25.0. - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2023.md) - [Commits](https://github.com/evanw/esbuild/compare/v0.18.12...v0.25.0) --- updated-dependencies: - dependency-name: esbuild dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- .../editors/code/package-lock.json | 605 ++++++++++-------- .../rust-analyzer/editors/code/package.json | 2 +- 2 files changed, 342 insertions(+), 265 deletions(-) diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index 6027f813311c..86a066454a5c 100644 --- a/src/tools/rust-analyzer/editors/code/package-lock.json +++ b/src/tools/rust-analyzer/editors/code/package-lock.json @@ -23,7 +23,7 @@ "@typescript-eslint/parser": "^6.0.0", "@vscode/test-electron": "^2.3.8", "@vscode/vsce": "^3.0.0", - "esbuild": "^0.18.12", + "esbuild": "^0.25.0", "eslint": "^8.44.0", "eslint-config-prettier": "^8.8.0", "ovsx": "^0.8.2", @@ -256,356 +256,429 @@ "node": ">=16" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.12.tgz", - "integrity": "sha512-LIxaNIQfkFZbTLb4+cX7dozHlAbAshhFE5PKdro0l+FnCpx1GDJaQ2WMcqm+ToXKMt8p8Uojk/MFRuGyz3V5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.12.tgz", - "integrity": "sha512-BMAlczRqC/LUt2P97E4apTBbkvS9JTJnp2DKFbCwpZ8vBvXVbNdqmvzW/OsdtI/+mGr+apkkpqGM8WecLkPgrA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.12.tgz", - "integrity": "sha512-zU5MyluNsykf5cOJ0LZZZjgAHbhPJ1cWfdH1ZXVMXxVMhEV0VZiZXQdwBBVvmvbF28EizeK7obG9fs+fpmS0eQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.12.tgz", - "integrity": "sha512-zUZMep7YONnp6954QOOwEBwFX9svlKd3ov6PkxKd53LGTHsp/gy7vHaPGhhjBmEpqXEXShi6dddjIkmd+NgMsA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.12.tgz", - "integrity": "sha512-ohqLPc7i67yunArPj1+/FeeJ7AgwAjHqKZ512ADk3WsE3FHU9l+m5aa7NdxXr0HmN1bjDlUslBjWNbFlD9y12Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.12.tgz", - "integrity": "sha512-GIIHtQXqgeOOqdG16a/A9N28GpkvjJnjYMhOnXVbn3EDJcoItdR58v/pGN31CHjyXDc8uCcRnFWmqaJt24AYJg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.12.tgz", - "integrity": "sha512-zK0b9a1/0wZY+6FdOS3BpZcPc1kcx2G5yxxfEJtEUzVxI6n/FrC2Phsxj/YblPuBchhBZ/1wwn7AyEBUyNSa6g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.12.tgz", - "integrity": "sha512-y75OijvrBE/1XRrXq1jtrJfG26eHeMoqLJ2dwQNwviwTuTtHGCojsDO6BJNF8gU+3jTn1KzJEMETytwsFSvc+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.12.tgz", - "integrity": "sha512-JKgG8Q/LL/9sw/iHHxQyVMoQYu3rU3+a5Z87DxC+wAu3engz+EmctIrV+FGOgI6gWG1z1+5nDDbXiRMGQZXqiw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.12.tgz", - "integrity": "sha512-yoRIAqc0B4lDIAAEFEIu9ttTRFV84iuAl0KNCN6MhKLxNPfzwCBvEMgwco2f71GxmpBcTtn7KdErueZaM2rEvw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.12.tgz", - "integrity": "sha512-qYgt3dHPVvf/MgbIBpJ4Sup/yb9DAopZ3a2JgMpNKIHUpOdnJ2eHBo/aQdnd8dJ21X/+sS58wxHtA9lEazYtXQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.12.tgz", - "integrity": "sha512-wHphlMLK4ufNOONqukELfVIbnGQJrHJ/mxZMMrP2jYrPgCRZhOtf0kC4yAXBwnfmULimV1qt5UJJOw4Kh13Yfg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.12.tgz", - "integrity": "sha512-TeN//1Ft20ZZW41+zDSdOI/Os1bEq5dbvBvYkberB7PHABbRcsteeoNVZFlI0YLpGdlBqohEpjrn06kv8heCJg==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.12.tgz", - "integrity": "sha512-AgUebVS4DoAblBgiB2ACQ/8l4eGE5aWBb8ZXtkXHiET9mbj7GuWt3OnsIW/zX+XHJt2RYJZctbQ2S/mDjbp0UA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.12.tgz", - "integrity": "sha512-dJ3Rb3Ei2u/ysSXd6pzleGtfDdc2MuzKt8qc6ls8vreP1G3B7HInX3i7gXS4BGeVd24pp0yqyS7bJ5NHaI9ing==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.12.tgz", - "integrity": "sha512-OrNJMGQbPaVyHHcDF8ybNSwu7TDOfX8NGpXCbetwOSP6txOJiWlgQnRymfC9ocR1S0Y5PW0Wb1mV6pUddqmvmQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.12.tgz", - "integrity": "sha512-55FzVCAiwE9FK8wWeCRuvjazNRJ1QqLCYGZVB6E8RuQuTeStSwotpSW4xoRGwp3a1wUsaVCdYcj5LGCASVJmMg==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", "cpu": [ - "x64" + "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.12.tgz", - "integrity": "sha512-qnluf8rfb6Y5Lw2tirfK2quZOBbVqmwxut7GPCIJsM8lc4AEUj9L8y0YPdLaPK0TECt4IdyBdBD/KRFKorlK3g==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.12.tgz", - "integrity": "sha512-+RkKpVQR7bICjTOPUpkTBTaJ4TFqQBX5Ywyd/HSdDkQGn65VPkTsR/pL4AMvuMWy+wnXgIl4EY6q4mVpJal8Kg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.12.tgz", - "integrity": "sha512-GNHuciv0mFM7ouzsU0+AwY+7eV4Mgo5WnbhfDCQGtpvOtD1vbOiRjPYG6dhmMoFyBjj+pNqQu2X+7DKn0KQ/Gw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.12.tgz", - "integrity": "sha512-kR8cezhYipbbypGkaqCTWIeu4zID17gamC8YTPXYtcN3E5BhhtTnwKBn9I0PJur/T6UVwIEGYzkffNL0lFvxEw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.12.tgz", - "integrity": "sha512-O0UYQVkvfM/jO8a4OwoV0mAKSJw+mjWTAd1MJd/1FCX6uiMdLmMRPK/w6e9OQ0ob2WGxzIm9va/KG0Ja4zIOgg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -2521,40 +2594,44 @@ } }, "node_modules/esbuild": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.12.tgz", - "integrity": "sha512-XuOVLDdtsDslXStStduT41op21Ytmf4/BDS46aa3xPJ7X5h2eMWBF1oAe3QjUH3bDksocNXgzGUZ7XHIBya6Tg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.12", - "@esbuild/android-arm64": "0.18.12", - "@esbuild/android-x64": "0.18.12", - "@esbuild/darwin-arm64": "0.18.12", - "@esbuild/darwin-x64": "0.18.12", - "@esbuild/freebsd-arm64": "0.18.12", - "@esbuild/freebsd-x64": "0.18.12", - "@esbuild/linux-arm": "0.18.12", - "@esbuild/linux-arm64": "0.18.12", - "@esbuild/linux-ia32": "0.18.12", - "@esbuild/linux-loong64": "0.18.12", - "@esbuild/linux-mips64el": "0.18.12", - "@esbuild/linux-ppc64": "0.18.12", - "@esbuild/linux-riscv64": "0.18.12", - "@esbuild/linux-s390x": "0.18.12", - "@esbuild/linux-x64": "0.18.12", - "@esbuild/netbsd-x64": "0.18.12", - "@esbuild/openbsd-x64": "0.18.12", - "@esbuild/sunos-x64": "0.18.12", - "@esbuild/win32-arm64": "0.18.12", - "@esbuild/win32-ia32": "0.18.12", - "@esbuild/win32-x64": "0.18.12" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/escalade": { diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 0a6037677052..ef69e754f2b0 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -59,7 +59,7 @@ "@typescript-eslint/parser": "^6.0.0", "@vscode/test-electron": "^2.3.8", "@vscode/vsce": "^3.0.0", - "esbuild": "^0.18.12", + "esbuild": "^0.25.0", "eslint": "^8.44.0", "eslint-config-prettier": "^8.8.0", "ovsx": "^0.8.2", From 11c49a659570d4f9a5a05497fcf8808d7881ecbd Mon Sep 17 00:00:00 2001 From: asuto15 Date: Tue, 11 Feb 2025 15:06:56 +0900 Subject: [PATCH 030/158] Fix highlighting for extern crate in doc comments --- .../crates/ide/src/syntax_highlighting/highlight.rs | 1 + .../src/syntax_highlighting/test_data/highlight_doctest.html | 3 +++ .../rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs | 3 +++ 3 files changed, 7 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 479c0b381a4b..c6e11b9cbdf7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -703,6 +703,7 @@ fn highlight_name_ref_by_syntax( }; match parent.kind() { + EXTERN_CRATE => HlTag::Symbol(SymbolKind::Module).into(), METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) .and_then(|it| highlight_method_call(sema, krate, &it, edition)) .unwrap_or_else(|| SymbolKind::Method.into()), diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 5ff96ae2a74f..2f7bc65d14bb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -50,6 +50,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd //! fn test() {} //! ``` +//! ```rust +//! extern crate Krate; +//! ``` mod outline_module; /// ``` diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index b9520ae2bba2..ad3d47639111 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -722,6 +722,9 @@ fn test_highlight_doc_comment() { //! fn test() {} //! ``` +//! ```rust +//! extern crate Krate; +//! ``` mod outline_module; /// ``` From 6e6bdc311add561e3f71a3d49c781e0cac49eb26 Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Tue, 11 Feb 2025 15:24:46 +0800 Subject: [PATCH 031/158] don't emit implicit drop inlay hints for macro --- .../crates/ide/src/inlay_hints/implicit_drop.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index 27c7c3d49818..8c91958d8c9e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -54,7 +54,8 @@ pub(super) fn hints( }; let range = match terminator.span { MirSpan::ExprId(e) => match source_map.expr_syntax(e) { - Ok(s) => { + // don't show inlay hint for macro + Ok(s) if !s.file_id.is_macro() => { let root = &s.file_syntax(sema.db); let expr = s.value.to_node(root); let expr = expr.syntax(); @@ -69,7 +70,7 @@ pub(super) fn hints( } } } - Err(_) => continue, + _ => continue, }, MirSpan::PatId(p) => match source_map.pat_syntax(p) { Ok(s) => s.value.text_range(), From 4036a7a77d04e48b0237baac07c7e4d9fc7dd6de Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Tue, 11 Feb 2025 15:27:34 +0800 Subject: [PATCH 032/158] add test case for ignoring inlay hint for macro call --- .../ide/src/inlay_hints/implicit_drop.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index 8c91958d8c9e..58dc0fdf62cf 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -229,6 +229,27 @@ mod tests { //^ drop(y) } //^ drop(x) +"#, + ); + } + + #[test] + fn ignore_inlay_hint_for_macro_call() { + check_with_config( + ONLY_DROP_CONFIG, + r#" + struct X; + + macro_rules! my_macro { + () => {{ + let bbb = X; + bbb + }}; + } + + fn test() -> X { + my_macro!() + } "#, ); } From d695e33c8304241a7feb6a81707e4ee7bc371e09 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 11 Feb 2025 12:10:32 -0800 Subject: [PATCH 033/158] manual: Fix URLs to rustdoc pages Now that the manual lives at /manual/, we need to use absolute URLs to link to rustdoc content. --- src/tools/rust-analyzer/xtask/src/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs index 18f49643dc71..e84c259e9797 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen.rs @@ -117,7 +117,7 @@ impl fmt::Display for Location { let path = self.file.strip_prefix(project_root()).unwrap().display().to_string(); let path = path.replace('\\', "/"); let name = self.file.file_name().unwrap(); - write!(f, " [{}]({}#{}) ", name.to_str().unwrap(), path, self.line) + write!(f, " [{}](/{}#{}) ", name.to_str().unwrap(), path, self.line) } } From 16abb39c9dd7e346ffecd5bf03c315bf374ece5f Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 11 Feb 2025 17:48:36 +0100 Subject: [PATCH 034/158] Reword file lock documentation to clarify advisory vs mandatory Remove the word "advisory", and make it more explicit that the lock may be advisory or mandatory depending on platform. --- library/std/src/fs.rs | 75 +++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 83b009c86dc0..7c8279f2555b 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -624,20 +624,20 @@ impl File { self.inner.datasync() } - /// Acquire an exclusive advisory lock on the file. Blocks until the lock can be acquired. + /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired. /// - /// This acquires an exclusive advisory lock; no other file handle to this file may acquire - /// another lock. + /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. /// - /// If this file handle/descriptor, or a clone of it, already holds an advisory lock the exact - /// behavior is unspecified and platform dependent, including the possibility that it will - /// deadlock. However, if this method returns, then an exclusive lock is held. + /// If this file handle/descriptor, or a clone of it, already holds an lock the exact behavior + /// is unspecified and platform dependent, including the possibility that it will deadlock. + /// However, if this method returns, then an exclusive lock is held. /// /// If the file not open for writing, it is unspecified whether this function returns an error. /// - /// Note, this is an advisory lock meant to interact with [`lock_shared`], [`try_lock`], - /// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`] - /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block. + /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], + /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with + /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not + /// cause non-lockholders to block. /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. @@ -650,6 +650,7 @@ impl File { /// /// [changes]: io#platform-specific-behavior /// + /// [`lock`]: File::lock /// [`lock_shared`]: File::lock_shared /// [`try_lock`]: File::try_lock /// [`try_lock_shared`]: File::try_lock_shared @@ -674,18 +675,19 @@ impl File { self.inner.lock() } - /// Acquire a shared (non-exclusive) advisory lock on the file. Blocks until the lock can be acquired. + /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired. /// - /// This acquires a shared advisory lock; more than one file handle may hold a shared lock, but - /// none may hold an exclusive lock at the same time. + /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may + /// hold an exclusive lock at the same time. /// - /// If this file handle/descriptor, or a clone of it, already holds an advisory lock, the exact - /// behavior is unspecified and platform dependent, including the possibility that it will - /// deadlock. However, if this method returns, then a shared lock is held. + /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior + /// is unspecified and platform dependent, including the possibility that it will deadlock. + /// However, if this method returns, then a shared lock is held. /// - /// Note, this is an advisory lock meant to interact with [`lock`], [`try_lock`], - /// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`] - /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block. + /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], + /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with + /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not + /// cause non-lockholders to block. /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. @@ -699,6 +701,7 @@ impl File { /// [changes]: io#platform-specific-behavior /// /// [`lock`]: File::lock + /// [`lock_shared`]: File::lock_shared /// [`try_lock`]: File::try_lock /// [`try_lock_shared`]: File::try_lock_shared /// [`unlock`]: File::unlock @@ -722,24 +725,23 @@ impl File { self.inner.lock_shared() } - /// Try to acquire an exclusive advisory lock on the file. + /// Try to acquire an exclusive lock on the file. /// /// Returns `Ok(false)` if a different lock is already held on this file (via another /// handle/descriptor). /// - /// This acquires an exclusive advisory lock; no other file handle to this file may acquire - /// another lock. + /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. /// - /// If this file handle/descriptor, or a clone of it, already holds an advisory lock, the exact - /// behavior is unspecified and platform dependent, including the possibility that it will - /// deadlock. However, if this method returns `Ok(true)`, then it has acquired an exclusive - /// lock. + /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior + /// is unspecified and platform dependent, including the possibility that it will deadlock. + /// However, if this method returns `Ok(true)`, then it has acquired an exclusive lock. /// /// If the file not open for writing, it is unspecified whether this function returns an error. /// - /// Note, this is an advisory lock meant to interact with [`lock`], [`lock_shared`], - /// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`] - /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block. + /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], + /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with + /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not + /// cause non-lockholders to block. /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. @@ -755,6 +757,7 @@ impl File { /// /// [`lock`]: File::lock /// [`lock_shared`]: File::lock_shared + /// [`try_lock`]: File::try_lock /// [`try_lock_shared`]: File::try_lock_shared /// [`unlock`]: File::unlock /// [`read`]: Read::read @@ -777,21 +780,22 @@ impl File { self.inner.try_lock() } - /// Try to acquire a shared (non-exclusive) advisory lock on the file. + /// Try to acquire a shared (non-exclusive) lock on the file. /// /// Returns `Ok(false)` if an exclusive lock is already held on this file (via another /// handle/descriptor). /// - /// This acquires a shared advisory lock; more than one file handle may hold a shared lock, but - /// none may hold an exclusive lock at the same time. + /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may + /// hold an exclusive lock at the same time. /// - /// If this file handle, or a clone of it, already holds an advisory lock, the exact behavior is + /// If this file handle, or a clone of it, already holds an lock, the exact behavior is /// unspecified and platform dependent, including the possibility that it will deadlock. /// However, if this method returns `Ok(true)`, then it has acquired a shared lock. /// - /// Note, this is an advisory lock meant to interact with [`lock`], [`try_lock`], - /// [`try_lock`], and [`unlock`]. Its interactions with other methods, such as [`read`] - /// and [`write`] are platform specific, and it may or may not cause non-lockholders to block. + /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], + /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with + /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not + /// cause non-lockholders to block. /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. @@ -808,6 +812,7 @@ impl File { /// [`lock`]: File::lock /// [`lock_shared`]: File::lock_shared /// [`try_lock`]: File::try_lock + /// [`try_lock_shared`]: File::try_lock_shared /// [`unlock`]: File::unlock /// [`read`]: Read::read /// [`write`]: Write::write From bc59397f8f320eefc5c2c60d1ad9fa816bbee2e4 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 11 Feb 2025 17:51:30 +0100 Subject: [PATCH 035/158] Document that locking a file fails on Windows if the file is opened only for append --- library/std/src/fs.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 7c8279f2555b..0707115cbdd9 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -648,6 +648,9 @@ impl File { /// and the `LockFileEx` function on Windows with the `LOCKFILE_EXCLUSIVE_LOCK` flag. Note that, /// this [may change in the future][changes]. /// + /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, + /// open it with either `.read(true).append(true)` or `.write(true)`. + /// /// [changes]: io#platform-specific-behavior /// /// [`lock`]: File::lock @@ -698,6 +701,9 @@ impl File { /// and the `LockFileEx` function on Windows. Note that, this /// [may change in the future][changes]. /// + /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, + /// open it with either `.read(true).append(true)` or `.write(true)`. + /// /// [changes]: io#platform-specific-behavior /// /// [`lock`]: File::lock @@ -753,6 +759,9 @@ impl File { /// and `LOCKFILE_FAIL_IMMEDIATELY` flags. Note that, this /// [may change in the future][changes]. /// + /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, + /// open it with either `.read(true).append(true)` or `.write(true)`. + /// /// [changes]: io#platform-specific-behavior /// /// [`lock`]: File::lock @@ -807,6 +816,9 @@ impl File { /// `LOCKFILE_FAIL_IMMEDIATELY` flag. Note that, this /// [may change in the future][changes]. /// + /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, + /// open it with either `.read(true).append(true)` or `.write(true)`. + /// /// [changes]: io#platform-specific-behavior /// /// [`lock`]: File::lock @@ -849,6 +861,9 @@ impl File { /// and the `UnlockFile` function on Windows. Note that, this /// [may change in the future][changes]. /// + /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, + /// open it with either `.read(true).append(true)` or `.write(true)`. + /// /// [changes]: io#platform-specific-behavior /// /// # Examples From 3a7a47b3b676defd22ef3789eefff99ebddc2934 Mon Sep 17 00:00:00 2001 From: Josh Rotenberg Date: Tue, 11 Feb 2025 13:52:01 -0800 Subject: [PATCH 036/158] remove unused plugin config --- src/tools/rust-analyzer/docs/book/book.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/book.toml b/src/tools/rust-analyzer/docs/book/book.toml index a6f6a6ed784d..5ca4badde874 100644 --- a/src/tools/rust-analyzer/docs/book/book.toml +++ b/src/tools/rust-analyzer/docs/book/book.toml @@ -34,8 +34,3 @@ use-boolean-and = true [output.html.fold] enable = true level = 3 - -[preprocessor.toc] -command = "mdbook-toc" -renderer = ["html"] -max-level = 3 From 3a041fcc2cc514ef87f29d8aa8300a0f6a2fa0da Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 09:24:33 +0100 Subject: [PATCH 037/158] Propogate error types in mir type projections --- src/tools/rust-analyzer/crates/hir-ty/src/mir.rs | 11 +++++++++-- .../src/handlers/unused_variables.rs | 13 +++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 84d8950b1aa2..41304bbd8a91 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -10,7 +10,7 @@ use crate::{ lang_items::is_box, mapping::ToChalk, CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap, - Substitution, TraitEnvironment, Ty, TyKind, + Substitution, TraitEnvironment, Ty, TyExt, TyKind, }; use base_db::CrateId; use chalk_ir::Mutability; @@ -144,6 +144,13 @@ impl ProjectionElem { closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty, krate: CrateId, ) -> Ty { + // we only bail on mir building when there are type mismatches + // but error types may pop up resulting in us still attempting to build the mir + // so just propagate the error type + if base.is_unknown() { + return TyKind::Error.intern(Interner); + } + if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) { base = normalize( db, @@ -166,7 +173,7 @@ impl ProjectionElem { TyKind::Error.intern(Interner) } }, - ProjectionElem::Field(Either::Left(f)) => match &base.kind(Interner) { + ProjectionElem::Field(Either::Left(f)) => match base.kind(Interner) { TyKind::Adt(_, subst) => { db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs index 67ece5669419..d5caf4de3367 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -260,6 +260,19 @@ fn main() { let arr = [1, 2, 3, 4, 5]; let [_x, _y @ ..] = arr; } +"#, + ); + } + + // regression test as we used to panic in this scenario + #[test] + fn unknown_struct_pattern_param_type() { + check_diagnostics( + r#" +struct S { field : u32 } +fn f(S { field }: error) { + // ^^^^^ 💡 warn: unused variable +} "#, ); } From c12a2e750d3dab2897f7b1c7471f10487d1f0285 Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Wed, 12 Feb 2025 17:18:42 +0800 Subject: [PATCH 038/158] minor: don't show drop hints for other pattern --- .../crates/ide/src/inlay_hints/implicit_drop.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index 58dc0fdf62cf..390139d214eb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -73,8 +73,8 @@ pub(super) fn hints( _ => continue, }, MirSpan::PatId(p) => match source_map.pat_syntax(p) { - Ok(s) => s.value.text_range(), - Err(_) => continue, + Ok(s) if !s.file_id.is_macro() => s.value.text_range(), + _ => continue, }, MirSpan::BindingId(b) => { match source_map @@ -82,13 +82,13 @@ pub(super) fn hints( .iter() .find_map(|p| source_map.pat_syntax(*p).ok()) { - Some(s) => s.value.text_range(), - None => continue, + Some(s) if !s.file_id.is_macro() => s.value.text_range(), + _ => continue, } } MirSpan::SelfParam => match source_map.self_param_syntax() { - Some(s) => s.value.text_range(), - None => continue, + Some(s) if !s.file_id.is_macro() => s.value.text_range(), + _ => continue, }, MirSpan::Unknown => continue, }; From a09ece29254cd06a1ee9529622e47c9a72645cb1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 7 Feb 2025 14:56:36 +0100 Subject: [PATCH 039/158] fix: Do not show safety hints for extern items lacking semantics --- .../crates/hir-def/src/dyn_map.rs | 7 ++-- .../crates/hir-def/src/item_scope.rs | 18 ++++++++- .../crates/hir-def/src/nameres/collector.rs | 24 +++++++----- .../rust-analyzer/crates/hir/src/from_id.rs | 1 + src/tools/rust-analyzer/crates/hir/src/lib.rs | 39 +++++++++++++++++-- .../rust-analyzer/crates/hir/src/semantics.rs | 1 + .../hir/src/semantics/child_by_source.rs | 3 ++ .../crates/hir/src/semantics/source_to_def.rs | 14 +++++-- .../rust-analyzer/crates/ide-db/src/defs.rs | 2 +- .../ide/src/inlay_hints/extern_block.rs | 19 +++++---- 10 files changed, 97 insertions(+), 31 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index 0f73595347b1..e9318d146ddf 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -31,9 +31,9 @@ pub mod keys { use crate::{ dyn_map::{DynMap, Policy}, - BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, - LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, - TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, + BlockId, ConstId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId, + ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, + TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, }; pub type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -44,6 +44,7 @@ pub mod keys { pub const STATIC: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const IMPL: Key = Key::new(); + pub const EXTERN_BLOCK: Key = Key::new(); pub const TRAIT: Key = Key::new(); pub const TRAIT_ALIAS: Key = Key::new(); pub const STRUCT: Key = Key::new(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 65a39c565611..0ca1eb9bcfe3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -18,8 +18,8 @@ use crate::{ db::DefDatabase, per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem}, visibility::{Visibility, VisibilityExplicitness}, - AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId, - Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, + AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId, + LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] @@ -158,6 +158,8 @@ pub struct ItemScope { declarations: Vec, impls: Vec, + #[allow(clippy::box_collection)] + extern_blocks: Option>>, unnamed_consts: Vec, /// Traits imported via `use Trait as _;`. unnamed_trait_imports: FxHashMap>, @@ -319,6 +321,10 @@ impl ItemScope { self.extern_crate_decls.iter().copied() } + pub fn extern_blocks(&self) -> impl Iterator + '_ { + self.extern_blocks.iter().flat_map(|it| it.iter()).copied() + } + pub fn use_decls(&self) -> impl ExactSizeIterator + '_ { self.use_decls.iter().copied() } @@ -469,6 +475,10 @@ impl ItemScope { self.impls.push(imp); } + pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) { + self.extern_blocks.get_or_insert_default().push(extern_block); + } + pub(crate) fn define_extern_crate_decl(&mut self, extern_crate: ExternCrateId) { self.extern_crate_decls.push(extern_crate); } @@ -806,7 +816,11 @@ impl ItemScope { use_imports_types, use_imports_macros, macro_invocations, + extern_blocks, } = self; + if let Some(it) = extern_blocks { + it.shrink_to_fit(); + } types.shrink_to_fit(); values.shrink_to_fit(); macros.shrink_to_fit(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 06276335b718..254c1379917b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -1759,16 +1759,20 @@ impl ModCollector<'_, '_> { ); } } - ModItem::ExternBlock(block) => self.collect( - &self.item_tree[block].children, - ItemContainerId::ExternBlockId( - ExternBlockLoc { - container: module, - id: ItemTreeId::new(self.tree_id, block), - } - .intern(db), - ), - ), + ModItem::ExternBlock(block) => { + let extern_block_id = ExternBlockLoc { + container: module, + id: ItemTreeId::new(self.tree_id, block), + } + .intern(db); + self.def_collector.def_map.modules[self.module_id] + .scope + .define_extern_block(extern_block_id); + self.collect( + &self.item_tree[block].children, + ItemContainerId::ExternBlockId(extern_block_id), + ) + } ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container), ModItem::MacroRules(id) => self.collect_macro_rules(id, module), ModItem::Macro2(id) => self.collect_macro_def(id, module), diff --git a/src/tools/rust-analyzer/crates/hir/src/from_id.rs b/src/tools/rust-analyzer/crates/hir/src/from_id.rs index 537401afdc34..72df07ef8c0c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/from_id.rs +++ b/src/tools/rust-analyzer/crates/hir/src/from_id.rs @@ -49,6 +49,7 @@ from_id![ (hir_def::LifetimeParamId, crate::LifetimeParam), (hir_def::MacroId, crate::Macro), (hir_def::ExternCrateId, crate::ExternCrateDecl), + (hir_def::ExternBlockId, crate::ExternBlock), ]; impl From for Adt { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 56090bc6b605..3c17ddb7b7db 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -55,8 +55,8 @@ use hir_def::{ resolver::{HasResolver, Resolver}, type_ref::TypesSourceMap, AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, - CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, - GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, + CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; @@ -2327,6 +2327,13 @@ impl Function { db.function_data(self.id).is_async() } + pub fn extern_block(self, db: &dyn HirDatabase) -> Option { + match self.id.lookup(db.upcast()).container { + ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }), + _ => None, + } + } + pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool { if self.is_async(db) { return true; @@ -2761,6 +2768,13 @@ impl Static { Type::from_value_def(db, self.id) } + pub fn extern_block(self, db: &dyn HirDatabase) -> Option { + match self.id.lookup(db.upcast()).container { + ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }), + _ => None, + } + } + /// Evaluate the static initializer. pub fn eval(self, db: &dyn HirDatabase) -> Result { db.const_eval(self.id.into(), Substitution::empty(Interner), None) @@ -2928,6 +2942,17 @@ impl HasVisibility for TypeAlias { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ExternBlock { + pub(crate) id: ExternBlockId, +} + +impl ExternBlock { + pub fn module(self, db: &dyn HirDatabase) -> Module { + Module { id: self.id.module(db.upcast()) } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StaticLifetime; @@ -6180,9 +6205,15 @@ impl HasContainer for TraitAlias { } } +impl HasContainer for ExternBlock { + fn container(&self, db: &dyn HirDatabase) -> ItemContainer { + ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container }) + } +} + fn container_id_to_hir(c: ItemContainerId) -> ItemContainer { match c { - ItemContainerId::ExternBlockId(_id) => ItemContainer::ExternBlock(), + ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }), ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }), ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }), ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }), @@ -6194,7 +6225,7 @@ pub enum ItemContainer { Trait(Trait), Impl(Impl), Module(Module), - ExternBlock(), + ExternBlock(ExternBlock), Crate(CrateId), } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 882a27182f01..c9145f7d212d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1998,6 +1998,7 @@ to_def_impls![ (crate::Adt, ast::Adt, adt_to_def), (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def), (crate::InlineAsmOperand, ast::AsmOperandNamed, asm_operand_to_def), + (crate::ExternBlock, ast::ExternBlock, extern_block_to_def), (MacroCallId, ast::MacroCall, macro_call_to_macro_call), ]; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index d5dfb9857186..d0fdf5cbdf7a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -74,6 +74,9 @@ impl ChildBySource for ItemScope { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { self.declarations().for_each(|item| add_module_def(db, res, file_id, item)); self.impls().for_each(|imp| insert_item_loc(db, res, file_id, imp, keys::IMPL)); + self.extern_blocks().for_each(|extern_block| { + insert_item_loc(db, res, file_id, extern_block, keys::EXTERN_BLOCK) + }); self.extern_crate_decls() .for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::EXTERN_CRATE)); self.use_decls().for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::USE)); diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 3c9e7065c41d..4e61f5b5a35b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -92,10 +92,10 @@ use hir_def::{ DynMap, }, hir::{BindingId, Expr, LabelId}, - AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, - FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId, - ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, - VariantId, + AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, + ExternCrateId, FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, + Lookup, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, + UnionId, UseId, VariantId, }; use hir_expand::{ attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId, @@ -308,6 +308,12 @@ impl SourceToDefCtx<'_, '_> { ) -> Option { self.to_def(src, keys::EXTERN_CRATE) } + pub(super) fn extern_block_to_def( + &mut self, + src: InFile<&ast::ExternBlock>, + ) -> Option { + self.to_def(src, keys::EXTERN_BLOCK) + } #[allow(dead_code)] pub(super) fn use_to_def(&mut self, src: InFile<&ast::Use>) -> Option { self.to_def(src, keys::USE) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index bad536080567..6f71c3d9bd7e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -108,7 +108,7 @@ impl Definition { ItemContainer::Trait(it) => Some(it.into()), ItemContainer::Impl(it) => Some(it.into()), ItemContainer::Module(it) => Some(it.into()), - ItemContainer::ExternBlock() | ItemContainer::Crate(_) => None, + ItemContainer::ExternBlock(_) | ItemContainer::Crate(_) => None, } } match self { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs index 2bc91b68ed8f..652dff0bc56e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs @@ -7,7 +7,7 @@ use crate::{InlayHint, InlayHintsConfig}; pub(super) fn extern_block_hints( acc: &mut Vec, - FamousDefs(_sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, extern_block: ast::ExternBlock, @@ -16,6 +16,7 @@ pub(super) fn extern_block_hints( return None; } let abi = extern_block.abi()?; + sema.to_def(&extern_block)?; acc.push(InlayHint { range: abi.syntax().text_range(), position: crate::InlayHintPosition::Before, @@ -33,7 +34,7 @@ pub(super) fn extern_block_hints( pub(super) fn fn_hints( acc: &mut Vec, - FamousDefs(_sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, fn_: &ast::Fn, @@ -43,14 +44,16 @@ pub(super) fn fn_hints( if !implicit_unsafe { return None; } - let fn_ = fn_.fn_token()?; - acc.push(item_hint(config, extern_block, fn_)); + let fn_token = fn_.fn_token()?; + if sema.to_def(fn_).is_some_and(|def| def.extern_block(sema.db).is_some()) { + acc.push(item_hint(config, extern_block, fn_token)); + } Some(()) } pub(super) fn static_hints( acc: &mut Vec, - FamousDefs(_sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, static_: &ast::Static, @@ -60,8 +63,10 @@ pub(super) fn static_hints( if !implicit_unsafe { return None; } - let static_ = static_.static_token()?; - acc.push(item_hint(config, extern_block, static_)); + let static_token = static_.static_token()?; + if sema.to_def(static_).is_some_and(|def| def.extern_block(sema.db).is_some()) { + acc.push(item_hint(config, extern_block, static_token)); + } Some(()) } From 0d8015cb23a99a014e7bc82c19cd81e8ffa536a3 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 13 Jan 2025 04:31:15 +0800 Subject: [PATCH 040/158] fix: handle character boundary in search mode --- .../crates/hir-def/src/import_map.rs | 20 +- .../docs/book/src/assists_generated.md | 3820 +++++++++++++++++ .../docs/book/src/diagnostics_generated.md | 516 +++ .../docs/book/src/features_generated.md | 940 ++++ 4 files changed, 5295 insertions(+), 1 deletion(-) create mode 100644 src/tools/rust-analyzer/docs/book/src/assists_generated.md create mode 100644 src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md create mode 100644 src/tools/rust-analyzer/docs/book/src/features_generated.md diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 6137bd34d64a..d43776b8a66a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -320,7 +320,7 @@ impl SearchMode { }; match m { Some((index, _)) => { - name = &name[index + 1..]; + name = name[index..].strip_prefix(|_: char| true).unwrap_or_default(); true } None => false, @@ -1039,4 +1039,22 @@ pub mod fmt { "#]], ); } + + #[test] + fn unicode_fn_name() { + let ra_fixture = r#" + //- /main.rs crate:main deps:dep + //- /dep.rs crate:dep + pub fn あい() {} + "#; + + check_search( + ra_fixture, + "main", + Query::new("あ".to_owned()).fuzzy(), + expect![[r#" + dep::あい (f) + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md new file mode 100644 index 000000000000..3617badeef55 --- /dev/null +++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md @@ -0,0 +1,3820 @@ +//! Generated by `cargo xtask codegen assists-doc-tests`, do not edit by hand. + +### `add_braces` +**Source:** [add_braces.rs](crates/ide-assists/src/handlers/add_braces.rs#8) + +Adds braces to lambda and match arm expressions. + +#### Before +```rust +fn foo(n: i32) -> i32 { + match n { + 1 =>┃ n + 1, + _ => 0 + } +} +``` + +#### After +```rust +fn foo(n: i32) -> i32 { + match n { + 1 => { + n + 1 + }, + _ => 0 + } +} +``` + + +### `add_explicit_type` +**Source:** [add_explicit_type.rs](crates/ide-assists/src/handlers/add_explicit_type.rs#7) + +Specify type for a let binding. + +#### Before +```rust +fn main() { + let x┃ = 92; +} +``` + +#### After +```rust +fn main() { + let x: i32 = 92; +} +``` + + +### `add_hash` +**Source:** [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#89) + +Adds a hash to a raw string literal. + +#### Before +```rust +fn main() { + r#"Hello,┃ World!"#; +} +``` + +#### After +```rust +fn main() { + r##"Hello, World!"##; +} +``` + + +### `add_impl_default_members` +**Source:** [add_missing_impl_members.rs](crates/ide-assists/src/handlers/add_missing_impl_members.rs#58) + +Adds scaffold for overriding default impl members. + +#### Before +```rust +trait Trait { + type X; + fn foo(&self); + fn bar(&self) {} +} + +impl Trait for () { + type X = (); + fn foo(&self) {}┃ +} +``` + +#### After +```rust +trait Trait { + type X; + fn foo(&self); + fn bar(&self) {} +} + +impl Trait for () { + type X = (); + fn foo(&self) {} + + ┃fn bar(&self) {} +} +``` + + +### `add_impl_missing_members` +**Source:** [add_missing_impl_members.rs](crates/ide-assists/src/handlers/add_missing_impl_members.rs#16) + +Adds scaffold for required impl members. + +#### Before +```rust +trait Trait { + type X; + fn foo(&self) -> T; + fn bar(&self) {} +} + +impl Trait for () {┃ + +} +``` + +#### After +```rust +trait Trait { + type X; + fn foo(&self) -> T; + fn bar(&self) {} +} + +impl Trait for () { + ┃type X; + + fn foo(&self) -> u32 { + todo!() + } +} +``` + + +### `add_label_to_loop` +**Source:** [add_label_to_loop.rs](crates/ide-assists/src/handlers/add_label_to_loop.rs#9) + +Adds a label to a loop. + +#### Before +```rust +fn main() { + loop┃ { + break; + continue; + } +} +``` + +#### After +```rust +fn main() { + 'l: loop { + break 'l; + continue 'l; + } +} +``` + + +### `add_lifetime_to_type` +**Source:** [add_lifetime_to_type.rs](crates/ide-assists/src/handlers/add_lifetime_to_type.rs#5) + +Adds a new lifetime to a struct, enum or union. + +#### Before +```rust +struct Point { + x: &┃u32, + y: u32, +} +``` + +#### After +```rust +struct Point<'a> { + x: &'a u32, + y: u32, +} +``` + + +### `add_missing_match_arms` +**Source:** [add_missing_match_arms.rs](crates/ide-assists/src/handlers/add_missing_match_arms.rs#14) + +Adds missing clauses to a `match` expression. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + ┃ + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move { distance } => ${1:todo!()}, + Action::Stop => ${2:todo!()},┃ + } +} +``` + + +### `add_return_type` +**Source:** [add_return_type.rs](crates/ide-assists/src/handlers/add_return_type.rs#6) + +Adds the return type to a function or closure inferred from its tail expression if it doesn't have a return +type specified. This assists is useable in a functions or closures tail expression or return type position. + +#### Before +```rust +fn foo() { 4┃2i32 } +``` + +#### After +```rust +fn foo() -> i32 { 42i32 } +``` + + +### `add_turbo_fish` +**Source:** [add_turbo_fish.rs](crates/ide-assists/src/handlers/add_turbo_fish.rs#14) + +Adds `::<_>` to a call of a generic method or function. + +#### Before +```rust +fn make() -> T { todo!() } +fn main() { + let x = make┃(); +} +``` + +#### After +```rust +fn make() -> T { todo!() } +fn main() { + let x = make::<${0:_}>(); +} +``` + + +### `apply_demorgan` +**Source:** [apply_demorgan.rs](crates/ide-assists/src/handlers/apply_demorgan.rs#16) + +Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). +This transforms expressions of the form `!l || !r` into `!(l && r)`. +This also works with `&&`. This assist can only be applied with the cursor +on either `||` or `&&`. + +#### Before +```rust +fn main() { + if x != 4 ||┃ y < 3.14 {} +} +``` + +#### After +```rust +fn main() { + if !(x == 4 && y >= 3.14) {} +} +``` + + +### `apply_demorgan_iterator` +**Source:** [apply_demorgan.rs](crates/ide-assists/src/handlers/apply_demorgan.rs#132) + +Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to +`Iterator::all` and `Iterator::any`. + +This transforms expressions of the form `!iter.any(|x| predicate(x))` into +`iter.all(|x| !predicate(x))` and vice versa. This also works the other way for +`Iterator::all` into `Iterator::any`. + +#### Before +```rust +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().┃any(|num| num == 4) { + println!("foo"); + } +} +``` + +#### After +```rust +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| num != 4) { + println!("foo"); + } +} +``` + + +### `auto_import` +**Source:** [auto_import.rs](crates/ide-assists/src/handlers/auto_import.rs#73) + +If the name is unresolved, provides all possible imports for it. + +#### Before +```rust +fn main() { + let map = HashMap┃::new(); +} +``` + +#### After +```rust +use std::collections::HashMap; + +fn main() { + let map = HashMap::new(); +} +``` + + +### `bind_unused_param` +**Source:** [bind_unused_param.rs](crates/ide-assists/src/handlers/bind_unused_param.rs#12) + +Binds unused function parameter to an underscore. + +#### Before +```rust +fn some_function(x: i32┃) {} +``` + +#### After +```rust +fn some_function(x: i32) { + let _ = x; +} +``` + + +### `bool_to_enum` +**Source:** [bool_to_enum.rs](crates/ide-assists/src/handlers/bool_to_enum.rs#29) + +This converts boolean local variables, fields, constants, and statics into a new +enum with two variants `Bool::True` and `Bool::False`, as well as replacing +all assignments with the variants and replacing all usages with `== Bool::True` or +`== Bool::False`. + +#### Before +```rust +fn main() { + let ┃bool = true; + + if bool { + println!("foo"); + } +} +``` + +#### After +```rust +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let bool = Bool::True; + + if bool == Bool::True { + println!("foo"); + } +} +``` + + +### `change_visibility` +**Source:** [change_visibility.rs](crates/ide-assists/src/handlers/change_visibility.rs#13) + +Adds or changes existing visibility specifier. + +#### Before +```rust +┃fn frobnicate() {} +``` + +#### After +```rust +pub(crate) fn frobnicate() {} +``` + + +### `comment_to_doc` +**Source:** [convert_comment_from_or_to_doc.rs](crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs#9) + +Converts comments to documentation. + +#### Before +```rust +// Wow what ┃a nice module +// I sure hope this shows up when I hover over it +``` + +#### After +```rust +//! Wow what a nice module +//! I sure hope this shows up when I hover over it +``` + + +### `convert_bool_then_to_if` +**Source:** [convert_bool_then.rs](crates/ide-assists/src/handlers/convert_bool_then.rs#131) + +Converts a `bool::then` method call to an equivalent if expression. + +#### Before +```rust +fn main() { + (0 == 0).then┃(|| val) +} +``` + +#### After +```rust +fn main() { + if 0 == 0 { + Some(val) + } else { + None + } +} +``` + + +### `convert_closure_to_fn` +**Source:** [convert_closure_to_fn.rs](crates/ide-assists/src/handlers/convert_closure_to_fn.rs#25) + +This converts a closure to a freestanding function, changing all captures to parameters. + +#### Before +```rust +fn main() { + let mut s = String::new(); + let closure = |┃a| s.push_str(a); + closure("abc"); +} +``` + +#### After +```rust +fn main() { + let mut s = String::new(); + fn closure(a: &str, s: &mut String) { + s.push_str(a) + } + closure("abc", &mut s); +} +``` + + +### `convert_for_loop_with_for_each` +**Source:** [convert_iter_for_each_to_for.rs](crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#76) + +Converts a for loop into a for_each loop on the Iterator. + +#### Before +```rust +fn main() { + let x = vec![1, 2, 3]; + for┃ v in x { + let y = v * 2; + } +} +``` + +#### After +```rust +fn main() { + let x = vec![1, 2, 3]; + x.into_iter().for_each(|v| { + let y = v * 2; + }); +} +``` + + +### `convert_from_to_tryfrom` +**Source:** [convert_from_to_tryfrom.rs](crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs#10) + +Converts a From impl to a TryFrom impl, wrapping returns in `Ok`. + +#### Before +```rust +impl ┃From for Thing { + fn from(val: usize) -> Self { + Thing { + b: val.to_string(), + a: val + } + } +} +``` + +#### After +```rust +impl TryFrom for Thing { + type Error = ${0:()}; + + fn try_from(val: usize) -> Result { + Ok(Thing { + b: val.to_string(), + a: val + }) + } +} +``` + + +### `convert_if_to_bool_then` +**Source:** [convert_bool_then.rs](crates/ide-assists/src/handlers/convert_bool_then.rs#20) + +Converts an if expression into a corresponding `bool::then` call. + +#### Before +```rust +fn main() { + if┃ cond { + Some(val) + } else { + None + } +} +``` + +#### After +```rust +fn main() { + cond.then(|| val) +} +``` + + +### `convert_integer_literal` +**Source:** [convert_integer_literal.rs](crates/ide-assists/src/handlers/convert_integer_literal.rs#5) + +Converts the base of integer literals to other bases. + +#### Before +```rust +const _: i32 = 10┃; +``` + +#### After +```rust +const _: i32 = 0b1010; +``` + + +### `convert_into_to_from` +**Source:** [convert_into_to_from.rs](crates/ide-assists/src/handlers/convert_into_to_from.rs#8) + +Converts an Into impl to an equivalent From impl. + +#### Before +```rust +impl ┃Into for usize { + fn into(self) -> Thing { + Thing { + b: self.to_string(), + a: self + } + } +} +``` + +#### After +```rust +impl From for Thing { + fn from(val: usize) -> Self { + Thing { + b: val.to_string(), + a: val + } + } +} +``` + + +### `convert_iter_for_each_to_for` +**Source:** [convert_iter_for_each_to_for.rs](crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#11) + +Converts an Iterator::for_each function into a for loop. + +#### Before +```rust +fn main() { + let iter = iter::repeat((9, 2)); + iter.for_each┃(|(x, y)| { + println!("x: {}, y: {}", x, y); + }); +} +``` + +#### After +```rust +fn main() { + let iter = iter::repeat((9, 2)); + for (x, y) in iter { + println!("x: {}, y: {}", x, y); + } +} +``` + + +### `convert_let_else_to_match` +**Source:** [convert_let_else_to_match.rs](crates/ide-assists/src/handlers/convert_let_else_to_match.rs#9) + +Converts let-else statement to let statement and match expression. + +#### Before +```rust +fn main() { + let Ok(mut x) = f() else┃ { return }; +} +``` + +#### After +```rust +fn main() { + let mut x = match f() { + Ok(x) => x, + _ => return, + }; +} +``` + + +### `convert_match_to_let_else` +**Source:** [convert_match_to_let_else.rs](crates/ide-assists/src/handlers/convert_match_to_let_else.rs#12) + +Converts let statement with match initializer to let-else statement. + +#### Before +```rust +fn foo(opt: Option<()>) { + let val┃ = match opt { + Some(it) => it, + None => return, + }; +} +``` + +#### After +```rust +fn foo(opt: Option<()>) { + let Some(val) = opt else { return }; +} +``` + + +### `convert_named_struct_to_tuple_struct` +**Source:** [convert_named_struct_to_tuple_struct.rs](crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs#11) + +Converts struct with named fields to tuple struct, and analogously for enum variants with named +fields. + +#### Before +```rust +struct Point┃ { x: f32, y: f32 } + +impl Point { + pub fn new(x: f32, y: f32) -> Self { + Point { x, y } + } + + pub fn x(&self) -> f32 { + self.x + } + + pub fn y(&self) -> f32 { + self.y + } +} +``` + +#### After +```rust +struct Point(f32, f32); + +impl Point { + pub fn new(x: f32, y: f32) -> Self { + Point(x, y) + } + + pub fn x(&self) -> f32 { + self.0 + } + + pub fn y(&self) -> f32 { + self.1 + } +} +``` + + +### `convert_nested_function_to_closure` +**Source:** [convert_nested_function_to_closure.rs](crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs#7) + +Converts a function that is defined within the body of another function into a closure. + +#### Before +```rust +fn main() { + fn fo┃o(label: &str, number: u64) { + println!("{}: {}", label, number); + } + + foo("Bar", 100); +} +``` + +#### After +```rust +fn main() { + let foo = |label: &str, number: u64| { + println!("{}: {}", label, number); + }; + + foo("Bar", 100); +} +``` + + +### `convert_to_guarded_return` +**Source:** [convert_to_guarded_return.rs](crates/ide-assists/src/handlers/convert_to_guarded_return.rs#24) + +Replace a large conditional with a guarded return. + +#### Before +```rust +fn main() { + ┃if cond { + foo(); + bar(); + } +} +``` + +#### After +```rust +fn main() { + if !cond { + return; + } + foo(); + bar(); +} +``` + + +### `convert_tuple_return_type_to_struct` +**Source:** [convert_tuple_return_type_to_struct.rs](crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs#20) + +This converts the return type of a function from a tuple type +into a tuple struct and updates the body accordingly. + +#### Before +```rust +fn bar() { + let (a, b, c) = foo(); +} + +fn foo() -> (┃u32, u32, u32) { + (1, 2, 3) +} +``` + +#### After +```rust +fn bar() { + let FooResult(a, b, c) = foo(); +} + +struct FooResult(u32, u32, u32); + +fn foo() -> FooResult { + FooResult(1, 2, 3) +} +``` + + +### `convert_tuple_struct_to_named_struct` +**Source:** [convert_tuple_struct_to_named_struct.rs](crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs#10) + +Converts tuple struct to struct with named fields, and analogously for tuple enum variants. + +#### Before +```rust +struct Point┃(f32, f32); + +impl Point { + pub fn new(x: f32, y: f32) -> Self { + Point(x, y) + } + + pub fn x(&self) -> f32 { + self.0 + } + + pub fn y(&self) -> f32 { + self.1 + } +} +``` + +#### After +```rust +struct Point { field1: f32, field2: f32 } + +impl Point { + pub fn new(x: f32, y: f32) -> Self { + Point { field1: x, field2: y } + } + + pub fn x(&self) -> f32 { + self.field1 + } + + pub fn y(&self) -> f32 { + self.field2 + } +} +``` + + +### `convert_two_arm_bool_match_to_matches_macro` +**Source:** [convert_two_arm_bool_match_to_matches_macro.rs](crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs#8) + +Convert 2-arm match that evaluates to a boolean into the equivalent matches! invocation. + +#### Before +```rust +fn main() { + match scrutinee┃ { + Some(val) if val.cond() => true, + _ => false, + } +} +``` + +#### After +```rust +fn main() { + matches!(scrutinee, Some(val) if val.cond()) +} +``` + + +### `convert_while_to_loop` +**Source:** [convert_while_to_loop.rs](crates/ide-assists/src/handlers/convert_while_to_loop.rs#20) + +Replace a while with a loop. + +#### Before +```rust +fn main() { + ┃while cond { + foo(); + } +} +``` + +#### After +```rust +fn main() { + loop { + if !cond { + break; + } + foo(); + } +} +``` + + +### `destructure_struct_binding` +**Source:** [destructure_struct_binding.rs](crates/ide-assists/src/handlers/destructure_struct_binding.rs#18) + +Destructures a struct binding in place. + +#### Before +```rust +struct Foo { + bar: i32, + baz: i32, +} +fn main() { + let ┃foo = Foo { bar: 1, baz: 2 }; + let bar2 = foo.bar; + let baz2 = &foo.baz; +} +``` + +#### After +```rust +struct Foo { + bar: i32, + baz: i32, +} +fn main() { + let Foo { bar, baz } = Foo { bar: 1, baz: 2 }; + let bar2 = bar; + let baz2 = &baz; +} +``` + + +### `destructure_tuple_binding` +**Source:** [destructure_tuple_binding.rs](crates/ide-assists/src/handlers/destructure_tuple_binding.rs#19) + +Destructures a tuple binding in place. + +#### Before +```rust +fn main() { + let ┃t = (1,2); + let v = t.0; +} +``` + +#### After +```rust +fn main() { + let (┃_0, _1) = (1,2); + let v = _0; +} +``` + + +### `desugar_async_into_impl_future` +**Source:** [toggle_async_sugar.rs](crates/ide-assists/src/handlers/toggle_async_sugar.rs#103) + +Rewrites asynchronous function from `async fn` into `-> impl Future`. +This action does not touch the function body and therefore `0` +block does not transform to `async { 0 }`. + +#### Before +```rust +pub as┃ync fn foo() -> usize { + 0 +} +``` + +#### After +```rust +pub fn foo() -> impl core::future::Future { + 0 +} +``` + + +### `desugar_doc_comment` +**Source:** [desugar_doc_comment.rs](crates/ide-assists/src/handlers/desugar_doc_comment.rs#14) + +Desugars doc-comments to the attribute form. + +#### Before +```rust +/// Multi-line┃ +/// comment +``` + +#### After +```rust +#[doc = r"Multi-line +comment"] +``` + + +### `expand_glob_import` +**Source:** [expand_glob_import.rs](crates/ide-assists/src/handlers/expand_glob_import.rs#18) + +Expands glob imports. + +#### Before +```rust +mod foo { + pub struct Bar; + pub struct Baz; +} + +use foo::*┃; + +fn qux(bar: Bar, baz: Baz) {} +``` + +#### After +```rust +mod foo { + pub struct Bar; + pub struct Baz; +} + +use foo::{Bar, Baz}; + +fn qux(bar: Bar, baz: Baz) {} +``` + + +### `explicit_enum_discriminant` +**Source:** [explicit_enum_discriminant.rs](crates/ide-assists/src/handlers/explicit_enum_discriminant.rs#11) + +Adds explicit discriminant to all enum variants. + +#### Before +```rust +enum TheEnum┃ { + Foo, + Bar, + Baz = 42, + Quux, +} +``` + +#### After +```rust +enum TheEnum { + Foo = 0, + Bar = 1, + Baz = 42, + Quux = 43, +} +``` + + +### `extract_constant` +**Source:** [extract_variable.rs](crates/ide-assists/src/handlers/extract_variable.rs#35) + +Extracts subexpression into a constant. + +#### Before +```rust +fn main() { + ┃(1 + 2)┃ * 4; +} +``` + +#### After +```rust +fn main() { + const ┃VAR_NAME: i32 = 1 + 2; + VAR_NAME * 4; +} +``` + + +### `extract_expressions_from_format_string` +**Source:** [extract_expressions_from_format_string.rs](crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs#14) + +Move an expression out of a format string. + +#### Before +```rust +fn main() { + print!("{var} {x + 1}┃"); +} +``` + +#### After +```rust +fn main() { + print!("{var} {}"┃, x + 1); +} +``` + + +### `extract_function` +**Source:** [extract_function.rs](crates/ide-assists/src/handlers/extract_function.rs#39) + +Extracts selected statements and comments into new function. + +#### Before +```rust +fn main() { + let n = 1; + ┃let m = n + 2; + // calculate + let k = m + n;┃ + let g = 3; +} +``` + +#### After +```rust +fn main() { + let n = 1; + fun_name(n); + let g = 3; +} + +fn ┃fun_name(n: i32) { + let m = n + 2; + // calculate + let k = m + n; +} +``` + + +### `extract_module` +**Source:** [extract_module.rs](crates/ide-assists/src/handlers/extract_module.rs#29) + +Extracts a selected region as separate module. All the references, visibility and imports are +resolved. + +#### Before +```rust +┃fn foo(name: i32) -> i32 { + name + 1 +}┃ + +fn bar(name: i32) -> i32 { + name + 2 +} +``` + +#### After +```rust +mod modname { + pub(crate) fn foo(name: i32) -> i32 { + name + 1 + } +} + +fn bar(name: i32) -> i32 { + name + 2 +} +``` + + +### `extract_static` +**Source:** [extract_variable.rs](crates/ide-assists/src/handlers/extract_variable.rs#52) + +Extracts subexpression into a static. + +#### Before +```rust +fn main() { + ┃(1 + 2)┃ * 4; +} +``` + +#### After +```rust +fn main() { + static ┃VAR_NAME: i32 = 1 + 2; + VAR_NAME * 4; +} +``` + + +### `extract_struct_from_enum_variant` +**Source:** [extract_struct_from_enum_variant.rs](crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs#26) + +Extracts a struct from enum variant. + +#### Before +```rust +enum A { ┃One(u32, u32) } +``` + +#### After +```rust +struct One(u32, u32); + +enum A { One(One) } +``` + + +### `extract_type_alias` +**Source:** [extract_type_alias.rs](crates/ide-assists/src/handlers/extract_type_alias.rs#10) + +Extracts the selected type as a type alias. + +#### Before +```rust +struct S { + field: ┃(u8, u8, u8)┃, +} +``` + +#### After +```rust +type ┃Type = (u8, u8, u8); + +struct S { + field: Type, +} +``` + + +### `extract_variable` +**Source:** [extract_variable.rs](crates/ide-assists/src/handlers/extract_variable.rs#18) + +Extracts subexpression into a variable. + +#### Before +```rust +fn main() { + ┃(1 + 2)┃ * 4; +} +``` + +#### After +```rust +fn main() { + let ┃var_name = 1 + 2; + var_name * 4; +} +``` + + +### `fill_record_pattern_fields` +**Source:** [fill_record_pattern_fields.rs](crates/ide-assists/src/handlers/fill_record_pattern_fields.rs#8) + +Fills fields by replacing rest pattern in record patterns. + +#### Before +```rust +struct Bar { y: Y, z: Z } + +fn foo(bar: Bar) { + let Bar { ..┃ } = bar; +} +``` + +#### After +```rust +struct Bar { y: Y, z: Z } + +fn foo(bar: Bar) { + let Bar { y, z } = bar; +} +``` + + +### `fix_visibility` +**Source:** [fix_visibility.rs](crates/ide-assists/src/handlers/fix_visibility.rs#14) + +Makes inaccessible item public. + +#### Before +```rust +mod m { + fn frobnicate() {} +} +fn main() { + m::frobnicate┃(); +} +``` + +#### After +```rust +mod m { + ┃pub(crate) fn frobnicate() {} +} +fn main() { + m::frobnicate(); +} +``` + + +### `flip_binexpr` +**Source:** [flip_binexpr.rs](crates/ide-assists/src/handlers/flip_binexpr.rs#8) + +Flips operands of a binary expression. + +#### Before +```rust +fn main() { + let _ = 90 +┃ 2; +} +``` + +#### After +```rust +fn main() { + let _ = 2 + 90; +} +``` + + +### `flip_comma` +**Source:** [flip_comma.rs](crates/ide-assists/src/handlers/flip_comma.rs#10) + +Flips two comma-separated items. + +#### Before +```rust +fn main() { + ((1, 2),┃ (3, 4)); +} +``` + +#### After +```rust +fn main() { + ((3, 4), (1, 2)); +} +``` + + +### `flip_trait_bound` +**Source:** [flip_trait_bound.rs](crates/ide-assists/src/handlers/flip_trait_bound.rs#9) + +Flips two trait bounds. + +#### Before +```rust +fn foo() { } +``` + +#### After +```rust +fn foo() { } +``` + + +### `generate_constant` +**Source:** [generate_constant.rs](crates/ide-assists/src/handlers/generate_constant.rs#14) + +Generate a named constant. + +#### Before +```rust +struct S { i: usize } +impl S { pub fn new(n: usize) {} } +fn main() { + let v = S::new(CAPA┃CITY); +} +``` + +#### After +```rust +struct S { i: usize } +impl S { pub fn new(n: usize) {} } +fn main() { + const CAPACITY: usize = ┃; + let v = S::new(CAPACITY); +} +``` + + +### `generate_default_from_enum_variant` +**Source:** [generate_default_from_enum_variant.rs](crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs#6) + +Adds a Default impl for an enum using a variant. + +#### Before +```rust +enum Version { + Undefined, + Minor┃, + Major, +} +``` + +#### After +```rust +enum Version { + Undefined, + Minor, + Major, +} + +impl Default for Version { + fn default() -> Self { + Self::Minor + } +} +``` + + +### `generate_default_from_new` +**Source:** [generate_default_from_new.rs](crates/ide-assists/src/handlers/generate_default_from_new.rs#13) + +Generates default implementation from new method. + +#### Before +```rust +struct Example { _inner: () } + +impl Example { + pub fn n┃ew() -> Self { + Self { _inner: () } + } +} +``` + +#### After +```rust +struct Example { _inner: () } + +impl Example { + pub fn new() -> Self { + Self { _inner: () } + } +} + +impl Default for Example { + fn default() -> Self { + Self::new() + } +} +``` + + +### `generate_delegate_methods` +**Source:** [generate_delegate_methods.rs](crates/ide-assists/src/handlers/generate_delegate_methods.rs#15) + +Generate delegate methods. + +#### Before +```rust +struct Age(u8); +impl Age { + fn age(&self) -> u8 { + self.0 + } +} + +struct Person { + ag┃e: Age, +} +``` + +#### After +```rust +struct Age(u8); +impl Age { + fn age(&self) -> u8 { + self.0 + } +} + +struct Person { + age: Age, +} + +impl Person { + ┃fn age(&self) -> u8 { + self.age.age() + } +} +``` + + +### `generate_delegate_trait` +**Source:** [generate_delegate_trait.rs](crates/ide-assists/src/handlers/generate_delegate_trait.rs#29) + +Generate delegate trait implementation for `StructField`s. + +#### Before +```rust +trait SomeTrait { + type T; + fn fn_(arg: u32) -> u32; + fn method_(&mut self) -> bool; +} +struct A; +impl SomeTrait for A { + type T = u32; + + fn fn_(arg: u32) -> u32 { + 42 + } + + fn method_(&mut self) -> bool { + false + } +} +struct B { + a┃: A, +} +``` + +#### After +```rust +trait SomeTrait { + type T; + fn fn_(arg: u32) -> u32; + fn method_(&mut self) -> bool; +} +struct A; +impl SomeTrait for A { + type T = u32; + + fn fn_(arg: u32) -> u32 { + 42 + } + + fn method_(&mut self) -> bool { + false + } +} +struct B { + a: A, +} + +impl SomeTrait for B { + type T = ::T; + + fn fn_(arg: u32) -> u32 { + ::fn_(arg) + } + + fn method_(&mut self) -> bool { + ::method_(&mut self.a) + } +} +``` + + +### `generate_deref` +**Source:** [generate_deref.rs](crates/ide-assists/src/handlers/generate_deref.rs#16) + +Generate `Deref` impl using the given struct field. + +#### Before +```rust +struct A; +struct B { + ┃a: A +} +``` + +#### After +```rust +struct A; +struct B { + a: A +} + +impl core::ops::Deref for B { + type Target = A; + + fn deref(&self) -> &Self::Target { + &self.a + } +} +``` + + +### `generate_derive` +**Source:** [generate_derive.rs](crates/ide-assists/src/handlers/generate_derive.rs#8) + +Adds a new `#[derive()]` clause to a struct or enum. + +#### Before +```rust +struct Point { + x: u32, + y: u32,┃ +} +``` + +#### After +```rust +#[derive(┃)] +struct Point { + x: u32, + y: u32, +} +``` + + +### `generate_doc_example` +**Source:** [generate_documentation_template.rs](crates/ide-assists/src/handlers/generate_documentation_template.rs#76) + +Generates a rustdoc example when editing an item's documentation. + +#### Before +```rust +/// Adds two numbers.┃ +pub fn add(a: i32, b: i32) -> i32 { a + b } +``` + +#### After +```rust +/// Adds two numbers. +/// +/// # Examples +/// +/// ``` +/// use ra_test_fixture::add; +/// +/// assert_eq!(add(a, b), ); +/// ``` +pub fn add(a: i32, b: i32) -> i32 { a + b } +``` + + +### `generate_documentation_template` +**Source:** [generate_documentation_template.rs](crates/ide-assists/src/handlers/generate_documentation_template.rs#13) + +Adds a documentation template above a function definition / declaration. + +#### Before +```rust +pub struct S; +impl S { + pub unsafe fn set_len┃(&mut self, len: usize) -> Result<(), std::io::Error> { + /* ... */ + } +} +``` + +#### After +```rust +pub struct S; +impl S { + /// Sets the length of this [`S`]. + /// + /// # Errors + /// + /// This function will return an error if . + /// + /// # Safety + /// + /// . + pub unsafe fn set_len(&mut self, len: usize) -> Result<(), std::io::Error> { + /* ... */ + } +} +``` + + +### `generate_enum_as_method` +**Source:** [generate_enum_projection_method.rs](crates/ide-assists/src/handlers/generate_enum_projection_method.rs#59) + +Generate an `as_` method for this enum variant. + +#### Before +```rust +enum Value { + Number(i32), + Text(String)┃, +} +``` + +#### After +```rust +enum Value { + Number(i32), + Text(String), +} + +impl Value { + fn as_text(&self) -> Option<&String> { + if let Self::Text(v) = self { + Some(v) + } else { + None + } + } +} +``` + + +### `generate_enum_is_method` +**Source:** [generate_enum_is_method.rs](crates/ide-assists/src/handlers/generate_enum_is_method.rs#11) + +Generate an `is_` method for this enum variant. + +#### Before +```rust +enum Version { + Undefined, + Minor┃, + Major, +} +``` + +#### After +```rust +enum Version { + Undefined, + Minor, + Major, +} + +impl Version { + /// Returns `true` if the version is [`Minor`]. + /// + /// [`Minor`]: Version::Minor + #[must_use] + fn is_minor(&self) -> bool { + matches!(self, Self::Minor) + } +} +``` + + +### `generate_enum_try_into_method` +**Source:** [generate_enum_projection_method.rs](crates/ide-assists/src/handlers/generate_enum_projection_method.rs#12) + +Generate a `try_into_` method for this enum variant. + +#### Before +```rust +enum Value { + Number(i32), + Text(String)┃, +} +``` + +#### After +```rust +enum Value { + Number(i32), + Text(String), +} + +impl Value { + fn try_into_text(self) -> Result { + if let Self::Text(v) = self { + Ok(v) + } else { + Err(self) + } + } +} +``` + + +### `generate_enum_variant` +**Source:** [generate_enum_variant.rs](crates/ide-assists/src/handlers/generate_enum_variant.rs#10) + +Adds a variant to an enum. + +#### Before +```rust +enum Countries { + Ghana, +} + +fn main() { + let country = Countries::Lesotho┃; +} +``` + +#### After +```rust +enum Countries { + Ghana, + Lesotho, +} + +fn main() { + let country = Countries::Lesotho; +} +``` + + +### `generate_fn_type_alias_named` +**Source:** [generate_fn_type_alias.rs](crates/ide-assists/src/handlers/generate_fn_type_alias.rs#10) + +Generate a type alias for the function with named parameters. + +#### Before +```rust +unsafe fn fo┃o(n: i32) -> i32 { 42i32 } +``` + +#### After +```rust +type ${0:FooFn} = unsafe fn(n: i32) -> i32; + +unsafe fn foo(n: i32) -> i32 { 42i32 } +``` + + +### `generate_fn_type_alias_unnamed` +**Source:** [generate_fn_type_alias.rs](crates/ide-assists/src/handlers/generate_fn_type_alias.rs#24) + +Generate a type alias for the function with unnamed parameters. + +#### Before +```rust +unsafe fn fo┃o(n: i32) -> i32 { 42i32 } +``` + +#### After +```rust +type ${0:FooFn} = unsafe fn(i32) -> i32; + +unsafe fn foo(n: i32) -> i32 { 42i32 } +``` + + +### `generate_from_impl_for_enum` +**Source:** [generate_from_impl_for_enum.rs](crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs#8) + +Adds a From impl for this enum variant with one tuple field. + +#### Before +```rust +enum A { ┃One(u32) } +``` + +#### After +```rust +enum A { One(u32) } + +impl From for A { + fn from(v: u32) -> Self { + Self::One(v) + } +} +``` + + +### `generate_function` +**Source:** [generate_function.rs](crates/ide-assists/src/handlers/generate_function.rs#28) + +Adds a stub function with a signature matching the function under the cursor. + +#### Before +```rust +struct Baz; +fn baz() -> Baz { Baz } +fn foo() { + bar┃("", baz()); +} + +``` + +#### After +```rust +struct Baz; +fn baz() -> Baz { Baz } +fn foo() { + bar("", baz()); +} + +fn bar(arg: &str, baz: Baz) ${0:-> _} { + todo!() +} + +``` + + +### `generate_getter` +**Source:** [generate_getter_or_setter.rs](crates/ide-assists/src/handlers/generate_getter_or_setter.rs#73) + +Generate a getter method. + +#### Before +```rust +struct Person { + nam┃e: String, +} +``` + +#### After +```rust +struct Person { + name: String, +} + +impl Person { + fn ┃name(&self) -> &str { + &self.name + } +} +``` + + +### `generate_getter_mut` +**Source:** [generate_getter_or_setter.rs](crates/ide-assists/src/handlers/generate_getter_or_setter.rs#127) + +Generate a mut getter method. + +#### Before +```rust +struct Person { + nam┃e: String, +} +``` + +#### After +```rust +struct Person { + name: String, +} + +impl Person { + fn ┃name_mut(&mut self) -> &mut String { + &mut self.name + } +} +``` + + +### `generate_impl` +**Source:** [generate_impl.rs](crates/ide-assists/src/handlers/generate_impl.rs#20) + +Adds a new inherent impl for a type. + +#### Before +```rust +struct Ctx┃ { + data: T, +} +``` + +#### After +```rust +struct Ctx { + data: T, +} + +impl Ctx {┃} +``` + + +### `generate_is_empty_from_len` +**Source:** [generate_is_empty_from_len.rs](crates/ide-assists/src/handlers/generate_is_empty_from_len.rs#12) + +Generates is_empty implementation from the len method. + +#### Before +```rust +struct MyStruct { data: Vec } + +impl MyStruct { + #[must_use] + p┃ub fn len(&self) -> usize { + self.data.len() + } +} +``` + +#### After +```rust +struct MyStruct { data: Vec } + +impl MyStruct { + #[must_use] + pub fn len(&self) -> usize { + self.data.len() + } + + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} +``` + + +### `generate_mut_trait_impl` +**Source:** [generate_mut_trait_impl.rs](crates/ide-assists/src/handlers/generate_mut_trait_impl.rs#12) + +Adds a IndexMut impl from the `Index` trait. + +#### Before +```rust +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index┃ for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +``` + +#### After +```rust +pub enum Axis { X = 0, Y = 1, Z = 2 } + +┃impl core::ops::IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl core::ops::Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +``` + + +### `generate_new` +**Source:** [generate_new.rs](crates/ide-assists/src/handlers/generate_new.rs#14) + +Adds a `fn new` for a type. + +#### Before +```rust +struct Ctx { + data: T,┃ +} +``` + +#### After +```rust +struct Ctx { + data: T, +} + +impl Ctx { + fn ┃new(data: T) -> Self { + Self { data } + } +} +``` + + +### `generate_setter` +**Source:** [generate_getter_or_setter.rs](crates/ide-assists/src/handlers/generate_getter_or_setter.rs#13) + +Generate a setter method. + +#### Before +```rust +struct Person { + nam┃e: String, +} +``` + +#### After +```rust +struct Person { + name: String, +} + +impl Person { + fn ┃set_name(&mut self, name: String) { + self.name = name; + } +} +``` + + +### `generate_trait_from_impl` +**Source:** [generate_trait_from_impl.rs](crates/ide-assists/src/handlers/generate_trait_from_impl.rs#18) + +Generate trait for an already defined inherent impl and convert impl to a trait impl. + +#### Before +```rust +struct Foo([i32; N]); + +macro_rules! const_maker { + ($t:ty, $v:tt) => { + const CONST: $t = $v; + }; +} + +impl Fo┃o { + // Used as an associated constant. + const CONST_ASSOC: usize = N * 4; + + fn create() -> Option<()> { + Some(()) + } + + const_maker! {i32, 7} +} +``` + +#### After +```rust +struct Foo([i32; N]); + +macro_rules! const_maker { + ($t:ty, $v:tt) => { + const CONST: $t = $v; + }; +} + +trait ${0:NewTrait} { + // Used as an associated constant. + const CONST_ASSOC: usize = N * 4; + + fn create() -> Option<()>; + + const_maker! {i32, 7} +} + +impl ${0:NewTrait} for Foo { + // Used as an associated constant. + const CONST_ASSOC: usize = N * 4; + + fn create() -> Option<()> { + Some(()) + } + + const_maker! {i32, 7} +} +``` + + +### `generate_trait_impl` +**Source:** [generate_impl.rs](crates/ide-assists/src/handlers/generate_impl.rs#66) + +Adds a new trait impl for a type. + +#### Before +```rust +struct ┃Ctx { + data: T, +} +``` + +#### After +```rust +struct Ctx { + data: T, +} + +impl ${0:_} for Ctx {} +``` + + +### `inline_call` +**Source:** [inline_call.rs](crates/ide-assists/src/handlers/inline_call.rs#170) + +Inlines a function or method body creating a `let` statement per parameter unless the parameter +can be inlined. The parameter will be inlined either if it the supplied argument is a simple local +or if the parameter is only accessed inside the function body once. + +#### Before +```rust +fn foo(name: Option<&str>) { + let name = name.unwrap┃(); +} +``` + +#### After +```rust +fn foo(name: Option<&str>) { + let name = match name { + Some(val) => val, + None => panic!("called `Option::unwrap()` on a `None` value"), + }; +} +``` + + +### `inline_const_as_literal` +**Source:** [inline_const_as_literal.rs](crates/ide-assists/src/handlers/inline_const_as_literal.rs#6) + +Evaluate and inline const variable as literal. + +#### Before +```rust +const STRING: &str = "Hello, World!"; + +fn something() -> &'static str { + STRING┃ +} +``` + +#### After +```rust +const STRING: &str = "Hello, World!"; + +fn something() -> &'static str { + "Hello, World!" +} +``` + + +### `inline_into_callers` +**Source:** [inline_call.rs](crates/ide-assists/src/handlers/inline_call.rs#32) + +Inline a function or method body into all of its callers where possible, creating a `let` statement per parameter +unless the parameter can be inlined. The parameter will be inlined either if it the supplied argument is a simple local +or if the parameter is only accessed inside the function body once. +If all calls can be inlined the function will be removed. + +#### Before +```rust +fn print(_: &str) {} +fn foo┃(word: &str) { + if !word.is_empty() { + print(word); + } +} +fn bar() { + foo("안녕하세요"); + foo("여러분"); +} +``` + +#### After +```rust +fn print(_: &str) {} + +fn bar() { + { + let word: &str = "안녕하세요"; + if !word.is_empty() { + print(word); + } + }; + { + let word: &str = "여러분"; + if !word.is_empty() { + print(word); + } + }; +} +``` + + +### `inline_local_variable` +**Source:** [inline_local_variable.rs](crates/ide-assists/src/handlers/inline_local_variable.rs#17) + +Inlines a local variable. + +#### Before +```rust +fn main() { + let x┃ = 1 + 2; + x * 4; +} +``` + +#### After +```rust +fn main() { + (1 + 2) * 4; +} +``` + + +### `inline_macro` +**Source:** [inline_macro.rs](crates/ide-assists/src/handlers/inline_macro.rs#7) + +Takes a macro and inlines it one step. + +#### Before +```rust +macro_rules! num { + (+$($t:tt)+) => (1 + num!($($t )+)); + (-$($t:tt)+) => (-1 + num!($($t )+)); + (+) => (1); + (-) => (-1); +} + +fn main() { + let number = num┃!(+ + + - + +); + println!("{number}"); +} +``` + +#### After +```rust +macro_rules! num { + (+$($t:tt)+) => (1 + num!($($t )+)); + (-$($t:tt)+) => (-1 + num!($($t )+)); + (+) => (1); + (-) => (-1); +} + +fn main() { + let number = 1+num!(+ + - + +); + println!("{number}"); +} +``` + + +### `inline_type_alias` +**Source:** [inline_type_alias.rs](crates/ide-assists/src/handlers/inline_type_alias.rs#106) + +Replace a type alias with its concrete type. + +#### Before +```rust +type A = Vec; + +fn main() { + let a: ┃A; +} +``` + +#### After +```rust +type A = Vec; + +fn main() { + let a: Vec; +} +``` + + +### `inline_type_alias_uses` +**Source:** [inline_type_alias.rs](crates/ide-assists/src/handlers/inline_type_alias.rs#24) + +Inline a type alias into all of its uses where possible. + +#### Before +```rust +type ┃A = i32; +fn id(x: A) -> A { + x +}; +fn foo() { + let _: A = 3; +} +``` + +#### After +```rust + +fn id(x: i32) -> i32 { + x +}; +fn foo() { + let _: i32 = 3; +} +``` + + +### `into_to_qualified_from` +**Source:** [into_to_qualified_from.rs](crates/ide-assists/src/handlers/into_to_qualified_from.rs#10) + +Convert an `into` method call to a fully qualified `from` call. + +#### Before +```rust +//- minicore: from +struct B; +impl From for B { + fn from(a: i32) -> Self { + B + } +} + +fn main() -> () { + let a = 3; + let b: B = a.in┃to(); +} +``` + +#### After +```rust +struct B; +impl From for B { + fn from(a: i32) -> Self { + B + } +} + +fn main() -> () { + let a = 3; + let b: B = B::from(a); +} +``` + + +### `introduce_named_generic` +**Source:** [introduce_named_generic.rs](crates/ide-assists/src/handlers/introduce_named_generic.rs#7) + +Replaces `impl Trait` function argument with the named generic. + +#### Before +```rust +fn foo(bar: ┃impl Bar) {} +``` + +#### After +```rust +fn foo<┃B: Bar>(bar: B) {} +``` + + +### `introduce_named_lifetime` +**Source:** [introduce_named_lifetime.rs](crates/ide-assists/src/handlers/introduce_named_lifetime.rs#13) + +Change an anonymous lifetime to a named lifetime. + +#### Before +```rust +impl Cursor<'_┃> { + fn node(self) -> &SyntaxNode { + match self { + Cursor::Replace(node) | Cursor::Before(node) => node, + } + } +} +``` + +#### After +```rust +impl<'a> Cursor<'a> { + fn node(self) -> &SyntaxNode { + match self { + Cursor::Replace(node) | Cursor::Before(node) => node, + } + } +} +``` + + +### `invert_if` +**Source:** [invert_if.rs](crates/ide-assists/src/handlers/invert_if.rs#13) + +This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}` +This also works with `!=`. This assist can only be applied with the cursor on `if`. + +#### Before +```rust +fn main() { + if┃ !y { A } else { B } +} +``` + +#### After +```rust +fn main() { + if y { B } else { A } +} +``` + + +### `line_to_block` +**Source:** [convert_comment_block.rs](crates/ide-assists/src/handlers/convert_comment_block.rs#9) + +Converts comments between block and single-line form. + +#### Before +```rust + // Multi-line┃ + // comment +``` + +#### After +```rust + /* + Multi-line + comment + */ +``` + + +### `make_raw_string` +**Source:** [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#7) + +Adds `r#` to a plain string literal. + +#### Before +```rust +fn main() { + "Hello,┃ World!"; +} +``` + +#### After +```rust +fn main() { + r#"Hello, World!"#; +} +``` + + +### `make_usual_string` +**Source:** [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#47) + +Turns a raw string into a plain string. + +#### Before +```rust +fn main() { + r#"Hello,┃ "World!""#; +} +``` + +#### After +```rust +fn main() { + "Hello, \"World!\""; +} +``` + + +### `merge_imports` +**Source:** [merge_imports.rs](crates/ide-assists/src/handlers/merge_imports.rs#21) + +Merges neighbor imports with a common prefix. + +#### Before +```rust +use std::┃fmt::Formatter; +use std::io; +``` + +#### After +```rust +use std::{fmt::Formatter, io}; +``` + + +### `merge_match_arms` +**Source:** [merge_match_arms.rs](crates/ide-assists/src/handlers/merge_match_arms.rs#12) + +Merges the current match arm with the following if their bodies are identical. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + ┃Action::Move(..) => foo(), + Action::Stop => foo(), + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move(..) | Action::Stop => foo(), + } +} +``` + + +### `merge_nested_if` +**Source:** [merge_nested_if.rs](crates/ide-assists/src/handlers/merge_nested_if.rs#11) + +This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}` +This assist can only be applied with the cursor on `if`. + +#### Before +```rust +fn main() { + i┃f x == 3 { if y == 4 { 1 } } +} +``` + +#### After +```rust +fn main() { + if x == 3 && y == 4 { 1 } +} +``` + + +### `move_arm_cond_to_match_guard` +**Source:** [move_guard.rs](crates/ide-assists/src/handlers/move_guard.rs#69) + +Moves if expression from match arm body into a guard. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move { distance } => ┃if distance > 10 { foo() }, + _ => (), + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move { distance } if distance > 10 => foo(), + _ => (), + } +} +``` + + +### `move_bounds_to_where_clause` +**Source:** [move_bounds.rs](crates/ide-assists/src/handlers/move_bounds.rs#12) + +Moves inline type bounds to a where clause. + +#### Before +```rust +fn apply U>(f: F, x: T) -> U { + f(x) +} +``` + +#### After +```rust +fn apply(f: F, x: T) -> U where F: FnOnce(T) -> U { + f(x) +} +``` + + +### `move_const_to_impl` +**Source:** [move_const_to_impl.rs](crates/ide-assists/src/handlers/move_const_to_impl.rs#14) + +Move a local constant item in a method to impl's associated constant. All the references will be +qualified with `Self::`. + +#### Before +```rust +struct S; +impl S { + fn foo() -> usize { + /// The answer. + const C┃: usize = 42; + + C * C + } +} +``` + +#### After +```rust +struct S; +impl S { + /// The answer. + const C: usize = 42; + + fn foo() -> usize { + Self::C * Self::C + } +} +``` + + +### `move_from_mod_rs` +**Source:** [move_from_mod_rs.rs](crates/ide-assists/src/handlers/move_from_mod_rs.rs#12) + +Moves xxx/mod.rs to xxx.rs. + +#### Before +```rust +//- /main.rs +mod a; +//- /a/mod.rs +┃fn t() {}┃ +``` + +#### After +```rust +fn t() {} +``` + + +### `move_guard_to_arm_body` +**Source:** [move_guard.rs](crates/ide-assists/src/handlers/move_guard.rs#8) + +Moves match guard into match arm body. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move { distance } ┃if distance > 10 => foo(), + _ => (), + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move { distance } => if distance > 10 { + foo() + }, + _ => (), + } +} +``` + + +### `move_module_to_file` +**Source:** [move_module_to_file.rs](crates/ide-assists/src/handlers/move_module_to_file.rs#15) + +Moves inline module's contents to a separate file. + +#### Before +```rust +mod ┃foo { + fn t() {} +} +``` + +#### After +```rust +mod foo; +``` + + +### `move_to_mod_rs` +**Source:** [move_to_mod_rs.rs](crates/ide-assists/src/handlers/move_to_mod_rs.rs#12) + +Moves xxx.rs to xxx/mod.rs. + +#### Before +```rust +//- /main.rs +mod a; +//- /a.rs +┃fn t() {}┃ +``` + +#### After +```rust +fn t() {} +``` + + +### `normalize_import` +**Source:** [normalize_import.rs](crates/ide-assists/src/handlers/normalize_import.rs#9) + +Normalizes an import. + +#### Before +```rust +use┃ std::{io, {fmt::Formatter}}; +``` + +#### After +```rust +use std::{fmt::Formatter, io}; +``` + + +### `promote_local_to_const` +**Source:** [promote_local_to_const.rs](crates/ide-assists/src/handlers/promote_local_to_const.rs#17) + +Promotes a local variable to a const item changing its name to a `SCREAMING_SNAKE_CASE` variant +if the local uses no non-const expressions. + +#### Before +```rust +fn main() { + let foo┃ = true; + + if foo { + println!("It's true"); + } else { + println!("It's false"); + } +} +``` + +#### After +```rust +fn main() { + const ┃FOO: bool = true; + + if FOO { + println!("It's true"); + } else { + println!("It's false"); + } +} +``` + + +### `pull_assignment_up` +**Source:** [pull_assignment_up.rs](crates/ide-assists/src/handlers/pull_assignment_up.rs#11) + +Extracts variable assignment to outside an if or match statement. + +#### Before +```rust +fn main() { + let mut foo = 6; + + if true { + ┃foo = 5; + } else { + foo = 4; + } +} +``` + +#### After +```rust +fn main() { + let mut foo = 6; + + foo = if true { + 5 + } else { + 4 + }; +} +``` + + +### `qualify_method_call` +**Source:** [qualify_method_call.rs](crates/ide-assists/src/handlers/qualify_method_call.rs#10) + +Replaces the method call with a qualified function call. + +#### Before +```rust +struct Foo; +impl Foo { + fn foo(&self) {} +} +fn main() { + let foo = Foo; + foo.fo┃o(); +} +``` + +#### After +```rust +struct Foo; +impl Foo { + fn foo(&self) {} +} +fn main() { + let foo = Foo; + Foo::foo(&foo); +} +``` + + +### `qualify_path` +**Source:** [qualify_path.rs](crates/ide-assists/src/handlers/qualify_path.rs#24) + +If the name is unresolved, provides all possible qualified paths for it. + +#### Before +```rust +fn main() { + let map = HashMap┃::new(); +} +``` + +#### After +```rust +fn main() { + let map = std::collections::HashMap::new(); +} +``` + + +### `reformat_number_literal` +**Source:** [number_representation.rs](crates/ide-assists/src/handlers/number_representation.rs#7) + +Adds or removes separators from integer literal. + +#### Before +```rust +const _: i32 = 1012345┃; +``` + +#### After +```rust +const _: i32 = 1_012_345; +``` + + +### `remove_dbg` +**Source:** [remove_dbg.rs](crates/ide-assists/src/handlers/remove_dbg.rs#9) + +Removes `dbg!()` macro call. + +#### Before +```rust +fn main() { + let x = ┃dbg!(42 * dbg!(4 + 2));┃ +} +``` + +#### After +```rust +fn main() { + let x = 42 * (4 + 2); +} +``` + + +### `remove_hash` +**Source:** [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#117) + +Removes a hash from a raw string literal. + +#### Before +```rust +fn main() { + r#"Hello,┃ World!"#; +} +``` + +#### After +```rust +fn main() { + r"Hello, World!"; +} +``` + + +### `remove_mut` +**Source:** [remove_mut.rs](crates/ide-assists/src/handlers/remove_mut.rs#5) + +Removes the `mut` keyword. + +#### Before +```rust +impl Walrus { + fn feed(&mut┃ self, amount: u32) {} +} +``` + +#### After +```rust +impl Walrus { + fn feed(&self, amount: u32) {} +} +``` + + +### `remove_parentheses` +**Source:** [remove_parentheses.rs](crates/ide-assists/src/handlers/remove_parentheses.rs#5) + +Removes redundant parentheses. + +#### Before +```rust +fn main() { + _ = ┃(2) + 2; +} +``` + +#### After +```rust +fn main() { + _ = 2 + 2; +} +``` + + +### `remove_unused_imports` +**Source:** [remove_unused_imports.rs](crates/ide-assists/src/handlers/remove_unused_imports.rs#17) + +Removes any use statements in the current selection that are unused. + +#### Before +```rust +struct X(); +mod foo { + use super::X┃; +} +``` + +#### After +```rust +struct X(); +mod foo { +} +``` + + +### `remove_unused_param` +**Source:** [remove_unused_param.rs](crates/ide-assists/src/handlers/remove_unused_param.rs#15) + +Removes unused function parameter. + +#### Before +```rust +fn frobnicate(x: i32┃) {} + +fn main() { + frobnicate(92); +} +``` + +#### After +```rust +fn frobnicate() {} + +fn main() { + frobnicate(); +} +``` + + +### `reorder_fields` +**Source:** [reorder_fields.rs](crates/ide-assists/src/handlers/reorder_fields.rs#8) + +Reorder the fields of record literals and record patterns in the same order as in +the definition. + +#### Before +```rust +struct Foo {foo: i32, bar: i32}; +const test: Foo = ┃Foo {bar: 0, foo: 1} +``` + +#### After +```rust +struct Foo {foo: i32, bar: i32}; +const test: Foo = Foo {foo: 1, bar: 0} +``` + + +### `reorder_impl_items` +**Source:** [reorder_impl_items.rs](crates/ide-assists/src/handlers/reorder_impl_items.rs#11) + +Reorder the items of an `impl Trait`. The items will be ordered +in the same order as in the trait definition. + +#### Before +```rust +trait Foo { + type A; + const B: u8; + fn c(); +} + +struct Bar; +┃impl Foo for Bar┃ { + const B: u8 = 17; + fn c() {} + type A = String; +} +``` + +#### After +```rust +trait Foo { + type A; + const B: u8; + fn c(); +} + +struct Bar; +impl Foo for Bar { + type A = String; + const B: u8 = 17; + fn c() {} +} +``` + + +### `replace_arith_with_checked` +**Source:** [replace_arith_op.rs](crates/ide-assists/src/handlers/replace_arith_op.rs#9) + +Replaces arithmetic on integers with the `checked_*` equivalent. + +#### Before +```rust +fn main() { + let x = 1 ┃+ 2; +} +``` + +#### After +```rust +fn main() { + let x = 1.checked_add(2); +} +``` + + +### `replace_arith_with_saturating` +**Source:** [replace_arith_op.rs](crates/ide-assists/src/handlers/replace_arith_op.rs#28) + +Replaces arithmetic on integers with the `saturating_*` equivalent. + +#### Before +```rust +fn main() { + let x = 1 ┃+ 2; +} +``` + +#### After +```rust +fn main() { + let x = 1.saturating_add(2); +} +``` + + +### `replace_arith_with_wrapping` +**Source:** [replace_arith_op.rs](crates/ide-assists/src/handlers/replace_arith_op.rs#50) + +Replaces arithmetic on integers with the `wrapping_*` equivalent. + +#### Before +```rust +fn main() { + let x = 1 ┃+ 2; +} +``` + +#### After +```rust +fn main() { + let x = 1.wrapping_add(2); +} +``` + + +### `replace_char_with_string` +**Source:** [replace_string_with_char.rs](crates/ide-assists/src/handlers/replace_string_with_char.rs#51) + +Replace a char literal with a string literal. + +#### Before +```rust +fn main() { + find('{┃'); +} +``` + +#### After +```rust +fn main() { + find("{"); +} +``` + + +### `replace_derive_with_manual_impl` +**Source:** [replace_derive_with_manual_impl.rs](crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs#20) + +Converts a `derive` impl into a manual one. + +#### Before +```rust +#[derive(Deb┃ug, Display)] +struct S; +``` + +#### After +```rust +#[derive(Display)] +struct S; + +impl Debug for S { + ┃fn fmt(&self, f: &mut Formatter) -> Result<()> { + f.debug_struct("S").finish() + } +} +``` + + +### `replace_if_let_with_match` +**Source:** [replace_if_let_with_match.rs](crates/ide-assists/src/handlers/replace_if_let_with_match.rs#20) + +Replaces a `if let` expression with a `match` expression. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + ┃if let Action::Move { distance } = action { + foo(distance) + } else { + bar() + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move { distance } => foo(distance), + _ => bar(), + } +} +``` + + +### `replace_is_some_with_if_let_some` +**Source:** [replace_is_method_with_if_let_method.rs](crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs#9) + +Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`. + +#### Before +```rust +fn main() { + let x = Some(1); + if x.is_som┃e() {} +} +``` + +#### After +```rust +fn main() { + let x = Some(1); + if let Some(${0:x1}) = x {} +} +``` + + +### `replace_let_with_if_let` +**Source:** [replace_let_with_if_let.rs](crates/ide-assists/src/handlers/replace_let_with_if_let.rs#9) + +Replaces `let` with an `if let`. + +#### Before +```rust + +fn main(action: Action) { + ┃let x = compute(); +} + +fn compute() -> Option { None } +``` + +#### After +```rust + +fn main(action: Action) { + if let Some(x) = compute() { + } +} + +fn compute() -> Option { None } +``` + + +### `replace_match_with_if_let` +**Source:** [replace_if_let_with_match.rs](crates/ide-assists/src/handlers/replace_if_let_with_match.rs#188) + +Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + ┃match action { + Action::Move { distance } => foo(distance), + _ => bar(), + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + if let Action::Move { distance } = action { + foo(distance) + } else { + bar() + } +} +``` + + +### `replace_named_generic_with_impl` +**Source:** [replace_named_generic_with_impl.rs](crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs#18) + +Replaces named generic with an `impl Trait` in function argument. + +#### Before +```rust +fn new>(location: P) -> Self {} +``` + +#### After +```rust +fn new(location: impl AsRef) -> Self {} +``` + + +### `replace_qualified_name_with_use` +**Source:** [replace_qualified_name_with_use.rs](crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs#13) + +Adds a use statement for a given fully-qualified name. + +#### Before +```rust +fn process(map: std::collections::┃HashMap) {} +``` + +#### After +```rust +use std::collections::HashMap; + +fn process(map: HashMap) {} +``` + + +### `replace_string_with_char` +**Source:** [replace_string_with_char.rs](crates/ide-assists/src/handlers/replace_string_with_char.rs#11) + +Replace string literal with char literal. + +#### Before +```rust +fn main() { + find("{┃"); +} +``` + +#### After +```rust +fn main() { + find('{'); +} +``` + + +### `replace_try_expr_with_match` +**Source:** [replace_try_expr_with_match.rs](crates/ide-assists/src/handlers/replace_try_expr_with_match.rs#18) + +Replaces a `try` expression with a `match` expression. + +#### Before +```rust +fn handle() { + let pat = Some(true)┃?; +} +``` + +#### After +```rust +fn handle() { + let pat = match Some(true) { + Some(it) => it, + None => return None, + }; +} +``` + + +### `replace_turbofish_with_explicit_type` +**Source:** [replace_turbofish_with_explicit_type.rs](crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs#12) + +Converts `::<_>` to an explicit type assignment. + +#### Before +```rust +fn make() -> T { ) } +fn main() { + let a = make┃::(); +} +``` + +#### After +```rust +fn make() -> T { ) } +fn main() { + let a: i32 = make(); +} +``` + + +### `replace_with_eager_method` +**Source:** [replace_method_eager_lazy.rs](crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#89) + +Replace `unwrap_or_else` with `unwrap_or` and `ok_or_else` with `ok_or`. + +#### Before +```rust +fn foo() { + let a = Some(1); + a.unwra┃p_or_else(|| 2); +} +``` + +#### After +```rust +fn foo() { + let a = Some(1); + a.unwrap_or(2); +} +``` + + +### `replace_with_lazy_method` +**Source:** [replace_method_eager_lazy.rs](crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#9) + +Replace `unwrap_or` with `unwrap_or_else` and `ok_or` with `ok_or_else`. + +#### Before +```rust +fn foo() { + let a = Some(1); + a.unwra┃p_or(2); +} +``` + +#### After +```rust +fn foo() { + let a = Some(1); + a.unwrap_or_else(|| 2); +} +``` + + +### `sort_items` +**Source:** [sort_items.rs](crates/ide-assists/src/handlers/sort_items.rs#12) + +Sorts item members alphabetically: fields, enum variants and methods. + +#### Before +```rust +struct ┃Foo┃ { second: u32, first: String } +``` + +#### After +```rust +struct Foo { first: String, second: u32 } +``` + +--- + +#### Before +```rust +trait ┃Bar┃ { + fn second(&self) -> u32; + fn first(&self) -> String; +} +``` + +#### After +```rust +trait Bar { + fn first(&self) -> String; + fn second(&self) -> u32; +} +``` + +--- + +#### Before +```rust +struct Baz; +impl ┃Baz┃ { + fn second(&self) -> u32; + fn first(&self) -> String; +} +``` + +#### After +```rust +struct Baz; +impl Baz { + fn first(&self) -> String; + fn second(&self) -> u32; +} +``` + +--- +There is a difference between sorting enum variants: + +#### Before +```rust +enum ┃Animal┃ { + Dog(String, f64), + Cat { weight: f64, name: String }, +} +``` + +#### After +```rust +enum Animal { + Cat { weight: f64, name: String }, + Dog(String, f64), +} +``` + +and sorting a single enum struct variant: + +#### Before +```rust +enum Animal { + Dog(String, f64), + Cat ┃{ weight: f64, name: String }┃, +} +``` + +#### After +```rust +enum Animal { + Dog(String, f64), + Cat { name: String, weight: f64 }, +} +``` + + +### `split_import` +**Source:** [split_import.rs](crates/ide-assists/src/handlers/split_import.rs#5) + +Wraps the tail of import into braces. + +#### Before +```rust +use std::┃collections::HashMap; +``` + +#### After +```rust +use std::{collections::HashMap}; +``` + + +### `sugar_impl_future_into_async` +**Source:** [toggle_async_sugar.rs](crates/ide-assists/src/handlers/toggle_async_sugar.rs#13) + +Rewrites asynchronous function from `-> impl Future` into `async fn`. +This action does not touch the function body and therefore `async { 0 }` +block does not transform to just `0`. + +#### Before +```rust +pub fn foo() -> impl core::future::F┃uture { + async { 0 } +} +``` + +#### After +```rust +pub async fn foo() -> usize { + async { 0 } +} +``` + + +### `toggle_ignore` +**Source:** [toggle_ignore.rs](crates/ide-assists/src/handlers/toggle_ignore.rs#8) + +Adds `#[ignore]` attribute to the test. + +#### Before +```rust +┃#[test] +fn arithmetics { + assert_eq!(2 + 2, 5); +} +``` + +#### After +```rust +#[test] +#[ignore] +fn arithmetics { + assert_eq!(2 + 2, 5); +} +``` + + +### `toggle_macro_delimiter` +**Source:** [toggle_macro_delimiter.rs](crates/ide-assists/src/handlers/toggle_macro_delimiter.rs#9) + +Change macro delimiters in the order of `( -> { -> [ -> (`. + +#### Before +```rust +macro_rules! sth { + () => {}; +} + +sth!┃( ); +``` + +#### After +```rust +macro_rules! sth { + () => {}; +} + +sth!{ } +``` + + +### `unmerge_match_arm` +**Source:** [unmerge_match_arm.rs](crates/ide-assists/src/handlers/unmerge_match_arm.rs#10) + +Splits the current match with a `|` pattern into two arms with identical bodies. + +#### Before +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move(..) ┃| Action::Stop => foo(), + } +} +``` + +#### After +```rust +enum Action { Move { distance: u32 }, Stop } + +fn handle(action: Action) { + match action { + Action::Move(..) => foo(), + Action::Stop => foo(), + } +} +``` + + +### `unmerge_use` +**Source:** [unmerge_use.rs](crates/ide-assists/src/handlers/unmerge_use.rs#12) + +Extracts single use item from use list. + +#### Before +```rust +use std::fmt::{Debug, Display┃}; +``` + +#### After +```rust +use std::fmt::{Debug}; +use std::fmt::Display; +``` + + +### `unnecessary_async` +**Source:** [unnecessary_async.rs](crates/ide-assists/src/handlers/unnecessary_async.rs#17) + +Removes the `async` mark from functions which have no `.await` in their body. +Looks for calls to the functions and removes the `.await` on the call site. + +#### Before +```rust +pub asy┃nc fn foo() {} +pub async fn bar() { foo().await } +``` + +#### After +```rust +pub fn foo() {} +pub async fn bar() { foo() } +``` + + +### `unqualify_method_call` +**Source:** [unqualify_method_call.rs](crates/ide-assists/src/handlers/unqualify_method_call.rs#9) + +Transforms universal function call syntax into a method call. + +#### Before +```rust +fn main() { + std::ops::Add::add┃(1, 2); +} +``` + +#### After +```rust +use std::ops::Add; + +fn main() { + 1.add(2); +} +``` + + +### `unwrap_block` +**Source:** [unwrap_block.rs](crates/ide-assists/src/handlers/unwrap_block.rs#12) + +This assist removes if...else, for, while and loop control statements to just keep the body. + +#### Before +```rust +fn foo() { + if true {┃ + println!("foo"); + } +} +``` + +#### After +```rust +fn foo() { + println!("foo"); +} +``` + + +### `unwrap_option_return_type` +**Source:** [unwrap_return_type.rs](crates/ide-assists/src/handlers/unwrap_return_type.rs#13) + +Unwrap the function's return type. + +#### Before +```rust +fn foo() -> Option┃ { Some(42i32) } +``` + +#### After +```rust +fn foo() -> i32 { 42i32 } +``` + + +### `unwrap_result_return_type` +**Source:** [unwrap_return_type.rs](crates/ide-assists/src/handlers/unwrap_return_type.rs#26) + +Unwrap the function's return type. + +#### Before +```rust +fn foo() -> Result┃ { Ok(42i32) } +``` + +#### After +```rust +fn foo() -> i32 { 42i32 } +``` + + +### `unwrap_tuple` +**Source:** [unwrap_tuple.rs](crates/ide-assists/src/handlers/unwrap_tuple.rs#8) + +Unwrap the tuple to different variables. + +#### Before +```rust +fn main() { + ┃let (foo, bar) = ("Foo", "Bar"); +} +``` + +#### After +```rust +fn main() { + let foo = "Foo"; + let bar = "Bar"; +} +``` + + +### `wrap_return_type_in_option` +**Source:** [wrap_return_type.rs](crates/ide-assists/src/handlers/wrap_return_type.rs#16) + +Wrap the function's return type into Option. + +#### Before +```rust +fn foo() -> i32┃ { 42i32 } +``` + +#### After +```rust +fn foo() -> Option { Some(42i32) } +``` + + +### `wrap_return_type_in_result` +**Source:** [wrap_return_type.rs](crates/ide-assists/src/handlers/wrap_return_type.rs#29) + +Wrap the function's return type into Result. + +#### Before +```rust +fn foo() -> i32┃ { 42i32 } +``` + +#### After +```rust +fn foo() -> Result { Ok(42i32) } +``` + + +### `wrap_unwrap_cfg_attr` +**Source:** [wrap_unwrap_cfg_attr.rs](crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs#12) + +Wraps an attribute to a cfg_attr attribute or unwraps a cfg_attr attribute to the inner attributes. + +#### Before +```rust +#[derive┃(Debug)] +struct S { + field: i32 +} +``` + +#### After +```rust +#[cfg_attr(┃, derive(Debug))] +struct S { + field: i32 +} +``` diff --git a/src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md b/src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md new file mode 100644 index 000000000000..d34c459ad025 --- /dev/null +++ b/src/tools/rust-analyzer/docs/book/src/diagnostics_generated.md @@ -0,0 +1,516 @@ +//! Generated by `cargo xtask codegen diagnostics-docs`, do not edit by hand. + +#### attribute-expansion-disabled + +Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#7) + + +This diagnostic is shown for attribute proc macros when attribute expansions have been disabled. + + + + +#### await-outside-of-async + +Source: [await_outside_of_async.rs](crates/ide-diagnostics/src/handlers/await_outside_of_async.rs#3) + + +This diagnostic is triggered if the `await` keyword is used outside of an async function or block + + + + +#### break-outside-of-loop + +Source: [break_outside_of_loop.rs](crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs#3) + + +This diagnostic is triggered if the `break` keyword is used outside of a loop. + + + + +#### cast-to-unsized + +Source: [invalid_cast.rs](crates/ide-diagnostics/src/handlers/invalid_cast.rs#106) + + +This diagnostic is triggered when casting to an unsized type + + + + +#### expected-function + +Source: [expected_function.rs](crates/ide-diagnostics/src/handlers/expected_function.rs#5) + + +This diagnostic is triggered if a call is made on something that is not callable. + + + + +#### generic-args-prohibited + +Source: [generic_args_prohibited.rs](crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs#10) + + +This diagnostic is shown when generic arguments are provided for a type that does not accept +generic arguments. + + + + +#### inactive-code + +Source: [inactive_code.rs](crates/ide-diagnostics/src/handlers/inactive_code.rs#6) + + +This diagnostic is shown for code with inactive `#[cfg]` attributes. + + + + +#### incoherent-impl + +Source: [incoherent_impl.rs](crates/ide-diagnostics/src/handlers/incoherent_impl.rs#6) + + +This diagnostic is triggered if the targe type of an impl is from a foreign crate. + + + + +#### incorrect-ident-case + +Source: [incorrect_case.rs](crates/ide-diagnostics/src/handlers/incorrect_case.rs#13) + + +This diagnostic is triggered if an item name doesn't follow [Rust naming convention](https://doc.rust-lang.org/1.0.0/style/style/naming/README.html). + + + + +#### invalid-cast + +Source: [invalid_cast.rs](crates/ide-diagnostics/src/handlers/invalid_cast.rs#18) + + +This diagnostic is triggered if the code contains an illegal cast + + + + +#### invalid-derive-target + +Source: [invalid_derive_target.rs](crates/ide-diagnostics/src/handlers/invalid_derive_target.rs#3) + + +This diagnostic is shown when the derive attribute is used on an item other than a `struct`, +`enum` or `union`. + + + + +#### macro-def-error + +Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#24) + + +This diagnostic is shown for macro expansion errors. + + + + +#### macro-error + +Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#3) + + +This diagnostic is shown for macro expansion errors. + + + + +#### malformed-derive + +Source: [malformed_derive.rs](crates/ide-diagnostics/src/handlers/malformed_derive.rs#3) + + +This diagnostic is shown when the derive attribute has invalid input. + + + + +#### mismatched-arg-count + +Source: [mismatched_arg_count.rs](crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs#31) + + +This diagnostic is triggered if a function is invoked with an incorrect amount of arguments. + + + + +#### mismatched-tuple-struct-pat-arg-count + +Source: [mismatched_arg_count.rs](crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs#11) + + +This diagnostic is triggered if a function is invoked with an incorrect amount of arguments. + + + + +#### missing-fields + +Source: [missing_fields.rs](crates/ide-diagnostics/src/handlers/missing_fields.rs#19) + + +This diagnostic is triggered if record lacks some fields that exist in the corresponding structure. + +Example: + +```rust +struct A { a: u8, b: u8 } + +let a = A { a: 10 }; +``` + + + + +#### missing-match-arm + +Source: [missing_match_arms.rs](crates/ide-diagnostics/src/handlers/missing_match_arms.rs#3) + + +This diagnostic is triggered if `match` block is missing one or more match arms. + + + + +#### missing-unsafe + +Source: [missing_unsafe.rs](crates/ide-diagnostics/src/handlers/missing_unsafe.rs#10) + + +This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block. + + + + +#### moved-out-of-ref + +Source: [moved_out_of_ref.rs](crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs#4) + + +This diagnostic is triggered on moving non copy things out of references. + + + + +#### need-mut + +Source: [mutability_errors.rs](crates/ide-diagnostics/src/handlers/mutability_errors.rs#8) + + +This diagnostic is triggered on mutating an immutable variable. + + + + +#### no-such-field + +Source: [no_such_field.rs](crates/ide-diagnostics/src/handlers/no_such_field.rs#12) + + +This diagnostic is triggered if created structure does not have field provided in record. + + + + +#### non-exhaustive-let + +Source: [non_exhaustive_let.rs](crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs#3) + + +This diagnostic is triggered if a `let` statement without an `else` branch has a non-exhaustive +pattern. + + + + +#### private-assoc-item + +Source: [private_assoc_item.rs](crates/ide-diagnostics/src/handlers/private_assoc_item.rs#3) + + +This diagnostic is triggered if the referenced associated item is not visible from the current +module. + + + + +#### private-field + +Source: [private_field.rs](crates/ide-diagnostics/src/handlers/private_field.rs#3) + + +This diagnostic is triggered if the accessed field is not visible from the current module. + + + + +#### proc-macro-disabled + +Source: [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#11) + + +This diagnostic is shown for proc macros that have been specifically disabled via `rust-analyzer.procMacro.ignored`. + + + + +#### remove-trailing-return + +Source: [remove_trailing_return.rs](crates/ide-diagnostics/src/handlers/remove_trailing_return.rs#8) + + +This diagnostic is triggered when there is a redundant `return` at the end of a function +or closure. + + + + +#### remove-unnecessary-else + +Source: [remove_unnecessary_else.rs](crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs#17) + + +This diagnostic is triggered when there is an `else` block for an `if` expression whose +then branch diverges (e.g. ends with a `return`, `continue`, `break` e.t.c). + + + + +#### replace-filter-map-next-with-find-map + +Source: [replace_filter_map_next_with_find_map.rs](crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs#11) + + +This diagnostic is triggered when `.filter_map(..).next()` is used, rather than the more concise `.find_map(..)`. + + + + +#### trait-impl-incorrect-safety + +Source: [trait_impl_incorrect_safety.rs](crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs#6) + + +Diagnoses incorrect safety annotations of trait impls. + + + + +#### trait-impl-missing-assoc_item + +Source: [trait_impl_missing_assoc_item.rs](crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs#7) + + +Diagnoses missing trait items in a trait impl. + + + + +#### trait-impl-orphan + +Source: [trait_impl_orphan.rs](crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs#5) + + +Only traits defined in the current crate can be implemented for arbitrary types + + + + +#### trait-impl-redundant-assoc_item + +Source: [trait_impl_redundant_assoc_item.rs](crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs#12) + + +Diagnoses redundant trait items in a trait impl. + + + + +#### type-mismatch + +Source: [type_mismatch.rs](crates/ide-diagnostics/src/handlers/type_mismatch.rs#20) + + +This diagnostic is triggered when the type of an expression or pattern does not match +the expected type. + + + + +#### typed-hole + +Source: [typed_hole.rs](crates/ide-diagnostics/src/handlers/typed_hole.rs#18) + + +This diagnostic is triggered when an underscore expression is used in an invalid position. + + + + +#### undeclared-label + +Source: [undeclared_label.rs](crates/ide-diagnostics/src/handlers/undeclared_label.rs#3) + + + + + + +#### unimplemented-builtin-macro + +Source: [unimplemented_builtin_macro.rs](crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs#3) + + +This diagnostic is shown for builtin macros which are not yet implemented by rust-analyzer + + + + +#### unlinked-file + +Source: [unlinked_file.rs](crates/ide-diagnostics/src/handlers/unlinked_file.rs#20) + + +This diagnostic is shown for files that are not included in any crate, or files that are part of +crates rust-analyzer failed to discover. The file will not have IDE features available. + + + + +#### unnecessary-braces + +Source: [useless_braces.rs](crates/ide-diagnostics/src/handlers/useless_braces.rs#9) + + +Diagnostic for unnecessary braces in `use` items. + + + + +#### unreachable-label + +Source: [unreachable_label.rs](crates/ide-diagnostics/src/handlers/unreachable_label.rs#3) + + + + + + +#### unresolved-assoc-item + +Source: [unresolved_assoc_item.rs](crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs#3) + + +This diagnostic is triggered if the referenced associated item does not exist. + + + + +#### unresolved-extern-crate + +Source: [unresolved_extern_crate.rs](crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs#3) + + +This diagnostic is triggered if rust-analyzer is unable to discover referred extern crate. + + + + +#### unresolved-field + +Source: [unresolved_field.rs](crates/ide-diagnostics/src/handlers/unresolved_field.rs#23) + + +This diagnostic is triggered if a field does not exist on a given type. + + + + +#### unresolved-ident + +Source: [unresolved_ident.rs](crates/ide-diagnostics/src/handlers/unresolved_ident.rs#3) + + +This diagnostic is triggered if an expr-position ident is invalid. + + + + +#### unresolved-import + +Source: [unresolved_import.rs](crates/ide-diagnostics/src/handlers/unresolved_import.rs#3) + + +This diagnostic is triggered if rust-analyzer is unable to resolve a path in +a `use` declaration. + + + + +#### unresolved-macro-call + +Source: [unresolved_macro_call.rs](crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs#3) + + +This diagnostic is triggered if rust-analyzer is unable to resolve the path +to a macro in a macro invocation. + + + + +#### unresolved-method + +Source: [unresolved_method.rs](crates/ide-diagnostics/src/handlers/unresolved_method.rs#15) + + +This diagnostic is triggered if a method does not exist on a given type. + + + + +#### unresolved-module + +Source: [unresolved_module.rs](crates/ide-diagnostics/src/handlers/unresolved_module.rs#8) + + +This diagnostic is triggered if rust-analyzer is unable to discover referred module. + + + + +#### unused-mut + +Source: [mutability_errors.rs](crates/ide-diagnostics/src/handlers/mutability_errors.rs#62) + + +This diagnostic is triggered when a mutable variable isn't actually mutated. + + + + +#### unused-variables + +Source: [unused_variables.rs](crates/ide-diagnostics/src/handlers/unused_variables.rs#13) + + +This diagnostic is triggered when a local variable is not used. + + diff --git a/src/tools/rust-analyzer/docs/book/src/features_generated.md b/src/tools/rust-analyzer/docs/book/src/features_generated.md new file mode 100644 index 000000000000..2c5829b1f54c --- /dev/null +++ b/src/tools/rust-analyzer/docs/book/src/features_generated.md @@ -0,0 +1,940 @@ +//! Generated by `cargo xtask codegen feature-docs`, do not edit by hand. + +### Annotations +**Source:** [annotations.rs](crates/ide/src/annotations.rs#19) + +Provides user with annotations above items for looking up references or impl blocks +and running/debugging binaries. + +![Annotations](https://user-images.githubusercontent.com/48062697/113020672-b7c34f00-917a-11eb-8f6e-858735660a0e.png) + + +### Auto Import +**Source:** [auto_import.rs](crates/ide-assists/src/handlers/auto_import.rs#15) + +Using the `auto-import` assist it is possible to insert missing imports for unresolved items. +When inserting an import it will do so in a structured manner by keeping imports grouped, +separated by a newline in the following order: + +- `std` and `core` +- External Crates +- Current Crate, paths prefixed by `crate` +- Current Module, paths prefixed by `self` +- Super Module, paths prefixed by `super` + +Example: +```rust +use std::fs::File; + +use itertools::Itertools; +use syntax::ast; + +use crate::utils::insert_use; + +use self::auto_import; + +use super::AssistContext; +``` + +#### Import Granularity + +It is possible to configure how use-trees are merged with the `imports.granularity.group` setting. +It has the following configurations: + +- `crate`: Merge imports from the same crate into a single use statement. This kind of + nesting is only supported in Rust versions later than 1.24. +- `module`: Merge imports from the same module into a single use statement. +- `item`: Don't merge imports at all, creating one import per item. +- `preserve`: Do not change the granularity of any imports. For auto-import this has the same + effect as `item`. +- `one`: Merge all imports into a single use statement as long as they have the same visibility + and attributes. + +In `VS Code` the configuration for this is `rust-analyzer.imports.granularity.group`. + +#### Import Prefix + +The style of imports in the same crate is configurable through the `imports.prefix` setting. +It has the following configurations: + +- `crate`: This setting will force paths to be always absolute, starting with the `crate` + prefix, unless the item is defined outside of the current crate. +- `self`: This setting will force paths that are relative to the current module to always + start with `self`. This will result in paths that always start with either `crate`, `self`, + `super` or an extern crate identifier. +- `plain`: This setting does not impose any restrictions in imports. + +In `VS Code` the configuration for this is `rust-analyzer.imports.prefix`. + +![Auto Import](https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif) + + +### Completion With Autoimport +**Source:** [flyimport.rs](crates/ide-completion/src/completions/flyimport.rs#20) + +When completing names in the current scope, proposes additional imports from other modules or crates, +if they can be qualified in the scope, and their name contains all symbols from the completion input. + +To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent. +If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the containing is checked case-insensitively. + +``` +fn main() { + pda$0 +} +# pub mod std { pub mod marker { pub struct PhantomData { } } } +``` +-> +``` +use std::marker::PhantomData; + +fn main() { + PhantomData +} +# pub mod std { pub mod marker { pub struct PhantomData { } } } +``` + +Also completes associated items, that require trait imports. +If any unresolved and/or partially-qualified path precedes the input, it will be taken into account. +Currently, only the imports with their import path ending with the whole qualifier will be proposed +(no fuzzy matching for qualifier). + +``` +mod foo { + pub mod bar { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } + } +} + +fn main() { + bar::Item::TEST_A$0 +} +``` +-> +``` +use foo::bar; + +mod foo { + pub mod bar { + pub struct Item; + + impl Item { + pub const TEST_ASSOC: usize = 3; + } + } +} + +fn main() { + bar::Item::TEST_ASSOC +} +``` + +NOTE: currently, if an assoc item comes from a trait that's not currently imported, and it also has an unresolved and/or partially-qualified path, +no imports will be proposed. + +#### Fuzzy search details + +To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only +(i.e. in `HashMap` in the `std::collections::HashMap` path). +For the same reasons, avoids searching for any path imports for inputs with their length less than 2 symbols +(but shows all associated items for any input length). + +#### Import configuration + +It is possible to configure how use-trees are merged with the `imports.granularity.group` setting. +Mimics the corresponding behavior of the `Auto Import` feature. + +#### LSP and performance implications + +The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits` +(case-sensitive) resolve client capability in its client capabilities. +This way the server is able to defer the costly computations, doing them for a selected completion item only. +For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones, +which might be slow ergo the feature is automatically disabled. + +#### Feature toggle + +The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.autoimport.enable` flag. +Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corresponding +capability enabled. + + +### Debug ItemTree +**Source:** [view_item_tree.rs](crates/ide/src/view_item_tree.rs#5) + +Displays the ItemTree of the currently open file, for debugging. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Debug ItemTree** | + + +### Expand Macro Recursively +**Source:** [expand_macro.rs](crates/ide/src/expand_macro.rs#18) + +Shows the full macro expansion of the macro at the current caret position. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Expand macro recursively at caret** | + +![Expand Macro Recursively](https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif) + + +### Expand and Shrink Selection +**Source:** [extend_selection.rs](crates/ide/src/extend_selection.rs#15) + +Extends or shrinks the current selection to the encompassing syntactic construct +(expression, statement, item, module, etc). It works with multiple cursors. + +| Editor | Shortcut | +|---------|----------| +| VS Code | Alt+Shift+→, Alt+Shift+← | + +![Expand and Shrink Selection](https://user-images.githubusercontent.com/48062697/113020651-b42fc800-917a-11eb-8a4f-cf1a07859fac.gif) + + +### File Structure +**Source:** [file_structure.rs](crates/ide/src/file_structure.rs#26) + +Provides a tree of the symbols defined in the file. Can be used to + +* fuzzy search symbol in a file (super useful) +* draw breadcrumbs to describe the context around the cursor +* draw outline of the file + +| Editor | Shortcut | +|---------|----------| +| VS Code | Ctrl+Shift+O | + +![File Structure](https://user-images.githubusercontent.com/48062697/113020654-b42fc800-917a-11eb-8388-e7dc4d92b02e.gif) + + +### Find All References +**Source:** [references.rs](crates/ide/src/references.rs#42) + +Shows all references of the item at the cursor location + +| Editor | Shortcut | +|---------|----------| +| VS Code | Shift+Alt+F12 | + +![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif) + + +### Folding +**Source:** [folding_ranges.rs](crates/ide/src/folding_ranges.rs#36) + +Defines folding regions for curly braced blocks, runs of consecutive use, mod, const or static +items, and `region` / `endregion` comment markers. + + +### Format String Completion +**Source:** [format_like.rs](crates/ide-completion/src/completions/postfix/format_like.rs#0) + +`"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`. + +The following postfix snippets are available: + +* `format` -> `format!(...)` +* `panic` -> `panic!(...)` +* `println` -> `println!(...)` +* `log`: +** `logd` -> `log::debug!(...)` +** `logt` -> `log::trace!(...)` +** `logi` -> `log::info!(...)` +** `logw` -> `log::warn!(...)` +** `loge` -> `log::error!(...)` + +![Format String Completion](https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif) + + +### Go to Declaration +**Source:** [goto_declaration.rs](crates/ide/src/goto_declaration.rs#13) + +Navigates to the declaration of an identifier. + +This is the same as `Go to Definition` with the following exceptions: +- outline modules will navigate to the `mod name;` item declaration +- trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl +- fields in patterns will navigate to the field declaration of the struct, union or variant + + +### Go to Definition +**Source:** [goto_definition.rs](crates/ide/src/goto_definition.rs#28) + +Navigates to the definition of an identifier. + +For outline modules, this will navigate to the source file of the module. + +| Editor | Shortcut | +|---------|----------| +| VS Code | F12 | + +![Go to Definition](https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif) + + +### Go to Implementation +**Source:** [goto_implementation.rs](crates/ide/src/goto_implementation.rs#11) + +Navigates to the impl items of types. + +| Editor | Shortcut | +|---------|----------| +| VS Code | Ctrl+F12 + +![Go to Implementation](https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif) + + +### Go to Type Definition +**Source:** [goto_type_definition.rs](crates/ide/src/goto_type_definition.rs#7) + +Navigates to the type of an identifier. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **Go to Type Definition** | + +![Go to Type Definition](https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif) + + +### Highlight Related +**Source:** [highlight_related.rs](crates/ide/src/highlight_related.rs#42) + +Highlights constructs related to the thing under the cursor: + +1. if on an identifier, highlights all references to that identifier in the current file + * additionally, if the identifier is a trait in a where clause, type parameter trait bound or use item, highlights all references to that trait's assoc items in the corresponding scope +1. if on an `async` or `await` token, highlights all yield points for that async context +1. if on a `return` or `fn` keyword, `?` character or `->` return type arrow, highlights all exit points for that context +1. if on a `break`, `loop`, `while` or `for` token, highlights all break points for that loop or block context +1. if on a `move` or `|` token that belongs to a closure, highlights all captures of the closure. + +Note: `?`, `|` and `->` do not currently trigger this behavior in the VSCode editor. + + +### Hover +**Source:** [hover.rs](crates/ide/src/hover.rs#116) + +Shows additional information, like the type of an expression or the documentation for a definition when "focusing" code. +Focusing is usually hovering with a mouse, but can also be triggered with a shortcut. + +![Hover](https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif) + + +### Inlay Hints +**Source:** [inlay_hints.rs](crates/ide/src/inlay_hints.rs#41) + +rust-analyzer shows additional information inline with the source code. +Editors usually render this using read-only virtual text snippets interspersed with code. + +rust-analyzer by default shows hints for + +* types of local variables +* names of function arguments +* names of const generic parameters +* types of chained expressions + +Optionally, one can enable additional hints for + +* return types of closure expressions +* elided lifetimes +* compiler inserted reborrows +* names of generic type and lifetime parameters + +Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if +any of the +[following criteria](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L92-L99) +are met: + +* the parameter name is a suffix of the function's name +* the argument is a qualified constructing or call expression where the qualifier is an ADT +* exact argument<->parameter match(ignoring leading underscore) or parameter is a prefix/suffix + of argument with _ splitting it off +* the parameter name starts with `ra_fixture` +* the parameter name is a +[well known name](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L200) +in a unary function +* the parameter name is a +[single character](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L201) +in a unary function + +![Inlay hints](https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png) + + +### Interpret A Function, Static Or Const. +**Source:** [interpret.rs](crates/ide/src/interpret.rs#8) + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Interpret** | + + +### Join Lines +**Source:** [join_lines.rs](crates/ide/src/join_lines.rs#20) + +Join selected lines into one, smartly fixing up whitespace, trailing commas, and braces. + +See [this gif](https://user-images.githubusercontent.com/1711539/124515923-4504e800-dde9-11eb-8d58-d97945a1a785.gif) for the cases handled specially by joined lines. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Join lines** | + +![Join Lines](https://user-images.githubusercontent.com/48062697/113020661-b6922200-917a-11eb-87c4-b75acc028f11.gif) + + +### Magic Completions +**Source:** [lib.rs](crates/ide-completion/src/lib.rs#78) + +In addition to usual reference completion, rust-analyzer provides some ✨magic✨ +completions as well: + +Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor +is placed at the appropriate position. Even though `if` is easy to type, you +still want to complete it, to get ` { }` for free! `return` is inserted with a +space or `;` depending on the return type of the function. + +When completing a function call, `()` are automatically inserted. If a function +takes arguments, the cursor is positioned inside the parenthesis. + +There are postfix completions, which can be triggered by typing something like +`foo().if`. The word after `.` determines postfix completion. Possible variants are: + +- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result` +- `expr.match` -> `match expr {}` +- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result` +- `expr.ref` -> `&expr` +- `expr.refm` -> `&mut expr` +- `expr.let` -> `let $0 = expr;` +- `expr.lete` -> `let $1 = expr else { $0 };` +- `expr.letm` -> `let mut $0 = expr;` +- `expr.not` -> `!expr` +- `expr.dbg` -> `dbg!(expr)` +- `expr.dbgr` -> `dbg!(&expr)` +- `expr.call` -> `(expr)` + +There also snippet completions: + +#### Expressions + +- `pd` -> `eprintln!(" = {:?}", );` +- `ppd` -> `eprintln!(" = {:#?}", );` + +#### Items + +- `tfn` -> `#[test] fn feature(){}` +- `tmod` -> +```rust +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_name() {} +} +``` + +And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities. +Those are the additional completion options with automatic `use` import and options from all project importable items, +fuzzy matched against the completion input. + +![Magic Completions](https://user-images.githubusercontent.com/48062697/113020667-b72ab880-917a-11eb-8778-716cf26a0eb3.gif) + + +### Matching Brace +**Source:** [matching_brace.rs](crates/ide/src/matching_brace.rs#6) + +If the cursor is on any brace (`<>(){}[]||`) which is a part of a brace-pair, +moves cursor to the matching brace. It uses the actual parser to determine +braces, so it won't confuse generics with comparisons. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Find matching brace** | + +![Matching Brace](https://user-images.githubusercontent.com/48062697/113065573-04298180-91b1-11eb-8dec-d4e2a202f304.gif) + + +### Memory Usage +**Source:** [apply_change.rs](crates/ide-db/src/apply_change.rs#43) + +Clears rust-analyzer's internal database and prints memory usage statistics. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Memory Usage (Clears Database)** + + +### Move Item +**Source:** [move_item.rs](crates/ide/src/move_item.rs#16) + +Move item under cursor or selection up and down. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Move item up** +| VS Code | **rust-analyzer: Move item down** + +![Move Item](https://user-images.githubusercontent.com/48062697/113065576-04298180-91b1-11eb-91ce-4505e99ed598.gif) + + +### On Enter +**Source:** [on_enter.rs](crates/ide/src/typing/on_enter.rs#17) + +rust-analyzer can override Enter key to make it smarter: + +- Enter inside triple-slash comments automatically inserts `///` +- Enter in the middle or after a trailing space in `//` inserts `//` +- Enter inside `//!` doc comments automatically inserts `//!` +- Enter after `{` indents contents and closing `}` of single-line block + +This action needs to be assigned to shortcut explicitly. + +Note that, depending on the other installed extensions, this feature can visibly slow down typing. +Similarly, if rust-analyzer crashes or stops responding, `Enter` might not work. +In that case, you can still press `Shift-Enter` to insert a newline. + +#### VS Code + +Add the following to `keybindings.json`: +```json +{ + "key": "Enter", + "command": "rust-analyzer.onEnter", + "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust" +} +```` + +When using the Vim plugin: +```json +{ + "key": "Enter", + "command": "rust-analyzer.onEnter", + "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust && vim.mode == 'Insert'" +} +```` + +![On Enter](https://user-images.githubusercontent.com/48062697/113065578-04c21800-91b1-11eb-82b8-22b8c481e645.gif) + + +### On Typing Assists +**Source:** [typing.rs](crates/ide/src/typing.rs#42) + +Some features trigger on typing certain characters: + +- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression +- typing `=` between two expressions adds `;` when in statement position +- typing `=` to turn an assignment into an equality comparison removes `;` when in expression position +- typing `.` in a chain method call auto-indents +- typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression +- typing `{` in a use item adds a closing `}` in the right place +- typing `>` to complete a return type `->` will insert a whitespace after it + +#### VS Code + +Add the following to `settings.json`: +```json +"editor.formatOnType": true, +``` + +![On Typing Assists](https://user-images.githubusercontent.com/48062697/113166163-69758500-923a-11eb-81ee-eb33ec380399.gif) +![On Typing Assists](https://user-images.githubusercontent.com/48062697/113171066-105c2000-923f-11eb-87ab-f4a263346567.gif) + + +### Open Docs +**Source:** [doc_links.rs](crates/ide/src/doc_links.rs#118) + +Retrieve a links to documentation for the given symbol. + +The simplest way to use this feature is via the context menu. Right-click on +the selected item. The context menu opens. Select **Open Docs**. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Open Docs** | + + +### Parent Module +**Source:** [parent_module.rs](crates/ide/src/parent_module.rs#14) + +Navigates to the parent module of the current module. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Locate parent module** | + +![Parent Module](https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif) + + +### Related Tests +**Source:** [runnables.rs](crates/ide/src/runnables.rs#202) + +Provides a sneak peek of all tests where the current item is used. + +The simplest way to use this feature is via the context menu. Right-click on +the selected item. The context menu opens. Select **Peek Related Tests**. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Peek Related Tests** | + + +### Rename +**Source:** [rename.rs](crates/ide/src/rename.rs#70) + +Renames the item below the cursor and all of its references + +| Editor | Shortcut | +|---------|----------| +| VS Code | F2 | + +![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif) + + +### Run +**Source:** [runnables.rs](crates/ide/src/runnables.rs#116) + +Shows a popup suggesting to run a test/benchmark/binary **at the current cursor +location**. Super useful for repeatedly running just a single test. Do bind this +to a shortcut! + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Run** | + +![Run](https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif) + + +### Semantic Syntax Highlighting +**Source:** [syntax_highlighting.rs](crates/ide/src/syntax_highlighting.rs#68) + +rust-analyzer highlights the code semantically. +For example, `Bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait. +rust-analyzer does not specify colors directly, instead it assigns a tag (like `struct`) and a set of modifiers (like `declaration`) to each token. +It's up to the client to map those to specific colors. + +The general rule is that a reference to an entity gets colored the same way as the entity itself. +We also give special modifier for `mut` and `&mut` local variables. + + +#### Token Tags + +Rust-analyzer currently emits the following token tags: + +- For items: + +| | | +|-----------|--------------------------------| +| attribute | Emitted for attribute macros. | +|enum| Emitted for enums. | +|function| Emitted for free-standing functions. | +|derive| Emitted for derive macros. | +|macro| Emitted for function-like macros. | +|method| Emitted for associated functions, also knowns as methods. | +|namespace| Emitted for modules. | +|struct| Emitted for structs.| +|trait| Emitted for traits.| +|typeAlias| Emitted for type aliases and `Self` in `impl`s.| +|union| Emitted for unions.| + +- For literals: + +| | | +|-----------|--------------------------------| +| boolean| Emitted for the boolean literals `true` and `false`.| +| character| Emitted for character literals.| +| number| Emitted for numeric literals.| +| string| Emitted for string literals.| +| escapeSequence| Emitted for escaped sequences inside strings like `\n`.| +| formatSpecifier| Emitted for format specifiers `{:?}` in `format!`-like macros.| + +- For operators: + +| | | +|-----------|--------------------------------| +|operator| Emitted for general operators.| +|arithmetic| Emitted for the arithmetic operators `+`, `-`, `*`, `/`, `+=`, `-=`, `*=`, `/=`.| +|bitwise| Emitted for the bitwise operators `|`, `&`, `!`, `^`, `|=`, `&=`, `^=`.| +|comparison| Emitted for the comparison oerators `>`, `<`, `==`, `>=`, `<=`, `!=`.| +|logical| Emitted for the logical operatos `||`, `&&`, `!`.| + +- For punctuation: + +| | | +|-----------|--------------------------------| +|punctuation| Emitted for general punctuation.| +|attributeBracket| Emitted for attribute invocation brackets, that is the `#[` and `]` tokens.| +|angle| Emitted for `<>` angle brackets.| +|brace| Emitted for `{}` braces.| +|bracket| Emitted for `[]` brackets.| +|parenthesis| Emitted for `()` parentheses.| +|colon| Emitted for the `:` token.| +|comma| Emitted for the `,` token.| +|dot| Emitted for the `.` token.| +|semi| Emitted for the `;` token.| +|macroBang| Emitted for the `!` token in macro calls.| + +- + +| | | +|-----------|--------------------------------| +|builtinAttribute| Emitted for names to builtin attributes in attribute path, the `repr` in `#[repr(u8)]` for example.| +|builtinType| Emitted for builtin types like `u32`, `str` and `f32`.| +|comment| Emitted for comments.| +|constParameter| Emitted for const parameters.| +|deriveHelper| Emitted for derive helper attributes.| +|enumMember| Emitted for enum variants.| +|generic| Emitted for generic tokens that have no mapping.| +|keyword| Emitted for keywords.| +|label| Emitted for labels.| +|lifetime| Emitted for lifetimes.| +|parameter| Emitted for non-self function parameters.| +|property| Emitted for struct and union fields.| +|selfKeyword| Emitted for the self function parameter and self path-specifier.| +|selfTypeKeyword| Emitted for the Self type parameter.| +|toolModule| Emitted for tool modules.| +|typeParameter| Emitted for type parameters.| +|unresolvedReference| Emitted for unresolved references, names that rust-analyzer can't find the definition of.| +|variable| Emitted for locals, constants and statics.| + + +#### Token Modifiers + +Token modifiers allow to style some elements in the source code more precisely. + +Rust-analyzer currently emits the following token modifiers: + +| | | +|-----------|--------------------------------| +|async| Emitted for async functions and the `async` and `await` keywords.| +|attribute| Emitted for tokens inside attributes.| +|callable| Emitted for locals whose types implements one of the `Fn*` traits.| +|constant| Emitted for const.| +|consuming| Emitted for locals that are being consumed when use in a function call.| +|controlFlow| Emitted for control-flow related tokens, this includes th `?` operator.| +|crateRoot| Emitted for crate names, like `serde` and `crate.| +|declaration| Emitted for names of definitions, like `foo` in `fn foo(){}`.| +|defaultLibrary| Emitted for items from built-in crates (std, core, allc, test and proc_macro).| +|documentation| Emitted for documentation comment.| +|injected| Emitted for doc-string injected highlighting like rust source blocks in documentation.| +|intraDocLink| Emitted for intra doc links in doc-string.| +|library| Emitted for items that are defined outside of the current crae.| +|macro| Emitted for tokens inside macro call.| +|mutable| Emitted for mutable locals and statics as well as functions taking `&mut self`.| +|public| Emitted for items that are from the current crate and are `pub.| +|reference| Emitted for locals behind a reference and functions taking self` by reference.| +|static| Emitted for "static" functions, also known as functions that d not take a `self` param, as well as statics and consts.| +|trait| Emitted for associated trait item.| +|unsafe| Emitted for unsafe operations, like unsafe function calls, as ell as the `unsafe` token.| + +![Semantic Syntax Highlighting](https://user-images.githubusercontent.com/48062697/113164457-06cfb980-9239-11eb-819b-0f93e646acf8.png) +![Semantic Syntax Highlighting](https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png) + + +### Show Dependency Tree +**Source:** [fetch_crates.rs](crates/ide/src/fetch_crates.rs#13) + +Shows a view tree with all the dependencies of this project + +| Editor | Panel Name | +|---------|------------| +| VS Code | **Rust Dependencies** | + +![Show Dependency Tree](https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png) + + +### Show Syntax Tree +**Source:** [view_syntax_tree.rs](crates/ide/src/view_syntax_tree.rs#14) + +Shows a tree view with the syntax tree of the current file + +| Editor | Panel Name | +|---------|-------------| +| VS Code | **Rust Syntax Tree** | + + +### Status +**Source:** [status.rs](crates/ide/src/status.rs#28) + +Shows internal statistic about memory usage of rust-analyzer. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: Status** | + +![Status](https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif) + + +### Structural Search and Replace +**Source:** [lib.rs](crates/ide-ssr/src/lib.rs#6) + +Search and replace with named wildcards that will match any expression, type, path, pattern or item. +The syntax for a structural search replace command is ` ==>> `. +A `$` placeholder in the search pattern will match any AST node and `$` will reference it in the replacement. +Within a macro call, a placeholder will match up until whatever token follows the placeholder. + +All paths in both the search pattern and the replacement template must resolve in the context +in which this command is invoked. Paths in the search pattern will then match the code if they +resolve to the same item, even if they're written differently. For example if we invoke the +command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers +to `foo::Bar` will match. + +Paths in the replacement template will be rendered appropriately for the context in which the +replacement occurs. For example if our replacement template is `foo::Bar` and we match some +code in the `foo` module, we'll insert just `Bar`. + +Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will +match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`. When a +placeholder is the receiver of a method call in the search pattern (e.g. `$s.foo()`), but not in +the replacement template (e.g. `bar($s)`), then *, & and &mut will be added as needed to mirror +whatever autoderef and autoref was happening implicitly in the matched code. + +The scope of the search / replace will be restricted to the current selection if any, otherwise +it will apply to the whole workspace. + +Placeholders may be given constraints by writing them as `${::...}`. + +Supported constraints: + +| Constraint | Restricts placeholder | +|---------------|------------------------| +| kind(literal) | Is a literal (e.g. `42` or `"forty two"`) | +| not(a) | Negates the constraint `a` | + +Available via the command `rust-analyzer.ssr`. + +```rust +// Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)] + +// BEFORE +String::from(foo(y + 5, z)) + +// AFTER +String::from((y + 5).foo(z)) +``` + +| Editor | Action Name | +|---------|--------------| +| VS Code | **rust-analyzer: Structural Search Replace** | + +Also available as an assist, by writing a comment containing the structural +search and replace rule. You will only see the assist if the comment can +be parsed as a valid structural search and replace rule. + +```rust +// Place the cursor on the line below to see the assist 💡. +// foo($a, $b) ==>> ($a).foo($b) +``` + + +### User Snippet Completions +**Source:** [snippet.rs](crates/ide-completion/src/snippet.rs#5) + +rust-analyzer allows the user to define custom (postfix)-snippets that may depend on items to be accessible for the current scope to be applicable. + +A custom snippet can be defined by adding it to the `rust-analyzer.completion.snippets.custom` object respectively. + +```json +{ + "rust-analyzer.completion.snippets.custom": { + "thread spawn": { + "prefix": ["spawn", "tspawn"], + "body": [ + "thread::spawn(move || {", + "\t$0", + "});", + ], + "description": "Insert a thread::spawn call", + "requires": "std::thread", + "scope": "expr", + } + } +} +``` + +In the example above: + +* `"thread spawn"` is the name of the snippet. + +* `prefix` defines one or more trigger words that will trigger the snippets completion. +Using `postfix` will instead create a postfix snippet. + +* `body` is one or more lines of content joined via newlines for the final output. + +* `description` is an optional description of the snippet, if unset the snippet name will be used. + +* `requires` is an optional list of item paths that have to be resolvable in the current crate where the completion is rendered. + + +### View Crate Graph +**Source:** [view_crate_graph.rs](crates/ide/src/view_crate_graph.rs#8) + +Renders the currently loaded crate graph as an SVG graphic. Requires the `dot` tool, which +is part of graphviz, to be installed. + +Only workspace crates are included, no crates.io dependencies or sysroot crates. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: View Crate Graph** | + + +### View Hir +**Source:** [view_hir.rs](crates/ide/src/view_hir.rs#5) + +| Editor | Action Name | +|---------|--------------| +| VS Code | **rust-analyzer: View Hir** + +![View Hir](https://user-images.githubusercontent.com/48062697/113065588-068bdb80-91b1-11eb-9a78-0b4ef1e972fb.gif) + + +### View Memory Layout +**Source:** [view_memory_layout.rs](crates/ide/src/view_memory_layout.rs#74) + +Displays the recursive memory layout of a datatype. + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: View Memory Layout** | + + +### View Mir +**Source:** [view_mir.rs](crates/ide/src/view_mir.rs#5) + +| Editor | Action Name | +|---------|-------------| +| VS Code | **rust-analyzer: View Mir** + + +### Workspace Symbol +**Source:** [symbol_index.rs](crates/ide-db/src/symbol_index.rs#174) + +Uses fuzzy-search to find types, modules and functions by name across your +project and dependencies. This is **the** most useful feature, which improves code +navigation tremendously. It mostly works on top of the built-in LSP +functionality, however `#` and `*` symbols can be used to narrow down the +search. Specifically, + +- `Foo` searches for `Foo` type in the current workspace +- `foo#` searches for `foo` function in the current workspace +- `Foo*` searches for `Foo` type among dependencies, including `stdlib` +- `foo#*` searches for `foo` function among dependencies + +That is, `#` switches from "types" to all symbols, `*` switches from the current +workspace to dependencies. + +Note that filtering does not currently work in VSCode due to the editor never +sending the special symbols to the language server. Instead, you can configure +the filtering via the `rust-analyzer.workspace.symbol.search.scope` and +`rust-analyzer.workspace.symbol.search.kind` settings. Symbols prefixed +with `__` are hidden from the search results unless configured otherwise. + +| Editor | Shortcut | +|---------|-----------| +| VS Code | Ctrl+T From f26f1dda44552500b9653d4ec81862275cbc0ccd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 08:30:30 +0100 Subject: [PATCH 041/158] Spawn toolchain querying processes in parallel --- .../crates/project-model/src/sysroot.rs | 23 +- .../crates/project-model/src/tests.rs | 10 +- .../crates/project-model/src/workspace.rs | 296 ++++++++++++------ .../rust-analyzer/src/cli/rustc_tests.rs | 6 +- .../crates/rust-analyzer/src/reload.rs | 1 + .../rust-analyzer/tests/slow-tests/main.rs | 6 +- 6 files changed, 229 insertions(+), 113 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 8f633d24be9a..4659d5288b1b 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -34,14 +34,14 @@ pub struct Sysroot { } #[derive(Debug, Clone, Eq, PartialEq)] -pub(crate) enum SysrootWorkspace { +pub enum SysrootWorkspace { Workspace(CargoWorkspace), Stitched(Stitched), Empty, } #[derive(Debug, Clone, Eq, PartialEq)] -pub(crate) struct Stitched { +pub struct Stitched { crates: Arena, } @@ -227,18 +227,21 @@ impl Sysroot { } } - pub fn load_workspace(&mut self, sysroot_source_config: &SysrootSourceWorkspaceConfig) { + pub fn load_workspace( + &self, + sysroot_source_config: &SysrootSourceWorkspaceConfig, + ) -> Option { assert!(matches!(self.workspace, SysrootWorkspace::Empty), "workspace already loaded"); - let Self { root: _, src_root: Some(src_root), workspace, error: _ } = self else { return }; + let Self { root: _, src_root: Some(src_root), workspace: _, error: _ } = self else { + return None; + }; if let SysrootSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config { let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap(); if fs::metadata(&library_manifest).is_ok() { if let Some(loaded) = Self::load_library_via_cargo(library_manifest, src_root, cargo_config) { - *workspace = loaded; - self.load_core_check(); - return; + return Some(loaded); } } } @@ -286,11 +289,11 @@ impl Sysroot { } } } - *workspace = SysrootWorkspace::Stitched(stitched); - self.load_core_check(); + Some(SysrootWorkspace::Stitched(stitched)) } - fn load_core_check(&mut self) { + pub fn set_workspace(&mut self, workspace: SysrootWorkspace) { + self.workspace = workspace; if self.error.is_none() { if let Some(src_root) = &self.src_root { let has_core = match &self.workspace { diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 285608654366..6d9e68f0043d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -125,7 +125,10 @@ fn get_fake_sysroot() -> Sysroot { let sysroot_dir = AbsPathBuf::assert(sysroot_path); let sysroot_src_dir = sysroot_dir.clone(); let mut sysroot = Sysroot::new(Some(sysroot_dir), Some(sysroot_src_dir)); - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } sysroot } @@ -271,7 +274,10 @@ fn smoke_test_real_sysroot_cargo() { AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))), &Default::default(), ); - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } assert!(matches!(sysroot.workspace(), SysrootWorkspace::Workspace(_))); let project_workspace = ProjectWorkspace { kind: ProjectWorkspaceKind::Cargo { diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index dcd62753cb2f..e21c373b75ff 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -2,7 +2,7 @@ //! metadata` or `rust-project.json`) into representation stored in the salsa //! database -- `CrateGraph`. -use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync}; +use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync, thread}; use anyhow::Context; use base_db::{ @@ -186,7 +186,7 @@ impl ProjectWorkspace { let project_location = project_json.parent().to_path_buf(); let project_json: ProjectJson = ProjectJson::new(Some(project_json.clone()), &project_location, data); - ProjectWorkspace::load_inline(project_json, config) + ProjectWorkspace::load_inline(project_json, config, progress) } ProjectManifest::CargoScript(rust_file) => { ProjectWorkspace::load_detached_file(rust_file, config)? @@ -204,14 +204,28 @@ impl ProjectWorkspace { config: &CargoConfig, progress: &dyn Fn(String), ) -> Result { - let mut sysroot = match (&config.sysroot, &config.sysroot_src) { + progress("Discovering sysroot".to_owned()); + let CargoConfig { + features, + rustc_source, + extra_args, + extra_env, + set_test, + cfg_overrides, + extra_includes, + sysroot, + sysroot_src, + target, + .. + } = config; + let mut sysroot = match (sysroot, sysroot_src) { (Some(RustLibSource::Discover), None) => { - Sysroot::discover(cargo_toml.parent(), &config.extra_env) + Sysroot::discover(cargo_toml.parent(), extra_env) } (Some(RustLibSource::Discover), Some(sysroot_src)) => { Sysroot::discover_with_src_override( cargo_toml.parent(), - &config.extra_env, + extra_env, sysroot_src.clone(), ) } @@ -224,100 +238,147 @@ impl ProjectWorkspace { (None, _) => Sysroot::empty(), }; - let rustc_dir = match &config.rustc_source { - Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone()) - .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))), - Some(RustLibSource::Discover) => sysroot - .discover_rustc_src() - .ok_or_else(|| Some("Failed to discover rustc source for sysroot.".to_owned())), - None => Err(None), - }; - tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot"); + progress("Querying project metadata".to_owned()); let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml); let targets = - target_tuple::get(toolchain_config, config.target.as_deref(), &config.extra_env) - .unwrap_or_default(); - let toolchain = version::get(toolchain_config, &config.extra_env) - .inspect_err(|e| { - tracing::error!(%e, - "failed fetching toolchain version for {cargo_toml:?} workspace" - ) - }) - .ok() - .flatten(); - let rustc_cfg = - rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), &config.extra_env); - let cfg_overrides = config.cfg_overrides.clone(); - let data_layout = target_data_layout::get( - toolchain_config, - targets.first().map(Deref::deref), - &config.extra_env, - ); - if let Err(e) = &data_layout { - tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace"); - } - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata( - sysroot_metadata_config(&config.extra_env, &targets), - )); + target_tuple::get(toolchain_config, target.as_deref(), extra_env).unwrap_or_default(); - let rustc = rustc_dir.and_then(|rustc_dir| { - info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source"); - match CargoWorkspace::fetch_metadata( - &rustc_dir, - cargo_toml.parent(), - &CargoMetadataConfig { - features: crate::CargoFeatures::default(), - targets: targets.clone(), - extra_args: config.extra_args.clone(), - extra_env: config.extra_env.clone(), - }, - &sysroot, - false, - progress, - ) { - Ok((meta, _error)) => { - let workspace = CargoWorkspace::new(meta, cargo_toml.clone(), Env::default()); - let build_scripts = WorkspaceBuildScripts::rustc_crates( - &workspace, - cargo_toml.parent(), - &config.extra_env, + // We spawn a bunch of processes to query various information about the workspace's + // toolchain and sysroot + // We can speed up loading a bit by spawning all of these processes in parallel (especially + // on systems were process spawning is delayed) + let join = thread::scope(|s| { + let workspace_dir = cargo_toml.parent(); + let toolchain = s.spawn(|| { + version::get(toolchain_config, extra_env) + .inspect_err(|e| { + tracing::error!(%e, + "failed fetching toolchain version for {cargo_toml:?} workspace" + ) + }) + .ok() + .flatten() + }); + + let rustc_cfg = s.spawn(|| { + rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), extra_env) + }); + let data_layout = s.spawn(|| { + target_data_layout::get( + toolchain_config, + targets.first().map(Deref::deref), + extra_env, + ).inspect_err(|e| { + tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace") + }) + }); + + let rustc_dir = s.spawn(|| { + let rustc_dir = match rustc_source { + Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone()) + .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))), + Some(RustLibSource::Discover) => { + sysroot.discover_rustc_src().ok_or_else(|| { + Some("Failed to discover rustc source for sysroot.".to_owned()) + }) + } + None => Err(None), + }; + rustc_dir.and_then(|rustc_dir| { + info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source"); + match CargoWorkspace::fetch_metadata( + &rustc_dir, + workspace_dir, + &CargoMetadataConfig { + features: crate::CargoFeatures::default(), + targets: targets.clone(), + extra_args: extra_args.clone(), + extra_env: extra_env.clone(), + }, &sysroot, - ); - Ok(Box::new((workspace, build_scripts))) - } - Err(e) => { - tracing::error!( - %e, - "Failed to read Cargo metadata from rustc source at {rustc_dir}", - ); - Err(Some(format!( - "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}" - ))) - } - } + false, + &|_| (), + ) { + Ok((meta, _error)) => { + let workspace = + CargoWorkspace::new(meta, cargo_toml.clone(), Env::default()); + let build_scripts = WorkspaceBuildScripts::rustc_crates( + &workspace, + workspace_dir, + extra_env, + &sysroot, + ); + Ok(Box::new((workspace, build_scripts))) + } + Err(e) => { + tracing::error!( + %e, + "Failed to read Cargo metadata from rustc source at {rustc_dir}", + ); + Err(Some(format!( + "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}" + ))) + } + } + }) + }); + + let cargo_metadata = s.spawn(|| { + CargoWorkspace::fetch_metadata( + cargo_toml, + workspace_dir, + &CargoMetadataConfig { + features: features.clone(), + targets: targets.clone(), + extra_args: extra_args.clone(), + extra_env: extra_env.clone(), + }, + &sysroot, + false, + &|_| (), + ) + }); + let loaded_sysroot = s.spawn(|| { + sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata( + sysroot_metadata_config(extra_env, &targets), + )) + }); + let cargo_config_extra_env = + s.spawn(|| cargo_config_env(cargo_toml, extra_env, &sysroot)); + thread::Result::Ok(( + toolchain.join()?, + rustc_cfg.join()?, + data_layout.join()?, + rustc_dir.join()?, + loaded_sysroot.join()?, + cargo_metadata.join()?, + cargo_config_extra_env.join()?, + )) }); - let (meta, error) = CargoWorkspace::fetch_metadata( - cargo_toml, - cargo_toml.parent(), - &CargoMetadataConfig { - features: config.features.clone(), - targets, - extra_args: config.extra_args.clone(), - extra_env: config.extra_env.clone(), - }, - &sysroot, - false, - progress, - ) - .with_context(|| { + let ( + toolchain, + rustc_cfg, + data_layout, + rustc, + loaded_sysroot, + cargo_metadata, + cargo_config_extra_env, + ) = match join { + Ok(it) => it, + Err(e) => std::panic::resume_unwind(e), + }; + + let (meta, error) = cargo_metadata.with_context(|| { format!( "Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}", ) })?; - let cargo_config_extra_env = cargo_config_env(cargo_toml, &config.extra_env, &sysroot); let cargo = CargoWorkspace::new(meta, cargo_toml.clone(), cargo_config_extra_env); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } Ok(ProjectWorkspace { kind: ProjectWorkspaceKind::Cargo { @@ -325,33 +386,67 @@ impl ProjectWorkspace { build_scripts: WorkspaceBuildScripts::default(), rustc, error: error.map(Arc::new), - set_test: config.set_test, + set_test: *set_test, }, sysroot, rustc_cfg, - cfg_overrides, + cfg_overrides: cfg_overrides.clone(), toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), - extra_includes: config.extra_includes.clone(), + extra_includes: extra_includes.clone(), }) } - pub fn load_inline(project_json: ProjectJson, config: &CargoConfig) -> ProjectWorkspace { + pub fn load_inline( + project_json: ProjectJson, + config: &CargoConfig, + progress: &dyn Fn(String), + ) -> ProjectWorkspace { + progress("Discovering sysroot".to_owned()); let mut sysroot = Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone()); - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::Stitched); - let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref()); - let toolchain = version::get(query_config, &config.extra_env).ok().flatten(); + let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::Stitched); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } + + tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot"); + progress("Querying project metadata".to_owned()); + let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref()); + let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env) + .unwrap_or_default(); + + // We spawn a bunch of processes to query various information about the workspace's + // toolchain and sysroot + // We can speed up loading a bit by spawning all of these processes in parallel (especially + // on systems were process spawning is delayed) + let join = thread::scope(|s| { + let toolchain = + s.spawn(|| version::get(query_config, &config.extra_env).ok().flatten()); + let rustc_cfg = s.spawn(|| { + rustc_cfg::get(query_config, targets.first().map(Deref::deref), &config.extra_env) + }); + let data_layout = s.spawn(|| { + target_data_layout::get( + query_config, + targets.first().map(Deref::deref), + &config.extra_env, + ) + }); + thread::Result::Ok((toolchain.join()?, rustc_cfg.join()?, data_layout.join()?)) + }); + + let (toolchain, rustc_cfg, target_layout) = match join { + Ok(it) => it, + Err(e) => std::panic::resume_unwind(e), + }; - let target = config.target.as_deref(); - let rustc_cfg = rustc_cfg::get(query_config, target, &config.extra_env); - let data_layout = target_data_layout::get(query_config, target, &config.extra_env); ProjectWorkspace { kind: ProjectWorkspaceKind::Json(project_json), sysroot, rustc_cfg, toolchain, - target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), + target_layout: target_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), extra_includes: config.extra_includes.clone(), } @@ -374,9 +469,12 @@ impl ProjectWorkspace { .unwrap_or_default(); let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env); let data_layout = target_data_layout::get(query_config, None, &config.extra_env); - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata( + let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata( sysroot_metadata_config(&config.extra_env, &targets), )); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } let cargo_script = CargoWorkspace::fetch_metadata( detached_file, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 199f61e70f02..59dec9a9f36f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -75,7 +75,11 @@ impl Tester { }; let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env); - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } + let data_layout = target_data_layout::get( QueryConfig::Rustc(&sysroot, tmp_file.parent().unwrap().as_ref()), None, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index e3c003dbf8b1..ba72ea35df66 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -316,6 +316,7 @@ impl GlobalState { let workspace = project_model::ProjectWorkspace::load_inline( it.clone(), &cargo_config, + &progress, ); Ok(workspace) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index e764bd477034..a33b9e46fed2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1152,7 +1152,11 @@ fn resolve_proc_macro() { &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()), &Default::default(), ); - sysroot.load_workspace(&project_model::SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = + sysroot.load_workspace(&project_model::SysrootSourceWorkspaceConfig::default_cargo()); + if let Some(loaded_sysroot) = loaded_sysroot { + sysroot.set_workspace(loaded_sysroot); + } let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap(); From d9256abe72cb6a0e08c34edad64f24cb1bfb89e2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 15:15:47 +0100 Subject: [PATCH 042/158] Improve error recovery when method-calling a field --- .../crates/hir-ty/src/infer/expr.rs | 204 +++++++++++------- .../rust-analyzer/crates/hir-ty/src/tests.rs | 2 +- .../crates/hir-ty/src/tests/diagnostics.rs | 25 +++ 3 files changed, 152 insertions(+), 79 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 86e5afdb5092..41d739a078e6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -489,78 +489,7 @@ impl InferenceContext<'_> { ty } - Expr::Call { callee, args, .. } => { - let callee_ty = self.infer_expr(*callee, &Expectation::none(), ExprIsRead::Yes); - let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false, true); - let (res, derefed_callee) = loop { - let Some((callee_deref_ty, _)) = derefs.next() else { - break (None, callee_ty.clone()); - }; - if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) { - break (Some(res), callee_deref_ty); - } - }; - // if the function is unresolved, we use is_varargs=true to - // suppress the arg count diagnostic here - let is_varargs = - derefed_callee.callable_sig(self.db).is_some_and(|sig| sig.is_varargs) - || res.is_none(); - let (param_tys, ret_ty) = match res { - Some((func, params, ret_ty)) => { - let mut adjustments = auto_deref_adjust_steps(&derefs); - if let TyKind::Closure(c, _) = - self.table.resolve_completely(callee_ty.clone()).kind(Interner) - { - if let Some(par) = self.current_closure { - self.closure_dependencies.entry(par).or_default().push(*c); - } - self.deferred_closures.entry(*c).or_default().push(( - derefed_callee.clone(), - callee_ty.clone(), - params.clone(), - tgt_expr, - )); - } - if let Some(fn_x) = func { - self.write_fn_trait_method_resolution( - fn_x, - &derefed_callee, - &mut adjustments, - &callee_ty, - ¶ms, - tgt_expr, - ); - } - self.write_expr_adj(*callee, adjustments); - (params, ret_ty) - } - None => { - self.push_diagnostic(InferenceDiagnostic::ExpectedFunction { - call_expr: tgt_expr, - found: callee_ty.clone(), - }); - (Vec::new(), self.err_ty()) - } - }; - let indices_to_skip = self.check_legacy_const_generics(derefed_callee, args); - self.register_obligations_for_call(&callee_ty); - - let expected_inputs = self.expected_inputs_for_expected_output( - expected, - ret_ty.clone(), - param_tys.clone(), - ); - - self.check_call_arguments( - tgt_expr, - args, - &expected_inputs, - ¶m_tys, - &indices_to_skip, - is_varargs, - ); - self.normalize_associated_types_in(ret_ty) - } + Expr::Call { callee, args, .. } => self.infer_call(tgt_expr, *callee, args, expected), Expr::MethodCall { receiver, args, method_name, generic_args } => self .infer_method_call( tgt_expr, @@ -1872,6 +1801,107 @@ impl InferenceContext<'_> { } } + fn infer_call( + &mut self, + tgt_expr: ExprId, + callee: ExprId, + args: &[ExprId], + expected: &Expectation, + ) -> Ty { + let callee_ty = self.infer_expr(callee, &Expectation::none(), ExprIsRead::Yes); + let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false, true); + let (res, derefed_callee) = loop { + let Some((callee_deref_ty, _)) = derefs.next() else { + break (None, callee_ty.clone()); + }; + if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) { + break (Some(res), callee_deref_ty); + } + }; + // if the function is unresolved, we use is_varargs=true to + // suppress the arg count diagnostic here + let is_varargs = + derefed_callee.callable_sig(self.db).is_some_and(|sig| sig.is_varargs) || res.is_none(); + let (param_tys, ret_ty) = match res { + Some((func, params, ret_ty)) => { + let mut adjustments = auto_deref_adjust_steps(&derefs); + if let TyKind::Closure(c, _) = + self.table.resolve_completely(callee_ty.clone()).kind(Interner) + { + if let Some(par) = self.current_closure { + self.closure_dependencies.entry(par).or_default().push(*c); + } + self.deferred_closures.entry(*c).or_default().push(( + derefed_callee.clone(), + callee_ty.clone(), + params.clone(), + tgt_expr, + )); + } + if let Some(fn_x) = func { + self.write_fn_trait_method_resolution( + fn_x, + &derefed_callee, + &mut adjustments, + &callee_ty, + ¶ms, + tgt_expr, + ); + } + self.write_expr_adj(callee, adjustments); + (params, ret_ty) + } + None => { + self.push_diagnostic(InferenceDiagnostic::ExpectedFunction { + call_expr: tgt_expr, + found: callee_ty.clone(), + }); + (Vec::new(), self.err_ty()) + } + }; + let indices_to_skip = self.check_legacy_const_generics(derefed_callee, args); + self.check_call( + tgt_expr, + args, + callee_ty, + ¶m_tys, + ret_ty, + &indices_to_skip, + is_varargs, + expected, + ) + } + + fn check_call( + &mut self, + tgt_expr: ExprId, + args: &[ExprId], + callee_ty: Ty, + param_tys: &[Ty], + ret_ty: Ty, + indices_to_skip: &[u32], + is_varargs: bool, + expected: &Expectation, + ) -> Ty { + self.register_obligations_for_call(&callee_ty); + + let expected_inputs = self.expected_inputs_for_expected_output( + expected, + ret_ty.clone(), + param_tys.to_owned(), + ); + + self.check_call_arguments( + tgt_expr, + args, + &expected_inputs, + param_tys, + indices_to_skip, + is_varargs, + ); + self.normalize_associated_types_in(ret_ty) + } + fn infer_method_call( &mut self, tgt_expr: ExprId, @@ -1939,14 +1969,32 @@ impl InferenceContext<'_> { expr: tgt_expr, receiver: receiver_ty.clone(), name: method_name.clone(), - field_with_same_name: field_with_same_name_exists, + field_with_same_name: field_with_same_name_exists.clone(), assoc_func_with_same_name, }); - ( - receiver_ty, - Binders::empty(Interner, self.err_ty()), - Substitution::empty(Interner), - ) + + return match field_with_same_name_exists { + Some(field_ty) => match field_ty.callable_sig(self.db) { + Some(sig) => self.check_call( + tgt_expr, + args, + field_ty, + sig.params(), + sig.ret().clone(), + &[], + true, + expected, + ), + None => { + self.check_call_arguments(tgt_expr, args, &[], &[], &[], true); + field_ty + } + }, + None => { + self.check_call_arguments(tgt_expr, args, &[], &[], &[], true); + self.err_ty() + } + }; } }; self.check_method_call(tgt_expr, args, method_ty, substs, receiver_ty, expected) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 69ec35f406df..f5a4d4ff35c3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -117,7 +117,7 @@ fn check_impl( expected.trim_start_matches("adjustments:").trim().to_owned(), ); } else { - panic!("unexpected annotation: {expected}"); + panic!("unexpected annotation: {expected} @ {range:?}"); } had_annotations = true; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs index def06f2d59d2..d0d31bf2a5a6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs @@ -153,3 +153,28 @@ fn consume() -> Option<()> { "#, ); } + +#[test] +fn method_call_on_field() { + check( + r#" +struct S { + field: fn() -> u32, + field2: u32 +} + +fn main() { + let s = S { field: || 0, field2: 0 }; + s.field(0); + // ^ type: i32 + // ^^^^^^^^^^ type: u32 + s.field2(0); + // ^ type: i32 + // ^^^^^^^^^^^ type: u32 + s.not_a_field(0); + // ^ type: i32 + // ^^^^^^^^^^^^^^^^ type: {unknown} +} +"#, + ); +} From 875f3e2c883fd71eb5210f34790e705b45097442 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 16:32:11 +0100 Subject: [PATCH 043/158] Rename sysroot src/lib related things --- .../crates/project-model/src/lib.rs | 10 +- .../crates/project-model/src/sysroot.rs | 158 ++++++++++-------- .../crates/project-model/src/tests.rs | 12 +- .../crates/project-model/src/workspace.rs | 37 ++-- .../rust-analyzer/src/cli/rustc_tests.rs | 6 +- .../rust-analyzer/tests/slow-tests/main.rs | 2 +- 6 files changed, 121 insertions(+), 104 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index fc1fd7b877fc..0c7344746824 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -260,19 +260,19 @@ fn parse_cfg(s: &str) -> Result { } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum SysrootSourceWorkspaceConfig { +pub enum RustSourceWorkspaceConfig { CargoMetadata(CargoMetadataConfig), Stitched, } -impl Default for SysrootSourceWorkspaceConfig { +impl Default for RustSourceWorkspaceConfig { fn default() -> Self { - SysrootSourceWorkspaceConfig::default_cargo() + RustSourceWorkspaceConfig::default_cargo() } } -impl SysrootSourceWorkspaceConfig { +impl RustSourceWorkspaceConfig { pub fn default_cargo() -> Self { - SysrootSourceWorkspaceConfig::CargoMetadata(Default::default()) + RustSourceWorkspaceConfig::CargoMetadata(Default::default()) } } diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 4659d5288b1b..510c18dd147e 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -22,19 +22,19 @@ use toolchain::{probe_for_binary, Tool}; use crate::{ cargo_workspace::CargoMetadataConfig, utf8_stdout, CargoWorkspace, ManifestPath, - SysrootSourceWorkspaceConfig, + RustSourceWorkspaceConfig, }; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Sysroot { root: Option, - src_root: Option, - workspace: SysrootWorkspace, + rust_lib_src_root: Option, + workspace: RustLibSrcWorkspace, error: Option, } #[derive(Debug, Clone, Eq, PartialEq)] -pub enum SysrootWorkspace { +pub enum RustLibSrcWorkspace { Workspace(CargoWorkspace), Stitched(Stitched), Empty, @@ -42,18 +42,20 @@ pub enum SysrootWorkspace { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Stitched { - crates: Arena, + crates: Arena, } -impl ops::Index for Stitched { - type Output = SysrootCrateData; - fn index(&self, index: SysrootCrate) -> &SysrootCrateData { +impl ops::Index for Stitched { + type Output = RustLibSrcCrateData; + fn index(&self, index: RustLibSrcCrate) -> &RustLibSrcCrateData { &self.crates[index] } } impl Stitched { - pub(crate) fn public_deps(&self) -> impl Iterator + '_ { + pub(crate) fn public_deps( + &self, + ) -> impl Iterator + '_ { // core is added as a dependency before std in order to // mimic rustcs dependency order [("core", true), ("alloc", false), ("std", true), ("test", false)].into_iter().filter_map( @@ -63,32 +65,37 @@ impl Stitched { ) } - pub(crate) fn proc_macro(&self) -> Option { + pub(crate) fn proc_macro(&self) -> Option { self.by_name("proc_macro") } - pub(crate) fn crates(&self) -> impl ExactSizeIterator + '_ { + pub(crate) fn crates(&self) -> impl ExactSizeIterator + '_ { self.crates.iter().map(|(id, _data)| id) } - fn by_name(&self, name: &str) -> Option { + fn by_name(&self, name: &str) -> Option { let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?; Some(id) } } -pub(crate) type SysrootCrate = Idx; +pub(crate) type RustLibSrcCrate = Idx; #[derive(Debug, Clone, Eq, PartialEq)] -pub(crate) struct SysrootCrateData { +pub(crate) struct RustLibSrcCrateData { pub(crate) name: String, pub(crate) root: ManifestPath, - pub(crate) deps: Vec, + pub(crate) deps: Vec, } impl Sysroot { pub const fn empty() -> Sysroot { - Sysroot { root: None, src_root: None, workspace: SysrootWorkspace::Empty, error: None } + Sysroot { + root: None, + rust_lib_src_root: None, + workspace: RustLibSrcWorkspace::Empty, + error: None, + } } /// Returns sysroot "root" directory, where `bin/`, `etc/`, `lib/`, `libexec/` @@ -100,15 +107,15 @@ impl Sysroot { /// Returns the sysroot "source" directory, where stdlib sources are located, like: /// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library` - pub fn src_root(&self) -> Option<&AbsPath> { - self.src_root.as_deref() + pub fn rust_lib_src_root(&self) -> Option<&AbsPath> { + self.rust_lib_src_root.as_deref() } - pub fn is_empty(&self) -> bool { + pub fn is_rust_lib_src_empty(&self) -> bool { match &self.workspace { - SysrootWorkspace::Workspace(ws) => ws.packages().next().is_none(), - SysrootWorkspace::Stitched(stitched) => stitched.crates.is_empty(), - SysrootWorkspace::Empty => true, + RustLibSrcWorkspace::Workspace(ws) => ws.packages().next().is_none(), + RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.is_empty(), + RustLibSrcWorkspace::Empty => true, } } @@ -118,13 +125,13 @@ impl Sysroot { pub fn num_packages(&self) -> usize { match &self.workspace { - SysrootWorkspace::Workspace(ws) => ws.packages().count(), - SysrootWorkspace::Stitched(c) => c.crates().count(), - SysrootWorkspace::Empty => 0, + RustLibSrcWorkspace::Workspace(ws) => ws.packages().count(), + RustLibSrcWorkspace::Stitched(c) => c.crates().count(), + RustLibSrcWorkspace::Empty => 0, } } - pub(crate) fn workspace(&self) -> &SysrootWorkspace { + pub(crate) fn workspace(&self) -> &RustLibSrcWorkspace { &self.workspace } } @@ -133,33 +140,33 @@ impl Sysroot { /// Attempts to discover the toolchain's sysroot from the given `dir`. pub fn discover(dir: &AbsPath, extra_env: &FxHashMap) -> Sysroot { let sysroot_dir = discover_sysroot_dir(dir, extra_env); - let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| { - discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env) + let rust_lib_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| { + discover_rust_lib_src_dir_or_add_component(sysroot_dir, dir, extra_env) }); - Sysroot::assemble(Some(sysroot_dir), sysroot_src_dir) + Sysroot::assemble(Some(sysroot_dir), rust_lib_src_dir) } pub fn discover_with_src_override( current_dir: &AbsPath, extra_env: &FxHashMap, - sysroot_src_dir: AbsPathBuf, + rust_lib_src_dir: AbsPathBuf, ) -> Sysroot { let sysroot_dir = discover_sysroot_dir(current_dir, extra_env); - Sysroot::assemble(Some(sysroot_dir), Some(Ok(sysroot_src_dir))) + Sysroot::assemble(Some(sysroot_dir), Some(Ok(rust_lib_src_dir))) } - pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot { - let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir) + pub fn discover_rust_lib_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot { + let rust_lib_src_dir = discover_rust_lib_src_dir(&sysroot_dir) .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}")); - Sysroot::assemble(Some(Ok(sysroot_dir)), Some(sysroot_src_dir)) + Sysroot::assemble(Some(Ok(sysroot_dir)), Some(rust_lib_src_dir)) } pub fn discover_rustc_src(&self) -> Option { get_rustc_src(self.root()?) } - pub fn new(sysroot_dir: Option, sysroot_src_dir: Option) -> Sysroot { - Self::assemble(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok)) + pub fn new(sysroot_dir: Option, rust_lib_src_dir: Option) -> Sysroot { + Self::assemble(sysroot_dir.map(Ok), rust_lib_src_dir.map(Ok)) } /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists. @@ -200,7 +207,7 @@ impl Sysroot { fn assemble( sysroot_dir: Option>, - sysroot_src_dir: Option>, + rust_lib_src_dir: Option>, ) -> Sysroot { let mut errors = String::new(); let root = match sysroot_dir { @@ -211,8 +218,8 @@ impl Sysroot { } None => None, }; - let src_root = match sysroot_src_dir { - Some(Ok(sysroot_src_dir)) => Some(sysroot_src_dir), + let rust_lib_src_root = match rust_lib_src_dir { + Some(Ok(rust_lib_src_dir)) => Some(rust_lib_src_dir), Some(Err(e)) => { format_to!(errors, "{e}\n"); None @@ -221,21 +228,22 @@ impl Sysroot { }; Sysroot { root, - src_root, - workspace: SysrootWorkspace::Empty, + rust_lib_src_root, + workspace: RustLibSrcWorkspace::Empty, error: errors.is_empty().not().then_some(errors), } } pub fn load_workspace( &self, - sysroot_source_config: &SysrootSourceWorkspaceConfig, - ) -> Option { - assert!(matches!(self.workspace, SysrootWorkspace::Empty), "workspace already loaded"); - let Self { root: _, src_root: Some(src_root), workspace: _, error: _ } = self else { + sysroot_source_config: &RustSourceWorkspaceConfig, + ) -> Option { + assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded"); + let Self { root: _, rust_lib_src_root: Some(src_root), workspace: _, error: _ } = self + else { return None; }; - if let SysrootSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config { + if let RustSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config { let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap(); if fs::metadata(&library_manifest).is_ok() { if let Some(loaded) = @@ -258,7 +266,7 @@ impl Sysroot { .find(|it| fs::metadata(it).is_ok()); if let Some(root) = root { - stitched.crates.alloc(SysrootCrateData { + stitched.crates.alloc(RustLibSrcCrateData { name: name.into(), root, deps: Vec::new(), @@ -289,21 +297,23 @@ impl Sysroot { } } } - Some(SysrootWorkspace::Stitched(stitched)) + Some(RustLibSrcWorkspace::Stitched(stitched)) } - pub fn set_workspace(&mut self, workspace: SysrootWorkspace) { + pub fn set_workspace(&mut self, workspace: RustLibSrcWorkspace) { self.workspace = workspace; if self.error.is_none() { - if let Some(src_root) = &self.src_root { + if let Some(src_root) = &self.rust_lib_src_root { let has_core = match &self.workspace { - SysrootWorkspace::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"), - SysrootWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(), - SysrootWorkspace::Empty => true, + RustLibSrcWorkspace::Workspace(ws) => { + ws.packages().any(|p| ws[p].name == "core") + } + RustLibSrcWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(), + RustLibSrcWorkspace::Empty => true, }; if !has_core { - let var_note = if env::var_os("RUST_SRC_PATH").is_some() { - " (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)" + let var_note = if env::var_os("rust_lib_src_PATH").is_some() { + " (env var `rust_lib_src_PATH` is set and may be incorrect, try unsetting it)" } else { ", try running `rustup component add rust-src` to possibly fix this" }; @@ -317,9 +327,9 @@ impl Sysroot { fn load_library_via_cargo( library_manifest: ManifestPath, - sysroot_src_dir: &AbsPathBuf, + rust_lib_src_dir: &AbsPathBuf, cargo_config: &CargoMetadataConfig, - ) -> Option { + ) -> Option { tracing::debug!("Loading library metadata: {library_manifest}"); let mut cargo_config = cargo_config.clone(); // the sysroot uses `public-dependency`, so we make cargo think it's a nightly @@ -330,7 +340,7 @@ impl Sysroot { let (mut res, _) = match CargoWorkspace::fetch_metadata( &library_manifest, - sysroot_src_dir, + rust_lib_src_dir, &cargo_config, &Sysroot::empty(), // Make sure we never attempt to write to the sysroot @@ -394,7 +404,7 @@ impl Sysroot { }); let cargo_workspace = CargoWorkspace::new(res, library_manifest, Default::default()); - Some(SysrootWorkspace::Workspace(cargo_workspace)) + Some(RustLibSrcWorkspace::Workspace(cargo_workspace)) } } @@ -410,36 +420,38 @@ fn discover_sysroot_dir( Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout))) } -fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option { - if let Ok(path) = env::var("RUST_SRC_PATH") { +fn discover_rust_lib_src_dir(sysroot_path: &AbsPathBuf) -> Option { + if let Ok(path) = env::var("rust_lib_src_PATH") { if let Ok(path) = AbsPathBuf::try_from(path.as_str()) { let core = path.join("core"); if fs::metadata(&core).is_ok() { - tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {path}"); + tracing::debug!("Discovered sysroot by rust_lib_src_PATH: {path}"); return Some(path); } - tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {core:?}), ignoring"); + tracing::debug!( + "rust_lib_src_PATH is set, but is invalid (no core: {core:?}), ignoring" + ); } else { - tracing::debug!("RUST_SRC_PATH is set, but is invalid, ignoring"); + tracing::debug!("rust_lib_src_PATH is set, but is invalid, ignoring"); } } - get_rust_src(sysroot_path) + get_rust_lib_src(sysroot_path) } -fn discover_sysroot_src_dir_or_add_component( +fn discover_rust_lib_src_dir_or_add_component( sysroot_path: &AbsPathBuf, current_dir: &AbsPath, extra_env: &FxHashMap, ) -> Result { - discover_sysroot_src_dir(sysroot_path) + discover_rust_lib_src_dir(sysroot_path) .or_else(|| { let mut rustup = toolchain::command(Tool::Rustup.prefer_proxy(), current_dir); rustup.envs(extra_env); rustup.args(["component", "add", "rust-src"]); tracing::info!("adding rust-src component by {:?}", rustup); utf8_stdout(&mut rustup).ok()?; - get_rust_src(sysroot_path) + get_rust_lib_src(sysroot_path) }) .ok_or_else(|| { tracing::error!(%sysroot_path, "can't load standard library, try installing `rust-src`"); @@ -464,11 +476,11 @@ fn get_rustc_src(sysroot_path: &AbsPath) -> Option { } } -fn get_rust_src(sysroot_path: &AbsPath) -> Option { - let rust_src = sysroot_path.join("lib/rustlib/src/rust/library"); - tracing::debug!("checking sysroot library: {rust_src}"); - if fs::metadata(&rust_src).is_ok() { - Some(rust_src) +fn get_rust_lib_src(sysroot_path: &AbsPath) -> Option { + let rust_lib_src = sysroot_path.join("lib/rustlib/src/rust/library"); + tracing::debug!("checking sysroot library: {rust_lib_src}"); + if fs::metadata(&rust_lib_src).is_ok() { + Some(rust_lib_src) } else { None } diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 6d9e68f0043d..25e4368d95a8 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -12,9 +12,9 @@ use span::FileId; use triomphe::Arc; use crate::{ - sysroot::SysrootWorkspace, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides, - ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, - SysrootSourceWorkspaceConfig, WorkspaceBuildScripts, + sysroot::RustLibSrcWorkspace, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides, + ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, RustSourceWorkspaceConfig, + Sysroot, WorkspaceBuildScripts, }; fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { @@ -125,7 +125,7 @@ fn get_fake_sysroot() -> Sysroot { let sysroot_dir = AbsPathBuf::assert(sysroot_path); let sysroot_src_dir = sysroot_dir.clone(); let mut sysroot = Sysroot::new(Some(sysroot_dir), Some(sysroot_src_dir)); - let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } @@ -274,11 +274,11 @@ fn smoke_test_real_sysroot_cargo() { AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))), &Default::default(), ); - let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } - assert!(matches!(sysroot.workspace(), SysrootWorkspace::Workspace(_))); + assert!(matches!(sysroot.workspace(), RustLibSrcWorkspace::Workspace(_))); let project_workspace = ProjectWorkspace { kind: ProjectWorkspaceKind::Cargo { cargo: cargo_workspace, diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index e21c373b75ff..4f8449cb68c3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -23,10 +23,10 @@ use crate::{ cargo_workspace::{CargoMetadataConfig, DepKind, PackageData, RustLibSource}, env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env}, project_json::{Crate, CrateArrayIdx}, - sysroot::{SysrootCrate, SysrootWorkspace}, + sysroot::{RustLibSrcCrate, RustLibSrcWorkspace}, toolchain_info::{rustc_cfg, target_data_layout, target_tuple, version, QueryConfig}, CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath, Package, - ProjectJson, ProjectManifest, Sysroot, SysrootSourceWorkspaceConfig, TargetData, TargetKind, + ProjectJson, ProjectManifest, RustSourceWorkspaceConfig, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts, }; use tracing::{debug, error, info}; @@ -230,7 +230,7 @@ impl ProjectWorkspace { ) } (Some(RustLibSource::Path(path)), None) => { - Sysroot::discover_sysroot_src_dir(path.clone()) + Sysroot::discover_rust_lib_src_dir(path.clone()) } (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => { Sysroot::new(Some(sysroot.clone()), Some(sysroot_src.clone())) @@ -238,7 +238,7 @@ impl ProjectWorkspace { (None, _) => Sysroot::empty(), }; - tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot"); + tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot"); progress("Querying project metadata".to_owned()); let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml); let targets = @@ -340,7 +340,7 @@ impl ProjectWorkspace { ) }); let loaded_sysroot = s.spawn(|| { - sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata( + sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata( sysroot_metadata_config(extra_env, &targets), )) }); @@ -405,12 +405,12 @@ impl ProjectWorkspace { progress("Discovering sysroot".to_owned()); let mut sysroot = Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone()); - let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::Stitched); + let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::Stitched); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } - tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot"); + tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot"); progress("Querying project metadata".to_owned()); let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref()); let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env) @@ -458,7 +458,7 @@ impl ProjectWorkspace { ) -> anyhow::Result { let dir = detached_file.parent(); let mut sysroot = match &config.sysroot { - Some(RustLibSource::Path(path)) => Sysroot::discover_sysroot_src_dir(path.clone()), + Some(RustLibSource::Path(path)) => Sysroot::discover_rust_lib_src_dir(path.clone()), Some(RustLibSource::Discover) => Sysroot::discover(dir, &config.extra_env), None => Sysroot::empty(), }; @@ -469,7 +469,7 @@ impl ProjectWorkspace { .unwrap_or_default(); let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env); let data_layout = target_data_layout::get(query_config, None, &config.extra_env); - let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata( + let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata( sysroot_metadata_config(&config.extra_env, &targets), )); if let Some(loaded_sysroot) = loaded_sysroot { @@ -643,7 +643,7 @@ impl ProjectWorkspace { pub fn to_roots(&self) -> Vec { let mk_sysroot = || { let mut r = match self.sysroot.workspace() { - SysrootWorkspace::Workspace(ws) => ws + RustLibSrcWorkspace::Workspace(ws) => ws .packages() .filter_map(|pkg| { if ws[pkg].is_local { @@ -664,12 +664,17 @@ impl ProjectWorkspace { Some(PackageRoot { is_local: false, include, exclude }) }) .collect(), - SysrootWorkspace::Stitched(_) | SysrootWorkspace::Empty => vec![], + RustLibSrcWorkspace::Stitched(_) | RustLibSrcWorkspace::Empty => vec![], }; r.push(PackageRoot { is_local: false, - include: self.sysroot.src_root().map(|it| it.to_path_buf()).into_iter().collect(), + include: self + .sysroot + .rust_lib_src_root() + .map(|it| it.to_path_buf()) + .into_iter() + .collect(), exclude: Vec::new(), }); r @@ -1483,7 +1488,7 @@ fn sysroot_to_crate_graph( ) -> (SysrootPublicDeps, Option) { let _p = tracing::info_span!("sysroot_to_crate_graph").entered(); match sysroot.workspace() { - SysrootWorkspace::Workspace(cargo) => { + RustLibSrcWorkspace::Workspace(cargo) => { let (mut cg, mut pm) = cargo_to_crate_graph( load, None, @@ -1558,7 +1563,7 @@ fn sysroot_to_crate_graph( (SysrootPublicDeps { deps: pub_deps }, libproc_macro) } - SysrootWorkspace::Stitched(stitched) => { + RustLibSrcWorkspace::Stitched(stitched) => { let cfg_options = Arc::new({ let mut cfg_options = CfgOptions::default(); cfg_options.extend(rustc_cfg); @@ -1566,7 +1571,7 @@ fn sysroot_to_crate_graph( cfg_options.insert_atom(sym::miri.clone()); cfg_options }); - let sysroot_crates: FxHashMap = stitched + let sysroot_crates: FxHashMap = stitched .crates() .filter_map(|krate| { let file_id = load(&stitched[krate].root)?; @@ -1611,7 +1616,7 @@ fn sysroot_to_crate_graph( stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); (public_deps, libproc_macro) } - SysrootWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None), + RustLibSrcWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 59dec9a9f36f..b9b7ad1faf89 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -12,8 +12,8 @@ use paths::Utf8PathBuf; use profile::StopWatch; use project_model::toolchain_info::{target_data_layout, QueryConfig}; use project_model::{ - CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource, Sysroot, - SysrootSourceWorkspaceConfig, + CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource, + RustSourceWorkspaceConfig, Sysroot, }; use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; @@ -75,7 +75,7 @@ impl Tester { }; let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env); - let loaded_sysroot = sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo()); + let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index a33b9e46fed2..6f26bdc2cf02 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1153,7 +1153,7 @@ fn resolve_proc_macro() { &Default::default(), ); let loaded_sysroot = - sysroot.load_workspace(&project_model::SysrootSourceWorkspaceConfig::default_cargo()); + sysroot.load_workspace(&project_model::RustSourceWorkspaceConfig::default_cargo()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } From 7ef1fcf972be411f4e4f6855b963904b90c6eb5e Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 11 Feb 2025 15:16:54 -0800 Subject: [PATCH 044/158] manual: Separate out installation and configuration pages Organise the installation content into: * VS Code instructions * Binary installation * Editor configuration --- .../rust-analyzer/docs/book/src/SUMMARY.md | 3 + .../docs/book/src/installation.md | 632 +----------------- .../docs/book/src/other_editors.md | 423 ++++++++++++ .../docs/book/src/rust_analyzer_binary.md | 74 ++ .../rust-analyzer/docs/book/src/vs_code.md | 121 ++++ 5 files changed, 635 insertions(+), 618 deletions(-) create mode 100644 src/tools/rust-analyzer/docs/book/src/other_editors.md create mode 100644 src/tools/rust-analyzer/docs/book/src/rust_analyzer_binary.md create mode 100644 src/tools/rust-analyzer/docs/book/src/vs_code.md diff --git a/src/tools/rust-analyzer/docs/book/src/SUMMARY.md b/src/tools/rust-analyzer/docs/book/src/SUMMARY.md index b3ed1e6df0a7..9dc4f1f2d2a1 100644 --- a/src/tools/rust-analyzer/docs/book/src/SUMMARY.md +++ b/src/tools/rust-analyzer/docs/book/src/SUMMARY.md @@ -2,6 +2,9 @@ - [Introduction](README.md) - [Installation](installation.md) + - [VS Code](vs_code.md) + - [rust-analyzer Binary](rust_analyzer_binary.md) + - [Other Editors](other_editors.md) - [Troubleshooting](troubleshooting.md) - [Configuration](configuration.md) - [Non-Cargo Based Projects](non_cargo_based_projects.md) diff --git a/src/tools/rust-analyzer/docs/book/src/installation.md b/src/tools/rust-analyzer/docs/book/src/installation.md index 5b697e9bc33d..3a4c0cf22774 100644 --- a/src/tools/rust-analyzer/docs/book/src/installation.md +++ b/src/tools/rust-analyzer/docs/book/src/installation.md @@ -1,20 +1,20 @@ # Installation -In theory, one should be able to just install the [`rust-analyzer` -binary](#rust-analyzer-language-server-binary) and have it automatically -work with any editor. We are not there yet, so some editor specific -setup is required. +To use rust-analyzer, you need a `rust-analyzer` binary, a text editor +that supports LSP, and the source code of the Rust standard library. -Additionally, rust-analyzer needs the sources of the standard library. -If the source code is not present, rust-analyzer will attempt to install -it automatically. +If you're [using VS Code](./vs_code.html), the extension bundles a +copy of the `rust-analyzer` binary. For other editors, you'll need to +[install the binary](./rust_analyzer_binary.html) and [configure your +editor](./other_editors.html). -To add the sources manually, run the following command: +## Rust Standard Library + +rust-analyzer will attempt to install the standard library source code +automatically. You can also install it manually with `rustup`. $ rustup component add rust-src -## Toolchain - Only the latest stable standard library source is officially supported for use with rust-analyzer. If you are using an older toolchain or have an override set, rust-analyzer may fail to understand the Rust source. @@ -25,620 +25,16 @@ If you are using an override in your project, you can still force rust-analyzer to use the stable toolchain via the environment variable `RUSTUP_TOOLCHAIN`. For example, with VS Code or coc-rust-analyzer: - { "rust-analyzer.server.extraEnv": { "RUSTUP_TOOLCHAIN": "stable" } } - -## VS Code - -This is the best supported editor at the moment. The rust-analyzer -plugin for VS Code is maintained [in -tree](https://github.com/rust-lang/rust-analyzer/tree/master/editors/code). - -You can install the latest release of the plugin from [the -marketplace](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer). - -Note that the plugin may cause conflicts with the [previous official -Rust -plugin](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust). -The latter is no longer maintained and should be uninstalled. - -The server binary is stored in the extension install directory, which -starts with `rust-lang.rust-analyzer-` and is located under: - -- Linux: `~/.vscode/extensions` - -- Linux (Remote, such as WSL): `~/.vscode-server/extensions` - -- macOS: `~/.vscode/extensions` - -- Windows: `%USERPROFILE%\.vscode\extensions` - -As an exception, on NixOS, the extension makes a copy of the server and -stores it under -`~/.config/Code/User/globalStorage/rust-lang.rust-analyzer`. - -Note that we only support the two most recent versions of VS Code. - -### Updates - -The extension will be updated automatically as new versions become -available. It will ask your permission to download the matching language -server version binary if needed. - -#### Nightly - -We ship nightly releases for VS Code. To help us out by testing the -newest code, you can enable pre-release versions in the Code extension -page. - -### Manual installation - -Alternatively, download a VSIX corresponding to your platform from the -[releases](https://github.com/rust-lang/rust-analyzer/releases) page. - -Install the extension with the `Extensions: Install from VSIX` command -within VS Code, or from the command line via: - - $ code --install-extension /path/to/rust-analyzer.vsix - -If you are running an unsupported platform, you can install -`rust-analyzer-no-server.vsix` and compile or obtain a server binary. -Copy the server anywhere, then add the path to your settings.json, for -example: - - { "rust-analyzer.server.path": "~/.local/bin/rust-analyzer-linux" } - -### Building From Source - -Both the server and the Code plugin can be installed from source: - - $ git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer - $ cargo xtask install - -You’ll need Cargo, nodejs (matching a supported version of VS Code) and -npm for this. - -Note that installing via `xtask install` does not work for VS Code -Remote, instead you’ll need to install the `.vsix` manually. - -If you’re not using Code, you can compile and install only the LSP -server: - - $ cargo xtask install --server - -Make sure that `.cargo/bin` is in `$PATH` and precedes paths where -`rust-analyzer` may also be installed. Specifically, `rustup` includes a -proxy called `rust-analyzer`, which can cause problems if you’re -planning to use a source build or even a downloaded binary. - -## rust-analyzer Language Server Binary - -Other editors generally require the `rust-analyzer` binary to be in -`$PATH`. You can download pre-built binaries from the -[releases](https://github.com/rust-lang/rust-analyzer/releases) page. -You will need to uncompress and rename the binary for your platform, -e.g. from `rust-analyzer-aarch64-apple-darwin.gz` on Mac OS to -`rust-analyzer`, make it executable, then move it into a directory in -your `$PATH`. - -On Linux to install the `rust-analyzer` binary into `~/.local/bin`, -these commands should work: - - $ mkdir -p ~/.local/bin - $ curl -L https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz | gunzip -c - > ~/.local/bin/rust-analyzer - $ chmod +x ~/.local/bin/rust-analyzer - -Make sure that `~/.local/bin` is listed in the `$PATH` variable and use -the appropriate URL if you’re not on a `x86-64` system. - -You don’t have to use `~/.local/bin`, any other path like `~/.cargo/bin` -or `/usr/local/bin` will work just as well. - -Alternatively, you can install it from source using the command below. -You’ll need the latest stable version of the Rust toolchain. - - $ git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer - $ cargo xtask install --server - -If your editor can’t find the binary even though the binary is on your -`$PATH`, the likely explanation is that it doesn’t see the same `$PATH` -as the shell, see [this -issue](https://github.com/rust-lang/rust-analyzer/issues/1811). On Unix, -running the editor from a shell or changing the `.desktop` file to set -the environment should help. - -### rustup - -`rust-analyzer` is available in `rustup`: - - $ rustup component add rust-analyzer - -### Arch Linux - -The `rust-analyzer` binary can be installed from the repos or AUR (Arch -User Repository): - -- [`rust-analyzer`](https://www.archlinux.org/packages/extra/x86_64/rust-analyzer/) - (built from latest tagged source) - -- [`rust-analyzer-git`](https://aur.archlinux.org/packages/rust-analyzer-git) - (latest Git version) - -Install it with pacman, for example: - - $ pacman -S rust-analyzer - -### Gentoo Linux - -`rust-analyzer` is installed when the `rust-analyzer` use flag is set for dev-lang/rust or dev-lang/rust-bin. You also need to set the `rust-src` use flag. - -### macOS - -The `rust-analyzer` binary can be installed via -[Homebrew](https://brew.sh/). - - $ brew install rust-analyzer - -### Windows - -It is recommended to install the latest Microsoft Visual C++ Redistributable prior to installation. -Download links can be found -[here](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist). - -## VS Code or VSCodium in Flatpak - -Setting up `rust-analyzer` with a Flatpak version of Code is not trivial -because of the Flatpak sandbox. While the sandbox can be disabled for -some directories, `/usr/bin` will always be mounted under -`/run/host/usr/bin`. This prevents access to the system’s C compiler, a -system-wide installation of Rust, or any other libraries you might want -to link to. Some compilers and libraries can be acquired as Flatpak -SDKs, such as `org.freedesktop.Sdk.Extension.rust-stable` or -`org.freedesktop.Sdk.Extension.llvm15`. - -If you use a Flatpak SDK for Rust, it must be in your `PATH`: - - * install the SDK extensions with `flatpak install org.freedesktop.Sdk.Extension.{llvm15,rust-stable}//23.08` - * enable SDK extensions in the editor with the environment variable `FLATPAK_ENABLE_SDK_EXT=llvm15,rust-stable` (this can be done using flatseal or `flatpak override`) - -If you want to use Flatpak in combination with `rustup`, the following -steps might help: - -- both Rust and `rustup` have to be installed using - . Distro packages *will not* work. - -- you need to launch Code, open a terminal and run `echo $PATH` - -- using - [Flatseal](https://flathub.org/apps/details/com.github.tchx84.Flatseal), - you must add an environment variable called `PATH`. Set its value to - the output from above, appending `:~/.cargo/bin`, where `~` is the - path to your home directory. You must replace `~`, as it won’t be - expanded otherwise. - -- while Flatseal is open, you must enable access to "All user files" - -A C compiler should already be available via `org.freedesktop.Sdk`. Any -other tools or libraries you will need to acquire from Flatpak. - -## Emacs - -Prerequisites: You have installed the [`rust-analyzer` -binary](#rust-analyzer-language-server-binary). - -To use `rust-analyzer`, you need to install and enable one of the two -popular LSP client implementations for Emacs, -[Eglot](https://github.com/joaotavora/eglot) or [LSP -Mode](https://github.com/emacs-lsp/lsp-mode). Both enable -`rust-analyzer` by default in rust buffers if it is available. - -### Eglot - -Eglot is the more minimalistic and lightweight LSP client for Emacs, -integrates well with existing Emacs functionality and is built into -Emacs starting from release 29. - -After installing Eglot, e.g. via `M-x package-install` (not needed from -Emacs 29), you can enable it via the `M-x eglot` command or load it -automatically in `rust-mode` via - - (add-hook 'rust-mode-hook 'eglot-ensure) - -To enable clippy, you will need to configure the initialization options -to pass the `check.command` setting. - - (add-to-list 'eglot-server-programs - '((rust-ts-mode rust-mode) . - ("rust-analyzer" :initializationOptions (:check (:command "clippy"))))) - -For more detailed instructions and options see the [Eglot -manual](https://joaotavora.github.io/eglot) (also available from Emacs -via `M-x info`) and the [Eglot -readme](https://github.com/joaotavora/eglot/blob/master/README.md). - -Eglot does not support the rust-analyzer extensions to the -language-server protocol and does not aim to do so in the future. The -[eglot-x](https://github.com/nemethf/eglot-x#rust-analyzer-extensions) -package adds experimental support for those LSP extensions. - -### LSP Mode - -LSP-mode is the original LSP-client for emacs. Compared to Eglot it has -a larger codebase and supports more features, like LSP protocol -extensions. With extension packages like [LSP -UI](https://github.com/emacs-lsp/lsp-mode) it offers a lot of visual -eyecandy. Further it integrates well with [DAP -mode](https://github.com/emacs-lsp/dap-mode) for support of the Debug -Adapter Protocol. - -You can install LSP-mode via `M-x package-install` and then run it via -the `M-x lsp` command or load it automatically in rust buffers with - - (add-hook 'rust-mode-hook 'lsp-deferred) - -For more information on how to set up LSP mode and its extension package -see the instructions in the [LSP mode -manual](https://emacs-lsp.github.io/lsp-mode/page/installation). Also -see the [rust-analyzer -section](https://emacs-lsp.github.io/lsp-mode/page/lsp-rust-analyzer/) -for `rust-analyzer` specific options and commands, which you can -optionally bind to keys. - -Note the excellent -[guide](https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/) from -[@rksm](https://github.com/rksm) on how to set-up Emacs for Rust -development with LSP mode and several other packages. - -## Vim/Neovim - -Prerequisites: You have installed the [`rust-analyzer` -binary](#rust-analyzer-language-server-binary). Not needed if the -extension can install/update it on its own, coc-rust-analyzer is one -example. - -There are several LSP client implementations for Vim or Neovim: - -### coc-rust-analyzer - -1. Install coc.nvim by following the instructions at - [coc.nvim](https://github.com/neoclide/coc.nvim) (Node.js required) - -2. Run `:CocInstall coc-rust-analyzer` to install - [coc-rust-analyzer](https://github.com/fannheyward/coc-rust-analyzer), - this extension implements *most* of the features supported in the - VSCode extension: - - - automatically install and upgrade stable/nightly releases - - - same configurations as VSCode extension, - `rust-analyzer.server.path`, `rust-analyzer.cargo.features` etc. - - - same commands too, `rust-analyzer.analyzerStatus`, - `rust-analyzer.ssr` etc. - - - inlay hints for variables and method chaining, *Neovim Only* - -Note: for code actions, use `coc-codeaction-cursor` and -`coc-codeaction-selected`; `coc-codeaction` and `coc-codeaction-line` -are unlikely to be useful. - -### LanguageClient-neovim - -1. Install LanguageClient-neovim by following the instructions - [here](https://github.com/autozimu/LanguageClient-neovim) - - - The GitHub project wiki has extra tips on configuration - -2. Configure by adding this to your Vim/Neovim config file (replacing - the existing Rust-specific line if it exists): - - let g:LanguageClient_serverCommands = { - \ 'rust': ['rust-analyzer'], - \ } - -### YouCompleteMe - -Install YouCompleteMe by following the instructions -[here](https://github.com/ycm-core/YouCompleteMe#installation). - -rust-analyzer is the default in ycm, it should work out of the box. - -### ALE - -To use the LSP server in [ale](https://github.com/dense-analysis/ale): - - let g:ale_linters = {'rust': ['analyzer']} - -### nvim-lsp - -Neovim 0.5 has built-in language server support. For a quick start -configuration of rust-analyzer, use -[neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig#rust_analyzer). -Once `neovim/nvim-lspconfig` is installed, use -`lua require'lspconfig'.rust_analyzer.setup({})` in your `init.vim`. - -You can also pass LSP settings to the server: - - lua << EOF - local lspconfig = require'lspconfig' - - local on_attach = function(client) - require'completion'.on_attach(client) - end - - lspconfig.rust_analyzer.setup({ - on_attach = on_attach, - settings = { - ["rust-analyzer"] = { - imports = { - granularity = { - group = "module", - }, - prefix = "self", - }, - cargo = { - buildScripts = { - enable = true, - }, - }, - procMacro = { - enable = true - }, - } - } - }) - EOF - -If you're running Neovim 0.10 or later, you can enable inlay hints via `on_attach`: - -```vim -lspconfig.rust_analyzer.setup({ - on_attach = function(client, bufnr) - vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) - end -}) +```json +{ "rust-analyzer.server.extraEnv": { "RUSTUP_TOOLCHAIN": "stable" } } ``` -Note that the hints are only visible after `rust-analyzer` has finished loading **and** you have to -edit the file to trigger a re-render. - -See for more tips on -getting started. - -Check out for a batteries -included rust-analyzer setup for Neovim. - -### vim-lsp - -vim-lsp is installed by following [the plugin -instructions](https://github.com/prabirshrestha/vim-lsp). It can be as -simple as adding this line to your `.vimrc`: - - Plug 'prabirshrestha/vim-lsp' - -Next you need to register the `rust-analyzer` binary. If it is avim.lspvailable -in `$PATH`, you may want to add this to your `.vimrc`: - - if executable('rust-analyzer') - au User lsp_setup call lsp#register_server({ - \ 'name': 'Rust Language Server', - \ 'cmd': {server_info->['rust-analyzer']}, - \ 'whitelist': ['rust'], - \ }) - endif - -There is no dedicated UI for the server configuration, so you would need -to send any options as a value of the `initialization_options` field, as -described in the [Configuration](#configuration) section. Here is an -example of how to enable the proc-macro support: - - if executable('rust-analyzer') - au User lsp_setup call lsp#register_server({ - \ 'name': 'Rust Language Server', - \ 'cmd': {server_info->['rust-analyzer']}, - \ 'whitelist': ['rust'], - \ 'initialization_options': { - \ 'cargo': { - \ 'buildScripts': { - \ 'enable': v:true, - \ }, - \ }, - \ 'procMacro': { - \ 'enable': v:true, - \ }, - \ }, - \ }) - endif - -## Sublime Text - -### Sublime Text 4: - -- Follow the instructions in - [LSP-rust-analyzer](https://github.com/sublimelsp/LSP-rust-analyzer). - -Install -[LSP-file-watcher-chokidar](https://packagecontrol.io/packages/LSP-file-watcher-chokidar) -to enable file watching (`workspace/didChangeWatchedFiles`). - -### Sublime Text 3: - -- Install the [`rust-analyzer` - binary](#rust-analyzer-language-server-binary). - -- Install the [LSP package](https://packagecontrol.io/packages/LSP). - -- From the command palette, run `LSP: Enable Language Server Globally` - and select `rust-analyzer`. - -If it worked, you should see "rust-analyzer, Line X, Column Y" on the -left side of the status bar, and after waiting a bit, functionalities -like tooltips on hovering over variables should become available. - -If you get an error saying `No such file or directory: 'rust-analyzer'`, -see the [`rust-analyzer` binary](#rust-analyzer-language-server-binary) -section on installing the language server binary. - -## GNOME Builder - -GNOME Builder 3.37.1 and newer has native `rust-analyzer` support. If -the LSP binary is not available, GNOME Builder can install it when -opening a Rust file. - -## Eclipse IDE - -Support for Rust development in the Eclipse IDE is provided by [Eclipse -Corrosion](https://github.com/eclipse/corrosion). If available in PATH -or in some standard location, `rust-analyzer` is detected and powers -editing of Rust files without further configuration. If `rust-analyzer` -is not detected, Corrosion will prompt you for configuration of your -Rust toolchain and language server with a link to the *Window > -Preferences > Rust* preference page; from here a button allows to -download and configure `rust-analyzer`, but you can also reference -another installation. You’ll need to close and reopen all .rs and Cargo -files, or to restart the IDE, for this change to take effect. - -## Kate Text Editor - -Support for the language server protocol is built into Kate through the -LSP plugin, which is included by default. It is preconfigured to use -rust-analyzer for Rust sources since Kate 21.12. - -To change rust-analyzer config options, start from the following example -and put it into Kate’s "User Server Settings" tab (located under the LSP -Client settings): - - { - "servers": { - "rust": { - "initializationOptions": { - "cachePriming": { - "enable": false - }, - "check": { - "allTargets": false - }, - "checkOnSave": false - } - } - } - } - -Then click on apply, and restart the LSP server for your rust project. - -## juCi++ - -[juCi++](https://gitlab.com/cppit/jucipp) has built-in support for the -language server protocol, and since version 1.7.0 offers installation of -both Rust and rust-analyzer when opening a Rust file. - -## Kakoune - -[Kakoune](https://kakoune.org/) supports LSP with the help of -[`kak-lsp`](https://github.com/kak-lsp/kak-lsp). Follow the -[instructions](https://github.com/kak-lsp/kak-lsp#installation) to -install `kak-lsp`. To configure `kak-lsp`, refer to the [configuration -section](https://github.com/kak-lsp/kak-lsp#configuring-kak-lsp) which -is basically about copying the [configuration -file](https://github.com/kak-lsp/kak-lsp/blob/master/kak-lsp.toml) in -the right place (latest versions should use `rust-analyzer` by default). - -Finally, you need to configure Kakoune to talk to `kak-lsp` (see [Usage -section](https://github.com/kak-lsp/kak-lsp#usage)). A basic -configuration will only get you LSP but you can also activate inlay -diagnostics and auto-formatting on save. The following might help you -get all of this. - - eval %sh{kak-lsp --kakoune -s $kak_session} # Not needed if you load it with plug.kak. - hook global WinSetOption filetype=rust %{ - # Enable LSP - lsp-enable-window - - # Auto-formatting on save - hook window BufWritePre .* lsp-formatting-sync - - # Configure inlay hints (only on save) - hook window -group rust-inlay-hints BufWritePost .* rust-analyzer-inlay-hints - hook -once -always window WinSetOption filetype=.* %{ - remove-hooks window rust-inlay-hints - } - } - -## Helix - -[Helix](https://docs.helix-editor.com/) supports LSP by default. -However, it won’t install `rust-analyzer` automatically. You can follow -instructions for installing [`rust-analyzer` -binary](#rust-analyzer-language-server-binary). - -## Visual Studio 2022 - -There are multiple rust-analyzer extensions for Visual Studio 2022 on -Windows: - -### rust-analyzer.vs - -(License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 -International) - -[Visual Studio -Marketplace](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer) - -[GitHub](https://github.com/kitamstudios/rust-analyzer/) - -Support for Rust development in the Visual Studio IDE is enabled by the -[rust-analyzer](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer) -package. Either click on the download link or install from IDE’s -extension manager. For now [Visual Studio -2022](https://visualstudio.microsoft.com/downloads/) is required. All -editions are supported viz. Community, Professional & Enterprise. The -package aims to provide 0-friction installation and therefore comes -loaded with most things required including rust-analyzer binary. If -anything it needs is missing, appropriate errors / warnings will guide -the user. E.g. cargo.exe needs to be in path and the package will tell -you as much. This package is under rapid active development. So if you -encounter any issues please file it at -[rust-analyzer.vs](https://github.com/kitamstudios/rust-analyzer/). - -### VS\_RustAnalyzer - -(License: GPL) - -[Visual Studio -Marketplace](https://marketplace.visualstudio.com/items?itemName=cchharris.vsrustanalyzer) - -[GitHub](https://github.com/cchharris/VS-RustAnalyzer) - -### SourceGear Rust - -(License: closed source) - -[Visual Studio -Marketplace](https://marketplace.visualstudio.com/items?itemName=SourceGear.SourceGearRust) - -[GitHub (docs, issues, -discussions)](https://github.com/sourcegear/rust-vs-extension) - -- Free (no-cost) - -- Supports all editions of Visual Studio 2022 on Windows: Community, - Professional, or Enterprise - -## Lapce - -[Lapce](https://lapce.dev/) has a Rust plugin which you can install -directly. Unfortunately, it downloads an old version of `rust-analyzer`, -but you can set the server path under Settings. - ## Crates There is a package named `ra_ap_rust_analyzer` available on -[crates.io](https://crates.io/crates/ra_ap_rust-analyzer), for someone -who wants to use it programmatically. +[crates.io](https://crates.io/crates/ra_ap_rust-analyzer), for people +who want to use rust-analyzer programmatically. For more details, see [the publish workflow](https://github.com/rust-lang/rust-analyzer/blob/master/.github/workflows/autopublish.yaml). -## Zed - -[Zed](https://zed.dev) has native `rust-analyzer` support. If the LSP -binary is not available, Zed can install it when opening a Rust file. diff --git a/src/tools/rust-analyzer/docs/book/src/other_editors.md b/src/tools/rust-analyzer/docs/book/src/other_editors.md new file mode 100644 index 000000000000..0a9a453e0137 --- /dev/null +++ b/src/tools/rust-analyzer/docs/book/src/other_editors.md @@ -0,0 +1,423 @@ +# Other Editors + +rust-analyzer works with any editor that supports the [Language Server +Protocol](https://microsoft.github.io/language-server-protocol/). + +This page assumes that you have already [installed the rust-analyzer +binary](./rust_analyzer_binary.html). + +## Emacs + +To use `rust-analyzer`, you need to install and enable one of the two +popular LSP client implementations for Emacs, +[Eglot](https://github.com/joaotavora/eglot) or [LSP +Mode](https://github.com/emacs-lsp/lsp-mode). Both enable +`rust-analyzer` by default in Rust buffers if it is available. + +### Eglot + +Eglot is the more minimalistic and lightweight LSP client for Emacs, +integrates well with existing Emacs functionality and is built into +Emacs starting from release 29. + +After installing Eglot, e.g. via `M-x package-install` (not needed from +Emacs 29), you can enable it via the `M-x eglot` command or load it +automatically in `rust-mode` via + +``` +(add-hook 'rust-mode-hook 'eglot-ensure) +``` + +To enable clippy, you will need to configure the initialization options +to pass the `check.command` setting. + +``` +(add-to-list 'eglot-server-programs + '((rust-ts-mode rust-mode) . + ("rust-analyzer" :initializationOptions (:check (:command "clippy"))))) +``` + +For more detailed instructions and options see the [Eglot +manual](https://joaotavora.github.io/eglot) (also available from Emacs +via `M-x info`) and the [Eglot +readme](https://github.com/joaotavora/eglot/blob/master/README.md). + +Eglot does not support the rust-analyzer extensions to the +language-server protocol and does not aim to do so in the future. The +[eglot-x](https://github.com/nemethf/eglot-x#rust-analyzer-extensions) +package adds experimental support for those LSP extensions. + +### LSP Mode + +LSP-mode is the original LSP-client for emacs. Compared to Eglot it has +a larger codebase and supports more features, like LSP protocol +extensions. With extension packages like [LSP +UI](https://github.com/emacs-lsp/lsp-mode) it offers a lot of visual +eyecandy. Further it integrates well with [DAP +mode](https://github.com/emacs-lsp/dap-mode) for support of the Debug +Adapter Protocol. + +You can install LSP-mode via `M-x package-install` and then run it via +the `M-x lsp` command or load it automatically in rust buffers with + +``` +(add-hook 'rust-mode-hook 'lsp-deferred) +``` + +For more information on how to set up LSP mode and its extension package +see the instructions in the [LSP mode +manual](https://emacs-lsp.github.io/lsp-mode/page/installation). Also +see the [rust-analyzer +section](https://emacs-lsp.github.io/lsp-mode/page/lsp-rust-analyzer/) +for `rust-analyzer` specific options and commands, which you can +optionally bind to keys. + +Note the excellent +[guide](https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/) from +[@rksm](https://github.com/rksm) on how to set-up Emacs for Rust +development with LSP mode and several other packages. + +## Vim/Neovim + +There are several LSP client implementations for Vim or Neovim: + +### coc-rust-analyzer + +1. Install coc.nvim by following the instructions at + [coc.nvim](https://github.com/neoclide/coc.nvim) (Node.js required) + +2. Run `:CocInstall coc-rust-analyzer` to install + [coc-rust-analyzer](https://github.com/fannheyward/coc-rust-analyzer), + this extension implements *most* of the features supported in the + VSCode extension: + + - automatically install and upgrade stable/nightly releases + + - same configurations as VSCode extension, + `rust-analyzer.server.path`, `rust-analyzer.cargo.features` etc. + + - same commands too, `rust-analyzer.analyzerStatus`, + `rust-analyzer.ssr` etc. + + - inlay hints for variables and method chaining, *Neovim Only* + +Note: coc-rust-analyzer is capable of installing or updating the +rust-analyzer binary on its own. + +Note: for code actions, use `coc-codeaction-cursor` and +`coc-codeaction-selected`; `coc-codeaction` and `coc-codeaction-line` +are unlikely to be useful. + +### LanguageClient-neovim + +1. Install LanguageClient-neovim by following the instructions + [here](https://github.com/autozimu/LanguageClient-neovim) + + - The GitHub project wiki has extra tips on configuration + +2. Configure by adding this to your Vim/Neovim config file (replacing + the existing Rust-specific line if it exists): + + let g:LanguageClient_serverCommands = { + \ 'rust': ['rust-analyzer'], + \ } + +### YouCompleteMe + +Install YouCompleteMe by following the instructions +[here](https://github.com/ycm-core/YouCompleteMe#installation). + +rust-analyzer is the default in ycm, it should work out of the box. + +### ALE + +To use the LSP server in [ale](https://github.com/dense-analysis/ale): + + let g:ale_linters = {'rust': ['analyzer']} + +### nvim-lsp + +Neovim 0.5 has built-in language server support. For a quick start +configuration of rust-analyzer, use +[neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig#rust_analyzer). +Once `neovim/nvim-lspconfig` is installed, use +`lua require'lspconfig'.rust_analyzer.setup({})` in your `init.vim`. + +You can also pass LSP settings to the server: + +```lua +lua << EOF +local lspconfig = require'lspconfig' + +local on_attach = function(client) + require'completion'.on_attach(client) +end + +lspconfig.rust_analyzer.setup({ + on_attach = on_attach, + settings = { + ["rust-analyzer"] = { + imports = { + granularity = { + group = "module", + }, + prefix = "self", + }, + cargo = { + buildScripts = { + enable = true, + }, + }, + procMacro = { + enable = true + }, + } + } +}) +EOF +``` + +If you're running Neovim 0.10 or later, you can enable inlay hints via `on_attach`: + +```lua +lspconfig.rust_analyzer.setup({ + on_attach = function(client, bufnr) + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) + end +}) +``` + +Note that the hints are only visible after `rust-analyzer` has finished loading **and** you have to +edit the file to trigger a re-render. + +See for more tips on +getting started. + +Check out for a batteries +included rust-analyzer setup for Neovim. + +### vim-lsp + +vim-lsp is installed by following [the plugin +instructions](https://github.com/prabirshrestha/vim-lsp). It can be as +simple as adding this line to your `.vimrc`: + + Plug 'prabirshrestha/vim-lsp' + +Next you need to register the `rust-analyzer` binary. If it is avim.lspvailable +in `$PATH`, you may want to add this to your `.vimrc`: + + if executable('rust-analyzer') + au User lsp_setup call lsp#register_server({ + \ 'name': 'Rust Language Server', + \ 'cmd': {server_info->['rust-analyzer']}, + \ 'whitelist': ['rust'], + \ }) + endif + +There is no dedicated UI for the server configuration, so you would need +to send any options as a value of the `initialization_options` field, as +described in the [Configuration](#configuration) section. Here is an +example of how to enable the proc-macro support: + + if executable('rust-analyzer') + au User lsp_setup call lsp#register_server({ + \ 'name': 'Rust Language Server', + \ 'cmd': {server_info->['rust-analyzer']}, + \ 'whitelist': ['rust'], + \ 'initialization_options': { + \ 'cargo': { + \ 'buildScripts': { + \ 'enable': v:true, + \ }, + \ }, + \ 'procMacro': { + \ 'enable': v:true, + \ }, + \ }, + \ }) + endif + +## Sublime Text + +### Sublime Text 4: + +- Follow the instructions in + [LSP-rust-analyzer](https://github.com/sublimelsp/LSP-rust-analyzer). + +Install +[LSP-file-watcher-chokidar](https://packagecontrol.io/packages/LSP-file-watcher-chokidar) +to enable file watching (`workspace/didChangeWatchedFiles`). + +### Sublime Text 3: + +- Install the [LSP package](https://packagecontrol.io/packages/LSP). + +- From the command palette, run `LSP: Enable Language Server Globally` + and select `rust-analyzer`. + +If it worked, you should see "rust-analyzer, Line X, Column Y" on the +left side of the status bar, and after waiting a bit, functionalities +like tooltips on hovering over variables should become available. + +If you get an error saying `No such file or directory: 'rust-analyzer'`, +see the [rust-analyzer binary installation](./rust_analyzer_binary.html) section. + +## GNOME Builder + +GNOME Builder 3.37.1 and newer has native `rust-analyzer` support. If +the LSP binary is not available, GNOME Builder can install it when +opening a Rust file. + +## Eclipse IDE + +Support for Rust development in the Eclipse IDE is provided by [Eclipse +Corrosion](https://github.com/eclipse/corrosion). If available in PATH +or in some standard location, `rust-analyzer` is detected and powers +editing of Rust files without further configuration. If `rust-analyzer` +is not detected, Corrosion will prompt you for configuration of your +Rust toolchain and language server with a link to the *Window > +Preferences > Rust* preference page; from here a button allows to +download and configure `rust-analyzer`, but you can also reference +another installation. You’ll need to close and reopen all .rs and Cargo +files, or to restart the IDE, for this change to take effect. + +## Kate Text Editor + +Support for the language server protocol is built into Kate through the +LSP plugin, which is included by default. It is preconfigured to use +rust-analyzer for Rust sources since Kate 21.12. + +To change rust-analyzer config options, start from the following example +and put it into Kate’s "User Server Settings" tab (located under the LSP +Client settings): + +```json +{ + "servers": { + "rust": { + "initializationOptions": { + "cachePriming": { + "enable": false + }, + "check": { + "allTargets": false + }, + "checkOnSave": false + } + } + } +} +``` + +Then click on apply, and restart the LSP server for your rust project. + +## juCi++ + +[juCi++](https://gitlab.com/cppit/jucipp) has built-in support for the +language server protocol, and since version 1.7.0 offers installation of +both Rust and rust-analyzer when opening a Rust file. + +## Kakoune + +[Kakoune](https://kakoune.org/) supports LSP with the help of +[`kak-lsp`](https://github.com/kak-lsp/kak-lsp). Follow the +[instructions](https://github.com/kak-lsp/kak-lsp#installation) to +install `kak-lsp`. To configure `kak-lsp`, refer to the [configuration +section](https://github.com/kak-lsp/kak-lsp#configuring-kak-lsp) which +is basically about copying the [configuration +file](https://github.com/kak-lsp/kak-lsp/blob/master/kak-lsp.toml) in +the right place (latest versions should use `rust-analyzer` by default). + +Finally, you need to configure Kakoune to talk to `kak-lsp` (see [Usage +section](https://github.com/kak-lsp/kak-lsp#usage)). A basic +configuration will only get you LSP but you can also activate inlay +diagnostics and auto-formatting on save. The following might help you +get all of this. + + eval %sh{kak-lsp --kakoune -s $kak_session} # Not needed if you load it with plug.kak. + hook global WinSetOption filetype=rust %{ + # Enable LSP + lsp-enable-window + + # Auto-formatting on save + hook window BufWritePre .* lsp-formatting-sync + + # Configure inlay hints (only on save) + hook window -group rust-inlay-hints BufWritePost .* rust-analyzer-inlay-hints + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window rust-inlay-hints + } + } + +## Helix + +[Helix](https://docs.helix-editor.com/) supports LSP by default. +However, it won’t install `rust-analyzer` automatically. You can follow +instructions for [installing the rust-analyzer +binary](./rust_analyzer_binary.html). + +## Visual Studio 2022 + +There are multiple rust-analyzer extensions for Visual Studio 2022 on +Windows: + +### rust-analyzer.vs + +(License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 +International) + +[Visual Studio +Marketplace](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer) + +[GitHub](https://github.com/kitamstudios/rust-analyzer/) + +Support for Rust development in the Visual Studio IDE is enabled by the +[rust-analyzer](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer) +package. Either click on the download link or install from IDE’s +extension manager. For now [Visual Studio +2022](https://visualstudio.microsoft.com/downloads/) is required. All +editions are supported viz. Community, Professional & Enterprise. The +package aims to provide 0-friction installation and therefore comes +loaded with most things required including rust-analyzer binary. If +anything it needs is missing, appropriate errors / warnings will guide +the user. E.g. cargo.exe needs to be in path and the package will tell +you as much. This package is under rapid active development. So if you +encounter any issues please file it at +[rust-analyzer.vs](https://github.com/kitamstudios/rust-analyzer/). + +### VS RustAnalyzer + +(License: GPL) + +[Visual Studio +Marketplace](https://marketplace.visualstudio.com/items?itemName=cchharris.vsrustanalyzer) + +[GitHub](https://github.com/cchharris/VS-RustAnalyzer) + +### SourceGear Rust + +(License: closed source) + +[Visual Studio +Marketplace](https://marketplace.visualstudio.com/items?itemName=SourceGear.SourceGearRust) + +[GitHub (docs, issues, +discussions)](https://github.com/sourcegear/rust-vs-extension) + +- Free (no-cost) + +- Supports all editions of Visual Studio 2022 on Windows: Community, + Professional, or Enterprise + +## Lapce + +[Lapce](https://lapce.dev/) has a Rust plugin which you can install +directly. Unfortunately, it downloads an old version of `rust-analyzer`, +but you can set the server path under Settings. + +## Zed + +[Zed](https://zed.dev) has native `rust-analyzer` support. If the +rust-analyzer binary is not available, Zed can install it when opening +a Rust file. diff --git a/src/tools/rust-analyzer/docs/book/src/rust_analyzer_binary.md b/src/tools/rust-analyzer/docs/book/src/rust_analyzer_binary.md new file mode 100644 index 000000000000..c7ac3087ced7 --- /dev/null +++ b/src/tools/rust-analyzer/docs/book/src/rust_analyzer_binary.md @@ -0,0 +1,74 @@ +# rust-analyzer Binary + +Text editors require the `rust-analyzer` binary to be in +`$PATH`. You can download pre-built binaries from the +[releases](https://github.com/rust-lang/rust-analyzer/releases) page. +You will need to uncompress and rename the binary for your platform, +e.g. from `rust-analyzer-aarch64-apple-darwin.gz` on Mac OS to +`rust-analyzer`, make it executable, then move it into a directory in +your `$PATH`. + +On Linux to install the `rust-analyzer` binary into `~/.local/bin`, +these commands should work: + + $ mkdir -p ~/.local/bin + $ curl -L https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz | gunzip -c - > ~/.local/bin/rust-analyzer + $ chmod +x ~/.local/bin/rust-analyzer + +Make sure that `~/.local/bin` is listed in the `$PATH` variable and use +the appropriate URL if you’re not on a `x86-64` system. + +You don’t have to use `~/.local/bin`, any other path like `~/.cargo/bin` +or `/usr/local/bin` will work just as well. + +Alternatively, you can install it from source using the command below. +You’ll need the latest stable version of the Rust toolchain. + + $ git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer + $ cargo xtask install --server + +If your editor can’t find the binary even though the binary is on your +`$PATH`, the likely explanation is that it doesn’t see the same `$PATH` +as the shell, see [this +issue](https://github.com/rust-lang/rust-analyzer/issues/1811). On Unix, +running the editor from a shell or changing the `.desktop` file to set +the environment should help. + +### rustup + +`rust-analyzer` is available in `rustup`: + + $ rustup component add rust-analyzer + +### Arch Linux + +The `rust-analyzer` binary can be installed from the repos or AUR (Arch +User Repository): + +- [`rust-analyzer`](https://www.archlinux.org/packages/extra/x86_64/rust-analyzer/) + (built from latest tagged source) + +- [`rust-analyzer-git`](https://aur.archlinux.org/packages/rust-analyzer-git) + (latest Git version) + +Install it with pacman, for example: + + $ pacman -S rust-analyzer + +### Gentoo Linux + +`rust-analyzer` is installed when the `rust-analyzer` use flag is set for dev-lang/rust or dev-lang/rust-bin. You also need to set the `rust-src` use flag. + +### macOS + +The `rust-analyzer` binary can be installed via +[Homebrew](https://brew.sh/). + + $ brew install rust-analyzer + +### Windows + +It is recommended to install the latest Microsoft Visual C++ Redistributable prior to installation. +Download links can be found +[here](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist). + diff --git a/src/tools/rust-analyzer/docs/book/src/vs_code.md b/src/tools/rust-analyzer/docs/book/src/vs_code.md new file mode 100644 index 000000000000..233b862d2c6b --- /dev/null +++ b/src/tools/rust-analyzer/docs/book/src/vs_code.md @@ -0,0 +1,121 @@ +# VS Code + +This is the best supported editor at the moment. The rust-analyzer +plugin for VS Code is maintained [in +tree](https://github.com/rust-lang/rust-analyzer/tree/master/editors/code). + +You can install the latest release of the plugin from [the +marketplace](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer). + +Note that the plugin may cause conflicts with the [previous official +Rust +plugin](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust). +The latter is no longer maintained and should be uninstalled. + +The server binary is stored in the extension install directory, which +starts with `rust-lang.rust-analyzer-` and is located under: + +- Linux: `~/.vscode/extensions` + +- Linux (Remote, such as WSL): `~/.vscode-server/extensions` + +- macOS: `~/.vscode/extensions` + +- Windows: `%USERPROFILE%\.vscode\extensions` + +As an exception, on NixOS, the extension makes a copy of the server and +stores it under +`~/.config/Code/User/globalStorage/rust-lang.rust-analyzer`. + +Note that we only support the two most recent versions of VS Code. + +### Updates + +The extension will be updated automatically as new versions become +available. It will ask your permission to download the matching language +server version binary if needed. + +#### Nightly + +We ship nightly releases for VS Code. To help us out by testing the +newest code, you can enable pre-release versions in the Code extension +page. + +### Manual installation + +Alternatively, download a VSIX corresponding to your platform from the +[releases](https://github.com/rust-lang/rust-analyzer/releases) page. + +Install the extension with the `Extensions: Install from VSIX` command +within VS Code, or from the command line via: + + $ code --install-extension /path/to/rust-analyzer.vsix + +If you are running an unsupported platform, you can install +`rust-analyzer-no-server.vsix` and compile or obtain a server binary. +Copy the server anywhere, then add the path to your settings.json, for +example: + +```json +{ "rust-analyzer.server.path": "~/.local/bin/rust-analyzer-linux" } +``` + +### Building From Source + +Both the server and the Code plugin can be installed from source: + + $ git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer + $ cargo xtask install + +You’ll need Cargo, nodejs (matching a supported version of VS Code) and +npm for this. + +Note that installing via `xtask install` does not work for VS Code +Remote, instead you’ll need to install the `.vsix` manually. + +If you’re not using Code, you can compile and install only the LSP +server: + + $ cargo xtask install --server + +Make sure that `.cargo/bin` is in `$PATH` and precedes paths where +`rust-analyzer` may also be installed. Specifically, `rustup` includes a +proxy called `rust-analyzer`, which can cause problems if you’re +planning to use a source build or even a downloaded binary. + +## VS Code or VSCodium in Flatpak + +Setting up `rust-analyzer` with a Flatpak version of Code is not trivial +because of the Flatpak sandbox. While the sandbox can be disabled for +some directories, `/usr/bin` will always be mounted under +`/run/host/usr/bin`. This prevents access to the system’s C compiler, a +system-wide installation of Rust, or any other libraries you might want +to link to. Some compilers and libraries can be acquired as Flatpak +SDKs, such as `org.freedesktop.Sdk.Extension.rust-stable` or +`org.freedesktop.Sdk.Extension.llvm15`. + +If you use a Flatpak SDK for Rust, it must be in your `PATH`: + + * install the SDK extensions with `flatpak install org.freedesktop.Sdk.Extension.{llvm15,rust-stable}//23.08` + * enable SDK extensions in the editor with the environment variable `FLATPAK_ENABLE_SDK_EXT=llvm15,rust-stable` (this can be done using flatseal or `flatpak override`) + +If you want to use Flatpak in combination with `rustup`, the following +steps might help: + +- both Rust and `rustup` have to be installed using + . Distro packages *will not* work. + +- you need to launch Code, open a terminal and run `echo $PATH` + +- using + [Flatseal](https://flathub.org/apps/details/com.github.tchx84.Flatseal), + you must add an environment variable called `PATH`. Set its value to + the output from above, appending `:~/.cargo/bin`, where `~` is the + path to your home directory. You must replace `~`, as it won’t be + expanded otherwise. + +- while Flatseal is open, you must enable access to "All user files" + +A C compiler should already be available via `org.freedesktop.Sdk`. Any +other tools or libraries you will need to acquire from Flatpak. + From d72b2df1526b9a2c168ffc851cc805db3f4fd8df Mon Sep 17 00:00:00 2001 From: asuto15 Date: Thu, 13 Feb 2025 03:58:20 +0900 Subject: [PATCH 045/158] Add modifiers to highlighting for extern crate --- .../ide/src/syntax_highlighting/highlight.rs | 19 ++++++++++++++++++- .../test_data/highlight_doctest.html | 8 +++++++- .../ide/src/syntax_highlighting/tests.rs | 6 ++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index c6e11b9cbdf7..d580b3001c3e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -703,7 +703,24 @@ fn highlight_name_ref_by_syntax( }; match parent.kind() { - EXTERN_CRATE => HlTag::Symbol(SymbolKind::Module).into(), + EXTERN_CRATE => { + let mut h: Highlight = HlTag::Symbol(SymbolKind::Module).into(); + let is_crate_root = if let Some(extern_crate) = ast::ExternCrate::cast(parent.clone()) { + if let Some(first_segment) = extern_crate.name_ref() { + first_segment.syntax().text() == name.syntax().text() + } else { + false + } + } else { + false + }; + + if is_crate_root { + h |= HlMod::CrateRoot; + } + + h | HlMod::Library + }, METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) .and_then(|it| highlight_method_call(sema, krate, &it, edition)) .unwrap_or_else(|| SymbolKind::Method.into()), diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 2f7bc65d14bb..9a55f7d01b90 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -51,7 +51,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd //! ``` //! ```rust -//! extern crate Krate; +//! extern crate self; +//! extern crate std; +//! extern crate core; +//! extern crate alloc; +//! extern crate proc_macro; +//! extern crate test; +//! extern crate Krate; //! ``` mod outline_module; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index ad3d47639111..364d0909243f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -723,6 +723,12 @@ fn test_highlight_doc_comment() { //! ``` //! ```rust +//! extern crate self; +//! extern crate std; +//! extern crate core; +//! extern crate alloc; +//! extern crate proc_macro; +//! extern crate test; //! extern crate Krate; //! ``` mod outline_module; From 21b0c22054d0a3e58d496b6b5fb920ca9468efed Mon Sep 17 00:00:00 2001 From: asuto15 Date: Thu, 13 Feb 2025 04:33:08 +0900 Subject: [PATCH 046/158] Delete useless comma --- .../crates/ide/src/syntax_highlighting/highlight.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index d580b3001c3e..8abaccd25368 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -720,7 +720,7 @@ fn highlight_name_ref_by_syntax( } h | HlMod::Library - }, + } METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) .and_then(|it| highlight_method_call(sema, krate, &it, edition)) .unwrap_or_else(|| SymbolKind::Method.into()), From b3ef716d165c70f4f2cfb239813d8fdd5a1193f0 Mon Sep 17 00:00:00 2001 From: David Richey Date: Wed, 12 Feb 2025 13:16:38 -0600 Subject: [PATCH 047/158] Apply cfg.setTest to json projects --- .../crates/project-model/src/tests.rs | 5 +- .../crates/project-model/src/workspace.rs | 84 ++++++++++--------- .../output/rust_project_cfg_groups.txt | 2 + ...rust_project_hello_world_project_model.txt | 1 + .../rust-analyzer/src/cli/rustc_tests.rs | 2 +- 5 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 25e4368d95a8..54eb0e3478a7 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -42,7 +42,6 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace { build_scripts: WorkspaceBuildScripts::default(), rustc: Err(None), error: None, - set_test: true, }, cfg_overrides: Default::default(), sysroot: Sysroot::empty(), @@ -50,6 +49,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace { toolchain: None, target_layout: Err("target_data_layout not loaded".into()), extra_includes: Vec::new(), + set_test: true, } } @@ -65,6 +65,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) { target_layout: Err(Arc::from("test has no data layout")), cfg_overrides: Default::default(), extra_includes: Vec::new(), + set_test: true, }; to_crate_graph(project_workspace, &mut Default::default()) } @@ -285,7 +286,6 @@ fn smoke_test_real_sysroot_cargo() { build_scripts: WorkspaceBuildScripts::default(), rustc: Err(None), error: None, - set_test: true, }, sysroot, rustc_cfg: Vec::new(), @@ -293,6 +293,7 @@ fn smoke_test_real_sysroot_cargo() { toolchain: None, target_layout: Err("target_data_layout not loaded".into()), extra_includes: Vec::new(), + set_test: true, }; project_workspace.to_crate_graph( &mut { diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 4f8449cb68c3..f5d46daa80fa 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -64,6 +64,8 @@ pub struct ProjectWorkspace { pub cfg_overrides: CfgOverrides, /// Additional includes to add for the VFS. pub extra_includes: Vec, + /// Set `cfg(test)` for local crates + pub set_test: bool, } #[derive(Clone)] @@ -79,7 +81,6 @@ pub enum ProjectWorkspaceKind { /// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been /// disabled or was otherwise not requested. rustc: Result, Option>, - set_test: bool, }, /// Project workspace was specified using a `rust-project.json` file. Json(ProjectJson), @@ -98,7 +99,6 @@ pub enum ProjectWorkspaceKind { file: ManifestPath, /// Is this file a cargo script file? cargo: Option<(CargoWorkspace, WorkspaceBuildScripts, Option>)>, - set_test: bool, }, } @@ -113,9 +113,10 @@ impl fmt::Debug for ProjectWorkspace { target_layout, cfg_overrides, extra_includes, + set_test, } = self; match kind { - ProjectWorkspaceKind::Cargo { cargo, error: _, build_scripts, rustc, set_test } => f + ProjectWorkspaceKind::Cargo { cargo, error: _, build_scripts, rustc } => f .debug_struct("Cargo") .field("root", &cargo.workspace_root().file_name()) .field("n_packages", &cargo.packages().len()) @@ -141,11 +142,12 @@ impl fmt::Debug for ProjectWorkspace { .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("n_cfg_overrides", &cfg_overrides.len()) - .field("n_extra_includes", &extra_includes.len()); + .field("n_extra_includes", &extra_includes.len()) + .field("set_test", set_test); debug_struct.finish() } - ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test } => f + ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script } => f .debug_struct("DetachedFiles") .field("file", &file) .field("cargo_script", &cargo_script.is_some()) @@ -386,7 +388,6 @@ impl ProjectWorkspace { build_scripts: WorkspaceBuildScripts::default(), rustc, error: error.map(Arc::new), - set_test: *set_test, }, sysroot, rustc_cfg, @@ -394,6 +395,7 @@ impl ProjectWorkspace { toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), extra_includes: extra_includes.clone(), + set_test: *set_test, }) } @@ -449,6 +451,7 @@ impl ProjectWorkspace { target_layout: target_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), extra_includes: config.extra_includes.clone(), + set_test: config.set_test, } } @@ -504,7 +507,6 @@ impl ProjectWorkspace { kind: ProjectWorkspaceKind::DetachedFile { file: detached_file.to_owned(), cargo: cargo_script, - set_test: config.set_test, }, sysroot, rustc_cfg, @@ -512,6 +514,7 @@ impl ProjectWorkspace { target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), extra_includes: config.extra_includes.clone(), + set_test: config.set_test, }) } @@ -696,7 +699,7 @@ impl ProjectWorkspace { .into_iter() .chain(mk_sysroot()) .collect::>(), - ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test: _ } => { + ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _ } => { cargo .packages() .map(|pkg| { @@ -831,8 +834,9 @@ impl ProjectWorkspace { sysroot, extra_env, cfg_overrides, + self.set_test, ), - ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test } => { + ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _ } => { cargo_to_crate_graph( load, rustc.as_ref().map(|a| a.as_ref()).ok(), @@ -841,10 +845,10 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, - *set_test, + self.set_test, ) } - ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => { + ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => { if let Some((cargo, build_scripts, _)) = cargo_script { cargo_to_crate_graph( &mut |path| load(path), @@ -854,7 +858,7 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, - *set_test, + self.set_test, ) } else { detached_file_to_crate_graph( @@ -863,7 +867,7 @@ impl ProjectWorkspace { file, sysroot, cfg_overrides, - *set_test, + self.set_test, ) } } @@ -885,34 +889,22 @@ impl ProjectWorkspace { } = other; (match (kind, o_kind) { ( - ProjectWorkspaceKind::Cargo { - cargo, - rustc, - build_scripts: _, - error: _, - set_test: _, - }, + ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts: _, error: _ }, ProjectWorkspaceKind::Cargo { cargo: o_cargo, rustc: o_rustc, build_scripts: _, error: _, - set_test: _, }, ) => cargo == o_cargo && rustc == o_rustc, (ProjectWorkspaceKind::Json(project), ProjectWorkspaceKind::Json(o_project)) => { project == o_project } ( - ProjectWorkspaceKind::DetachedFile { - file, - cargo: Some((cargo_script, _, _)), - set_test: _, - }, + ProjectWorkspaceKind::DetachedFile { file, cargo: Some((cargo_script, _, _)) }, ProjectWorkspaceKind::DetachedFile { file: o_file, cargo: Some((o_cargo_script, _, _)), - set_test: _, }, ) => file == o_file && cargo_script == o_cargo_script, _ => return false, @@ -940,13 +932,13 @@ fn project_json_to_crate_graph( sysroot: &Sysroot, extra_env: &FxHashMap, override_cfg: &CfgOverrides, + set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let mut res = (CrateGraph::default(), ProcMacroPaths::default()); let (crate_graph, proc_macros) = &mut res; let (public_deps, libproc_macro) = sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); - let r_a_cfg_flag = CfgAtom::Flag(sym::rust_analyzer.clone()); let mut cfg_cache: FxHashMap<&str, Vec> = FxHashMap::default(); let idx_to_crate_id: FxHashMap = project @@ -965,6 +957,7 @@ fn project_json_to_crate_graph( proc_macro_dylib_path, is_proc_macro, repository, + is_workspace_member, .. }, file_id, @@ -982,19 +975,28 @@ fn project_json_to_crate_graph( None => &rustc_cfg, }; - let mut cfg_options = target_cfgs - .iter() - .chain(cfg.iter()) - .chain(iter::once(&r_a_cfg_flag)) - .cloned() - .collect(); - override_cfg.apply( - &mut cfg_options, - display_name - .as_ref() - .map(|it| it.canonical_name().as_str()) - .unwrap_or_default(), - ); + let cfg_options = { + let mut cfg_options: CfgOptions = + target_cfgs.iter().chain(cfg.iter()).cloned().collect(); + + if *is_workspace_member { + if set_test { + // Add test cfg for local crates + cfg_options.insert_atom(sym::test.clone()); + } + cfg_options.insert_atom(sym::rust_analyzer.clone()); + } + + override_cfg.apply( + &mut cfg_options, + display_name + .as_ref() + .map(|it| it.canonical_name().as_str()) + .unwrap_or_default(), + ); + cfg_options + }; + let crate_graph_crate_id = crate_graph.add_crate_root( file_id, *edition, diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt index 2026ab2b8c2f..587d3c17827e 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt @@ -420,6 +420,7 @@ "group1_other_cfg=other_config", "group2_cfg=yet_another_config", "rust_analyzer", + "test", "true", ], ), @@ -496,6 +497,7 @@ "group2_cfg=fourth_config", "group2_cfg=yet_another_config", "rust_analyzer", + "test", "true", "unrelated_cfg", ], diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index a0e14b8fcb22..00805c79bcce 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -417,6 +417,7 @@ cfg_options: CfgOptions( [ "rust_analyzer", + "test", "true", ], ), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index b9b7ad1faf89..e9ca12deaf6e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -90,7 +90,6 @@ impl Tester { kind: ProjectWorkspaceKind::DetachedFile { file: ManifestPath::try_from(tmp_file).unwrap(), cargo: None, - set_test: true, }, sysroot, rustc_cfg: vec![], @@ -98,6 +97,7 @@ impl Tester { target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: Default::default(), extra_includes: vec![], + set_test: true, }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: false, From 7c61ec72e7b8ae411135d20fc25baf0fdcb62d52 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Fri, 14 Feb 2025 02:36:05 +0900 Subject: [PATCH 048/158] internal: Remove mutable syntax tree usages from `add_missing_match_arms` assist --- .../src/handlers/add_missing_match_arms.rs | 130 +++++++++--------- .../crates/syntax/src/ast/edit_in_place.rs | 46 ------- .../crates/syntax/src/ast/make.rs | 3 +- 3 files changed, 66 insertions(+), 113 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 5899ec5a0058..a9a2875a60c1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -6,7 +6,9 @@ use ide_db::syntax_helpers::suggest_name; use ide_db::RootDatabase; use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; use itertools::Itertools; -use syntax::ast::edit_in_place::Removable; +use syntax::ast::edit::IndentLevel; +use syntax::ast::edit_in_place::Indent; +use syntax::ast::syntax_factory::SyntaxFactory; use syntax::ast::{self, make, AstNode, MatchArmList, MatchExpr, Pat}; use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; @@ -200,8 +202,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) AssistId("add_missing_match_arms", AssistKind::QuickFix), "Fill match arms", ctx.sema.original_range(match_expr.syntax()).range, - |edit| { - let new_match_arm_list = match_arm_list.clone_for_update(); + |builder| { + let make = SyntaxFactory::new(); // having any hidden variants means that we need a catch-all arm needs_catch_all_arm |= has_hidden_variants; @@ -211,89 +213,85 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) // filter out hidden patterns because they're handled by the catch-all arm !hidden }) - .map(|(pat, _)| { - make::match_arm(pat, None, make::ext::expr_todo()).clone_for_update() - }); + .map(|(pat, _)| make.match_arm(pat, None, make::ext::expr_todo())); - let catch_all_arm = new_match_arm_list + let mut arms: Vec<_> = match_arm_list .arms() - .find(|arm| matches!(arm.pat(), Some(ast::Pat::WildcardPat(_)))); - if let Some(arm) = catch_all_arm { - let is_empty_expr = arm.expr().is_none_or(|e| match e { - ast::Expr::BlockExpr(b) => { - b.statements().next().is_none() && b.tail_expr().is_none() + .filter(|arm| { + if matches!(arm.pat(), Some(ast::Pat::WildcardPat(_))) { + let is_empty_expr = arm.expr().is_none_or(|e| match e { + ast::Expr::BlockExpr(b) => { + b.statements().next().is_none() && b.tail_expr().is_none() + } + ast::Expr::TupleExpr(t) => t.fields().next().is_none(), + _ => false, + }); + if is_empty_expr { + false + } else { + cov_mark::hit!(add_missing_match_arms_empty_expr); + true + } + } else { + true } - ast::Expr::TupleExpr(t) => t.fields().next().is_none(), - _ => false, - }); - if is_empty_expr { - arm.remove(); - } else { - cov_mark::hit!(add_missing_match_arms_empty_expr); - } - } + }) + .collect(); - let mut added_arms = Vec::new(); - let mut todo_placeholders = Vec::new(); - for arm in missing_arms { - todo_placeholders.push(arm.expr().unwrap()); - added_arms.push(arm); - } + let first_new_arm_idx = arms.len(); + arms.extend(missing_arms); if needs_catch_all_arm && !has_catch_all_arm { cov_mark::hit!(added_wildcard_pattern); - let arm = - make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo()) - .clone_for_update(); - todo_placeholders.push(arm.expr().unwrap()); - added_arms.push(arm); + let arm = make.match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo()); + arms.push(arm); } - let first_new_arm = added_arms.first().cloned(); - let last_new_arm = added_arms.last().cloned(); + let new_match_arm_list = make.match_arm_list(arms); - for arm in added_arms { - new_match_arm_list.add_arm(arm); - } - - if let Some(cap) = ctx.config.snippet_cap { - if let Some(it) = first_new_arm - .and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast)) - { - edit.add_placeholder_snippet(cap, it); - } - - for placeholder in todo_placeholders { - edit.add_placeholder_snippet(cap, placeholder); - } - - if let Some(arm) = last_new_arm { - edit.add_tabstop_after(cap, arm); - } - } - - // FIXME: Hack for mutable syntax trees not having great support for macros + // FIXME: Hack for syntax trees not having great support for macros // Just replace the element that the original range came from let old_place = { // Find the original element let file = ctx.sema.parse(arm_list_range.file_id); let old_place = file.syntax().covering_element(arm_list_range.range); - // Make `old_place` mut match old_place { - syntax::SyntaxElement::Node(it) => { - syntax::SyntaxElement::from(edit.make_syntax_mut(it)) - } + syntax::SyntaxElement::Node(it) => it, syntax::SyntaxElement::Token(it) => { // If a token is found, it is '{' or '}' // The parent is `{ ... }` - let parent = it.parent().expect("Token must have a parent."); - syntax::SyntaxElement::from(edit.make_syntax_mut(parent)) + it.parent().expect("Token must have a parent.") } } }; - syntax::ted::replace(old_place, new_match_arm_list.syntax()); + let mut editor = builder.make_editor(&old_place); + new_match_arm_list.indent(IndentLevel::from_node(&old_place)); + editor.replace(old_place, new_match_arm_list.syntax()); + + if let Some(cap) = ctx.config.snippet_cap { + if let Some(it) = new_match_arm_list + .arms() + .nth(first_new_arm_idx) + .and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast)) + { + editor.add_annotation(it.syntax(), builder.make_placeholder_snippet(cap)); + } + + for arm in new_match_arm_list.arms().skip(first_new_arm_idx) { + if let Some(expr) = arm.expr() { + editor.add_annotation(expr.syntax(), builder.make_placeholder_snippet(cap)); + } + } + + if let Some(arm) = new_match_arm_list.arms().skip(first_new_arm_idx).last() { + editor.add_annotation(arm.syntax(), builder.make_tabstop_after(cap)); + } + } + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } @@ -1502,10 +1500,10 @@ enum Test { fn foo(t: Test) { m!(match t { - Test::A => ${1:todo!()}, - Test::B => ${2:todo!()}, - Test::C => ${3:todo!()},$0 -}); + Test::A => ${1:todo!()}, + Test::B => ${2:todo!()}, + Test::C => ${3:todo!()},$0 + }); }"#, ); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs index 291fc646e216..aedf810b7943 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs @@ -710,52 +710,6 @@ impl ast::Fn { } } -impl Removable for ast::MatchArm { - fn remove(&self) { - if let Some(sibling) = self.syntax().prev_sibling_or_token() { - if sibling.kind() == SyntaxKind::WHITESPACE { - ted::remove(sibling); - } - } - if let Some(sibling) = self.syntax().next_sibling_or_token() { - if sibling.kind() == T![,] { - ted::remove(sibling); - } - } - ted::remove(self.syntax()); - } -} - -impl ast::MatchArmList { - pub fn add_arm(&self, arm: ast::MatchArm) { - normalize_ws_between_braces(self.syntax()); - let mut elements = Vec::new(); - let position = match self.arms().last() { - Some(last_arm) => { - if needs_comma(&last_arm) { - ted::append_child(last_arm.syntax(), make::token(SyntaxKind::COMMA)); - } - Position::after(last_arm.syntax().clone()) - } - None => match self.l_curly_token() { - Some(it) => Position::after(it), - None => Position::last_child_of(self.syntax()), - }, - }; - let indent = IndentLevel::from_node(self.syntax()) + 1; - elements.push(make::tokens::whitespace(&format!("\n{indent}")).into()); - elements.push(arm.syntax().clone().into()); - if needs_comma(&arm) { - ted::append_child(arm.syntax(), make::token(SyntaxKind::COMMA)); - } - ted::insert_all(position, elements); - - fn needs_comma(arm: &ast::MatchArm) -> bool { - arm.expr().is_some_and(|e| !e.is_block_like()) && arm.comma_token().is_none() - } - } -} - impl ast::LetStmt { pub fn set_ty(&self, ty: Option) { match ty { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index ff027ac5848b..9dc2d8325304 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -837,7 +837,8 @@ pub fn match_guard(condition: ast::Expr) -> ast::MatchGuard { pub fn match_arm_list(arms: impl IntoIterator) -> ast::MatchArmList { let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| { - let needs_comma = arm.expr().is_none_or(|it| !it.is_block_like()); + let needs_comma = + arm.comma_token().is_none() && arm.expr().is_none_or(|it| !it.is_block_like()); let comma = if needs_comma { "," } else { "" }; let arm = arm.syntax(); format_to_acc!(acc, " {arm}{comma}\n") From bad69a3d044f651e1fa652558ef47f247f885bc3 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 13 Feb 2025 18:45:31 -0800 Subject: [PATCH 049/158] add cargo's git checkouts to the list of paths to mark as read-only in vscode --- src/tools/rust-analyzer/editors/code/walkthrough-setup-tips.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/rust-analyzer/editors/code/walkthrough-setup-tips.md b/src/tools/rust-analyzer/editors/code/walkthrough-setup-tips.md index fda4ac80023f..aabe0dd662bd 100644 --- a/src/tools/rust-analyzer/editors/code/walkthrough-setup-tips.md +++ b/src/tools/rust-analyzer/editors/code/walkthrough-setup-tips.md @@ -5,6 +5,7 @@ Add the following to settings.json to mark Rust library sources as read-only: ```json "files.readonlyInclude": { "**/.cargo/registry/src/**/*.rs": true, + "**/.cargo/git/checkouts/**/*.rs": true, "**/lib/rustlib/src/rust/library/**/*.rs": true, }, ``` From bf3e787891e93cf7c596ec590a362985bd6057a4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 20 Jan 2025 11:07:09 +0100 Subject: [PATCH 050/158] Update to LLVM 20 --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f9bd42edab3f..97a0c0c54cf9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,7 +29,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/19.1-2024-12-03 + branch = rustc/20.1-2025-02-13 shallow = true [submodule "src/doc/embedded-book"] path = src/doc/embedded-book diff --git a/src/llvm-project b/src/llvm-project index 7e8c93c87c61..92e80685d0d5 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 7e8c93c87c611f21d9bd95100563392f4c18bfe7 +Subproject commit 92e80685d0d5dcea3ccf321995c43b72338639c6 From 97f6e4d34b7e103150c35d390e33d17041363af3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Feb 2025 14:50:40 +0100 Subject: [PATCH 051/158] Quote embedded codeview command line arguments The formatting of the command line arguments has been moved to the frontend in: https://github.com/llvm/llvm-project/commit/e190d074a0a77c9f8a7d7938a8187a7e2076e290 However, the Rust logic introduced in https://github.com/rust-lang/rust/commit/ad0ecebf432fcb80cb666034ea44f75b81e55f95 did not replicate the previous argument quoting behavior. --- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index a6b2384f2d7b..7eb11f9e6087 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -22,6 +22,7 @@ #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Program.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Target/TargetMachine.h" @@ -472,16 +473,19 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0'); auto Arg0 = std::string(ArgsCstrBuff); buffer_offset = Arg0.size() + 1; - auto ArgsCppStr = std::string(ArgsCstrBuff + buffer_offset, - ArgsCstrBuffLen - buffer_offset); - auto i = 0; - while (i != std::string::npos) { - i = ArgsCppStr.find('\0', i + 1); - if (i != std::string::npos) - ArgsCppStr.replace(i, 1, " "); + + std::string CommandlineArgs; + raw_string_ostream OS(CommandlineArgs); + ListSeparator LS(" "); + for (StringRef Arg : split(StringRef(ArgsCstrBuff + buffer_offset, + ArgsCstrBuffLen - buffer_offset), + '\0')) { + OS << LS; + sys::printArg(OS, Arg, /*Quote=*/true); } + OS.flush(); Options.MCOptions.Argv0 = Arg0; - Options.MCOptions.CommandlineArgs = ArgsCppStr; + Options.MCOptions.CommandlineArgs = CommandlineArgs; #else int buffer_offset = 0; assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0'); From 36c314cfb7999a66a49932822a336aea47f62292 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 14 Feb 2025 11:16:32 +0100 Subject: [PATCH 052/158] generate-copyright: pass the source root from bootstrap --- src/bootstrap/src/core/build_steps/run.rs | 1 + src/tools/generate-copyright/src/main.rs | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 167b8a5b168c..84c94a268a38 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -217,6 +217,7 @@ impl Step for GenerateCopyright { cmd.env("DEST", &dest); cmd.env("DEST_LIBSTD", &dest_libstd); cmd.env("OUT_DIR", &builder.out); + cmd.env("SRC_DIR", &builder.src); cmd.env("CARGO", &builder.initial_cargo); // it is important that generate-copyright runs from the root of the // source tree, because it uses relative paths diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index 7a014989e688..677ac76439e8 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -18,6 +18,7 @@ fn main() -> Result<(), Error> { let dest_file = env_path("DEST")?; let libstd_dest_file = env_path("DEST_LIBSTD")?; let out_dir = env_path("OUT_DIR")?; + let src_dir = env_path("SRC_DIR")?; let cargo = env_path("CARGO")?; let license_metadata = env_path("LICENSE_METADATA")?; @@ -27,7 +28,7 @@ fn main() -> Result<(), Error> { let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices( &cargo, &out_dir.join("vendor"), - &root_path, + &src_dir, &[ Path::new("./Cargo.toml"), Path::new("./src/tools/cargo/Cargo.toml"), @@ -38,7 +39,7 @@ fn main() -> Result<(), Error> { let library_collected_cargo_metadata = cargo_metadata::get_metadata_and_notices( &cargo, &out_dir.join("library-vendor"), - &root_path, + &src_dir, &[Path::new("./library/Cargo.toml")], )?; @@ -54,7 +55,7 @@ fn main() -> Result<(), Error> { let library_collected_tree_metadata = Metadata { files: collected_tree_metadata .files - .trim_clone(&Path::new("./library"), &Path::new(".")) + .trim_clone(&src_dir.join("library"), &src_dir) .unwrap(), }; From 08b4f6d2c650d3e6e9010e8a27631962bf31dec7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 14 Feb 2025 11:16:47 +0100 Subject: [PATCH 053/158] generate-copyright: pass the list of manifests from bootstrap --- src/bootstrap/src/core/build_steps/run.rs | 15 ++++++++ .../generate-copyright/src/cargo_metadata.rs | 6 ++-- src/tools/generate-copyright/src/main.rs | 35 +++++++++++++++---- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 84c94a268a38..3f5e701e7e17 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -9,6 +9,7 @@ use crate::Mode; use crate::core::build_steps::dist::distdir; use crate::core::build_steps::test; use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::build_steps::vendor::default_paths_to_vendor; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::core::config::flags::get_completion; @@ -212,7 +213,21 @@ impl Step for GenerateCopyright { let dest = builder.out.join("COPYRIGHT.html"); let dest_libstd = builder.out.join("COPYRIGHT-library.html"); + let paths_to_vendor = default_paths_to_vendor(builder); + for (_, submodules) in &paths_to_vendor { + for submodule in submodules { + builder.build.require_submodule(submodule, None); + } + } + let cargo_manifests = paths_to_vendor + .into_iter() + .map(|(path, _submodules)| path.to_str().unwrap().to_string()) + .inspect(|path| assert!(!path.contains(','), "{path} contains a comma in its name")) + .collect::>() + .join(","); + let mut cmd = builder.tool_cmd(Tool::GenerateCopyright); + cmd.env("CARGO_MANIFESTS", &cargo_manifests); cmd.env("LICENSE_METADATA", &license_metadata); cmd.env("DEST", &dest); cmd.env("DEST_LIBSTD", &dest_libstd); diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs index 51e353e9b229..16c5b5e7104e 100644 --- a/src/tools/generate-copyright/src/cargo_metadata.rs +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -54,7 +54,7 @@ pub fn get_metadata_and_notices( cargo: &Path, vendor_path: &Path, root_path: &Path, - manifest_paths: &[&Path], + manifest_paths: &[PathBuf], ) -> Result, Error> { let mut output = get_metadata(cargo, root_path, manifest_paths)?; @@ -77,7 +77,7 @@ pub fn get_metadata_and_notices( pub fn get_metadata( cargo: &Path, root_path: &Path, - manifest_paths: &[&Path], + manifest_paths: &[PathBuf], ) -> Result, Error> { let mut output = BTreeMap::new(); // Look at the metadata for each manifest @@ -114,7 +114,7 @@ pub fn get_metadata( } /// Run cargo-vendor, fetching into the given dir -fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> { +fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[PathBuf]) -> Result<(), Error> { let mut vendor_command = std::process::Command::new(cargo); vendor_command.env("RUSTC_BOOTSTRAP", "1"); vendor_command.arg("vendor"); diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index 677ac76439e8..7b7cf0f4b699 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -22,25 +22,35 @@ fn main() -> Result<(), Error> { let cargo = env_path("CARGO")?; let license_metadata = env_path("LICENSE_METADATA")?; - let root_path = std::path::absolute(".")?; + let cargo_manifests = env_string("CARGO_MANIFESTS")? + .split(",") + .map(|manifest| manifest.into()) + .collect::>(); + let library_manifests = cargo_manifests + .iter() + .filter(|path| { + if let Ok(stripped) = path.strip_prefix(&src_dir) { + stripped.starts_with("library") + } else { + panic!("manifest {path:?} not relative to source dir {src_dir:?}"); + } + }) + .cloned() + .collect::>(); // Scan Cargo dependencies let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices( &cargo, &out_dir.join("vendor"), &src_dir, - &[ - Path::new("./Cargo.toml"), - Path::new("./src/tools/cargo/Cargo.toml"), - Path::new("./library/Cargo.toml"), - ], + &cargo_manifests, )?; let library_collected_cargo_metadata = cargo_metadata::get_metadata_and_notices( &cargo, &out_dir.join("library-vendor"), &src_dir, - &[Path::new("./library/Cargo.toml")], + &library_manifests, )?; for (key, value) in collected_cargo_metadata.iter_mut() { @@ -194,6 +204,17 @@ struct License { copyright: Vec, } +/// Grab an environment variable as string, or fail nicely. +fn env_string(var: &str) -> Result { + match std::env::var(var) { + Ok(var) => Ok(var), + Err(std::env::VarError::NotUnicode(_)) => { + anyhow::bail!("environment variable {var} is not utf-8") + } + Err(std::env::VarError::NotPresent) => anyhow::bail!("missing environment variable {var}"), + } +} + /// Grab an environment variable as a PathBuf, or fail nicely. fn env_path(var: &str) -> Result { if let Some(var) = std::env::var_os(var) { From 66a45401556b3dbce317c681f3824aabb8a312bb Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 14 Feb 2025 15:31:34 +0300 Subject: [PATCH 054/158] Stabilize (and const-stabilize) `integer_sign_cast` --- library/core/src/num/int_macros.rs | 4 ++-- library/core/src/num/nonzero.rs | 8 ++++---- library/core/src/num/uint_macros.rs | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 96a290ad5a09..296b5ebdfafc 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -193,13 +193,13 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #![feature(integer_sign_cast)] /// #[doc = concat!("let n = -1", stringify!($SelfT), ";")] /// #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")] /// ``` - #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 21bad6705ab8..b59451d7c758 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1633,14 +1633,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// Basic usage: /// /// ``` - /// #![feature(integer_sign_cast)] /// # use std::num::NonZero; /// #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::MAX;")] /// #[doc = concat!("assert_eq!(n.cast_signed(), NonZero::new(-1", stringify!($Sint), ").unwrap());")] /// ``` - #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -2072,14 +2072,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// Basic usage: /// /// ``` - /// #![feature(integer_sign_cast)] /// # use std::num::NonZero; /// #[doc = concat!("let n = NonZero::new(-1", stringify!($Int), ").unwrap();")] /// #[doc = concat!("assert_eq!(n.cast_unsigned(), NonZero::<", stringify!($Uint), ">::MAX);")] /// ``` - #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 29f6791ee6ad..74d3ae699f66 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -223,13 +223,12 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// #![feature(integer_sign_cast)] - /// #[doc = concat!("let n = ", stringify!($SelfT), "::MAX;")] /// #[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")] /// ``` - #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] From 84485a8568f864befdf0eacb7eb275068403dd40 Mon Sep 17 00:00:00 2001 From: asuto15 Date: Sat, 15 Feb 2025 12:06:21 +0900 Subject: [PATCH 055/158] Delete library modifier to highlighting for extern crate --- .../ide/src/syntax_highlighting/highlight.rs | 19 +------------------ .../test_data/highlight_doctest.html | 12 ++++++------ 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 8abaccd25368..92211e9e3a9b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -703,24 +703,7 @@ fn highlight_name_ref_by_syntax( }; match parent.kind() { - EXTERN_CRATE => { - let mut h: Highlight = HlTag::Symbol(SymbolKind::Module).into(); - let is_crate_root = if let Some(extern_crate) = ast::ExternCrate::cast(parent.clone()) { - if let Some(first_segment) = extern_crate.name_ref() { - first_segment.syntax().text() == name.syntax().text() - } else { - false - } - } else { - false - }; - - if is_crate_root { - h |= HlMod::CrateRoot; - } - - h | HlMod::Library - } + EXTERN_CRATE => (HlTag::Symbol(SymbolKind::Module) | HlMod::CrateRoot).into(), METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) .and_then(|it| highlight_method_call(sema, krate, &it, edition)) .unwrap_or_else(|| SymbolKind::Method.into()), diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 9a55f7d01b90..eb77c14c2a57 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -52,12 +52,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd //! ```rust //! extern crate self; -//! extern crate std; -//! extern crate core; -//! extern crate alloc; -//! extern crate proc_macro; -//! extern crate test; -//! extern crate Krate; +//! extern crate std; +//! extern crate core; +//! extern crate alloc; +//! extern crate proc_macro; +//! extern crate test; +//! extern crate Krate; //! ``` mod outline_module; From eaf22bcdce02cca4d71fb6619f89fe048026a8bd Mon Sep 17 00:00:00 2001 From: asuto15 Date: Sat, 15 Feb 2025 13:18:18 +0900 Subject: [PATCH 056/158] fix: remove unnecessary conversion --- .../crates/ide/src/syntax_highlighting/highlight.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 92211e9e3a9b..194fde116011 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -703,7 +703,7 @@ fn highlight_name_ref_by_syntax( }; match parent.kind() { - EXTERN_CRATE => (HlTag::Symbol(SymbolKind::Module) | HlMod::CrateRoot).into(), + EXTERN_CRATE => HlTag::Symbol(SymbolKind::Module) | HlMod::CrateRoot, METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) .and_then(|it| highlight_method_call(sema, krate, &it, edition)) .unwrap_or_else(|| SymbolKind::Method.into()), From d22554a996a11bb1559ebf9e5bbd7db8f048fcad Mon Sep 17 00:00:00 2001 From: xizheyin Date: Sat, 15 Feb 2025 12:18:30 +0800 Subject: [PATCH 057/158] fix: Alloc new errorcode E0803 for E0495 Signed-off-by: xizheyin --- .../src/error_codes/E0803.md | 46 +++++++++++++++++++ compiler/rustc_error_codes/src/lib.rs | 1 + .../src/error_reporting/infer/region.rs | 4 +- ...d-bounds-compatibility-unnormalized.stderr | 4 +- tests/ui/issues/issue-20831-debruijn.stderr | 4 +- .../ui/nll/normalization-bounds-error.stderr | 4 +- ...ions-normalize-in-where-clause-list.stderr | 4 +- tests/ui/regions/resolve-re-error-ice.stderr | 4 +- tests/ui/static/static-lifetime.stderr | 4 +- ...trait-has-wrong-lifetime-parameters.stderr | 4 +- .../closure_wf_outlives.stderr | 4 +- 11 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0803.md diff --git a/compiler/rustc_error_codes/src/error_codes/E0803.md b/compiler/rustc_error_codes/src/error_codes/E0803.md new file mode 100644 index 000000000000..4c022688a2de --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0803.md @@ -0,0 +1,46 @@ +A trait implementation returns a reference without an +explicit lifetime linking it to `self`. +It commonly arises in generic trait implementations +requiring explicit lifetime bounds. + +Erroneous code example: + +```compile_fail,E0803 +trait DataAccess { + fn get_ref(&self) -> T; +} + +struct Container<'a> { + value: &'a f64, +} + +// Attempting to implement reference return +impl<'a> DataAccess<&f64> for Container<'a> { + fn get_ref(&self) -> &f64 { // Error: Lifetime mismatch + self.value + } +} +``` + +The trait method returns &f64 requiring an independent lifetime +The struct Container<'a> carries lifetime parameter 'a +The compiler cannot verify if the returned reference satisfies 'a constraints +Solution +Explicitly bind lifetimes to clarify constraints: +``` +// Modified trait with explicit lifetime binding +trait DataAccess<'a, T> { + fn get_ref(&'a self) -> T; +} + +struct Container<'a> { + value: &'a f64, +} + +// Correct implementation (bound lifetimes) +impl<'a> DataAccess<'a, &'a f64> for Container<'a> { + fn get_ref(&'a self) -> &'a f64 { + self.value + } +} +``` diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index e970b16f6106..098ca42be2b4 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -546,6 +546,7 @@ E0799: 0799, E0800: 0800, E0801: 0801, E0802: 0802, +E0803: 0803, ); ) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index f35a5349ecb3..5f54087eba29 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -2,7 +2,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - Applicability, Diag, E0309, E0310, E0311, E0495, Subdiagnostic, struct_span_code_err, + Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, struct_span_code_err, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { struct_span_code_err!( self.dcx(), var_origin.span(), - E0495, + E0803, "cannot infer an appropriate lifetime{} due to conflicting requirements", var_description ) diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index f498257e12f1..f8ee6fef8242 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5 | LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { @@ -25,4 +25,4 @@ LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0803`. diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr index fe310998f091..bed75ed6ba20 100644 --- a/tests/ui/issues/issue-20831-debruijn.stderr +++ b/tests/ui/issues/issue-20831-debruijn.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/issue-20831-debruijn.rs:28:33 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { @@ -48,4 +48,4 @@ LL | fn subscribe(&mut self, t : Box $DIR/normalization-bounds-error.rs:12:31 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} @@ -36,4 +36,4 @@ LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0803`. diff --git a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr index 2e76333e26f0..ca9ceeeeff35 100644 --- a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 | LL | fn bar<'a, 'b>() @@ -24,4 +24,4 @@ LL | fn bar<'a, 'b>() error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0803`. diff --git a/tests/ui/regions/resolve-re-error-ice.stderr b/tests/ui/regions/resolve-re-error-ice.stderr index 41c5f0fa92eb..f463a97c5bc1 100644 --- a/tests/ui/regions/resolve-re-error-ice.stderr +++ b/tests/ui/regions/resolve-re-error-ice.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter '_ in generic type due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter '_ in generic type due to conflicting requirements --> $DIR/resolve-re-error-ice.rs:12:5 | LL | fn key_set(&self) -> Subject<'a, Keys, (), R> { @@ -34,4 +34,4 @@ LL | struct Subject<'a, T, V, R>(PhantomData<(&'a T, V, R)>); error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0803`. diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr index 7a956dbfeef6..9b5869fd0dc4 100644 --- a/tests/ui/static/static-lifetime.stderr +++ b/tests/ui/static/static-lifetime.stderr @@ -11,7 +11,7 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^ = note: but lifetime parameter must outlive the static lifetime -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/static-lifetime.rs:3:34 | LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} @@ -38,5 +38,5 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} error: aborting due to 2 previous errors -Some errors have detailed explanations: E0478, E0495. +Some errors have detailed explanations: E0478, E0803. For more information about an error, try `rustc --explain E0478`. diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr index 8bf8536c74e4..4e324209fe9e 100644 --- a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { @@ -24,4 +24,4 @@ LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0803`. diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr index 04288112fa86..ae00d3fc6678 100644 --- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -15,7 +15,7 @@ note: but lifetime parameter must outlive the lifetime `'b` as defined here LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0803]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/closure_wf_outlives.rs:34:9 | LL | || {} @@ -63,5 +63,5 @@ LL | type Opaque = impl Sized; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0310, E0478, E0495. +Some errors have detailed explanations: E0310, E0478, E0803. For more information about an error, try `rustc --explain E0310`. From ea10f8efa1d9515a2ced80a05245c5bd19e55040 Mon Sep 17 00:00:00 2001 From: Niklas Korz Date: Sat, 15 Feb 2025 12:04:48 +0100 Subject: [PATCH 058/158] boostrap: skip no_std targets in Std doc step --- src/bootstrap/src/core/build_steps/doc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index dedcc139ae19..1f0787b9c63b 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -580,6 +580,10 @@ impl Step for Std { fn make_run(run: RunConfig<'_>) { let crates = compile::std_crates_for_run_make(&run); + let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false); + if crates.is_empty() && target_is_no_std { + return; + } run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target, From 6e7838d81d99688575a1cfaa49b40fb6cae7b377 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 15 Feb 2025 13:23:32 +0100 Subject: [PATCH 059/158] Factor out business logic of expand_glob_import --- .../src/handlers/expand_glob_import.rs | 157 +++++++++--------- 1 file changed, 75 insertions(+), 82 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs index 094fdc46eb76..ea82bdc90267 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs @@ -3,10 +3,11 @@ use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolutio use ide_db::{ defs::{Definition, NameRefClass}, search::SearchScope, + source_change::SourceChangeBuilder, }; use stdx::never; use syntax::{ - ast::{self, make}, + ast::{self, make, Use, UseTree}, ted, AstNode, Direction, SyntaxNode, SyntaxToken, T, }; @@ -43,6 +44,7 @@ use crate::{ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let star = ctx.find_token_syntax_at_offset(T![*])?; let use_tree = star.parent().and_then(ast::UseTree::cast)?; + let use_item = star.parent_ancestors().find_map(ast::Use::cast)?; let (parent, mod_path) = find_parent_and_path(&star)?; let target_module = match ctx.sema.resolve_path(&mod_path)? { PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it), @@ -53,8 +55,9 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> let current_scope = ctx.sema.scope(&star.parent()?)?; let current_module = current_scope.module(); - let refs_in_target = find_refs_in_mod(ctx, target_module, current_module)?; - let imported_defs = find_imported_defs(ctx, star)?; + if !is_visible_from(ctx, &target_module, current_module) { + return None; + } let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()); acc.add( @@ -62,37 +65,51 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> "Expand glob import", target.text_range(), |builder| { - let use_tree = builder.make_mut(use_tree); - - let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); - let expanded = make::use_tree_list(names_to_import.iter().map(|n| { - let path = make::ext::ident_path( - &n.display(ctx.db(), current_module.krate().edition(ctx.db())).to_string(), - ); - make::use_tree(path, None, None, false) - })) - .clone_for_update(); - - match use_tree.star_token() { - Some(star) => { - let needs_braces = use_tree.path().is_some() && names_to_import.len() != 1; - if needs_braces { - ted::replace(star, expanded.syntax()) - } else { - let without_braces = expanded - .syntax() - .children_with_tokens() - .filter(|child| !matches!(child.kind(), T!['{'] | T!['}'])) - .collect(); - ted::replace_with_many(star, without_braces) - } - } - None => never!(), - } + build_expanded_import(ctx, builder, use_tree, use_item, target_module, current_module) }, ) } +fn build_expanded_import( + ctx: &AssistContext<'_>, + builder: &mut SourceChangeBuilder, + use_tree: UseTree, + use_item: Use, + target_module: Expandable, + current_module: Module, +) { + let refs_in_target = find_refs_in_mod(ctx, target_module, current_module); + let imported_defs = find_imported_defs(ctx, use_item); + + let use_tree = builder.make_mut(use_tree); + + let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); + let expanded = make::use_tree_list(names_to_import.iter().map(|n| { + let path = make::ext::ident_path( + &n.display(ctx.db(), current_module.krate().edition(ctx.db())).to_string(), + ); + make::use_tree(path, None, None, false) + })) + .clone_for_update(); + + match use_tree.star_token() { + Some(star) => { + let needs_braces = use_tree.path().is_some() && names_to_import.len() != 1; + if needs_braces { + ted::replace(star, expanded.syntax()) + } else { + let without_braces = expanded + .syntax() + .children_with_tokens() + .filter(|child| !matches!(child.kind(), T!['{'] | T!['}'])) + .collect(); + ted::replace_with_many(star, without_braces) + } + } + None => never!(), + } +} + enum Expandable { Module(Module), Enum(Enum), @@ -176,36 +193,24 @@ impl Refs { } } -fn find_refs_in_mod( - ctx: &AssistContext<'_>, - expandable: Expandable, - visible_from: Module, -) -> Option { - if !is_expandable_visible_from(ctx, &expandable, visible_from) { - return None; - } - +fn find_refs_in_mod(ctx: &AssistContext<'_>, expandable: Expandable, visible_from: Module) -> Refs { match expandable { Expandable::Module(module) => { let module_scope = module.scope(ctx.db(), Some(visible_from)); let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect(); - Some(Refs(refs)) + Refs(refs) } - Expandable::Enum(enm) => Some(Refs( + Expandable::Enum(enm) => Refs( enm.variants(ctx.db()) .into_iter() .map(|v| Ref { visible_name: v.name(ctx.db()), def: Definition::Variant(v) }) .collect(), - )), + ), } } -fn is_expandable_visible_from( - ctx: &AssistContext<'_>, - expandable: &Expandable, - from: Module, -) -> bool { +fn is_visible_from(ctx: &AssistContext<'_>, expandable: &Expandable, from: Module) -> bool { fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool { match module.parent(ctx.db()) { Some(parent) => { @@ -246,41 +251,29 @@ fn is_expandable_visible_from( // use foo::*$0; // use baz::Baz; // ↑ --------------- -fn find_imported_defs(ctx: &AssistContext<'_>, star: SyntaxToken) -> Option> { - let parent_use_item_syntax = star.parent_ancestors().find_map(|n| { - if ast::Use::can_cast(n.kind()) { - Some(n) - } else { - None - } - })?; - - Some( - [Direction::Prev, Direction::Next] - .into_iter() - .flat_map(|dir| { - parent_use_item_syntax - .siblings(dir.to_owned()) - .filter(|n| ast::Use::can_cast(n.kind())) - }) - .flat_map(|n| n.descendants().filter_map(ast::NameRef::cast)) - .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? { - NameRefClass::Definition( - def @ (Definition::Macro(_) - | Definition::Module(_) - | Definition::Function(_) - | Definition::Adt(_) - | Definition::Variant(_) - | Definition::Const(_) - | Definition::Static(_) - | Definition::Trait(_) - | Definition::TypeAlias(_)), - _, - ) => Some(def), - _ => None, - }) - .collect(), - ) +fn find_imported_defs(ctx: &AssistContext<'_>, use_item: Use) -> Vec { + [Direction::Prev, Direction::Next] + .into_iter() + .flat_map(|dir| { + use_item.syntax().siblings(dir.to_owned()).filter(|n| ast::Use::can_cast(n.kind())) + }) + .flat_map(|n| n.descendants().filter_map(ast::NameRef::cast)) + .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? { + NameRefClass::Definition( + def @ (Definition::Macro(_) + | Definition::Module(_) + | Definition::Function(_) + | Definition::Adt(_) + | Definition::Variant(_) + | Definition::Const(_) + | Definition::Static(_) + | Definition::Trait(_) + | Definition::TypeAlias(_)), + _, + ) => Some(def), + _ => None, + }) + .collect() } fn find_names_to_import( From 12530066a26262621616db9d53ed5d3b3872b606 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 15 Feb 2025 16:07:33 +0100 Subject: [PATCH 060/158] Implement expand_glob_reexport assist --- .../src/handlers/expand_glob_import.rs | 226 ++++++++++++++++-- .../crates/ide-assists/src/lib.rs | 1 + 2 files changed, 208 insertions(+), 19 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs index ea82bdc90267..0b95d6177f90 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs @@ -7,7 +7,7 @@ use ide_db::{ }; use stdx::never; use syntax::{ - ast::{self, make, Use, UseTree}, + ast::{self, make, Use, UseTree, VisibilityKind}, ted, AstNode, Direction, SyntaxNode, SyntaxToken, T, }; @@ -65,7 +65,76 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> "Expand glob import", target.text_range(), |builder| { - build_expanded_import(ctx, builder, use_tree, use_item, target_module, current_module) + build_expanded_import( + ctx, + builder, + use_tree, + use_item, + target_module, + current_module, + false, + ) + }, + ) +} + +// Assist: expand_glob_reexport +// +// Expands non-private glob imports. +// +// ``` +// mod foo { +// pub struct Bar; +// pub struct Baz; +// } +// +// pub use foo::*$0; +// ``` +// -> +// ``` +// mod foo { +// pub struct Bar; +// pub struct Baz; +// } +// +// pub use foo::{Bar, Baz}; +// ``` +pub(crate) fn expand_glob_reexport(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let star = ctx.find_token_syntax_at_offset(T![*])?; + let use_tree = star.parent().and_then(ast::UseTree::cast)?; + let use_item = star.parent_ancestors().find_map(ast::Use::cast)?; + let (parent, mod_path) = find_parent_and_path(&star)?; + let target_module = match ctx.sema.resolve_path(&mod_path)? { + PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it), + PathResolution::Def(ModuleDef::Adt(hir::Adt::Enum(e))) => Expandable::Enum(e), + _ => return None, + }; + + let current_scope = ctx.sema.scope(&star.parent()?)?; + let current_module = current_scope.module(); + + if let VisibilityKind::PubSelf = get_export_visibility_kind(&use_item) { + return None; + } + if !is_visible_from(ctx, &target_module, current_module) { + return None; + } + + let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone()); + acc.add( + AssistId("expand_glob_reexport", AssistKind::RefactorRewrite), + "Expand glob reexport", + target.text_range(), + |builder| { + build_expanded_import( + ctx, + builder, + use_tree, + use_item, + target_module, + current_module, + true, + ) }, ) } @@ -77,13 +146,27 @@ fn build_expanded_import( use_item: Use, target_module: Expandable, current_module: Module, + reexport_public_items: bool, ) { - let refs_in_target = find_refs_in_mod(ctx, target_module, current_module); + let (must_be_pub, visible_from) = if !reexport_public_items { + (false, current_module) + } else { + match get_export_visibility_kind(&use_item) { + VisibilityKind::Pub => (true, current_module.krate().root_module()), + VisibilityKind::PubCrate => (false, current_module.krate().root_module()), + _ => (false, current_module), + } + }; + + let refs_in_target = find_refs_in_mod(ctx, target_module, visible_from, must_be_pub); let imported_defs = find_imported_defs(ctx, use_item); + let filtered_defs = + if reexport_public_items { refs_in_target } else { refs_in_target.used_refs(ctx) }; + let use_tree = builder.make_mut(use_tree); - let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); + let names_to_import = find_names_to_import(filtered_defs, imported_defs); let expanded = make::use_tree_list(names_to_import.iter().map(|n| { let path = make::ext::ident_path( &n.display(ctx.db(), current_module.krate().edition(ctx.db())).to_string(), @@ -110,6 +193,21 @@ fn build_expanded_import( } } +fn get_export_visibility_kind(use_item: &Use) -> VisibilityKind { + use syntax::ast::HasVisibility as _; + match use_item.visibility() { + Some(vis) => match vis.kind() { + VisibilityKind::PubCrate => VisibilityKind::PubCrate, + VisibilityKind::Pub => VisibilityKind::Pub, + VisibilityKind::PubSelf => VisibilityKind::PubSelf, + // We don't handle pub(in ...) and pub(super) yet + VisibilityKind::In(_) => VisibilityKind::PubSelf, + VisibilityKind::PubSuper => VisibilityKind::PubSelf, + }, + None => VisibilityKind::PubSelf, + } +} + enum Expandable { Module(Module), Enum(Enum), @@ -147,14 +245,17 @@ struct Ref { // could be alias visible_name: Name, def: Definition, + is_pub: bool, } impl Ref { - fn from_scope_def(name: Name, scope_def: ScopeDef) -> Option { + fn from_scope_def(ctx: &AssistContext<'_>, name: Name, scope_def: ScopeDef) -> Option { match scope_def { - ScopeDef::ModuleDef(def) => { - Some(Ref { visible_name: name, def: Definition::from(def) }) - } + ScopeDef::ModuleDef(def) => Some(Ref { + visible_name: name, + def: Definition::from(def), + is_pub: matches!(def.visibility(ctx.db()), hir::Visibility::Public), + }), _ => None, } } @@ -193,18 +294,30 @@ impl Refs { } } -fn find_refs_in_mod(ctx: &AssistContext<'_>, expandable: Expandable, visible_from: Module) -> Refs { +fn find_refs_in_mod( + ctx: &AssistContext<'_>, + expandable: Expandable, + visible_from: Module, + must_be_pub: bool, +) -> Refs { match expandable { Expandable::Module(module) => { let module_scope = module.scope(ctx.db(), Some(visible_from)); - let refs = - module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect(); + let refs = module_scope + .into_iter() + .filter_map(|(n, d)| Ref::from_scope_def(ctx, n, d)) + .filter(|r| !must_be_pub || r.is_pub) + .collect(); Refs(refs) } Expandable::Enum(enm) => Refs( enm.variants(ctx.db()) .into_iter() - .map(|v| Ref { visible_name: v.name(ctx.db()), def: Definition::Variant(v) }) + .map(|v| Ref { + visible_name: v.name(ctx.db()), + def: Definition::Variant(v), + is_pub: true, + }) .collect(), ), } @@ -276,13 +389,9 @@ fn find_imported_defs(ctx: &AssistContext<'_>, use_item: Use) -> Vec .collect() } -fn find_names_to_import( - ctx: &AssistContext<'_>, - refs_in_target: Refs, - imported_defs: Vec, -) -> Vec { - let used_refs = refs_in_target.used_refs(ctx).filter_out_by_defs(imported_defs); - used_refs.0.iter().map(|r| r.visible_name.clone()).collect() +fn find_names_to_import(refs_in_target: Refs, imported_defs: Vec) -> Vec { + let final_refs = refs_in_target.filter_out_by_defs(imported_defs); + final_refs.0.iter().map(|r| r.visible_name.clone()).collect() } #[cfg(test)] @@ -1029,4 +1138,83 @@ mod abc { }"#, ) } + + #[test] + fn expanding_glob_reexport() { + check_assist( + expand_glob_reexport, + r" +mod foo { + pub struct Bar; + pub struct Baz; + struct Qux; + + pub fn f() {} + + pub(crate) fn g() {} + pub(self) fn h() {} +} + +pub use foo::*$0; +", + r" +mod foo { + pub struct Bar; + pub struct Baz; + struct Qux; + + pub fn f() {} + + pub(crate) fn g() {} + pub(self) fn h() {} +} + +pub use foo::{Bar, Baz, f}; +", + ) + } + + #[test] + fn expanding_recursive_glob_reexport() { + check_assist( + expand_glob_reexport, + r" +mod foo { + pub use bar::*; + mod bar { + pub struct Bar; + pub struct Baz; + } +} + +pub use foo::*$0; +", + r" +mod foo { + pub use bar::*; + mod bar { + pub struct Bar; + pub struct Baz; + } +} + +pub use foo::{Bar, Baz}; +", + ) + } + + #[test] + fn expanding_reexport_is_not_applicable_for_private_import() { + check_assist_not_applicable( + expand_glob_reexport, + r" +mod foo { + pub struct Bar; + pub struct Baz; +} + +use foo::*$0; +", + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 5c95b25f28dd..179742f91b4d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -270,6 +270,7 @@ mod handlers { destructure_tuple_binding::destructure_tuple_binding, destructure_struct_binding::destructure_struct_binding, expand_glob_import::expand_glob_import, + expand_glob_import::expand_glob_reexport, explicit_enum_discriminant::explicit_enum_discriminant, extract_expressions_from_format_string::extract_expressions_from_format_string, extract_struct_from_enum_variant::extract_struct_from_enum_variant, From 4c7b6099ca4eaad4f83280570673e79f70429ed4 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Fri, 14 Feb 2025 02:38:11 +0900 Subject: [PATCH 061/158] Temporarily ignore tests with comments --- .../ide-assists/src/handlers/add_missing_match_arms.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index a9a2875a60c1..4a9e2256e9b0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -1375,6 +1375,9 @@ fn main() { ); } + // FIXME: Preserving comments is quite hard in the current transitional syntax editing model. + // Once we migrate to new trivia model addressed in #6854, remove the ignore attribute. + #[ignore] #[test] fn add_missing_match_arms_preserves_comments() { check_assist( @@ -1403,6 +1406,9 @@ fn foo(a: A) { ); } + // FIXME: Preserving comments is quite hard in the current transitional syntax editing model. + // Once we migrate to new trivia model addressed in #6854, remove the ignore attribute. + #[ignore] #[test] fn add_missing_match_arms_preserves_comments_empty() { check_assist( From 824b18248c72a8d9fa0fd8ad57b1292cc079fb9f Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 15 Feb 2025 16:26:28 +0100 Subject: [PATCH 062/158] Re-generate doctests --- .../crates/ide-assists/src/tests/generated.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 4b0fa704a22b..0662527a387d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -909,6 +909,29 @@ fn qux(bar: Bar, baz: Baz) {} ) } +#[test] +fn doctest_expand_glob_reexport() { + check_doc_test( + "expand_glob_reexport", + r#####" +mod foo { + pub struct Bar; + pub struct Baz; +} + +pub use foo::*$0; +"#####, + r#####" +mod foo { + pub struct Bar; + pub struct Baz; +} + +pub use foo::{Bar, Baz}; +"#####, + ) +} + #[test] fn doctest_explicit_enum_discriminant() { check_doc_test( From 1d7cf0ff407beea447334c2784d39658e4be3ca0 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 15 Feb 2025 13:57:21 -0500 Subject: [PATCH 063/158] Replace some u64 hashes with Hash64 --- compiler/rustc_abi/src/layout.rs | 9 +++++---- compiler/rustc_abi/src/lib.rs | 7 ++++--- compiler/rustc_data_structures/src/hashes.rs | 5 +++++ compiler/rustc_middle/src/ty/layout.rs | 3 ++- compiler/rustc_middle/src/ty/mod.rs | 3 +-- compiler/rustc_ty_utils/src/layout.rs | 13 ++++++++----- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index b8773f9ff38f..9e33824afe20 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -2,6 +2,7 @@ use std::fmt::{self, Write}; use std::ops::{Bound, Deref}; use std::{cmp, iter}; +use rustc_data_structures::stable_hasher::Hash64; use rustc_index::Idx; use tracing::debug; @@ -133,7 +134,7 @@ impl LayoutCalculator { size, max_repr_align: None, unadjusted_abi_align: align.abi, - randomization_seed: combined_seed, + randomization_seed: Hash64::new(combined_seed), } } @@ -226,7 +227,7 @@ impl LayoutCalculator { size: Size::ZERO, max_repr_align: None, unadjusted_abi_align: dl.i8_align.abi, - randomization_seed: 0, + randomization_seed: Hash64::ZERO, } } @@ -1058,7 +1059,7 @@ impl LayoutCalculator { // unsizable tail fields are excluded so that we use the same seed for the sized and unsized layouts. let field_seed = fields_excluding_tail .iter() - .fold(0u64, |acc, f| acc.wrapping_add(f.randomization_seed)); + .fold(Hash64::ZERO, |acc, f| acc.wrapping_add(f.randomization_seed)); if optimize_field_order && fields.len() > 1 { // If `-Z randomize-layout` was enabled for the type definition we can shuffle @@ -1072,7 +1073,7 @@ impl LayoutCalculator { // `ReprOptions.field_shuffle_seed` is a deterministic seed we can use to randomize field // ordering. let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64( - field_seed.wrapping_add(repr.field_shuffle_seed), + field_seed.wrapping_add(repr.field_shuffle_seed).as_u64(), ); // Shuffle the ordering of the fields. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index da1c706d67cc..d3847e5f2722 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -48,6 +48,7 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub}; use std::str::FromStr; use bitflags::bitflags; +use rustc_data_structures::stable_hasher::Hash64; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::StableOrd; use rustc_index::{Idx, IndexSlice, IndexVec}; @@ -140,7 +141,7 @@ pub struct ReprOptions { /// hash without loss, but it does pay the price of being larger. /// Everything's a tradeoff, a 64-bit seed should be sufficient for our /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: u64, + pub field_shuffle_seed: Hash64, } impl ReprOptions { @@ -1727,7 +1728,7 @@ pub struct LayoutData { /// transmuted to `Foo` we aim to create probalistically distinct seeds so that Foo can choose /// to reorder its fields based on that information. The current implementation is a conservative /// approximation of this goal. - pub randomization_seed: u64, + pub randomization_seed: Hash64, } impl LayoutData { @@ -1781,7 +1782,7 @@ impl LayoutData { align, max_repr_align: None, unadjusted_abi_align: align.abi, - randomization_seed, + randomization_seed: Hash64::new(randomization_seed), } } } diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs index 8f4639fc2e66..b25758048bd3 100644 --- a/compiler/rustc_data_structures/src/hashes.rs +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -35,6 +35,11 @@ impl Hash64 { pub fn as_u64(self) -> u64 { self.inner } + + #[inline] + pub fn wrapping_add(self, other: Self) -> Self { + Self { inner: self.inner.wrapping_add(other.inner) } + } } impl BitXorAssign for Hash64 { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e5a4e38c8750..2e90e5251e2b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -7,6 +7,7 @@ use rustc_abi::{ PointeeInfo, PointerKind, Primitive, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, TyAbiInterface, VariantIdx, Variants, }; +use rustc_data_structures::stable_hasher::Hash64; use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, @@ -778,7 +779,7 @@ where size: Size::ZERO, max_repr_align: None, unadjusted_abi_align: tcx.data_layout.i8_align.abi, - randomization_seed: 0, + randomization_seed: Hash64::ZERO, }) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 52cb8f57a88a..cb5b5948e6f2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1487,8 +1487,7 @@ impl<'tcx> TyCtxt<'tcx> { // Generate a deterministically-derived seed from the item's path hash // to allow for cross-crate compilation to actually work - let mut field_shuffle_seed = - self.def_path_hash(did.to_def_id()).0.to_smaller_hash().as_u64(); + let mut field_shuffle_seed = self.def_path_hash(did.to_def_id()).0.to_smaller_hash(); // If the user defined a custom seed for layout randomization, xor the item's // path hash with the user defined seed, this will allowing determinism while diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ee271048fc17..6a67009fe90c 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -9,6 +9,7 @@ use rustc_abi::{ HasDataLayout, Layout, LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; +use rustc_data_structures::stable_hasher::Hash64; use rustc_index::bit_set::DenseBitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::bug; @@ -380,7 +381,7 @@ fn layout_of_uncached<'tcx>( size, max_repr_align: None, unadjusted_abi_align: element.align.abi, - randomization_seed: element.randomization_seed.wrapping_add(count), + randomization_seed: element.randomization_seed.wrapping_add(Hash64::new(count)), }) } ty::Slice(element) => { @@ -395,7 +396,9 @@ fn layout_of_uncached<'tcx>( max_repr_align: None, unadjusted_abi_align: element.align.abi, // adding a randomly chosen value to distinguish slices - randomization_seed: element.randomization_seed.wrapping_add(0x2dcba99c39784102), + randomization_seed: element + .randomization_seed + .wrapping_add(Hash64::new(0x2dcba99c39784102)), }) } ty::Str => tcx.mk_layout(LayoutData { @@ -408,7 +411,7 @@ fn layout_of_uncached<'tcx>( max_repr_align: None, unadjusted_abi_align: dl.i8_align.abi, // another random value - randomization_seed: 0xc1325f37d127be22, + randomization_seed: Hash64::new(0xc1325f37d127be22), }), // Odd unit types. @@ -585,7 +588,7 @@ fn layout_of_uncached<'tcx>( align, max_repr_align: None, unadjusted_abi_align: align.abi, - randomization_seed: e_ly.randomization_seed.wrapping_add(e_len), + randomization_seed: e_ly.randomization_seed.wrapping_add(Hash64::new(e_len)), }) } @@ -1051,7 +1054,7 @@ fn coroutine_layout<'tcx>( }; // this is similar to how ReprOptions populates its field_shuffle_seed - let def_hash = tcx.def_path_hash(def_id).0.to_smaller_hash().as_u64(); + let def_hash = tcx.def_path_hash(def_id).0.to_smaller_hash(); let layout = tcx.mk_layout(LayoutData { variants: Variants::Multiple { From 84bdc5de6e4f9dc3434b806a74d89b5b676f4a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 15 Feb 2025 22:05:54 +0100 Subject: [PATCH 064/158] HIR analysis: Remove unnecessary abstraction over list of clauses --- compiler/rustc_hir_analysis/src/bounds.rs | 100 -------------- .../src/collect/item_bounds.rs | 9 +- .../src/collect/predicates_of.rs | 35 +++-- .../src/hir_ty_lowering/bounds.rs | 37 +++--- .../src/hir_ty_lowering/dyn_compatibility.rs | 13 +- .../src/hir_ty_lowering/mod.rs | 123 ++++++++++-------- compiler/rustc_hir_analysis/src/lib.rs | 1 - compiler/rustc_middle/src/ty/generic_args.rs | 2 +- 8 files changed, 114 insertions(+), 206 deletions(-) delete mode 100644 compiler/rustc_hir_analysis/src/bounds.rs diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs deleted file mode 100644 index 9b02651a8bdf..000000000000 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ /dev/null @@ -1,100 +0,0 @@ -//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the -//! [`rustc_middle::ty`] form. - -use rustc_hir::LangItem; -use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; -use rustc_span::Span; - -/// Collects together a list of type bounds. These lists of bounds occur in many places -/// in Rust's syntax: -/// -/// ```text -/// trait Foo: Bar + Baz { } -/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter -/// -/// fn foo() { } -/// ^^^^^^^^^ bounding the type parameter `T` -/// -/// impl dyn Bar + Baz -/// ^^^^^^^^^ bounding the type-erased dynamic type -/// ``` -/// -/// Our representation is a bit mixed here -- in some cases, we -/// include the self type (e.g., `trait_bounds`) but in others we do not -#[derive(Default, PartialEq, Eq, Clone, Debug)] -pub(crate) struct Bounds<'tcx> { - clauses: Vec<(ty::Clause<'tcx>, Span)>, -} - -impl<'tcx> Bounds<'tcx> { - pub(crate) fn push_region_bound( - &mut self, - tcx: TyCtxt<'tcx>, - region: ty::PolyTypeOutlivesPredicate<'tcx>, - span: Span, - ) { - self.clauses - .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span)); - } - - pub(crate) fn push_trait_bound( - &mut self, - tcx: TyCtxt<'tcx>, - bound_trait_ref: ty::PolyTraitRef<'tcx>, - span: Span, - polarity: ty::PredicatePolarity, - ) { - let clause = ( - bound_trait_ref - .map_bound(|trait_ref| { - ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) - }) - .upcast(tcx), - span, - ); - // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands. - if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) { - self.clauses.insert(0, clause); - } else { - self.clauses.push(clause); - } - } - - pub(crate) fn push_projection_bound( - &mut self, - tcx: TyCtxt<'tcx>, - projection: ty::PolyProjectionPredicate<'tcx>, - span: Span, - ) { - self.clauses.push(( - projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).upcast(tcx), - span, - )); - } - - pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { - let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); - let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); - // Preferable to put this obligation first, since we report better errors for sized ambiguity. - self.clauses.insert(0, (trait_ref.upcast(tcx), span)); - } - - /// Push a `const` or `~const` bound as a `HostEffect` predicate. - pub(crate) fn push_const_bound( - &mut self, - tcx: TyCtxt<'tcx>, - bound_trait_ref: ty::PolyTraitRef<'tcx>, - constness: ty::BoundConstness, - span: Span, - ) { - if tcx.is_const_trait(bound_trait_ref.def_id()) { - self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, constness), span)); - } else { - tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait"); - } - } - - pub(crate) fn clauses(&self) -> impl Iterator, Span)> + '_ { - self.clauses.iter().cloned() - } -} diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 41c4cfbaa825..1c1a246cc151 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -13,7 +13,6 @@ use tracing::{debug, instrument}; use super::ItemCtxt; use super::predicates_of::assert_only_contains_predicates_from; -use crate::bounds::Bounds; use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter}; /// For associated types we include both bounds written on the type @@ -38,7 +37,7 @@ fn associated_type_bounds<'tcx>( ); let icx = ItemCtxt::new(tcx, assoc_item_def_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); // Associated types are implicitly sized unless a `?Sized` bound is found match filter { @@ -68,7 +67,7 @@ fn associated_type_bounds<'tcx>( ) }); - let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); + let all_bounds = tcx.arena.alloc_from_iter(bounds.into_iter().chain(bounds_from_parent)); debug!( "associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id.to_def_id()), @@ -327,7 +326,7 @@ fn opaque_type_bounds<'tcx>( ) -> &'tcx [(ty::Clause<'tcx>, Span)] { ty::print::with_reduced_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); // Opaque types are implicitly sized unless a `?Sized` bound is found match filter { @@ -343,7 +342,7 @@ fn opaque_type_bounds<'tcx>( } debug!(?bounds); - tcx.arena.alloc_from_iter(bounds.clauses()) + tcx.arena.alloc_slice(&bounds) }) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index d94383d6f3d8..70e7451a5fb0 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -13,7 +13,6 @@ use rustc_span::{DUMMY_SP, Ident, Span}; use tracing::{debug, instrument, trace}; use super::item_bounds::explicit_item_bounds_with_filter; -use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; use crate::delegation::inherit_predicates_for_delegation_item; @@ -178,7 +177,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // on a trait we must also consider the bounds that follow the trait's name, // like `trait Foo: A + B + C`. if let Some(self_bounds) = is_trait { - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds( tcx.types.self_param, self_bounds, @@ -186,7 +185,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ty::List::empty(), PredicateFilter::All, ); - predicates.extend(bounds.clauses()); + predicates.extend(bounds); } // In default impls, we can assume that the self type implements @@ -209,7 +208,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen GenericParamKind::Lifetime { .. } => (), GenericParamKind::Type { .. } => { let param_ty = icx.lowerer().lower_ty_param(param.hir_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); // Params are implicitly sized unless a `?Sized` bound is found icx.lowerer().add_sized_bound( &mut bounds, @@ -219,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen param.span, ); trace!(?bounds); - predicates.extend(bounds.clauses()); + predicates.extend(bounds); trace!(?predicates); } hir::GenericParamKind::Const { .. } => { @@ -264,7 +263,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } } - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds( ty, bound_pred.bounds, @@ -272,7 +271,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen bound_vars, PredicateFilter::All, ); - predicates.extend(bounds.clauses()); + predicates.extend(bounds); } hir::WherePredicateKind::RegionPredicate(region_pred) => { @@ -627,7 +626,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let icx = ItemCtxt::new(tcx, trait_def_id); let self_param_ty = tcx.types.self_param; - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter); let where_bounds_that_match = @@ -635,7 +634,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( // Combine the two lists to form the complete set of superbounds: let implied_bounds = - &*tcx.arena.alloc_from_iter(bounds.clauses().chain(where_bounds_that_match)); + &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match)); debug!(?implied_bounds); // Now require that immediate supertraits are lowered, which will, in @@ -904,7 +903,7 @@ impl<'tcx> ItemCtxt<'tcx> { param_def_id: LocalDefId, filter: PredicateFilter, ) -> Vec<(ty::Clause<'tcx>, Span)> { - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); for predicate in hir_generics.predicates { let hir_id = predicate.hir_id; @@ -938,7 +937,7 @@ impl<'tcx> ItemCtxt<'tcx> { ); } - bounds.clauses().collect() + bounds } } @@ -1007,7 +1006,7 @@ pub(super) fn const_conditions<'tcx>( }; let icx = ItemCtxt::new(tcx, def_id); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); for pred in generics.predicates { match pred.kind { @@ -1027,12 +1026,12 @@ pub(super) fn const_conditions<'tcx>( } if let Some((def_id, supertraits)) = trait_def_id_and_supertraits { - bounds.push_const_bound( - tcx, - ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())), - ty::BoundConstness::Maybe, + // We've checked above that the trait is conditionally const. + bounds.push(( + ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())) + .to_host_effect_clause(tcx, ty::BoundConstness::Maybe), DUMMY_SP, - ); + )); icx.lowerer().lower_bounds( tcx.types.self_param, @@ -1045,7 +1044,7 @@ pub(super) fn const_conditions<'tcx>( ty::ConstConditions { parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()), - predicates: tcx.arena.alloc_from_iter(bounds.clauses().map(|(clause, span)| { + predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| { ( clause.kind().map_bound(|clause| match clause { ty::ClauseKind::HostEffect(ty::HostEffectPredicate { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index ef6167907b5b..75c97001c327 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -8,7 +8,7 @@ use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::bug; -use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt}; +use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt, Upcast}; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; @@ -16,7 +16,6 @@ use smallvec::SmallVec; use tracing::{debug, instrument}; use super::errors::GenericsArgsErrExtend; -use crate::bounds::Bounds; use crate::errors; use crate::hir_ty_lowering::{ AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason, @@ -28,7 +27,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`. pub(crate) fn add_sized_bound( &self, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &'tcx [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, @@ -113,10 +112,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound { // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound; // we don't need to do anything. - } else if sized_def_id.is_some() { + } else if let Some(sized_def_id) = sized_def_id { // There was no `?Sized`, `!Sized` or explicit `Sized` bound; // add `Sized` if it's available. - bounds.push_sized(tcx, self_ty, span); + let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]); + // Preferable to put this obligation first, since we report better errors for sized ambiguity. + bounds.insert(0, (trait_ref.upcast(tcx), span)); } } @@ -146,7 +147,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, param_ty: Ty<'tcx>, hir_bounds: I, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, bound_vars: &'tcx ty::List, predicate_filter: PredicateFilter, ) where @@ -189,14 +190,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound); - bounds.push_region_bound( - self.tcx(), - ty::Binder::bind_with_vars( - ty::OutlivesPredicate(param_ty, region), - bound_vars, - ), - lifetime.ident.span, + let bound = ty::Binder::bind_with_vars( + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)), + bound_vars, ); + bounds.push((bound.upcast(self.tcx()), lifetime.ident.span)); } hir::GenericBound::Use(..) => { // We don't actually lower `use` into the type layer. @@ -219,7 +217,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_ref_id: hir::HirId, trait_ref: ty::PolyTraitRef<'tcx>, constraint: &hir::AssocItemConstraint<'tcx>, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, duplicates: &mut FxIndexMap, path_span: Span, predicate_filter: PredicateFilter, @@ -389,14 +387,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfAndAssociatedTypeBounds => { - bounds.push_projection_bound( - tcx, - projection_term.map_bound(|projection_term| ty::ProjectionPredicate { + let bound = projection_term.map_bound(|projection_term| { + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_term, term, - }), - constraint.span, - ); + }) + }); + bounds.push((bound.upcast(tcx), constraint.span)); } // SelfTraitThatDefines is only interested in trait predicates. PredicateFilter::SelfTraitThatDefines(_) => {} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index a8b37fa50542..830dca0d3cd5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -17,7 +17,6 @@ use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; use super::HirTyLowerer; -use crate::bounds::Bounds; use crate::hir_ty_lowering::{ GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason, }; @@ -36,7 +35,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let dummy_self = tcx.types.trait_object_dummy_self; - let mut user_written_bounds = Bounds::default(); + let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); for trait_bound in hir_bounds.iter() { if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { @@ -60,15 +59,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } let (trait_bounds, mut projection_bounds) = - traits::expand_trait_aliases(tcx, user_written_bounds.clauses()); + traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied()); let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds .into_iter() .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); // We don't support empty trait objects. if regular_traits.is_empty() && auto_traits.is_empty() { - let guar = - self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses()); + let guar = self.report_trait_object_with_no_traits_error( + span, + user_written_bounds.iter().copied(), + ); return Ty::new_error(tcx, guar); } // We don't support >1 principal @@ -84,7 +85,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check that there are no gross dyn-compatibility violations; // most importantly, that the supertraits don't contain `Self`, // to avoid ICEs. - for (clause, span) in user_written_bounds.clauses() { + for (clause, span) in user_written_bounds { if let Some(trait_pred) = clause.as_trait_clause() { let violations = hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id()); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 88323db6dda6..288e88f4aeb5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -49,9 +49,9 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, ObligationCtxt}; +use rustc_type_ir::Upcast; use tracing::{debug, instrument}; -use crate::bounds::Bounds; use crate::check::check_abi_fn_ptr; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; @@ -691,7 +691,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constness: hir::BoundConstness, polarity: hir::BoundPolarity, self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); @@ -720,6 +720,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bound_vars, ); + debug!(?poly_trait_ref); + let polarity = match polarity { rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive, rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative, @@ -741,6 +743,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } }; + // We deal with const conditions later. + match predicate_filter { + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfTraitThatDefines(..) + | PredicateFilter::SelfAndAssociatedTypeBounds => { + let bound = poly_trait_ref.map_bound(|trait_ref| { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) + }); + let bound = (bound.upcast(tcx), span); + // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands. + if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) { + bounds.insert(0, bound); + } else { + bounds.push(bound); + } + } + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} + } + if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness && !self.tcx().is_const_trait(trait_def_id) { @@ -765,58 +787,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { suggestion_pre, suggestion, }); - } - - match predicate_filter { - // This is only concerned with trait predicates. - PredicateFilter::SelfTraitThatDefines(..) => { - bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); - } - PredicateFilter::All - | PredicateFilter::SelfOnly - | PredicateFilter::SelfAndAssociatedTypeBounds => { - debug!(?poly_trait_ref); - bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); - - match constness { - hir::BoundConstness::Always(span) => { - if polarity == ty::PredicatePolarity::Positive { - bounds.push_const_bound( - tcx, - poly_trait_ref, - ty::BoundConstness::Const, - span, - ); + } else { + match predicate_filter { + // This is only concerned with trait predicates. + PredicateFilter::SelfTraitThatDefines(..) => {} + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfAndAssociatedTypeBounds => { + match constness { + hir::BoundConstness::Always(span) => { + if polarity == ty::PredicatePolarity::Positive { + bounds.push(( + poly_trait_ref + .to_host_effect_clause(tcx, ty::BoundConstness::Const), + span, + )); + } } + hir::BoundConstness::Maybe(_) => { + // We don't emit a const bound here, since that would mean that we + // unconditionally need to prove a `HostEffect` predicate, even when + // the predicates are being instantiated in a non-const context. This + // is instead handled in the `const_conditions` query. + } + hir::BoundConstness::Never => {} } - hir::BoundConstness::Maybe(_) => { - // We don't emit a const bound here, since that would mean that we - // unconditionally need to prove a `HostEffect` predicate, even when - // the predicates are being instantiated in a non-const context. This - // is instead handled in the `const_conditions` query. + } + // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert + // `~const` bounds. All other predicates are handled in their respective queries. + // + // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering + // here because we only call this on self bounds, and deal with the recursive case + // in `lower_assoc_item_constraint`. + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => { + match constness { + hir::BoundConstness::Maybe(span) => { + if polarity == ty::PredicatePolarity::Positive { + bounds.push(( + poly_trait_ref + .to_host_effect_clause(tcx, ty::BoundConstness::Maybe), + span, + )); + } + } + hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {} } - hir::BoundConstness::Never => {} } } - // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert - // `~const` bounds. All other predicates are handled in their respective queries. - // - // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering - // here because we only call this on self bounds, and deal with the recursive case - // in `lower_assoc_item_constraint`. - PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness { - hir::BoundConstness::Maybe(span) => { - if polarity == ty::PredicatePolarity::Positive { - bounds.push_const_bound( - tcx, - poly_trait_ref, - ty::BoundConstness::Maybe, - span, - ); - } - } - hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {} - }, } let mut dup_constraints = FxIndexMap::default(); @@ -2382,7 +2399,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Impl trait in bindings lower as an infer var with additional // set of type bounds. let self_ty = self.ty_infer(None, hir_ty.span); - let mut bounds = Bounds::default(); + let mut bounds = Vec::new(); self.lower_bounds( self_ty, hir_bounds.iter(), @@ -2390,11 +2407,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::List::empty(), PredicateFilter::All, ); - self.register_trait_ascription_bounds( - bounds.clauses().collect(), - hir_ty.hir_id, - hir_ty.span, - ); + self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span); self_ty } // If we encounter a type relative path with RTN generics, then it must have diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 8a529e9c686e..886360dfb6cf 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -80,7 +80,6 @@ This API is completely unstable and subject to change. pub mod check; pub mod autoderef; -mod bounds; mod check_unused; mod coherence; mod collect; diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index fd84d75b53f3..56a38a84c9f1 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -495,7 +495,7 @@ impl<'tcx> GenericArgs<'tcx> { self.iter().filter_map(|k| k.as_const()) } - /// Returns generic arguments that are not lifetimes or host effect params. + /// Returns generic arguments that are not lifetimes. #[inline] pub fn non_erasable_generics( &'tcx self, From ca288273b43d4218f00c15e31e78f89949d8cbba Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 8 Feb 2025 21:59:35 +0000 Subject: [PATCH 065/158] Make ub_check message clear that it's not an assert --- library/core/src/ub_checks.rs | 6 +++--- src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index b289f6026ffc..9eb71922218f 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -65,9 +65,9 @@ macro_rules! assert_unsafe_precondition { #[rustc_nounwind] const fn precondition_check($($name:$ty),*) { if !$e { - ::core::panicking::panic_nounwind( - concat!("unsafe precondition(s) violated: ", $message) - ); + ::core::panicking::panic_nounwind(concat!("unsafe precondition(s) violated: ", $message, + "\n\nThis indicates a bug in the program. \ + This Undefined Behavior check is optional, and cannot be relied on for safety.")); } } diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr index 782303d5f3f9..80dd2f39b426 100644 --- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr +++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr @@ -1,6 +1,8 @@ thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null and the specified memory ranges do not overlap + +This indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety. note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread caused non-unwinding panic. aborting. From 0f220efb1a9c1bab199baadcb01ce2129bce0037 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 15 Feb 2025 19:09:38 -0600 Subject: [PATCH 066/158] Restrict DerefPure for Cow impl to T = impl Clone, [impl Clone], str. --- library/alloc/src/borrow.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index dbfd2e74abee..17dad3277b95 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -340,8 +340,18 @@ where } } +// `Cow<'_, T>` can only implement `DerefPure` if `>` (and `BorrowMut`) is trusted. +// For now, we restrict `DerefPure for Cow` to `T: Sized` (`T as Borrow` is trusted), +// `str` (`String as Borrow` is trusted) and `[T]` (`Vec as Borrow<[T]>` is trusted). +// In the future, a `BorrowPure` trait analogous to `DerefPure` might generalize this. #[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl DerefPure for Cow<'_, B> where B::Owned: Borrow {} +unsafe impl DerefPure for Cow<'_, T> {} +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Cow<'_, str> {} +#[cfg(not(no_global_oom_handling))] +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Cow<'_, [T]> {} #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Cow<'_, B> where B: Eq + ToOwned {} From af804d23e204ffaec33aa7dfcd17cc31f082a559 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 10:51:58 +0100 Subject: [PATCH 067/158] Set `RUSTUP_TOOLCHAIN` when loading sysroot workspace --- .../crates/project-model/src/cargo_workspace.rs | 3 +++ src/tools/rust-analyzer/crates/project-model/src/sysroot.rs | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index e4a611346205..b5f4e43a115d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -277,6 +277,9 @@ impl CargoWorkspace { /// Fetches the metadata for the given `cargo_toml` manifest. /// A successful result may contain another metadata error if the initial fetching failed but /// the `--no-deps` retry succeeded. + /// + /// The sysroot is used to set the `RUSTUP_TOOLCHAIN` env var when invoking cargo + /// to ensure that the rustup proxy uses the correct toolchain. pub fn fetch_metadata( cargo_toml: &ManifestPath, current_dir: &AbsPath, diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 510c18dd147e..544ba43ba66f 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -247,7 +247,7 @@ impl Sysroot { let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap(); if fs::metadata(&library_manifest).is_ok() { if let Some(loaded) = - Self::load_library_via_cargo(library_manifest, src_root, cargo_config) + self.load_library_via_cargo(library_manifest, src_root, cargo_config) { return Some(loaded); } @@ -326,6 +326,7 @@ impl Sysroot { } fn load_library_via_cargo( + &self, library_manifest: ManifestPath, rust_lib_src_dir: &AbsPathBuf, cargo_config: &CargoMetadataConfig, @@ -342,7 +343,7 @@ impl Sysroot { &library_manifest, rust_lib_src_dir, &cargo_config, - &Sysroot::empty(), + self, // Make sure we never attempt to write to the sysroot true, &|_| (), From 95a5ecc995f031478708c6c654a196197e71ba20 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 16 Feb 2025 10:28:08 +0000 Subject: [PATCH 068/158] Enable relative-path-include-bytes on Windows --- .../relative-path-include-bytes-132203.edition2015.stdout | 2 +- .../rustdoc-ui/doctest/relative-path-include-bytes-132203.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout index ca6e77502640..13e142df8370 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout @@ -5,7 +5,7 @@ test $DIR/relative-path-include-bytes-132203.rs - (line 18) ... FAILED failures: ---- $DIR/relative-path-include-bytes-132203.rs - (line 18) stdout ---- -error: couldn't read `$DIR/relative-dir-empty-file`: No such file or directory (os error 2) +error: couldn't read `$DIR/relative-dir-empty-file`: $FILE_NOT_FOUND_MSG (os error 2) --> $DIR/relative-path-include-bytes-132203.rs:19:9 | LL | let x = include_bytes!("relative-dir-empty-file"); diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs index 6fddaa49face..ceacd69a5fd5 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs @@ -1,4 +1,3 @@ -//@ ignore-windows different error message //@ revisions: edition2015 edition2024 //@[edition2015]edition:2015 //@[edition2015]check-fail @@ -7,8 +6,9 @@ //@[edition2024]edition:2024 //@[edition2024]check-pass //@[edition2024]compile-flags:--test --test-args=--test-threads=1 -//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "tests.rustdoc-ui.doctest." -> "$$DIR/" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ normalize-stdout: "`: .* \(os error 2\)" -> "`: $$FILE_NOT_FOUND_MSG (os error 2)" // https://github.com/rust-lang/rust/issues/132203 // This version, because it's edition2024, passes thanks to the new From b621a485faf006c830996049ed6d601e0f562065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 15 Feb 2025 20:25:30 +0800 Subject: [PATCH 069/158] bootstrap: add more tracing to compiler/std/llvm flows --- src/bootstrap/src/core/build_steps/compile.rs | 186 +++++++++++++++++- src/bootstrap/src/core/build_steps/dist.rs | 41 +++- src/bootstrap/src/core/build_steps/llvm.rs | 17 +- src/bootstrap/src/core/build_steps/tool.rs | 24 +++ src/bootstrap/src/core/builder/mod.rs | 41 +++- src/bootstrap/src/core/config/config.rs | 9 + src/bootstrap/src/lib.rs | 9 + 7 files changed, 314 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 479327d63695..bae18a96d904 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -16,6 +16,8 @@ use std::process::Stdio; use std::{env, fs, str}; use serde_derive::Deserialize; +#[cfg(feature = "tracing")] +use tracing::{instrument, span}; use crate::core::build_steps::tool::SourceType; use crate::core::build_steps::{dist, llvm}; @@ -30,7 +32,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; -use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode}; +use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode, debug, trace}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { @@ -98,6 +100,7 @@ impl Step for Std { run.crate_or_deps("sysroot").path("library").alias("core") } + #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))] fn make_run(run: RunConfig<'_>) { let crates = std_crates_for_run_make(&run); let builder = run.builder; @@ -109,6 +112,14 @@ impl Step for Std { && builder.download_rustc() && builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none(); + trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository()); + trace!("download_rustc: {}", builder.download_rustc()); + trace!( + "last modified commit: {:?}", + builder.config.last_modified_commit(&["library"], "download-rustc", true) + ); + trace!(force_recompile); + run.builder.ensure(Std { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, @@ -124,6 +135,19 @@ impl Step for Std { /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "Std::run", + skip_all, + fields( + target = ?self.target, + compiler = ?self.compiler, + force_recompile = self.force_recompile + ), + ), + )] fn run(self, builder: &Builder<'_>) { let target = self.target; let compiler = self.compiler; @@ -148,6 +172,9 @@ impl Step for Std { if builder.config.keep_stage.contains(&compiler.stage) || builder.config.keep_stage_std.contains(&compiler.stage) { + trace!(keep_stage = ?builder.config.keep_stage); + trace!(keep_stage_std = ?builder.config.keep_stage_std); + builder.info("WARNING: Using a potentially old libstd. This may not behave well."); builder.ensure(StartupObjects { compiler, target }); @@ -163,7 +190,15 @@ impl Step for Std { let mut target_deps = builder.ensure(StartupObjects { compiler, target }); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + trace!(?compiler_to_use); + if compiler_to_use != compiler { + trace!( + ?compiler_to_use, + ?compiler, + "compiler != compiler_to_use, handling cross-compile scenario" + ); + builder.ensure(Std::new(compiler_to_use, target)); let msg = if compiler_to_use.host == target { format!( @@ -186,12 +221,21 @@ impl Step for Std { return; } + trace!( + ?compiler_to_use, + ?compiler, + "compiler == compiler_to_use, handling not-cross-compile scenario" + ); + target_deps.extend(self.copy_extra_objects(builder, &compiler, target)); // The LLD wrappers and `rust-lld` are self-contained linking components that can be // necessary to link the stdlib on some targets. We'll also need to copy these binaries to // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target. if compiler.stage == 0 && builder.is_builder_target(&compiler.host) { + trace!( + "(build == host) copying linking components to `stage0-sysroot` for bootstrapping" + ); // We want to copy the host `bin` folder within the `rustlib` folder in the sysroot. let src_sysroot_bin = builder .rustc_snapshot_sysroot() @@ -210,6 +254,7 @@ impl Step for Std { // with -Zalways-encode-mir. This frees us from the need to have a target linker, and the // fact that this is a check build integrates nicely with run_cargo. let mut cargo = if self.is_for_mir_opt_tests { + trace!("building special sysroot for mir-opt tests"); let mut cargo = builder::Cargo::new_for_mir_opt_tests( builder, compiler, @@ -222,6 +267,7 @@ impl Step for Std { cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml")); cargo } else { + trace!("building regular sysroot"); let mut cargo = builder::Cargo::new( builder, compiler, @@ -665,6 +711,19 @@ impl Step for StdLink { /// Note that this assumes that `compiler` has already generated the libstd /// libraries for `target`, and this method will find them in the relevant /// output directory. + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "StdLink::run", + skip_all, + fields( + compiler = ?self.compiler, + target_compiler = ?self.target_compiler, + target = ?self.target + ), + ), + )] fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; let target_compiler = self.target_compiler; @@ -822,6 +881,15 @@ impl Step for StartupObjects { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "StartupObjects::run", + skip_all, + fields(compiler = ?self.compiler, target = ?self.target), + ), + )] fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> { let for_compiler = self.compiler; let target = self.target; @@ -936,6 +1004,15 @@ impl Step for Rustc { /// This will build the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "Rustc::run", + skip_all, + fields(previous_compiler = ?self.compiler, target = ?self.target), + ), + )] fn run(self, builder: &Builder<'_>) -> u32 { let compiler = self.compiler; let target = self.target; @@ -943,6 +1020,8 @@ impl Step for Rustc { // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler, // so its artifacts can't be reused. if builder.download_rustc() && compiler.stage != 0 { + trace!(stage = compiler.stage, "`download_rustc` requested"); + let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); cp_rustc_component_to_ci_sysroot( builder, @@ -955,6 +1034,8 @@ impl Step for Rustc { builder.ensure(Std::new(compiler, target)); if builder.config.keep_stage.contains(&compiler.stage) { + trace!(stage = compiler.stage, "`keep-stage` requested"); + builder.info("WARNING: Using a potentially old librustc. This may not behave well."); builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes"); builder.ensure(RustcLink::from_rustc(self, compiler)); @@ -1374,6 +1455,19 @@ impl Step for RustcLink { } /// Same as `std_link`, only for librustc + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "RustcLink::run", + skip_all, + fields( + compiler = ?self.compiler, + previous_stage_compiler = ?self.previous_stage_compiler, + target = ?self.target, + ), + ), + )] fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; let previous_stage_compiler = self.previous_stage_compiler; @@ -1462,6 +1556,19 @@ impl Step for CodegenBackend { } } + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "CodegenBackend::run", + skip_all, + fields( + compiler = ?self.compiler, + target = ?self.target, + backend = ?self.target, + ), + ), + )] fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; let target = self.target; @@ -1470,6 +1577,7 @@ impl Step for CodegenBackend { builder.ensure(Rustc::new(compiler, target)); if builder.config.keep_stage.contains(&compiler.stage) { + trace!("`keep-stage` requested"); builder.info( "WARNING: Using a potentially old codegen backend. \ This may not behave well.", @@ -1617,6 +1725,15 @@ impl Step for Sysroot { /// Returns the sysroot that `compiler` is supposed to use. /// For the stage0 compiler, this is stage0-sysroot (because of the initial std build). /// For all other stages, it's the same stage directory that the compiler lives in. + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "Sysroot::run", + skip_all, + fields(compiler = ?self.compiler), + ), + )] fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let host_dir = builder.out.join(compiler.host); @@ -1633,6 +1750,7 @@ impl Step for Sysroot { } }; let sysroot = sysroot_dir(compiler.stage); + trace!(stage = ?compiler.stage, ?sysroot); builder .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display())); @@ -1787,10 +1905,20 @@ impl Step for Assemble { /// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// must have been previously produced by the `stage - 1` builder.build /// compiler. + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "Assemble::run", + skip_all, + fields(target_compiler = ?self.target_compiler), + ), + )] fn run(self, builder: &Builder<'_>) -> Compiler { let target_compiler = self.target_compiler; if target_compiler.stage == 0 { + trace!("stage 0 build compiler is always available, simply returning"); assert_eq!( builder.config.build, target_compiler.host, "Cannot obtain compiler for non-native build triple at stage 0" @@ -1806,9 +1934,13 @@ impl Step for Assemble { t!(fs::create_dir_all(&libdir_bin)); if builder.config.llvm_enabled(target_compiler.host) { + trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled"); + let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target: target_compiler.host }); if !builder.config.dry_run() && builder.config.llvm_tools_enabled { + trace!("LLVM tools enabled"); + let llvm_bin_dir = command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); @@ -1818,7 +1950,13 @@ impl Step for Assemble { // rustup, and lets developers use a locally built toolchain to // build projects that expect llvm tools to be present in the sysroot // (e.g. the `bootimage` crate). + + #[cfg(feature = "tracing")] + let _llvm_tools_span = + span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin) + .entered(); for tool in LLVM_TOOLS { + trace!("installing `{tool}`"); let tool_exe = exe(tool, target_compiler.host); let src_path = llvm_bin_dir.join(&tool_exe); // When using `download-ci-llvm`, some of the tools @@ -1838,6 +1976,7 @@ impl Step for Assemble { let maybe_install_llvm_bitcode_linker = |compiler| { if builder.config.llvm_bitcode_linker_enabled { + trace!("llvm-bitcode-linker enabled, installing"); let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker { compiler, target: target_compiler.host, @@ -1850,6 +1989,8 @@ impl Step for Assemble { // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0. if builder.download_rustc() { + trace!("`download-rustc` requested, reusing CI compiler for stage > 0"); + builder.ensure(Std::new(target_compiler, target_compiler.host)); let sysroot = builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false }); @@ -1879,16 +2020,17 @@ impl Step for Assemble { // // FIXME: It may be faster if we build just a stage 1 compiler and then // use that to bootstrap this compiler forward. + debug!( + "ensuring build compiler is available: compiler(stage = {}, host = {:?})", + target_compiler.stage - 1, + builder.config.build, + ); let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); // Build enzyme - let enzyme_install = if builder.config.llvm_enzyme { - Some(builder.ensure(llvm::Enzyme { target: build_compiler.host })) - } else { - None - }; - - if let Some(enzyme_install) = enzyme_install { + if builder.config.llvm_enzyme { + debug!("`llvm_enzyme` requested"); + let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host }); let lib_ext = std::env::consts::DLL_EXTENSION; let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext); let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host); @@ -1905,13 +2047,27 @@ impl Step for Assemble { // link to these. (FIXME: Is that correct? It seems to be correct most // of the time but I think we do link to these for stage2/bin compilers // when not performing a full bootstrap). + debug!( + ?build_compiler, + "target_compiler.host" = ?target_compiler.host, + "building compiler libraries to link to" + ); let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host)); // Current build_compiler.stage might be uplifted instead of being built; so update it // to not fail while linking the artifacts. + debug!( + "(old) build_compiler.stage" = build_compiler.stage, + "(adjusted) build_compiler.stage" = actual_stage, + "temporarily adjusting `build_compiler.stage` to account for uplifted libraries" + ); build_compiler.stage = actual_stage; + #[cfg(feature = "tracing")] + let _codegen_backend_span = + span!(tracing::Level::DEBUG, "building requested codegen backends").entered(); for backend in builder.config.codegen_backends(target_compiler.host) { if backend == "llvm" { + debug!("llvm codegen backend is already built as part of rustc"); continue; // Already built as part of rustc } @@ -1921,6 +2077,8 @@ impl Step for Assemble { backend: backend.clone(), }); } + #[cfg(feature = "tracing")] + drop(_codegen_backend_span); let stage = target_compiler.stage; let host = target_compiler.host; @@ -1980,6 +2138,7 @@ impl Step for Assemble { } } + debug!("copying codegen backends to sysroot"); copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler); if builder.config.lld_enabled { @@ -1990,6 +2149,11 @@ impl Step for Assemble { } if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled { + debug!( + "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \ + workaround faulty homebrew `strip`s" + ); + // `llvm-strip` is used by rustc, which is actually just a symlink to `llvm-objcopy`, so // copy and rename `llvm-objcopy`. // @@ -2022,6 +2186,11 @@ impl Step for Assemble { // Ensure that `libLLVM.so` ends up in the newly build compiler directory, // so that it can be found when the newly built `rustc` is run. + debug!( + "target_compiler.host" = ?target_compiler.host, + ?sysroot, + "ensuring availability of `libLLVM.so` in compiler directory" + ); dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot); dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot); @@ -2031,6 +2200,7 @@ impl Step for Assemble { let bindir = sysroot.join("bin"); t!(fs::create_dir_all(bindir)); let compiler = builder.rustc(target_compiler); + debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself"); builder.copy_link(&rustc, &compiler); target_compiler diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index ae3761a97e50..96d0cf48fbfe 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -16,6 +16,8 @@ use std::{env, fs}; use object::BinaryFormat; use object::read::archive::ArchiveFile; +#[cfg(feature = "tracing")] +use tracing::instrument; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::tool::{self, Tool}; @@ -30,7 +32,7 @@ use crate::utils::helpers::{ exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit, }; use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; -use crate::{Compiler, DependencyType, LLVM_TOOLS, Mode}; +use crate::{Compiler, DependencyType, LLVM_TOOLS, Mode, trace}; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { format!("{}-{}", component, builder.rust_package_vers()) @@ -2029,6 +2031,15 @@ fn install_llvm_file( /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking. /// /// Returns whether the files were actually copied. +#[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "maybe_install_llvm", + skip_all, + fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink), + ), +)] fn maybe_install_llvm( builder: &Builder<'_>, target: TargetSelection, @@ -2052,6 +2063,7 @@ fn maybe_install_llvm( // If the LLVM is coming from ourselves (just from CI) though, we // still want to install it, as it otherwise won't be available. if builder.is_system_llvm(target) { + trace!("system LLVM requested, no install"); return false; } @@ -2070,6 +2082,7 @@ fn maybe_install_llvm( } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) = llvm::prebuilt_llvm_config(builder, target, true) { + trace!("LLVM already built, installing LLVM files"); let mut cmd = command(llvm_config); cmd.arg("--libfiles"); builder.verbose(|| println!("running {cmd:?}")); @@ -2092,6 +2105,19 @@ fn maybe_install_llvm( } /// Maybe add libLLVM.so to the target lib-dir for linking. +#[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "maybe_install_llvm_target", + skip_all, + fields( + llvm_link_shared = ?builder.llvm_link_shared(), + target = ?target, + sysroot = ?sysroot, + ), + ), +)] pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib"); // We do not need to copy LLVM files into the sysroot if it is not @@ -2103,6 +2129,19 @@ pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, } /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself. +#[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "maybe_install_llvm_runtime", + skip_all, + fields( + llvm_link_shared = ?builder.llvm_link_shared(), + target = ?target, + sysroot = ?sysroot, + ), + ), +)] pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target })); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 18da0e8252b9..9f62879c36d9 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -16,6 +16,8 @@ use std::{env, fs}; use build_helper::ci::CiEnv; use build_helper::git::get_closest_merge_commit; +#[cfg(feature = "tracing")] +use tracing::instrument; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; @@ -24,7 +26,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ self, exe, get_clang_cl_resource_dir, t, unhashed_basename, up_to_date, }; -use crate::{CLang, GitRepo, Kind}; +use crate::{CLang, GitRepo, Kind, trace}; #[derive(Clone)] pub struct LlvmResult { @@ -934,6 +936,15 @@ impl Step for Enzyme { } /// Compile Enzyme for `target`. + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "Enzyme::run", + skip_all, + fields(target = ?self.target), + ), + )] fn run(self, builder: &Builder<'_>) -> PathBuf { builder.require_submodule( "src/tools/enzyme", @@ -959,7 +970,9 @@ impl Step for Enzyme { let out_dir = builder.enzyme_out(target); let stamp = BuildStamp::new(&out_dir).with_prefix("enzyme").add_stamp(smart_stamp_hash); + trace!("checking build stamp to see if we need to rebuild enzyme artifacts"); if stamp.is_up_to_date() { + trace!(?out_dir, "enzyme build artifacts are up to date"); if stamp.stamp().is_empty() { builder.info( "Could not determine the Enzyme submodule commit hash. \ @@ -973,6 +986,7 @@ impl Step for Enzyme { return out_dir; } + trace!(?target, "(re)building enzyme artifacts"); builder.info(&format!("Building Enzyme for {}", target)); t!(stamp.remove()); let _time = helpers::timeit(builder); @@ -994,6 +1008,7 @@ impl Step for Enzyme { (true, false) => "Release", (true, true) => "RelWithDebInfo", }; + trace!(?profile); cfg.out_dir(&out_dir) .profile(profile) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 1291a634a6f6..a54db9d78157 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,6 +1,9 @@ use std::path::PathBuf; use std::{env, fs}; +#[cfg(feature = "tracing")] +use tracing::instrument; + use crate::core::build_steps::compile::is_lto_stage; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, llvm}; @@ -304,6 +307,14 @@ macro_rules! bootstrap_tool { }); } + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = $tool_name, + skip_all, + ), + )] fn run(self, builder: &Builder<'_>) -> PathBuf { $( for submodule in $submodules { @@ -758,6 +769,15 @@ impl Step for LldWrapper { run.never() } + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "LldWrapper::run", + skip_all, + fields(build_compiler = ?self.build_compiler, target_compiler = ?self.target_compiler), + ), + )] fn run(self, builder: &Builder<'_>) { if builder.config.dry_run() { return; @@ -914,6 +934,10 @@ impl Step for LlvmBitcodeLinker { }); } + #[cfg_attr( + feature = "tracing", + instrument(level = "debug", name = "LlvmBitcodeLinker::run", skip_all) + )] fn run(self, builder: &Builder<'_>) -> PathBuf { let bin_name = "llvm-bitcode-linker"; diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index ecec589fc32e..6d77e38b1291 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -10,6 +10,8 @@ use std::time::{Duration, Instant}; use std::{env, fs}; use clap::ValueEnum; +#[cfg(feature = "tracing")] +use tracing::instrument; pub use self::cargo::{Cargo, cargo_profile_var}; pub use crate::Compiler; @@ -21,7 +23,7 @@ use crate::core::config::{DryRun, TargetSelection}; use crate::utils::cache::Cache; use crate::utils::exec::{BootstrapCommand, command}; use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t}; -use crate::{Build, Crate}; +use crate::{Build, Crate, trace}; mod cargo; @@ -1214,6 +1216,19 @@ impl<'a> Builder<'a> { /// compiler will run on, *not* the target it will build code for). Explicitly does not take /// `Compiler` since all `Compiler` instances are meant to be obtained through this function, /// since it ensures that they are valid (i.e., built and assembled). + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "Builder::compiler", + target = "COMPILER", + skip_all, + fields( + stage = stage, + host = ?host, + ), + ), + )] pub fn compiler(&self, stage: u32, host: TargetSelection) -> Compiler { self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) } @@ -1229,19 +1244,39 @@ impl<'a> Builder<'a> { /// sysroot. /// /// See `force_use_stage1` and `force_use_stage2` for documentation on what each argument is. + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "Builder::compiler_for", + target = "COMPILER_FOR", + skip_all, + fields( + stage = stage, + host = ?host, + target = ?target, + ), + ), + )] pub fn compiler_for( &self, stage: u32, host: TargetSelection, target: TargetSelection, ) -> Compiler { - if self.build.force_use_stage2(stage) { + #![allow(clippy::let_and_return)] + let resolved_compiler = if self.build.force_use_stage2(stage) { + trace!(target: "COMPILER_FOR", ?stage, "force_use_stage2"); self.compiler(2, self.config.build) } else if self.build.force_use_stage1(stage, target) { + trace!(target: "COMPILER_FOR", ?stage, "force_use_stage1"); self.compiler(1, self.config.build) } else { + trace!(target: "COMPILER_FOR", ?stage, ?host, "no force, fallback to `compiler()`"); self.compiler(stage, host) - } + }; + trace!(target: "COMPILER_FOR", ?resolved_compiler); + resolved_compiler } pub fn sysroot(&self, compiler: Compiler) -> PathBuf { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 62625fc3660f..d27a8b155df7 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2747,6 +2747,15 @@ impl Config { /// tarball). Typically [`crate::Build::require_submodule`] should be /// used instead to provide a nice error to the user if the submodule is /// missing. + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "Config::update_submodule", + skip_all, + fields(relative_path = ?relative_path), + ), + )] pub(crate) fn update_submodule(&self, relative_path: &str) { if !self.submodules() { return; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 7cd8aacf0d6c..34df3ca23201 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -469,6 +469,15 @@ impl Build { /// /// The given `err_hint` will be shown to the user if the submodule is not /// checked out and submodule management is disabled. + #[cfg_attr( + feature = "tracing", + instrument( + level = "trace", + name = "Build::require_submodule", + skip_all, + fields(submodule = submodule), + ), + )] pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) { // When testing bootstrap itself, it is much faster to ignore // submodules. Almost all Steps work fine without their submodules. From 7b118168c7902ae8ec266996a724cfec1c88ea1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 15 Feb 2025 22:58:46 +0800 Subject: [PATCH 070/158] bootstrap: take `target` by value in `is_builder_target` --- src/bootstrap/src/core/build_steps/compile.rs | 8 ++++---- src/bootstrap/src/core/build_steps/dist.rs | 6 +++--- src/bootstrap/src/core/build_steps/llvm.rs | 6 +++--- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/builder/tests.rs | 4 ++-- src/bootstrap/src/core/sanity.rs | 2 +- src/bootstrap/src/lib.rs | 10 +++++----- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index bae18a96d904..755ff4cd0f07 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -154,7 +154,7 @@ impl Step for Std { // When using `download-rustc`, we already have artifacts for the host available. Don't // recompile them. - if builder.download_rustc() && target == builder.build.build + if builder.download_rustc() && builder.is_builder_target(target) // NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so // its artifacts can't be reused. && compiler.stage != 0 @@ -232,7 +232,7 @@ impl Step for Std { // The LLD wrappers and `rust-lld` are self-contained linking components that can be // necessary to link the stdlib on some targets. We'll also need to copy these binaries to // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target. - if compiler.stage == 0 && builder.is_builder_target(&compiler.host) { + if compiler.stage == 0 && builder.is_builder_target(compiler.host) { trace!( "(build == host) copying linking components to `stage0-sysroot` for bootstrapping" ); @@ -1559,7 +1559,7 @@ impl Step for CodegenBackend { #[cfg_attr( feature = "tracing", instrument( - level = "debug", + level = "debug", name = "CodegenBackend::run", skip_all, fields( @@ -2485,7 +2485,7 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) // FIXME: to make things simpler for now, limit this to the host and target where we know // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not // cross-compiling. Expand this to other appropriate targets in the future. - if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(&target) || !path.exists() + if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(target) || !path.exists() { return; } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 96d0cf48fbfe..509ee9e1acf0 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -584,7 +584,7 @@ impl Step for DebuggerScripts { fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. - if !builder.is_builder_target(&compiler.host) { + if !builder.is_builder_target(compiler.host) { builder.info("\tskipping, not a build host"); true } else { @@ -639,7 +639,7 @@ fn copy_target_libs( for (path, dependency_type) in builder.read_stamp_file(stamp) { if dependency_type == DependencyType::TargetSelfContained { builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap())); - } else if dependency_type == DependencyType::Target || builder.is_builder_target(&target) { + } else if dependency_type == DependencyType::Target || builder.is_builder_target(target) { builder.copy_link(&path, &dst.join(path.file_name().unwrap())); } } @@ -788,7 +788,7 @@ impl Step for Analysis { fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; - if !builder.is_builder_target(&compiler.host) { + if !builder.is_builder_target(compiler.host) { return None; } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 9f62879c36d9..3025f9556607 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -518,7 +518,7 @@ impl Step for Llvm { } // https://llvm.org/docs/HowToCrossCompileLLVM.html - if !builder.is_builder_target(&target) { + if !builder.is_builder_target(target) { let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: builder.config.build }); if !builder.config.dry_run() { @@ -670,7 +670,7 @@ fn configure_cmake( } cfg.target(&target.triple).host(&builder.config.build.triple); - if !builder.is_builder_target(&target) { + if !builder.is_builder_target(target) { cfg.define("CMAKE_CROSSCOMPILING", "True"); if target.contains("netbsd") { @@ -1133,7 +1133,7 @@ impl Step for Lld { .define("LLVM_CMAKE_DIR", llvm_cmake_dir) .define("LLVM_INCLUDE_TESTS", "OFF"); - if !builder.is_builder_target(&target) { + if !builder.is_builder_target(target) { // Use the host llvm-tblgen binary. cfg.define( "LLVM_TABLEGEN_EXE", diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 26ed0e5deaa0..b3f4a7bad99c 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2743,7 +2743,7 @@ impl Step for Crate { cargo } else { // Also prepare a sysroot for the target. - if !builder.is_builder_target(&target) { + if !builder.is_builder_target(target) { builder.ensure(compile::Std::new(compiler, target).force_recompile(true)); builder.ensure(RemoteCopyLibs { compiler, target }); } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 5e3e0ef654fd..445b5dfbeab2 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1080,7 +1080,7 @@ fn test_is_builder_target() { let build = Build::new(config); let builder = Builder::new(&build); - assert!(builder.is_builder_target(&target1)); - assert!(!builder.is_builder_target(&target2)); + assert!(builder.is_builder_target(target1)); + assert!(!builder.is_builder_target(target2)); } } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 9e4a0816e0d4..241b7386d18c 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -329,7 +329,7 @@ than building it. if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up - if build.musl_root(*target).is_none() && build.is_builder_target(target) { + if build.musl_root(*target).is_none() && build.is_builder_target(*target) { let target = build.config.target_config.entry(*target).or_default(); target.musl_root = Some("/usr".into()); } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 34df3ca23201..62ddc7d682ee 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -748,7 +748,7 @@ impl Build { /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. fn llvm_out(&self, target: TargetSelection) -> PathBuf { - if self.config.llvm_from_ci && self.is_builder_target(&target) { + if self.config.llvm_from_ci && self.is_builder_target(target) { self.config.ci_llvm_root() } else { self.out.join(target).join("llvm") @@ -798,7 +798,7 @@ impl Build { fn is_system_llvm(&self, target: TargetSelection) -> bool { match self.config.target_config.get(&target) { Some(Target { llvm_config: Some(_), .. }) => { - let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(&target); + let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(target); !ci_llvm } // We're building from the in-tree src/llvm-project sources. @@ -1286,7 +1286,7 @@ Executed at: {executed_at}"#, // need to use CXX compiler as linker to resolve the exception functions // that are only existed in CXX libraries Some(self.cxx.borrow()[&target].path().into()) - } else if !self.is_builder_target(&target) + } else if !self.is_builder_target(target) && helpers::use_host_linker(target) && !target.is_msvc() { @@ -1939,8 +1939,8 @@ to download LLVM rather than building it. } /// Checks if the given target is the same as the builder target. - fn is_builder_target(&self, target: &TargetSelection) -> bool { - &self.config.build == target + fn is_builder_target(&self, target: TargetSelection) -> bool { + self.config.build == target } } From 05ba1a450adb266cdaa7001f73a2e5899405b3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 15 Feb 2025 22:59:01 +0800 Subject: [PATCH 071/158] rustc-dev-guide: document `COMPILER` and `COMPILER_FOR` tracing targets --- .../src/building/bootstrapping/debugging-bootstrap.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md index 04fa5b204dd4..04d8e91dcb4f 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md @@ -76,6 +76,14 @@ $ BOOTSTRAP_TRACING=CONFIG_HANDLING=TRACE ./x build library --stage 1 [tracing-env-filter]: https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber/filter/struct.EnvFilter.html +##### FIXME(#96176): specific tracing for `compiler()` vs `compiler_for()` + +The additional targets `COMPILER` and `COMPILER_FOR` are used to help trace what +`builder.compiler()` and `builder.compiler_for()` does. They should be removed +if [#96176][cleanup-compiler-for] is resolved. + +[cleanup-compiler-for]: https://github.com/rust-lang/rust/issues/96176 + ### Using `tracing` in bootstrap Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. Examples: From 930918d827f2598098ec8c6bf9aaa5a1e061fb3b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 10:51:58 +0100 Subject: [PATCH 072/158] Improve error recovery when method-calling an assoc function --- .../rust-analyzer/crates/hir-ty/src/infer.rs | 2 +- .../crates/hir-ty/src/infer/expr.rs | 91 ++++++++++++------- .../crates/hir-ty/src/tests/diagnostics.rs | 33 ++++++- .../hir-ty/src/tests/method_resolution.rs | 2 +- .../crates/hir/src/diagnostics.rs | 8 +- .../src/handlers/unresolved_method.rs | 45 ++++----- 6 files changed, 111 insertions(+), 70 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 9f20117bf14f..a8cd971b0579 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -236,7 +236,7 @@ pub enum InferenceDiagnostic { name: Name, /// Contains the type the field resolves to field_with_same_name: Option, - assoc_func_with_same_name: Option, + assoc_func_with_same_name: Option, }, UnresolvedAssocItem { id: ExprOrPatId, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 41d739a078e6..bff88143475c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -1922,21 +1922,32 @@ impl InferenceContext<'_> { VisibleFromModule::Filter(self.resolver.module()), method_name, ); - let (receiver_ty, method_ty, substs) = match resolved { + match resolved { Some((adjust, func, visible)) => { - let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty); - let generics = generics(self.db.upcast(), func.into()); - let substs = self.substs_for_method_call(generics, generic_args); - self.write_expr_adj(receiver, adjustments); - self.write_method_resolution(tgt_expr, func, substs.clone()); if !visible { self.push_diagnostic(InferenceDiagnostic::PrivateAssocItem { id: tgt_expr.into(), item: func.into(), }) } - (ty, self.db.value_ty(func.into()).unwrap(), substs) + + let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty); + self.write_expr_adj(receiver, adjustments); + + let generics = generics(self.db.upcast(), func.into()); + let substs = self.substs_for_method_call(generics, generic_args); + self.write_method_resolution(tgt_expr, func, substs.clone()); + self.check_method_call( + tgt_expr, + args, + self.db.value_ty(func.into()).expect("we have a function def"), + substs, + ty, + expected, + ) } + // Failed to resolve, report diagnostic and try to resolve as call to field access or + // assoc function None => { let field_with_same_name_exists = match self.lookup_field(&receiver_ty, method_name) { @@ -1956,12 +1967,11 @@ impl InferenceContext<'_> { VisibleFromModule::Filter(self.resolver.module()), Some(method_name), method_resolution::LookupMode::Path, - |_ty, item, visible| { - if visible { - Some(item) - } else { - None + |_ty, item, visible| match item { + hir_def::AssocItemId::FunctionId(function_id) if visible => { + Some(function_id) } + _ => None, }, ); @@ -1973,31 +1983,41 @@ impl InferenceContext<'_> { assoc_func_with_same_name, }); - return match field_with_same_name_exists { - Some(field_ty) => match field_ty.callable_sig(self.db) { - Some(sig) => self.check_call( - tgt_expr, - args, - field_ty, - sig.params(), - sig.ret().clone(), - &[], - true, - expected, - ), - None => { - self.check_call_arguments(tgt_expr, args, &[], &[], &[], true); - field_ty - } - }, + let recovered = match assoc_func_with_same_name { + Some(f) => { + let generics = generics(self.db.upcast(), f.into()); + let substs = self.substs_for_method_call(generics, generic_args); + let f = self + .db + .value_ty(f.into()) + .expect("we have a function def") + .substitute(Interner, &substs); + let sig = f.callable_sig(self.db).expect("we have a function def"); + Some((f, sig, true)) + } + None => field_with_same_name_exists.and_then(|field_ty| { + let callable_sig = field_ty.callable_sig(self.db)?; + Some((field_ty, callable_sig, false)) + }), + }; + match recovered { + Some((callee_ty, sig, strip_first)) => self.check_call( + tgt_expr, + args, + callee_ty, + sig.params().get(strip_first as usize..).unwrap_or(&[]), + sig.ret().clone(), + &[], + true, + expected, + ), None => { self.check_call_arguments(tgt_expr, args, &[], &[], &[], true); self.err_ty() } - }; + } } - }; - self.check_method_call(tgt_expr, args, method_ty, substs, receiver_ty, expected) + } } fn check_method_call( @@ -2067,9 +2087,10 @@ impl InferenceContext<'_> { expected_inputs: &[Ty], param_tys: &[Ty], skip_indices: &[u32], - is_varargs: bool, + ignore_arg_param_mismatch: bool, ) { - let arg_count_mismatch = args.len() != param_tys.len() + skip_indices.len() && !is_varargs; + let arg_count_mismatch = + !ignore_arg_param_mismatch && args.len() != param_tys.len() + skip_indices.len(); if arg_count_mismatch { self.push_diagnostic(InferenceDiagnostic::MismatchedArgCount { call_expr: expr, @@ -2098,7 +2119,7 @@ impl InferenceContext<'_> { continue; } - while skip_indices.peek().is_some_and(|i| *i < idx as u32) { + while skip_indices.peek().is_some_and(|&i| i < idx as u32) { skip_indices.next(); } if skip_indices.peek().copied() == Some(idx as u32) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs index d0d31bf2a5a6..855034117c0d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/diagnostics.rs @@ -159,18 +159,18 @@ fn method_call_on_field() { check( r#" struct S { - field: fn() -> u32, + field: fn(f32) -> u32, field2: u32 } fn main() { - let s = S { field: || 0, field2: 0 }; + let s = S { field: |_| 0, field2: 0 }; s.field(0); - // ^ type: i32 + // ^ expected f32, got i32 // ^^^^^^^^^^ type: u32 s.field2(0); // ^ type: i32 - // ^^^^^^^^^^^ type: u32 + // ^^^^^^^^^^^ type: {unknown} s.not_a_field(0); // ^ type: i32 // ^^^^^^^^^^^^^^^^ type: {unknown} @@ -178,3 +178,28 @@ fn main() { "#, ); } + +#[test] +fn method_call_on_assoc() { + check( + r#" +struct S; + +impl S { + fn not_a_method() -> f32 { 0.0 } + fn not_a_method2(this: Self, param: f32) -> Self { this } + fn not_a_method3(param: f32) -> Self { S } +} + +fn main() { + S.not_a_method(0); + // ^^^^^^^^^^^^^^^^^ type: f32 + S.not_a_method2(0); + // ^ expected f32, got i32 + // ^^^^^^^^^^^^^^^^^^ type: S + S.not_a_method3(0); + // ^^^^^^^^^^^^^^^^^^ type: S +} +"#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs index e5f791ea6ffc..3a258ecad10a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs @@ -1210,7 +1210,7 @@ impl Slice { fn main() { let foo: Slice; foo.into_vec(); // we shouldn't crash on this at least -} //^^^^^^^^^^^^^^ {unknown} +} //^^^^^^^^^^^^^^ () "#, ); } diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 5876529df96a..307673f52c7d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -10,7 +10,7 @@ use hir_def::{ hir::ExprOrPatId, path::{hir_segment_to_ast_segment, ModPath}, type_ref::TypesSourceMap, - AssocItemId, DefWithBodyId, SyntheticSyntax, + DefWithBodyId, SyntheticSyntax, }; use hir_expand::{name::Name, HirFileId, InFile}; use hir_ty::{ @@ -25,7 +25,7 @@ use syntax::{ }; use triomphe::Arc; -use crate::{AssocItem, Field, Local, Trait, Type}; +use crate::{AssocItem, Field, Function, Local, Trait, Type}; pub use hir_def::VariantId; pub use hir_ty::{ @@ -253,7 +253,7 @@ pub struct UnresolvedMethodCall { pub receiver: Type, pub name: Name, pub field_with_same_name: Option, - pub assoc_func_with_same_name: Option, + pub assoc_func_with_same_name: Option, } #[derive(Debug)] @@ -623,7 +623,7 @@ impl AnyDiagnostic { field_with_same_name: field_with_same_name .clone() .map(|ty| Type::new(db, def, ty)), - assoc_func_with_same_name: *assoc_func_with_same_name, + assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into), } .into() } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index dd1b593e8f6e..e4de107249bd 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -1,4 +1,4 @@ -use hir::{db::ExpandDatabase, AssocItem, FileRange, HirDisplay, InFile}; +use hir::{db::ExpandDatabase, FileRange, HirDisplay, InFile}; use ide_db::text_edit::TextEdit; use ide_db::{ assists::{Assist, AssistId, AssistKind}, @@ -112,7 +112,7 @@ fn field_fix( } fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option { - if let Some(assoc_item_id) = d.assoc_func_with_same_name { + if let Some(f) = d.assoc_func_with_same_name { let db = ctx.sema.db; let expr_ptr = &d.expr; @@ -127,30 +127,25 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) - let receiver = call.receiver()?; let receiver_type = &ctx.sema.type_of_expr(&receiver)?.original; - let need_to_take_receiver_as_first_arg = match hir::AssocItem::from(assoc_item_id) { - AssocItem::Function(f) => { - let assoc_fn_params = f.assoc_fn_params(db); - if assoc_fn_params.is_empty() { - false - } else { - assoc_fn_params - .first() - .map(|first_arg| { - // For generic type, say `Box`, take `Box::into_raw(b: Self)` as example, - // type of `b` is `Self`, which is `Box`, containing unspecified generics. - // However, type of `receiver` is specified, it could be `Box` or something like that, - // so `first_arg.ty() == receiver_type` evaluate to `false` here. - // Here add `first_arg.ty().as_adt() == receiver_type.as_adt()` as guard, - // apply `.as_adt()` over `Box` or `Box` gets `Box`, so we get `true` here. + let assoc_fn_params = f.assoc_fn_params(db); + let need_to_take_receiver_as_first_arg = if assoc_fn_params.is_empty() { + false + } else { + assoc_fn_params + .first() + .map(|first_arg| { + // For generic type, say `Box`, take `Box::into_raw(b: Self)` as example, + // type of `b` is `Self`, which is `Box`, containing unspecified generics. + // However, type of `receiver` is specified, it could be `Box` or something like that, + // so `first_arg.ty() == receiver_type` evaluate to `false` here. + // Here add `first_arg.ty().as_adt() == receiver_type.as_adt()` as guard, + // apply `.as_adt()` over `Box` or `Box` gets `Box`, so we get `true` here. - // FIXME: it fails when type of `b` is `Box` with other generic param different from `receiver` - first_arg.ty() == receiver_type - || first_arg.ty().as_adt() == receiver_type.as_adt() - }) - .unwrap_or(false) - } - } - _ => false, + // FIXME: it fails when type of `b` is `Box` with other generic param different from `receiver` + first_arg.ty() == receiver_type + || first_arg.ty().as_adt() == receiver_type.as_adt() + }) + .unwrap_or(false) }; let mut receiver_type_adt_name = From 345c313def0a559e7a29bc059c2e242ed398a760 Mon Sep 17 00:00:00 2001 From: may Date: Sun, 16 Feb 2025 12:02:06 +0100 Subject: [PATCH 073/158] fix docs for inherent str constructors --- library/core/src/str/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 05c16791ce7e..062f7dcc9402 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -198,7 +198,7 @@ impl str { /// Basic usage: /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// // some bytes, in a vector /// let sparkle_heart = vec![240, 159, 146, 150]; @@ -207,13 +207,13 @@ impl str { /// let sparkle_heart = str::from_utf8(&sparkle_heart)?; /// /// assert_eq!("💖", sparkle_heart); - /// # Ok::<_, str::Utf8Error>(()) + /// # Ok::<_, std::str::Utf8Error>(()) /// ``` /// /// Incorrect bytes: /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// // some invalid bytes, in a vector /// let sparkle_heart = vec![0, 159, 146, 150]; @@ -227,7 +227,7 @@ impl str { /// A "stack allocated string": /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// // some bytes, in a stack-allocated array /// let sparkle_heart = [240, 159, 146, 150]; @@ -249,7 +249,7 @@ impl str { /// Basic usage: /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// // "Hello, Rust!" as a mutable vector /// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33]; @@ -263,7 +263,7 @@ impl str { /// Incorrect bytes: /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// // Some invalid bytes in a mutable vector /// let mut invalid = vec![128, 223]; @@ -292,7 +292,7 @@ impl str { /// Basic usage: /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// // some bytes, in a vector /// let sparkle_heart = vec![240, 159, 146, 150]; @@ -321,7 +321,7 @@ impl str { /// Basic usage: /// /// ``` - /// use std::str; + /// #![feature(inherent_str_constructors)] /// /// let mut heart = vec![240, 159, 146, 150]; /// let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) }; From 2a8fbb5f5678e3fa61e06430da957662030ad404 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 16 Feb 2025 12:15:55 +0100 Subject: [PATCH 074/158] Re-add missing empty lines in the releases notes --- RELEASES.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index f0def1a0e423..038d7ca639f2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -34,7 +34,8 @@ Libraries --------- - [Panics in the standard library now have a leading `library/` in their path](https://github.com/rust-lang/rust/pull/132390) - [`std::env::home_dir()` on Windows now ignores the non-standard `$HOME` environment variable](https://github.com/rust-lang/rust/pull/132515) - It will be un-deprecated in a subsequent release. + + It will be un-deprecated in a subsequent release. - [Add `AsyncFn*` to the prelude in all editions.](https://github.com/rust-lang/rust/pull/132611) @@ -98,15 +99,18 @@ Rustdoc Compatibility Notes ------------------- - [`rustc` no longer treats the `test` cfg as a well known check-cfg](https://github.com/rust-lang/rust/pull/131729), instead it is up to the build systems and users of `--check-cfg`[^check-cfg] to set it as a well known cfg using `--check-cfg=cfg(test)`. + This is done to enable build systems like Cargo to set it conditionally, as not all source files are suitable for unit tests. [Cargo (for now) unconditionally sets the `test` cfg as a well known cfg](https://github.com/rust-lang/cargo/pull/14963). -[^check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html + [^check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html - [Disable potentially incorrect type inference if there are trivial and non-trivial where-clauses](https://github.com/rust-lang/rust/pull/132325) - `std::env::home_dir()` has been deprecated for years, because it can give surprising results in some Windows configurations if the `HOME` environment variable is set (which is not the normal configuration on Windows). We had previously avoided changing its behavior, out of concern for compatibility with code depending on this non-standard configuration. Given how long this function has been deprecated, we're now fixing its behavior as a bugfix. A subsequent release will remove the deprecation for this function. - [Make `core::ffi::c_char` signedness more closely match that of the platform-default `char`](https://github.com/rust-lang/rust/pull/132975) + This changed `c_char` from an `i8` to `u8` or vice versa on many Tier 2 and 3 targets (mostly Arm and RISC-V embedded targets). The new definition may result in compilation failures but fixes compatibility issues with C. + The `libc` crate matches this change as of its 0.2.169 release. - [When compiling a nested `macro_rules` macro from an external crate, the content of the inner `macro_rules` is now built with the edition of the external crate, not the local crate.](https://github.com/rust-lang/rust/pull/133274) - [Increase `sparcv9-sun-solaris` and `x86_64-pc-solaris` Solaris baseline to 11.4.](https://github.com/rust-lang/rust/pull/133293) From b54269c2b1c858a489ea588b3679bd21f0d06bbb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 12:20:41 +0100 Subject: [PATCH 075/158] fix: Stabilize sort order of runnables --- .../crates/ide/src/annotations.rs | 74 +++++++++++-------- .../rust-analyzer/crates/ide/src/runnables.rs | 4 +- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs index 006e6e8246e1..a0add4741f32 100644 --- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs +++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs @@ -1,6 +1,6 @@ use hir::{HasSource, InFile, InRealFile, Semantics}; use ide_db::{ - defs::Definition, helpers::visit_file_defs, FileId, FilePosition, FileRange, FxHashSet, + defs::Definition, helpers::visit_file_defs, FileId, FilePosition, FileRange, FxIndexSet, RootDatabase, }; use itertools::Itertools; @@ -55,7 +55,7 @@ pub(crate) fn annotations( config: &AnnotationConfig, file_id: FileId, ) -> Vec { - let mut annotations = FxHashSet::default(); + let mut annotations = FxIndexSet::default(); if config.annotate_runnables { for runnable in runnables(db, file_id) { @@ -170,7 +170,19 @@ pub(crate) fn annotations( })); } - annotations.into_iter().sorted_by_key(|a| (a.range.start(), a.range.end())).collect() + annotations + .into_iter() + .sorted_by_key(|a| { + ( + a.range.start(), + a.range.end(), + match &a.kind { + AnnotationKind::Runnable(runnable) => Some(runnable.nav.name.clone()), + _ => None, + }, + ) + }) + .collect() } pub(crate) fn resolve_annotation(db: &RootDatabase, mut annotation: Annotation) -> Annotation { @@ -535,6 +547,20 @@ fn main() { ), }, }, + Annotation { + range: 69..73, + kind: HasReferences { + pos: FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 69, + }, + data: Some( + [], + ), + }, + }, Annotation { range: 69..73, kind: Runnable( @@ -559,20 +585,6 @@ fn main() { }, ), }, - Annotation { - range: 69..73, - kind: HasReferences { - pos: FilePositionWrapper { - file_id: FileId( - 0, - ), - offset: 69, - }, - data: Some( - [], - ), - }, - }, ] "#]], ); @@ -717,6 +729,20 @@ fn main() { ), }, }, + Annotation { + range: 61..65, + kind: HasReferences { + pos: FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 61, + }, + data: Some( + [], + ), + }, + }, Annotation { range: 61..65, kind: Runnable( @@ -741,20 +767,6 @@ fn main() { }, ), }, - Annotation { - range: 61..65, - kind: HasReferences { - pos: FilePositionWrapper { - file_id: FileId( - 0, - ), - offset: 61, - }, - data: Some( - [], - ), - }, - }, ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 78c9f2309a0d..16dd039eabbe 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -13,7 +13,7 @@ use ide_db::{ documentation::docs_from_attrs, helpers::visit_file_defs, search::{FileReferenceNode, SearchScope}, - FilePosition, FxHashMap, FxHashSet, RootDatabase, SymbolKind, + FilePosition, FxHashMap, FxHashSet, FxIndexMap, RootDatabase, SymbolKind, }; use itertools::Itertools; use smallvec::SmallVec; @@ -130,7 +130,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { let mut res = Vec::new(); // Record all runnables that come from macro expansions here instead. // In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables. - let mut in_macro_expansion = FxHashMap::>::default(); + let mut in_macro_expansion = FxIndexMap::>::default(); let mut add_opt = |runnable: Option, def| { if let Some(runnable) = runnable.filter(|runnable| runnable.nav.file_id == file_id) { if let Some(def) = def { From c5f49cf07194185a02a5dd353d3125775fe5ed82 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 13:11:50 +0100 Subject: [PATCH 076/158] fix: Stabilize sort order of `related_tests` --- .../rust-analyzer/crates/ide/src/runnables.rs | 59 ++++++++++--------- .../ide/src/syntax_highlighting/tests.rs | 3 + 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 16dd039eabbe..9e3b70fa8eae 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -4,8 +4,8 @@ use arrayvec::ArrayVec; use ast::HasName; use cfg::{CfgAtom, CfgExpr}; use hir::{ - db::HirDatabase, sym, AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, HasSource, HirFileIdExt, - ModPath, Name, PathKind, Semantics, Symbol, + db::HirDatabase, sym, symbols::FxIndexSet, AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, + HasSource, HirFileIdExt, ModPath, Name, PathKind, Semantics, Symbol, }; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ @@ -13,7 +13,7 @@ use ide_db::{ documentation::docs_from_attrs, helpers::visit_file_defs, search::{FileReferenceNode, SearchScope}, - FilePosition, FxHashMap, FxHashSet, FxIndexMap, RootDatabase, SymbolKind, + FilePosition, FxHashMap, FxIndexMap, RootDatabase, SymbolKind, }; use itertools::Itertools; use smallvec::SmallVec; @@ -182,20 +182,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { r }) })); - res.sort_by(|Runnable { nav, kind, .. }, Runnable { nav: nav_b, kind: kind_b, .. }| { - // full_range.start < focus_range.start < name, should give us a decent unique ordering - nav.full_range - .start() - .cmp(&nav_b.full_range.start()) - .then_with(|| { - let t_0 = || TextSize::from(0); - nav.focus_range - .map_or_else(t_0, |it| it.start()) - .cmp(&nav_b.focus_range.map_or_else(t_0, |it| it.start())) - }) - .then_with(|| kind.disc().cmp(&kind_b.disc())) - .then_with(|| nav.name.cmp(&nav_b.name)) - }); + res.sort_by(cmp_runnables); res } @@ -215,12 +202,30 @@ pub(crate) fn related_tests( search_scope: Option, ) -> Vec { let sema = Semantics::new(db); - let mut res: FxHashSet = FxHashSet::default(); + let mut res: FxIndexSet = FxIndexSet::default(); let syntax = sema.parse_guess_edition(position.file_id).syntax().clone(); find_related_tests(&sema, &syntax, position, search_scope, &mut res); - res.into_iter().collect() + res.into_iter().sorted_by(cmp_runnables).collect() +} + +fn cmp_runnables( + Runnable { nav, kind, .. }: &Runnable, + Runnable { nav: nav_b, kind: kind_b, .. }: &Runnable, +) -> std::cmp::Ordering { + // full_range.start < focus_range.start < name, should give us a decent unique ordering + nav.full_range + .start() + .cmp(&nav_b.full_range.start()) + .then_with(|| { + let t_0 = || TextSize::from(0); + nav.focus_range + .map_or_else(t_0, |it| it.start()) + .cmp(&nav_b.focus_range.map_or_else(t_0, |it| it.start())) + }) + .then_with(|| kind.disc().cmp(&kind_b.disc())) + .then_with(|| nav.name.cmp(&nav_b.name)) } fn find_related_tests( @@ -228,7 +233,7 @@ fn find_related_tests( syntax: &SyntaxNode, position: FilePosition, search_scope: Option, - tests: &mut FxHashSet, + tests: &mut FxIndexSet, ) { // FIXME: why is this using references::find_defs, this should use ide_db::search let defs = match references::find_defs(sema, syntax, position.offset) { @@ -268,7 +273,7 @@ fn find_related_tests_in_module( syntax: &SyntaxNode, fn_def: &ast::Fn, parent_module: &hir::Module, - tests: &mut FxHashSet, + tests: &mut FxIndexSet, ) { let fn_name = match fn_def.name() { Some(it) => it, @@ -1501,18 +1506,18 @@ mod tests { file_id: FileId( 0, ), - full_range: 121..185, - focus_range: 136..145, - name: "foo2_test", + full_range: 52..115, + focus_range: 67..75, + name: "foo_test", kind: Function, }, NavigationTarget { file_id: FileId( 0, ), - full_range: 52..115, - focus_range: 67..75, - name: "foo_test", + full_range: 121..185, + focus_range: 136..145, + name: "foo2_test", kind: Function, }, ] diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index b9520ae2bba2..30b8fa74f81d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -1084,6 +1084,9 @@ pub struct Struct; ); } +// Rainbow highlighting uses a deterministic hash (fxhash) but the hashing does differ +// depending on the pointer width so only runs this on 64-bit targets. +#[cfg(target_pointer_width = "64")] #[test] fn test_rainbow_highlighting() { check_highlighting( From f53d0f502dba3b378d8baef159b97e685ba40f33 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 16 Feb 2025 00:40:25 +0300 Subject: [PATCH 077/158] invalid_from_utf8[_unchecked]: also lint inherent methods --- compiler/rustc_lint/messages.ftl | 4 +- compiler/rustc_lint/src/invalid_from_utf8.rs | 10 +- compiler/rustc_span/src/symbol.rs | 4 + library/core/src/str/mod.rs | 4 + tests/ui/lint/invalid_from_utf8.rs | 53 ++++- tests/ui/lint/invalid_from_utf8.stderr | 237 ++++++++++++++++--- 6 files changed, 269 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 480d97e377a4..dbe24c9cdf24 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -439,11 +439,11 @@ lint_invalid_crate_type_value = invalid `crate_type` value .suggestion = did you mean # FIXME: we should ordinalize $valid_up_to when we add support for doing so -lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error +lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes # FIXME: we should ordinalize $valid_up_to when we add support for doing so -lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior +lint_invalid_from_utf8_unchecked = calls to `{$method}` with an invalid literal are undefined behavior .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be directly compared to itself diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs index 0081374922e6..11eb079ddc09 100644 --- a/compiler/rustc_lint/src/invalid_from_utf8.rs +++ b/compiler/rustc_lint/src/invalid_from_utf8.rs @@ -70,12 +70,20 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 { sym::str_from_utf8_mut, sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut, + sym::str_inherent_from_utf8, + sym::str_inherent_from_utf8_mut, + sym::str_inherent_from_utf8_unchecked, + sym::str_inherent_from_utf8_unchecked_mut, ] .contains(&diag_item) { let lint = |label, utf8_error: Utf8Error| { let method = diag_item.as_str().strip_prefix("str_").unwrap(); - let method = format!("std::str::{method}"); + let method = if let Some(method) = method.strip_prefix("inherent_") { + format!("str::{method}") + } else { + format!("std::str::{method}") + }; let valid_up_to = utf8_error.valid_up_to(); let is_unchecked_variant = diag_item.as_str().contains("unchecked"); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 62723e385cf6..4c2f7ad6d3cc 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1973,6 +1973,10 @@ symbols! { str_from_utf8_mut, str_from_utf8_unchecked, str_from_utf8_unchecked_mut, + str_inherent_from_utf8, + str_inherent_from_utf8_mut, + str_inherent_from_utf8_unchecked, + str_inherent_from_utf8_unchecked_mut, str_len, str_split_whitespace, str_starts_with, diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 05c16791ce7e..fd2cd59f88e0 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -238,6 +238,7 @@ impl str { /// assert_eq!("💖", sparkle_heart); /// ``` #[unstable(feature = "inherent_str_constructors", issue = "131114")] + #[rustc_diagnostic_item = "str_inherent_from_utf8"] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { converts::from_utf8(v) } @@ -274,6 +275,7 @@ impl str { /// errors that can be returned. #[unstable(feature = "inherent_str_constructors", issue = "131114")] #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] + #[rustc_diagnostic_item = "str_inherent_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { converts::from_utf8_mut(v) } @@ -306,6 +308,7 @@ impl str { #[inline] #[must_use] #[unstable(feature = "inherent_str_constructors", issue = "131114")] + #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked"] pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { // SAFETY: converts::from_utf8_unchecked has the same safety requirements as this function. unsafe { converts::from_utf8_unchecked(v) } @@ -331,6 +334,7 @@ impl str { #[inline] #[must_use] #[unstable(feature = "inherent_str_constructors", issue = "131114")] + #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: converts::from_utf8_unchecked_mut has the same safety requirements as this function. unsafe { converts::from_utf8_unchecked_mut(v) } diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs index 2d1822a54ac3..8f8000fe34d4 100644 --- a/tests/ui/lint/invalid_from_utf8.rs +++ b/tests/ui/lint/invalid_from_utf8.rs @@ -1,7 +1,7 @@ //@ check-pass #![feature(concat_bytes)] - +#![feature(inherent_str_constructors)] #![warn(invalid_from_utf8_unchecked)] #![warn(invalid_from_utf8)] @@ -9,7 +9,9 @@ pub fn from_utf8_unchecked_mut() { // Valid unsafe { std::str::from_utf8_unchecked_mut(&mut [99, 108, 105, 112, 112, 121]); + str::from_utf8_unchecked_mut(&mut [99, 108, 105, 112, 112, 121]); std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']); + str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']); let x = 0xA0; std::str::from_utf8_unchecked_mut(&mut [0xC0, x]); @@ -19,8 +21,12 @@ pub fn from_utf8_unchecked_mut() { unsafe { std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]); //~^ WARN calls to `std::str::from_utf8_unchecked_mut` + str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]); + //~^ WARN calls to `str::from_utf8_unchecked_mut` std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); //~^ WARN calls to `std::str::from_utf8_unchecked_mut` + str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + //~^ WARN calls to `str::from_utf8_unchecked_mut` } } @@ -28,23 +34,35 @@ pub fn from_utf8_unchecked() { // Valid unsafe { std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]); + str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]); std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']); + str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']); std::str::from_utf8_unchecked(b"clippy"); + str::from_utf8_unchecked(b"clippy"); let x = 0xA0; std::str::from_utf8_unchecked(&[0xC0, x]); + str::from_utf8_unchecked(&[0xC0, x]); } // Invalid unsafe { std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); //~^ WARN calls to `std::str::from_utf8_unchecked` + str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); + //~^ WARN calls to `str::from_utf8_unchecked` std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); //~^ WARN calls to `std::str::from_utf8_unchecked` + str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + //~^ WARN calls to `str::from_utf8_unchecked` std::str::from_utf8_unchecked(b"cl\x82ippy"); //~^ WARN calls to `std::str::from_utf8_unchecked` + str::from_utf8_unchecked(b"cl\x82ippy"); + //~^ WARN calls to `str::from_utf8_unchecked` std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); //~^ WARN calls to `std::str::from_utf8_unchecked` + str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); + //~^ WARN calls to `str::from_utf8_unchecked` } } @@ -52,18 +70,25 @@ pub fn from_utf8_mut() { // Valid { std::str::from_utf8_mut(&mut [99, 108, 105, 112, 112, 121]); + str::from_utf8_mut(&mut [99, 108, 105, 112, 112, 121]); std::str::from_utf8_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']); + str::from_utf8_mut(&mut [b'c', b'l', b'i', b'p', b'p', b'y']); let x = 0xa0; std::str::from_utf8_mut(&mut [0xc0, x]); + str::from_utf8_mut(&mut [0xc0, x]); } // Invalid { std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); //~^ WARN calls to `std::str::from_utf8_mut` + str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); + //~^ WARN calls to `str::from_utf8_mut` std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); //~^ WARN calls to `std::str::from_utf8_mut` + str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + //~^ WARN calls to `str::from_utf8_mut` } } @@ -71,23 +96,35 @@ pub fn from_utf8() { // Valid { std::str::from_utf8(&[99, 108, 105, 112, 112, 121]); + str::from_utf8(&[99, 108, 105, 112, 112, 121]); std::str::from_utf8(&[b'c', b'l', b'i', b'p', b'p', b'y']); + str::from_utf8(&[b'c', b'l', b'i', b'p', b'p', b'y']); std::str::from_utf8(b"clippy"); + str::from_utf8(b"clippy"); let x = 0xA0; std::str::from_utf8(&[0xC0, x]); + str::from_utf8(&[0xC0, x]); } // Invalid { std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); + //~^ WARN calls to `str::from_utf8` std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + //~^ WARN calls to `str::from_utf8` std::str::from_utf8(b"cl\x82ippy"); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(b"cl\x82ippy"); + //~^ WARN calls to `str::from_utf8` std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); + //~^ WARN calls to `str::from_utf8` } } @@ -95,25 +132,39 @@ pub fn from_utf8_with_indirections() { let mut a = [99, 108, 130, 105, 112, 112, 121]; std::str::from_utf8_mut(&mut a); //~^ WARN calls to `std::str::from_utf8_mut` + str::from_utf8_mut(&mut a); + //~^ WARN calls to `str::from_utf8_mut` let mut b = &mut a; let mut c = b; std::str::from_utf8_mut(c); //~^ WARN calls to `std::str::from_utf8_mut` + str::from_utf8_mut(c); + //~^ WARN calls to `str::from_utf8_mut` let mut c = &[99, 108, 130, 105, 112, 112, 121]; std::str::from_utf8(c); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(c); + //~^ WARN calls to `str::from_utf8` const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; std::str::from_utf8(&INVALID_1); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(&INVALID_1); + //~^ WARN calls to `str::from_utf8` static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; std::str::from_utf8(&INVALID_2); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(&INVALID_2); + //~^ WARN calls to `str::from_utf8` const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; std::str::from_utf8(INVALID_3); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(INVALID_3); + //~^ WARN calls to `str::from_utf8` const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; std::str::from_utf8(INVALID_4); //~^ WARN calls to `std::str::from_utf8` + str::from_utf8(INVALID_4); + //~^ WARN calls to `str::from_utf8` } fn main() {} diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr index 07616e118010..715ecf56f218 100644 --- a/tests/ui/lint/invalid_from_utf8.stderr +++ b/tests/ui/lint/invalid_from_utf8.stderr @@ -1,5 +1,5 @@ -warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:20:9 +warning: calls to `std::str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:22:9 | LL | std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ @@ -12,48 +12,96 @@ note: the lint level is defined here LL | #![warn(invalid_from_utf8_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:22:9 +warning: calls to `str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:24:9 + | +LL | str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:26:9 | LL | std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:40:9 +warning: calls to `str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:28:9 + | +LL | str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:50:9 | LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:42:9 +warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:52:9 + | +LL | str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:54:9 | LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:44:9 +warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:56:9 + | +LL | str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:58:9 | LL | std::str::from_utf8_unchecked(b"cl\x82ippy"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:46:9 +warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:60:9 + | +LL | str::from_utf8_unchecked(b"cl\x82ippy"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^-------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:62:9 | LL | std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:63:9 +warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior + --> $DIR/invalid_from_utf8.rs:64:9 + | +LL | str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:84:9 | LL | std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ @@ -66,56 +114,113 @@ note: the lint level is defined here LL | #![warn(invalid_from_utf8)] | ^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:65:9 +warning: calls to `str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:86:9 + | +LL | str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); + | ^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:88:9 | LL | std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:83:9 +warning: calls to `str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:90:9 + | +LL | str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + | ^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:112:9 | LL | std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^----------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:85:9 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:114:9 + | +LL | str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); + | ^^^^^^^^^^^^^^^^----------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:116:9 | LL | std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:87:9 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:118:9 + | +LL | str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); + | ^^^^^^^^^^^^^^^^---------------------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:120:9 | LL | std::str::from_utf8(b"cl\x82ippy"); | ^^^^^^^^^^^^^^^^^^^^-------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:89:9 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:122:9 + | +LL | str::from_utf8(b"cl\x82ippy"); + | ^^^^^^^^^^^^^^^-------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:124:9 | LL | std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); | ^^^^^^^^^^^^^^^^^^^^---------------------------------^ | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:96:5 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:126:9 + | +LL | str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); + | ^^^^^^^^^^^^^^^---------------------------------^ + | | + | the literal was valid UTF-8 up to the 2 bytes + +warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:133:5 | LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8_mut(&mut a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:100:5 +warning: calls to `str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:135:5 + | +LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8_mut(&mut a); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:139:5 | LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -123,45 +228,99 @@ LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; LL | std::str::from_utf8_mut(c); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:103:5 +warning: calls to `str::from_utf8_mut` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:141:5 + | +LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8_mut(c); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:144:5 | LL | let mut c = &[99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8(c); | ^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:106:5 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:146:5 + | +LL | let mut c = &[99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8(c); + | ^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:149:5 | LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8(&INVALID_1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:109:5 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:151:5 + | +LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8(&INVALID_1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:154:5 | LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8(&INVALID_2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:112:5 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:156:5 + | +LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8(&INVALID_2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:159:5 | LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8(INVALID_3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:115:5 +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:161:5 + | +LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8(INVALID_3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: calls to `std::str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:164:5 | LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8(INVALID_4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 19 warnings emitted +warning: calls to `str::from_utf8` with an invalid literal always return an error + --> $DIR/invalid_from_utf8.rs:166:5 + | +LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +... +LL | str::from_utf8(INVALID_4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 38 warnings emitted From 77571a5c8bd1a8958865de75b8ec8b1bc2b4b756 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 16 Feb 2025 01:18:29 +0300 Subject: [PATCH 078/158] clippy: string_from_utf8_as_bytes: also detect inherent `from_utf8` --- src/tools/clippy/clippy_lints/src/strings.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 6164a6191db0..4a5f143a2d34 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{ - SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, - method_calls, peel_blocks, + SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, method_calls, path_def_id, + peel_blocks, }; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -253,8 +253,9 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { use rustc_ast::LitKind; if let ExprKind::Call(fun, [bytes_arg]) = e.kind - // Find std::str::converts::from_utf8 - && is_path_diagnostic_item(cx, fun, sym::str_from_utf8) + // Find `std::str::converts::from_utf8` or `std::primitive::str::from_utf8` + && let Some(sym::str_from_utf8 | sym::str_inherent_from_utf8) = + path_def_id(cx, fun).and_then(|id| cx.tcx.get_diagnostic_name(id)) // Find string::as_bytes && let ExprKind::AddrOf(BorrowKind::Ref, _, args) = bytes_arg.kind From 8a02724b9d0bf3a9e449a04c2d7efaa8a0521e1b Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sun, 16 Feb 2025 16:20:53 +0100 Subject: [PATCH 079/158] Fix const items not being allowed to be called `r#move` or `r#static` Because of an ambiguity with const closures, the parser needs to ensure that for a const item, the `const` keyword isn't followed by a `move` or `static` keyword, as that would indicate a const closure: ```rust fn main() { const move // ... } ``` This check did not take raw identifiers into account, therefore being unable to distinguish between `const move` and `const r#move`. The latter is obviously not a const closure, so it should be allowed as a const item. This fixes the check in the parser to only treat `const ...` as a const closure if it's followed by the *proper keyword*, and not a raw identifier. Additionally, this adds a large test that tests for all raw identifiers in all kinds of positions, including `const`, to prevent issues like this one from occurring again. --- compiler/rustc_parse/src/parser/mod.rs | 6 +- compiler/rustc_span/src/symbol.rs | 2 + tests/ui/parser/raw/raw-idents.rs | 158 +++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 tests/ui/parser/raw/raw-idents.rs diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ea464fc8ebbb..1de452dcf396 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -754,9 +754,9 @@ impl<'a> Parser<'a> { self.is_keyword_ahead(0, &[kw::Const]) && self.look_ahead(1, |t| match &t.kind { // async closures do not work with const closures, so we do not parse that here. - token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => { - true - } + token::Ident(kw::Move | kw::Static, IdentIsRaw::No) + | token::OrOr + | token::BinOp(token::Or) => true, _ => false, }) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 62723e385cf6..757450cc0685 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -104,6 +104,8 @@ symbols! { Gen: "gen", // >= 2024 Edition only Try: "try", // >= 2018 Edition only + // NOTE: When adding new keywords, consider adding them to the ui/parser/raw/raw-idents.rs test. + // "Lifetime keywords": regular keywords with a leading `'`. // Matching predicates: `is_any_keyword` UnderscoreLifetime: "'_", diff --git a/tests/ui/parser/raw/raw-idents.rs b/tests/ui/parser/raw/raw-idents.rs new file mode 100644 index 000000000000..93015ee6c494 --- /dev/null +++ b/tests/ui/parser/raw/raw-idents.rs @@ -0,0 +1,158 @@ +//@ check-pass +//@ revisions:e2015 e2018 e2021 e2024 +//@[e2015] edition:2015 +//@[e2018] edition:2018 +//@[e2021] edition:2021 +//@[e2024] edition:2024 + +// Ensure that all (usable as identifier) keywords work as raw identifiers in all positions. +// This was motivated by issue #137128, where `r#move`/`r#static`` did not work as `const` names +// due to a parser check not acounting for raw identifiers. + +#![crate_type = "lib"] +#![allow(dead_code, nonstandard_style)] + +// NOTE: It is vital to only use a `tt` fragment to avoid confusing +// the parser with nonterminals that can mask bugs. + +macro_rules! tests { + ($kw:tt) => { + mod $kw { + mod const_item { + const $kw: () = (); + } + mod static_item { + static $kw: () = (); + } + mod fn_item { + fn $kw() {} + } + mod mod_and_use_item { + mod $kw { + use super::$kw; + } + } + mod ty_alias_item { + type $kw = (); + } + mod struct_item { + struct $kw { $kw: () } + } + mod enum_item { + enum $kw { $kw } + } + mod union_item { + union $kw { $kw: () } + } + mod trait_item { + trait $kw { + fn $kw() {} + } + } + mod generics_and_impl { + struct A<$kw>($kw); + enum B<$kw> { A($kw) } + trait Tr<$kw> { + type $kw; + } + + impl<$kw> Tr<$kw> for A<$kw> { + type $kw = (); + } + impl<$kw> B<$kw> {} + } + mod extern_crate { + #[cfg(any())] + extern crate $kw; + } + mod body { + fn expr() { + let $kw = 0; + let b = $kw; + assert_eq!($kw, b); + type $kw = (); + let $kw: $kw = (); + let _ = $kw as $kw; + } + fn pat_const() { + const $kw: u8 = 0; + + // Ensure that $kw actually matches the constant. + #[forbid(unreachable_patterns)] + match 1 { + $kw => {} + _ => {} + } + } + fn pat_binding() { + match 1 { + $kw => {} + _ => {} + } + } + } + } + }; +} + +tests!(r#break); +tests!(r#const); +tests!(r#continue); +tests!(r#else); +tests!(r#enum); +tests!(r#extern); +tests!(r#false); +tests!(r#fn); +tests!(r#for); +tests!(r#if); +tests!(r#impl); +tests!(r#in); +tests!(r#let); +tests!(r#loop); +tests!(r#match); +tests!(r#mod); +tests!(r#move); +tests!(r#mut); +tests!(r#pub); +tests!(r#ref); +tests!(r#return); +tests!(r#static); +tests!(r#struct); +tests!(r#trait); +tests!(r#true); +tests!(r#type); +tests!(r#unsafe); +tests!(r#use); +tests!(r#where); +tests!(r#while); +tests!(r#abstract); +tests!(r#become); +tests!(r#box); +tests!(r#do); +tests!(r#final); +tests!(r#macro); +tests!(r#override); +tests!(r#priv); +tests!(r#typeof); +tests!(r#unsized); +tests!(r#virtual); +tests!(r#yield); +tests!(r#async); +tests!(r#await); +tests!(r#dyn); +tests!(r#gen); +tests!(r#try); + +// Weak keywords: +tests!(auto); +tests!(builtin); +tests!(catch); +tests!(default); +tests!(macro_rules); +tests!(raw); +tests!(reuse); +tests!(contract_ensures); +tests!(contract_requires); +tests!(safe); +tests!(union); +tests!(yeet); From 4a4207a65073dcf1148c298d76e2fda11974284c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Feb 2025 17:56:22 +0100 Subject: [PATCH 080/158] use add-core-stubs / minicore for a few more tests --- tests/assembly/asm/aarch64-types.rs | 8 --- tests/auxiliary/minicore.rs | 22 ++++++- tests/codegen/abi-win64-zst.rs | 7 ++- .../codegen/align-byval-alignment-mismatch.rs | 11 ++-- tests/codegen/align-byval-vector.rs | 11 ++-- tests/codegen/align-byval.rs | 14 ++--- tests/ui/abi/c-zst.aarch64-darwin.stderr | 2 +- tests/ui/abi/c-zst.powerpc-linux.stderr | 2 +- tests/ui/abi/c-zst.rs | 7 ++- tests/ui/abi/c-zst.s390x-linux.stderr | 2 +- tests/ui/abi/c-zst.sparc64-linux.stderr | 2 +- tests/ui/abi/c-zst.x86_64-linux.stderr | 2 +- .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 2 +- tests/ui/simd-abi-checks-empty-list.rs | 9 ++- tests/ui/simd-abi-checks-empty-list.stderr | 4 +- tests/ui/simd-abi-checks-s390x.rs | 15 ++--- tests/ui/simd-abi-checks-s390x.z10.stderr | 62 +++++++++---------- ...simd-abi-checks-s390x.z13_no_vector.stderr | 62 +++++++++---------- ...imd-abi-checks-s390x.z13_soft_float.stderr | 62 +++++++++---------- tests/ui/sse-abi-checks.rs | 8 +-- tests/ui/sse-abi-checks.stderr | 4 +- 21 files changed, 154 insertions(+), 164 deletions(-) diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 439385b14b05..8e4e08503253 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -11,8 +11,6 @@ #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] -// FIXME(f16_f128): Only needed for FIXME in check! and check_reg! -#![feature(auto_traits, lang_items)] extern crate minicore; use minicore::*; @@ -63,12 +61,6 @@ impl Copy for f16x8 {} impl Copy for f32x4 {} impl Copy for f64x2 {} -// FIXME(f16_f128): Only needed for FIXME in check! and check_reg! -#[lang = "freeze"] -unsafe auto trait Freeze {} -#[lang = "unpin"] -auto trait Unpin {} - extern "C" { fn extern_func(); static extern_static: u8; diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 1c5f9eeba3c4..0aa8b6b8f891 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -14,9 +14,20 @@ //! . // ignore-tidy-linelength -#![feature(no_core, lang_items, rustc_attrs, decl_macro, naked_functions, f16, f128)] +#![feature( + no_core, + lang_items, + auto_traits, + freeze_impls, + negative_impls, + rustc_attrs, + decl_macro, + naked_functions, + f16, + f128, + asm_experimental_arch +)] #![allow(unused, improper_ctypes_definitions, internal_features)] -#![feature(asm_experimental_arch)] #![no_std] #![no_core] @@ -42,6 +53,12 @@ pub trait Copy: Sized {} #[lang = "bikeshed_guaranteed_no_drop"] pub trait BikeshedGuaranteedNoDrop {} +#[lang = "freeze"] +pub unsafe auto trait Freeze {} + +#[lang = "unpin"] +pub auto trait Unpin {} + impl_marker_trait!( Copy => [ bool, char, @@ -83,6 +100,7 @@ impl Copy for ManuallyDrop {} pub struct UnsafeCell { value: T, } +impl !Freeze for UnsafeCell {} #[rustc_builtin_macro] pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { diff --git a/tests/codegen/abi-win64-zst.rs b/tests/codegen/abi-win64-zst.rs index dd3618981442..825a5c1b09c1 100644 --- a/tests/codegen/abi-win64-zst.rs +++ b/tests/codegen/abi-win64-zst.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Z merge-functions=disabled +//@ add-core-stubs //@ revisions: windows-gnu //@[windows-gnu] compile-flags: --target x86_64-pc-windows-gnu @@ -13,12 +14,12 @@ //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 -#![feature(no_core, lang_items, rustc_attrs, abi_vectorcall)] +#![feature(no_core, rustc_attrs, abi_vectorcall)] #![no_core] #![crate_type = "lib"] -#[lang = "sized"] -trait Sized {} +extern crate minicore; +use minicore::*; // Make sure the argument is always passed when explicitly requesting a Windows ABI. // Our goal here is to match clang: . diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs index 835cc7393e51..46cfb2972df3 100644 --- a/tests/codegen/align-byval-alignment-mismatch.rs +++ b/tests/codegen/align-byval-alignment-mismatch.rs @@ -1,4 +1,5 @@ // ignore-tidy-linelength +//@ add-core-stubs //@ revisions:i686-linux x86_64-linux //@[i686-linux] compile-flags: --target i686-unknown-linux-gnu -C panic=abort @@ -16,18 +17,14 @@ // on i686-unknown-linux-gnu, since the alignment needs to be increased, and should codegen // to a direct call on x86_64-unknown-linux-gnu, where byval alignment matches Rust alignment. -#![feature(no_core, lang_items)] +#![feature(no_core)] #![crate_type = "lib"] #![no_std] #![no_core] #![allow(non_camel_case_types)] -#[lang = "sized"] -trait Sized {} -#[lang = "freeze"] -trait Freeze {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; // This type has align 1 in Rust, but as a byval argument on i686-linux, it will have align 4. #[repr(C)] diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs index 60d49f930819..c33b41a7bbee 100644 --- a/tests/codegen/align-byval-vector.rs +++ b/tests/codegen/align-byval-vector.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions:x86-linux x86-darwin //@[x86-linux] compile-flags: --target i686-unknown-linux-gnu @@ -7,18 +8,14 @@ // Tests that aggregates containing vector types get their alignment increased to 16 on Darwin. -#![feature(no_core, lang_items, repr_simd, simd_ffi)] +#![feature(no_core, repr_simd, simd_ffi)] #![crate_type = "lib"] #![no_std] #![no_core] #![allow(non_camel_case_types)] -#[lang = "sized"] -trait Sized {} -#[lang = "freeze"] -trait Freeze {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; #[repr(simd)] pub struct i32x4([i32; 4]); diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index b057147ab13e..75dabd74a79c 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -1,4 +1,5 @@ // ignore-tidy-linelength +//@ add-core-stubs //@ revisions:m68k x86_64-linux x86_64-windows i686-linux i686-windows //@[m68k] compile-flags: --target m68k-unknown-linux-gnu @@ -16,20 +17,13 @@ // The only targets that use `byval` are m68k, x86-64, and x86. // Note also that Windows mandates a by-ref ABI here, so it does not use byval. -#![feature(no_core, lang_items)] +#![feature(no_core)] #![crate_type = "lib"] #![no_std] #![no_core] -#[lang = "sized"] -trait Sized {} -#[lang = "freeze"] -trait Freeze {} -#[lang = "copy"] -trait Copy {} - -impl Copy for i32 {} -impl Copy for i64 {} +extern crate minicore; +use minicore::*; // This struct can be represented as a pair, so it exercises the OperandValue::Pair // codepath in `codegen_argument`. diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index d9742612bcfd..c8f7d0a517c4 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -60,7 +60,7 @@ error: fn_abi_of(pass_zst) = FnAbi { conv: C, can_unwind: false, } - --> $DIR/c-zst.rs:63:1 + --> $DIR/c-zst.rs:64:1 | LL | extern "C" fn pass_zst(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 0e98b5f806bc..1015f7d88988 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -71,7 +71,7 @@ error: fn_abi_of(pass_zst) = FnAbi { conv: C, can_unwind: false, } - --> $DIR/c-zst.rs:63:1 + --> $DIR/c-zst.rs:64:1 | LL | extern "C" fn pass_zst(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/c-zst.rs b/tests/ui/abi/c-zst.rs index 6b299ffadb7b..c1dac41f876a 100644 --- a/tests/ui/abi/c-zst.rs +++ b/tests/ui/abi/c-zst.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ normalize-stderr: "(abi|pref|unadjusted_abi_align): Align\([1-8] bytes\)" -> "$1: $$SOME_ALIGN" /*! C doesn't have zero-sized types... except it does. @@ -52,12 +53,12 @@ extern "C" fn(i32, (), i32); //@[x86_64-pc-windows-gnu] needs-llvm-components: x86 -#![feature(lang_items, no_core, rustc_attrs)] +#![feature(no_core, rustc_attrs)] #![no_core] #![crate_type = "lib"] -#[lang = "sized"] -trait Sized {} +extern crate minicore; +use minicore::*; #[rustc_abi(debug)] extern "C" fn pass_zst(_: ()) {} //~ ERROR: fn_abi diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 0e98b5f806bc..1015f7d88988 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -71,7 +71,7 @@ error: fn_abi_of(pass_zst) = FnAbi { conv: C, can_unwind: false, } - --> $DIR/c-zst.rs:63:1 + --> $DIR/c-zst.rs:64:1 | LL | extern "C" fn pass_zst(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 0e98b5f806bc..1015f7d88988 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -71,7 +71,7 @@ error: fn_abi_of(pass_zst) = FnAbi { conv: C, can_unwind: false, } - --> $DIR/c-zst.rs:63:1 + --> $DIR/c-zst.rs:64:1 | LL | extern "C" fn pass_zst(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index d9742612bcfd..c8f7d0a517c4 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -60,7 +60,7 @@ error: fn_abi_of(pass_zst) = FnAbi { conv: C, can_unwind: false, } - --> $DIR/c-zst.rs:63:1 + --> $DIR/c-zst.rs:64:1 | LL | extern "C" fn pass_zst(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 0e98b5f806bc..1015f7d88988 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -71,7 +71,7 @@ error: fn_abi_of(pass_zst) = FnAbi { conv: C, can_unwind: false, } - --> $DIR/c-zst.rs:63:1 + --> $DIR/c-zst.rs:64:1 | LL | extern "C" fn pass_zst(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd-abi-checks-empty-list.rs b/tests/ui/simd-abi-checks-empty-list.rs index fd4957b5b939..ca0889364fc3 100644 --- a/tests/ui/simd-abi-checks-empty-list.rs +++ b/tests/ui/simd-abi-checks-empty-list.rs @@ -1,15 +1,14 @@ +//@ add-core-stubs //@ needs-llvm-components: sparc //@ compile-flags: --target=sparc-unknown-none-elf --crate-type=rlib //@ build-pass //@ ignore-pass (test emits codegen-time warnings) #![no_core] -#![feature(no_core, lang_items, repr_simd)] +#![feature(no_core, repr_simd)] #![allow(improper_ctypes_definitions)] -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; #[repr(simd)] pub struct SimdVec([i32; 4]); diff --git a/tests/ui/simd-abi-checks-empty-list.stderr b/tests/ui/simd-abi-checks-empty-list.stderr index 91c61884fd02..111dda42f33f 100644 --- a/tests/ui/simd-abi-checks-empty-list.stderr +++ b/tests/ui/simd-abi-checks-empty-list.stderr @@ -1,5 +1,5 @@ warning: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI - --> $DIR/simd-abi-checks-empty-list.rs:17:1 + --> $DIR/simd-abi-checks-empty-list.rs:16:1 | LL | pub extern "C" fn pass_by_vec(_: SimdVec) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -12,7 +12,7 @@ warning: 1 warning emitted Future incompatibility report: Future breakage diagnostic: warning: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI - --> $DIR/simd-abi-checks-empty-list.rs:17:1 + --> $DIR/simd-abi-checks-empty-list.rs:16:1 | LL | pub extern "C" fn pass_by_vec(_: SimdVec) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here diff --git a/tests/ui/simd-abi-checks-s390x.rs b/tests/ui/simd-abi-checks-s390x.rs index 7e408f665614..424ac00edcfc 100644 --- a/tests/ui/simd-abi-checks-s390x.rs +++ b/tests/ui/simd-abi-checks-s390x.rs @@ -1,3 +1,4 @@ +//@ add-core-stubs //@ revisions: z10 z13_no_vector z13_soft_float //@ build-fail //@[z10] compile-flags: --target s390x-unknown-linux-gnu @@ -8,20 +9,14 @@ //@[z13_soft_float] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector,+soft-float //@[z13_soft_float] needs-llvm-components: systemz -#![feature(no_core, lang_items, repr_simd, s390x_target_feature)] +#![feature(no_core, repr_simd, s390x_target_feature)] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types, improper_ctypes_definitions)] #![deny(abi_unsupported_vector_types)] -#[lang = "sized"] -pub trait Sized {} -#[lang = "copy"] -pub trait Copy {} -#[lang = "freeze"] -pub trait Freeze {} - -impl Copy for [T; N] {} +extern crate minicore; +use minicore::*; #[repr(simd)] pub struct i8x8([i8; 8]); @@ -34,8 +29,6 @@ pub struct Wrapper(T); #[repr(transparent)] pub struct TransparentWrapper(T); -impl Copy for i8 {} -impl Copy for i64 {} impl Copy for i8x8 {} impl Copy for i8x16 {} impl Copy for i8x32 {} diff --git a/tests/ui/simd-abi-checks-s390x.z10.stderr b/tests/ui/simd-abi-checks-s390x.z10.stderr index ab97299e84a7..d2f7abb7c322 100644 --- a/tests/ui/simd-abi-checks-s390x.z10.stderr +++ b/tests/ui/simd-abi-checks-s390x.z10.stderr @@ -1,5 +1,5 @@ error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 + --> $DIR/simd-abi-checks-s390x.rs:39:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -8,13 +8,13 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:52:1 + --> $DIR/simd-abi-checks-s390x.rs:45:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -24,7 +24,7 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -36,7 +36,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:107:1 + --> $DIR/simd-abi-checks-s390x.rs:100:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -48,7 +48,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:123:1 + --> $DIR/simd-abi-checks-s390x.rs:116:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -58,7 +58,7 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:129:1 + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -68,7 +68,7 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:141:1 + --> $DIR/simd-abi-checks-s390x.rs:134:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -78,7 +78,7 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:147:1 + --> $DIR/simd-abi-checks-s390x.rs:140:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -88,7 +88,7 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:159:1 + --> $DIR/simd-abi-checks-s390x.rs:152:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -98,7 +98,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:165:1 + --> $DIR/simd-abi-checks-s390x.rs:158:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -111,7 +111,7 @@ error: aborting due to 10 previous errors Future incompatibility report: Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 + --> $DIR/simd-abi-checks-s390x.rs:39:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -120,14 +120,14 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:52:1 + --> $DIR/simd-abi-checks-s390x.rs:45:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -136,14 +136,14 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -154,14 +154,14 @@ LL | | ) -> TransparentWrapper { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:107:1 + --> $DIR/simd-abi-checks-s390x.rs:100:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -172,14 +172,14 @@ LL | | ) -> TransparentWrapper { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:123:1 + --> $DIR/simd-abi-checks-s390x.rs:116:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -188,14 +188,14 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:129:1 + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -204,14 +204,14 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:141:1 + --> $DIR/simd-abi-checks-s390x.rs:134:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -220,14 +220,14 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:147:1 + --> $DIR/simd-abi-checks-s390x.rs:140:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -236,14 +236,14 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:159:1 + --> $DIR/simd-abi-checks-s390x.rs:152:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -252,14 +252,14 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:165:1 + --> $DIR/simd-abi-checks-s390x.rs:158:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -268,7 +268,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr b/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr index ab97299e84a7..d2f7abb7c322 100644 --- a/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr +++ b/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr @@ -1,5 +1,5 @@ error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 + --> $DIR/simd-abi-checks-s390x.rs:39:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -8,13 +8,13 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:52:1 + --> $DIR/simd-abi-checks-s390x.rs:45:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -24,7 +24,7 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -36,7 +36,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:107:1 + --> $DIR/simd-abi-checks-s390x.rs:100:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -48,7 +48,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:123:1 + --> $DIR/simd-abi-checks-s390x.rs:116:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -58,7 +58,7 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:129:1 + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -68,7 +68,7 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:141:1 + --> $DIR/simd-abi-checks-s390x.rs:134:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -78,7 +78,7 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:147:1 + --> $DIR/simd-abi-checks-s390x.rs:140:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -88,7 +88,7 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:159:1 + --> $DIR/simd-abi-checks-s390x.rs:152:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -98,7 +98,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:165:1 + --> $DIR/simd-abi-checks-s390x.rs:158:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -111,7 +111,7 @@ error: aborting due to 10 previous errors Future incompatibility report: Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 + --> $DIR/simd-abi-checks-s390x.rs:39:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -120,14 +120,14 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:52:1 + --> $DIR/simd-abi-checks-s390x.rs:45:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -136,14 +136,14 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -154,14 +154,14 @@ LL | | ) -> TransparentWrapper { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:107:1 + --> $DIR/simd-abi-checks-s390x.rs:100:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -172,14 +172,14 @@ LL | | ) -> TransparentWrapper { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:123:1 + --> $DIR/simd-abi-checks-s390x.rs:116:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -188,14 +188,14 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:129:1 + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -204,14 +204,14 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:141:1 + --> $DIR/simd-abi-checks-s390x.rs:134:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -220,14 +220,14 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:147:1 + --> $DIR/simd-abi-checks-s390x.rs:140:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -236,14 +236,14 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:159:1 + --> $DIR/simd-abi-checks-s390x.rs:152:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -252,14 +252,14 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:165:1 + --> $DIR/simd-abi-checks-s390x.rs:158:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -268,7 +268,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr index ab97299e84a7..d2f7abb7c322 100644 --- a/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr +++ b/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr @@ -1,5 +1,5 @@ error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 + --> $DIR/simd-abi-checks-s390x.rs:39:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -8,13 +8,13 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:52:1 + --> $DIR/simd-abi-checks-s390x.rs:45:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -24,7 +24,7 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -36,7 +36,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:107:1 + --> $DIR/simd-abi-checks-s390x.rs:100:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -48,7 +48,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:123:1 + --> $DIR/simd-abi-checks-s390x.rs:116:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -58,7 +58,7 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:129:1 + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -68,7 +68,7 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:141:1 + --> $DIR/simd-abi-checks-s390x.rs:134:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -78,7 +78,7 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:147:1 + --> $DIR/simd-abi-checks-s390x.rs:140:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -88,7 +88,7 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:159:1 + --> $DIR/simd-abi-checks-s390x.rs:152:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -98,7 +98,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:165:1 + --> $DIR/simd-abi-checks-s390x.rs:158:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -111,7 +111,7 @@ error: aborting due to 10 previous errors Future incompatibility report: Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 + --> $DIR/simd-abi-checks-s390x.rs:39:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -120,14 +120,14 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:52:1 + --> $DIR/simd-abi-checks-s390x.rs:45:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -136,14 +136,14 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -154,14 +154,14 @@ LL | | ) -> TransparentWrapper { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:107:1 + --> $DIR/simd-abi-checks-s390x.rs:100:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -172,14 +172,14 @@ LL | | ) -> TransparentWrapper { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:123:1 + --> $DIR/simd-abi-checks-s390x.rs:116:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -188,14 +188,14 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:129:1 + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -204,14 +204,14 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:141:1 + --> $DIR/simd-abi-checks-s390x.rs:134:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -220,14 +220,14 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:147:1 + --> $DIR/simd-abi-checks-s390x.rs:140:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -236,14 +236,14 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:159:1 + --> $DIR/simd-abi-checks-s390x.rs:152:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -252,14 +252,14 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:165:1 + --> $DIR/simd-abi-checks-s390x.rs:158:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -268,7 +268,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) = note: for more information, see issue #116558 = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) note: the lint level is defined here - --> $DIR/simd-abi-checks-s390x.rs:15:9 + --> $DIR/simd-abi-checks-s390x.rs:16:9 | LL | #![deny(abi_unsupported_vector_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-abi-checks.rs index 3c9fe1f0ddbd..cb3128a890f7 100644 --- a/tests/ui/sse-abi-checks.rs +++ b/tests/ui/sse-abi-checks.rs @@ -1,5 +1,6 @@ //! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled //! on a target, but disabled in this file via a `-C` flag. +//@ add-core-stubs //@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu -C target-feature=-sse,-sse2 //@ build-pass //@ ignore-pass (test emits codegen-time warnings) @@ -8,11 +9,8 @@ #![no_core] #![allow(improper_ctypes_definitions)] -#[lang = "sized"] -trait Sized {} - -#[lang = "copy"] -trait Copy {} +extern crate minicore; +use minicore::*; #[repr(simd)] pub struct SseVector([i64; 2]); diff --git a/tests/ui/sse-abi-checks.stderr b/tests/ui/sse-abi-checks.stderr index 712322a5848b..9944aa093b4e 100644 --- a/tests/ui/sse-abi-checks.stderr +++ b/tests/ui/sse-abi-checks.stderr @@ -1,5 +1,5 @@ warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled - --> $DIR/sse-abi-checks.rs:21:1 + --> $DIR/sse-abi-checks.rs:19:1 | LL | pub unsafe extern "C" fn f(_: SseVector) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -13,7 +13,7 @@ warning: 1 warning emitted Future incompatibility report: Future breakage diagnostic: warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled - --> $DIR/sse-abi-checks.rs:21:1 + --> $DIR/sse-abi-checks.rs:19:1 | LL | pub unsafe extern "C" fn f(_: SseVector) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here From 2e7158b4587a42043c88ab653b305c378b602b76 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 10 Feb 2025 11:33:02 +0200 Subject: [PATCH 081/158] Refactor path lowering And add a new diagnostic for non-`Fn` parenthesized generic args. Path lowering started to look like a mess, with each function carrying additional parameters for the diagnostic callback (since paths can occur both in type and in expression/pattern position, and their diagnostic handling is different) and the segment index, for the diagnostics report. So I refactored it from stateless functions on `TyLoweringContext` into stateful struct, `PathLoweringContext`, that tracks the process of lowering a path from resolution til assoc types selection. --- .../rust-analyzer/crates/hir-def/src/data.rs | 4 + .../rust-analyzer/crates/hir-def/src/path.rs | 10 +- .../crates/hir-def/src/resolver.rs | 3 +- .../crates/hir-expand/src/name.rs | 4 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 52 +- .../crates/hir-ty/src/infer/diagnostics.rs | 76 +- .../crates/hir-ty/src/infer/pat.rs | 14 +- .../crates/hir-ty/src/infer/path.rs | 150 +-- .../rust-analyzer/crates/hir-ty/src/lower.rs | 975 ++---------------- .../crates/hir-ty/src/lower/diagnostics.rs | 1 + .../crates/hir-ty/src/lower/path.rs | 911 ++++++++++++++++ .../crates/hir/src/diagnostics.rs | 16 +- ...nthesized_generic_args_without_fn_trait.rs | 59 ++ .../crates/ide-diagnostics/src/lib.rs | 8 +- .../test_data/highlight_general.html | 15 +- .../ide/src/syntax_highlighting/tests.rs | 15 +- .../crates/intern/src/symbol/symbols.rs | 33 +- .../crates/test-utils/src/minicore.rs | 6 + 18 files changed, 1220 insertions(+), 1132 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs create mode 100644 src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index c5bbd4edba9e..bec662787728 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -250,6 +250,7 @@ bitflags::bitflags! { const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 3; const SKIP_ARRAY_DURING_METHOD_DISPATCH = 1 << 4; const SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH = 1 << 5; + const RUSTC_PAREN_SUGAR = 1 << 6; } } @@ -294,6 +295,9 @@ impl TraitData { if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } + if attrs.by_key(&sym::rustc_paren_sugar).exists() { + flags |= TraitFlags::RUSTC_PAREN_SUGAR; + } let mut skip_array_during_method_dispatch = attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs index e59c37104dd6..e6c2504d07a5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs @@ -173,10 +173,7 @@ impl Path { segments: path.mod_path().segments(), generic_args: Some(path.generic_args()), }, - Path::LangItem(_, seg) => PathSegments { - segments: seg.as_ref().map_or(&[], |seg| std::slice::from_ref(seg)), - generic_args: None, - }, + Path::LangItem(_, seg) => PathSegments { segments: seg.as_slice(), generic_args: None }, } } @@ -240,6 +237,11 @@ pub struct PathSegment<'a> { pub args_and_bindings: Option<&'a GenericArgs>, } +impl PathSegment<'_> { + pub const MISSING: PathSegment<'static> = + PathSegment { name: &Name::missing(), args_and_bindings: None }; +} + #[derive(Debug, Clone, Copy)] pub struct PathSegments<'a> { segments: &'a [Name], diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 7e13ae2f7a1b..9dfb6e3cc4b7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -327,8 +327,9 @@ impl Resolver { | LangItemTarget::ImplDef(_) | LangItemTarget::Static(_) => return None, }; + // Remaining segments start from 0 because lang paths have no segments other than the remaining. return Some(( - ResolveValueResult::Partial(type_ns, 1, None), + ResolveValueResult::Partial(type_ns, 0, None), ResolvePathResultPrefixInfo::default(), )); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 21e5fb5ef9e1..0758bd4515ef 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -142,8 +142,8 @@ impl Name { /// Ideally, we want a `gensym` semantics for missing names -- each missing /// name is equal only to itself. It's not clear how to implement this in /// salsa though, so we punt on that bit for a moment. - pub fn missing() -> Name { - Name { symbol: sym::MISSING_NAME.clone(), ctx: () } + pub const fn missing() -> Name { + Name { symbol: sym::consts::MISSING_NAME, ctx: () } } /// Returns true if this is a fake name for things missing in the source code. See diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index cf6905a0b28f..3ac2d90468f4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -16,7 +16,7 @@ pub(crate) mod cast; pub(crate) mod closure; mod coerce; -mod diagnostics; +pub(crate) mod diagnostics; mod expr; mod mutability; mod pat; @@ -1480,21 +1480,22 @@ impl<'a> InferenceContext<'a> { &self.diagnostics, InferenceTyDiagnosticSource::Body, ); + let mut path_ctx = ctx.at_path(path, node); let (resolution, unresolved) = if value_ns { - let Some(res) = ctx.resolve_path_in_value_ns(path, node, HygieneId::ROOT) else { + let Some(res) = path_ctx.resolve_path_in_value_ns(HygieneId::ROOT) else { return (self.err_ty(), None); }; match res { ResolveValueResult::ValueNs(value, _) => match value { ValueNs::EnumVariantId(var) => { - let substs = ctx.substs_from_path(path, var.into(), true); + let substs = path_ctx.substs_from_path(var.into(), true); drop(ctx); let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); return (ty, Some(var.into())); } ValueNs::StructId(strukt) => { - let substs = ctx.substs_from_path(path, strukt.into(), true); + let substs = path_ctx.substs_from_path(strukt.into(), true); drop(ctx); let ty = self.db.ty(strukt.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); @@ -1509,7 +1510,7 @@ impl<'a> InferenceContext<'a> { ResolveValueResult::Partial(typens, unresolved, _) => (typens, Some(unresolved)), } } else { - match ctx.resolve_path_in_type_ns(path, node) { + match path_ctx.resolve_path_in_type_ns() { Some((it, idx)) => (it, idx), None => return (self.err_ty(), None), } @@ -1520,21 +1521,21 @@ impl<'a> InferenceContext<'a> { }; return match resolution { TypeNs::AdtId(AdtId::StructId(strukt)) => { - let substs = ctx.substs_from_path(path, strukt.into(), true); + let substs = path_ctx.substs_from_path(strukt.into(), true); drop(ctx); let ty = self.db.ty(strukt.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) } TypeNs::AdtId(AdtId::UnionId(u)) => { - let substs = ctx.substs_from_path(path, u.into(), true); + let substs = path_ctx.substs_from_path(u.into(), true); drop(ctx); let ty = self.db.ty(u.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); forbid_unresolved_segments((ty, Some(u.into())), unresolved) } TypeNs::EnumVariantId(var) => { - let substs = ctx.substs_from_path(path, var.into(), true); + let substs = path_ctx.substs_from_path(var.into(), true); drop(ctx); let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); @@ -1545,31 +1546,32 @@ impl<'a> InferenceContext<'a> { let substs = generics.placeholder_subst(self.db); let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs); - let Some(mut remaining_idx) = unresolved else { + let Some(remaining_idx) = unresolved else { drop(ctx); return self.resolve_variant_on_alias(ty, None, mod_path); }; let mut remaining_segments = path.segments().skip(remaining_idx); + if remaining_segments.len() >= 2 { + path_ctx.ignore_last_segment(); + } + // We need to try resolving unresolved segments one by one because each may resolve // to a projection, which `TyLoweringContext` cannot handle on its own. let mut tried_resolving_once = false; - while !remaining_segments.is_empty() { - let resolved_segment = path.segments().get(remaining_idx - 1).unwrap(); - let current_segment = remaining_segments.take(1); - + while let Some(current_segment) = remaining_segments.first() { // If we can resolve to an enum variant, it takes priority over associated type // of the same name. if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { let enum_data = self.db.enum_data(id); - let name = current_segment.first().unwrap().name; - if let Some(variant) = enum_data.variant(name) { + if let Some(variant) = enum_data.variant(current_segment.name) { return if remaining_segments.len() == 1 { (ty, Some(variant.into())) } else { // We still have unresolved paths, but enum variants never have // associated types! + // FIXME: Report an error. (self.err_ty(), None) }; } @@ -1578,23 +1580,13 @@ impl<'a> InferenceContext<'a> { if tried_resolving_once { // FIXME: with `inherent_associated_types` this is allowed, but our `lower_partly_resolved_path()` // will need to be updated to err at the correct segment. - // - // We need to stop here because otherwise the segment index passed to `lower_partly_resolved_path()` - // will be incorrect, and that can mess up error reporting. break; } // `lower_partly_resolved_path()` returns `None` as type namespace unless // `remaining_segments` is empty, which is never the case here. We don't know // which namespace the new `ty` is in until normalized anyway. - (ty, _) = ctx.lower_partly_resolved_path( - node, - resolution, - resolved_segment, - current_segment, - (remaining_idx - 1) as u32, - false, - ); + (ty, _) = path_ctx.lower_partly_resolved_path(resolution, false); tried_resolving_once = true; ty = self.table.insert_type_vars(ty); @@ -1604,8 +1596,6 @@ impl<'a> InferenceContext<'a> { return (self.err_ty(), None); } - // FIXME(inherent_associated_types): update `resolution` based on `ty` here. - remaining_idx += 1; remaining_segments = remaining_segments.skip(1); } drop(ctx); @@ -1621,11 +1611,7 @@ impl<'a> InferenceContext<'a> { (ty, variant) } TypeNs::TypeAliasId(it) => { - let resolved_seg = match unresolved { - None => path.segments().last().unwrap(), - Some(n) => path.segments().get(path.segments().len() - n - 1).unwrap(), - }; - let substs = ctx.substs_from_path_segment(resolved_seg, it.into(), true, None); + let substs = path_ctx.substs_from_path_segment(it.into(), true, None); drop(ctx); let ty = self.db.ty(it.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs index b85378531ad6..8c0446953a6b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs @@ -5,16 +5,13 @@ use std::cell::RefCell; use std::ops::{Deref, DerefMut}; -use hir_def::expr_store::HygieneId; -use hir_def::hir::ExprOrPatId; -use hir_def::path::{Path, PathSegment, PathSegments}; -use hir_def::resolver::{ResolveValueResult, Resolver, TypeNs}; -use hir_def::type_ref::TypesMap; -use hir_def::TypeOwnerId; +use either::Either; +use hir_def::{hir::ExprOrPatId, path::Path, resolver::Resolver, type_ref::TypesMap, TypeOwnerId}; -use crate::db::HirDatabase; use crate::{ - InferenceDiagnostic, InferenceTyDiagnosticSource, Ty, TyLoweringContext, TyLoweringDiagnostic, + db::HirDatabase, + lower::path::{PathDiagnosticCallback, PathLoweringContext}, + InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringContext, TyLoweringDiagnostic, }; // Unfortunately, this struct needs to use interior mutability (but we encapsulate it) @@ -44,6 +41,11 @@ impl Diagnostics { } } +pub(crate) struct PathDiagnosticCallbackData<'a> { + node: ExprOrPatId, + diagnostics: &'a Diagnostics, +} + pub(super) struct InferenceTyLoweringContext<'a> { ctx: TyLoweringContext<'a>, diagnostics: &'a Diagnostics, @@ -51,6 +53,7 @@ pub(super) struct InferenceTyLoweringContext<'a> { } impl<'a> InferenceTyLoweringContext<'a> { + #[inline] pub(super) fn new( db: &'a dyn HirDatabase, resolver: &'a Resolver, @@ -62,65 +65,42 @@ impl<'a> InferenceTyLoweringContext<'a> { Self { ctx: TyLoweringContext::new(db, resolver, types_map, owner), diagnostics, source } } - pub(super) fn resolve_path_in_type_ns( - &mut self, - path: &Path, + #[inline] + pub(super) fn at_path<'b>( + &'b mut self, + path: &'b Path, node: ExprOrPatId, - ) -> Option<(TypeNs, Option)> { - let diagnostics = self.diagnostics; - self.ctx.resolve_path_in_type_ns(path, &mut |_, diag| { - diagnostics.push(InferenceDiagnostic::PathDiagnostic { node, diag }) - }) - } - - pub(super) fn resolve_path_in_value_ns( - &mut self, - path: &Path, - node: ExprOrPatId, - hygiene_id: HygieneId, - ) -> Option { - let diagnostics = self.diagnostics; - self.ctx.resolve_path_in_value_ns(path, hygiene_id, &mut |_, diag| { - diagnostics.push(InferenceDiagnostic::PathDiagnostic { node, diag }) - }) - } - - pub(super) fn lower_partly_resolved_path( - &mut self, - node: ExprOrPatId, - resolution: TypeNs, - resolved_segment: PathSegment<'_>, - remaining_segments: PathSegments<'_>, - resolved_segment_idx: u32, - infer_args: bool, - ) -> (Ty, Option) { - let diagnostics = self.diagnostics; - self.ctx.lower_partly_resolved_path( - resolution, - resolved_segment, - remaining_segments, - resolved_segment_idx, - infer_args, - &mut |_, diag| diagnostics.push(InferenceDiagnostic::PathDiagnostic { node, diag }), - ) + ) -> PathLoweringContext<'b, 'a> { + let on_diagnostic = PathDiagnosticCallback { + data: Either::Right(PathDiagnosticCallbackData { diagnostics: self.diagnostics, node }), + callback: |data, _, diag| { + let data = data.as_ref().right().unwrap(); + data.diagnostics + .push(InferenceDiagnostic::PathDiagnostic { node: data.node, diag }); + }, + }; + PathLoweringContext::new(&mut self.ctx, on_diagnostic, path) } } impl<'a> Deref for InferenceTyLoweringContext<'a> { type Target = TyLoweringContext<'a>; + #[inline] fn deref(&self) -> &Self::Target { &self.ctx } } impl DerefMut for InferenceTyLoweringContext<'_> { + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.ctx } } impl Drop for InferenceTyLoweringContext<'_> { + #[inline] fn drop(&mut self) { self.diagnostics .push_ty_diagnostics(self.source, std::mem::take(&mut self.ctx.diagnostics)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index 5ff22bea34de..d0fe00ecebdd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -564,9 +564,17 @@ impl InferenceContext<'_> { | Pat::Range { .. } | Pat::Slice { .. } => true, Pat::Or(pats) => pats.iter().all(|p| self.is_non_ref_pat(body, *p)), - Pat::Path(p) => { - let v = self.resolve_value_path_inner(p, pat.into()); - v.is_some_and(|x| !matches!(x.0, hir_def::resolver::ValueNs::ConstId(_))) + Pat::Path(path) => { + // A const is a reference pattern, but other value ns things aren't (see #16131). We don't need more than + // the hir-def resolver for this, because if there are segments left, this can only be an (associated) const. + // + // Do not use `TyLoweringContext`'s resolution, we want to ignore errors here (they'll be reported elsewhere). + let resolution = self.resolver.resolve_path_in_value_ns_fully( + self.db.upcast(), + path, + body.pat_path_hygiene(pat), + ); + resolution.is_some_and(|it| !matches!(it, hir_def::resolver::ValueNs::ConstId(_))) } Pat::ConstBlock(..) => false, Pat::Lit(expr) => !matches!( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 36ec60a7a2f6..3794912ee980 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -7,7 +7,6 @@ use hir_def::{ AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, }; use hir_expand::name::Name; -use intern::sym; use stdx::never; use crate::{ @@ -94,7 +93,14 @@ impl InferenceContext<'_> { return Some(ValuePathResolution::NonGeneric(ty)); }; - let substs = self.with_body_ty_lowering(|ctx| ctx.substs_from_path(path, value_def, true)); + let substs = self.with_body_ty_lowering(|ctx| { + let mut path_ctx = ctx.at_path(path, id); + let last_segment = path.segments().len().checked_sub(1); + if let Some(last_segment) = last_segment { + path_ctx.set_current_segment(last_segment) + } + path_ctx.substs_from_path(value_def, true) + }); let substs = substs.as_slice(Interner); if let ValueNs::EnumVariantId(_) = value { @@ -156,15 +162,16 @@ impl InferenceContext<'_> { &self.diagnostics, InferenceTyDiagnosticSource::Body, ); + let mut path_ctx = ctx.at_path(path, id); let (value, self_subst) = if let Some(type_ref) = path.type_anchor() { let last = path.segments().last()?; - let (ty, orig_ns) = ctx.lower_ty_ext(type_ref); + let (ty, orig_ns) = path_ctx.ty_ctx().lower_ty_ext(type_ref); let ty = self.table.insert_type_vars(ty); let ty = self.table.normalize_associated_types_in(ty); - let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); - let (ty, _) = ctx.lower_ty_relative_path(ty, orig_ns, remaining_segments_for_ty); + path_ctx.ignore_last_segment(); + let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns); drop(ctx); let ty = self.table.insert_type_vars(ty); let ty = self.table.normalize_associated_types_in(ty); @@ -172,14 +179,52 @@ impl InferenceContext<'_> { } else { let hygiene = self.body.expr_or_pat_path_hygiene(id); // FIXME: report error, unresolved first path segment - let value_or_partial = ctx.resolve_path_in_value_ns(path, id, hygiene)?; - drop(ctx); + let value_or_partial = path_ctx.resolve_path_in_value_ns(hygiene)?; match value_or_partial { - ResolveValueResult::ValueNs(it, _) => (it, None), - ResolveValueResult::Partial(def, remaining_index, _) => self - .resolve_assoc_item(id, def, path, remaining_index, id) - .map(|(it, substs)| (it, Some(substs)))?, + ResolveValueResult::ValueNs(it, _) => { + drop(ctx); + (it, None) + } + ResolveValueResult::Partial(def, remaining_index, _) => { + // there may be more intermediate segments between the resolved one and + // the end. Only the last segment needs to be resolved to a value; from + // the segments before that, we need to get either a type or a trait ref. + + let remaining_segments = path.segments().skip(remaining_index); + let is_before_last = remaining_segments.len() == 1; + let last_segment = remaining_segments + .last() + .expect("there should be at least one segment here"); + + let (resolution, substs) = match (def, is_before_last) { + (TypeNs::TraitId(trait_), true) => { + let self_ty = self.table.new_type_var(); + let trait_ref = + path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty); + drop(ctx); + self.resolve_trait_assoc_item(trait_ref, last_segment, id) + } + (def, _) => { + // Either we already have a type (e.g. `Vec::new`), or we have a + // trait but it's not the last segment, so the next segment + // should resolve to an associated type of that trait (e.g. `::Item::default`) + path_ctx.ignore_last_segment(); + let (ty, _) = path_ctx.lower_partly_resolved_path(def, true); + drop(ctx); + if ty.is_unknown() { + return None; + } + + let ty = self.insert_type_vars(ty); + let ty = self.normalize_associated_types_in(ty); + + self.resolve_ty_assoc_item(ty, last_segment.name, id) + } + }?; + (resolution, Some(substs)) + } } }; Some((value, self_subst)) @@ -212,89 +257,6 @@ impl InferenceContext<'_> { } } - fn resolve_assoc_item( - &mut self, - node: ExprOrPatId, - def: TypeNs, - path: &Path, - remaining_index: usize, - id: ExprOrPatId, - ) -> Option<(ValueNs, Substitution)> { - // there may be more intermediate segments between the resolved one and - // the end. Only the last segment needs to be resolved to a value; from - // the segments before that, we need to get either a type or a trait ref. - - let _d; - let (resolved_segment, remaining_segments) = match path { - Path::Normal { .. } | Path::BarePath(_) => { - assert!(remaining_index < path.segments().len()); - ( - path.segments().get(remaining_index - 1).unwrap(), - path.segments().skip(remaining_index), - ) - } - Path::LangItem(..) => ( - PathSegment { - name: { - _d = Name::new_symbol_root(sym::Unknown.clone()); - &_d - }, - args_and_bindings: None, - }, - path.segments(), - ), - }; - let is_before_last = remaining_segments.len() == 1; - - match (def, is_before_last) { - (TypeNs::TraitId(trait_), true) => { - let segment = - remaining_segments.last().expect("there should be at least one segment here"); - let self_ty = self.table.new_type_var(); - let trait_ref = self.with_body_ty_lowering(|ctx| { - ctx.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty) - }); - self.resolve_trait_assoc_item(trait_ref, segment, id) - } - (def, _) => { - // Either we already have a type (e.g. `Vec::new`), or we have a - // trait but it's not the last segment, so the next segment - // should resolve to an associated type of that trait (e.g. `::Item::default`) - let remaining_segments_for_ty = - remaining_segments.take(remaining_segments.len() - 1); - let mut ctx = TyLoweringContext::new( - self.db, - &self.resolver, - &self.body.types, - self.owner.into(), - &self.diagnostics, - InferenceTyDiagnosticSource::Body, - ); - let (ty, _) = ctx.lower_partly_resolved_path( - node, - def, - resolved_segment, - remaining_segments_for_ty, - (remaining_index - 1) as u32, - true, - ); - drop(ctx); - if ty.is_unknown() { - return None; - } - - let ty = self.insert_type_vars(ty); - let ty = self.normalize_associated_types_in(ty); - - let segment = - remaining_segments.last().expect("there should be at least one segment here"); - - self.resolve_ty_assoc_item(ty, segment.name, id) - } - } - } - fn resolve_trait_assoc_item( &mut self, trait_ref: TraitRef, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 595929a8f41b..af73b5ed9a7b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -6,6 +6,7 @@ //! //! This usually involves resolving names, collecting generic arguments etc. pub(crate) mod diagnostics; +pub(crate) mod path; use std::{ cell::OnceCell, @@ -26,29 +27,26 @@ use hir_def::{ builtin_type::BuiltinType, data::{adt::StructKind, TraitFlags}, expander::Expander, - expr_store::HygieneId, generics::{ GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, }, lang_item::LangItem, nameres::MacroSubNs, - path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments}, - resolver::{HasResolver, LifetimeNs, ResolveValueResult, Resolver, TypeNs, ValueNs}, + path::{GenericArg, ModPath, Path, PathKind}, + resolver::{HasResolver, LifetimeNs, Resolver, TypeNs}, type_ref::{ ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap, }, AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, - LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, - TypeOwnerId, UnionId, VariantId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, LocalFieldId, + Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, UnionId, VariantId, }; use hir_expand::{name::Name, ExpandResult}; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashSet; use rustc_pattern_analysis::Captures; -use smallvec::SmallVec; use stdx::{impl_from, never}; use syntax::ast; use triomphe::{Arc, ThinArc}; @@ -62,18 +60,19 @@ use crate::{ db::HirDatabase, error_lifetime, generics::{generics, trait_self_param_idx, Generics}, - lower::diagnostics::*, + lower::{ + diagnostics::*, + path::{PathDiagnosticCallback, PathLoweringContext}, + }, make_binders, mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk}, - static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, - utils::{ - all_super_trait_refs, associated_type_by_name_including_super_traits, InTypeConstIdMetadata, - }, - AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, - FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, - LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, ProjectionTy, - QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, - TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, + static_lifetime, to_chalk_trait_id, to_placeholder_idx, + utils::{all_super_trait_refs, InTypeConstIdMetadata}, + AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, + FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, + LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, QuantifiedWhereClause, + QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, + TyKind, WhereClause, }; #[derive(Debug, Default)] @@ -106,6 +105,8 @@ impl ImplTraitLoweringState { } } +pub(crate) struct PathDiagnosticCallbackData(TypeRefId); + #[derive(Debug)] pub struct TyLoweringContext<'a> { pub db: &'a dyn HirDatabase, @@ -527,9 +528,8 @@ impl<'a> TyLoweringContext<'a> { if path.segments().len() > 1 { return None; } - let resolution = match self - .resolve_path_in_type_ns(path, &mut Self::on_path_diagnostic_callback(type_ref_id)) - { + let mut ctx = self.at_path(PathId::from_type_ref_unchecked(type_ref_id)); + let resolution = match ctx.resolve_path_in_type_ns() { Some((it, None)) => it, _ => return None, }; @@ -539,409 +539,36 @@ impl<'a> TyLoweringContext<'a> { } } - pub(crate) fn lower_ty_relative_path( - &mut self, - ty: Ty, - // We need the original resolution to lower `Self::AssocTy` correctly - res: Option, - remaining_segments: PathSegments<'_>, - ) -> (Ty, Option) { - match remaining_segments.len() { - 0 => (ty, res), - 1 => { - // resolve unselected assoc types - let segment = remaining_segments.first().unwrap(); - (self.select_associated_type(res, segment), None) - } - _ => { - // FIXME report error (ambiguous associated type) - (TyKind::Error.intern(Interner), None) - } + #[inline] + fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static> { + PathDiagnosticCallback { + data: Either::Left(PathDiagnosticCallbackData(type_ref)), + callback: |data, this, diag| { + let type_ref = data.as_ref().left().unwrap().0; + this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag)) + }, } } - pub(crate) fn lower_partly_resolved_path( - &mut self, - resolution: TypeNs, - resolved_segment: PathSegment<'_>, - remaining_segments: PathSegments<'_>, - _resolved_segment_idx: u32, - infer_args: bool, - _on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic), - ) -> (Ty, Option) { - let ty = match resolution { - TypeNs::TraitId(trait_) => { - let ty = match remaining_segments.len() { - 1 => { - let trait_ref = self.lower_trait_ref_from_resolved_path( - trait_, - resolved_segment, - TyKind::Error.intern(Interner), - ); - let segment = remaining_segments.first().unwrap(); - let found = self - .db - .trait_data(trait_ref.hir_trait_id()) - .associated_type_by_name(segment.name); - - match found { - Some(associated_ty) => { - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`trait_ref.substitution`). - let substitution = self.substs_from_path_segment( - segment, - associated_ty.into(), - false, - None, - ); - let len_self = - generics(self.db.upcast(), associated_ty.into()).len_self(); - let substitution = Substitution::from_iter( - Interner, - substitution - .iter(Interner) - .take(len_self) - .chain(trait_ref.substitution.iter(Interner)), - ); - TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(associated_ty), - substitution, - })) - .intern(Interner) - } - None => { - // FIXME: report error (associated type not found) - TyKind::Error.intern(Interner) - } - } - } - 0 => { - // Trait object type without dyn; this should be handled in upstream. See - // `lower_path()`. - stdx::never!("unexpected fully resolved trait path"); - TyKind::Error.intern(Interner) - } - _ => { - // FIXME report error (ambiguous associated type) - TyKind::Error.intern(Interner) - } - }; - return (ty, None); - } - TypeNs::TraitAliasId(_) => { - // FIXME(trait_alias): Implement trait alias. - return (TyKind::Error.intern(Interner), None); - } - TypeNs::GenericParam(param_id) => match self.type_param_mode { - ParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) - } - ParamLoweringMode::Variable => { - let idx = match self - .generics() - .expect("generics in scope") - .type_or_const_param_idx(param_id.into()) - { - None => { - never!("no matching generics"); - return (TyKind::Error.intern(Interner), None); - } - Some(idx) => idx, - }; - - TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) - } - } - .intern(Interner), - TypeNs::SelfType(impl_id) => { - let generics = self.generics().expect("impl should have generic param scope"); - - match self.type_param_mode { - ParamLoweringMode::Placeholder => { - // `def` can be either impl itself or item within, and we need impl itself - // now. - let generics = generics.parent_or_self(); - let subst = generics.placeholder_subst(self.db); - self.db.impl_self_ty(impl_id).substitute(Interner, &subst) - } - ParamLoweringMode::Variable => { - let starting_from = match generics.def() { - GenericDefId::ImplId(_) => 0, - // `def` is an item within impl. We need to substitute `BoundVar`s but - // remember that they are for parent (i.e. impl) generic params so they - // come after our own params. - _ => generics.len_self(), - }; - TyBuilder::impl_self_ty(self.db, impl_id) - .fill_with_bound_vars(self.in_binders, starting_from) - .build() - } - } - } - TypeNs::AdtSelfType(adt) => { - let generics = generics(self.db.upcast(), adt.into()); - let substs = match self.type_param_mode { - ParamLoweringMode::Placeholder => generics.placeholder_subst(self.db), - ParamLoweringMode::Variable => { - generics.bound_vars_subst(self.db, self.in_binders) - } - }; - self.db.ty(adt.into()).substitute(Interner, &substs) - } - - TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args), - TypeNs::BuiltinType(it) => { - self.lower_path_inner(resolved_segment, it.into(), infer_args) - } - TypeNs::TypeAliasId(it) => { - self.lower_path_inner(resolved_segment, it.into(), infer_args) - } - // FIXME: report error - TypeNs::EnumVariantId(_) => return (TyKind::Error.intern(Interner), None), - }; - self.lower_ty_relative_path(ty, Some(resolution), remaining_segments) - } - - fn handle_type_ns_resolution( - &mut self, - resolution: &TypeNs, - resolved_segment: PathSegment<'_>, - resolved_segment_idx: usize, - on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic), - ) { - let mut prohibit_generics_on_resolved = |reason| { - if resolved_segment.args_and_bindings.is_some() { - on_diagnostic( - self, - PathLoweringDiagnostic::GenericArgsProhibited { - segment: resolved_segment_idx as u32, - reason, - }, - ); - } - }; - - match resolution { - TypeNs::SelfType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) - } - TypeNs::GenericParam(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam) - } - TypeNs::AdtSelfType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) - } - TypeNs::BuiltinType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy) - } - TypeNs::AdtId(_) - | TypeNs::EnumVariantId(_) - | TypeNs::TypeAliasId(_) - | TypeNs::TraitId(_) - | TypeNs::TraitAliasId(_) => {} - } - } - - pub(crate) fn resolve_path_in_type_ns_fully( - &mut self, - path: &Path, - on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic), - ) -> Option { - let (res, unresolved) = self.resolve_path_in_type_ns(path, on_diagnostic)?; - if unresolved.is_some() { - return None; - } - Some(res) - } - - pub(crate) fn resolve_path_in_type_ns( - &mut self, - path: &Path, - on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic), - ) -> Option<(TypeNs, Option)> { - let (resolution, remaining_index, _, prefix_info) = - self.resolver.resolve_path_in_type_ns_with_prefix_info(self.db.upcast(), path)?; - let segments = path.segments(); - - match path { - // `segments.is_empty()` can occur with `self`. - Path::Normal(..) if !segments.is_empty() => (), - _ => return Some((resolution, remaining_index)), - }; - - let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index { - None if prefix_info.enum_variant => { - (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2)) - } - None => (segments.strip_last(), segments.len() - 1, None), - Some(i) => (segments.take(i - 1), i - 1, None), - }; - - for (i, mod_segment) in module_segments.iter().enumerate() { - if mod_segment.args_and_bindings.is_some() { - on_diagnostic( - self, - PathLoweringDiagnostic::GenericArgsProhibited { - segment: i as u32, - reason: GenericArgsProhibitedReason::Module, - }, - ); - } - } - - if let Some(enum_segment) = enum_segment { - if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) - && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) - { - on_diagnostic( - self, - PathLoweringDiagnostic::GenericArgsProhibited { - segment: (enum_segment + 1) as u32, - reason: GenericArgsProhibitedReason::EnumVariant, - }, - ); - } - } - - self.handle_type_ns_resolution( - &resolution, - segments.get(resolved_segment_idx).expect("should have resolved segment"), - resolved_segment_idx, - on_diagnostic, - ); - - Some((resolution, remaining_index)) - } - - pub(crate) fn resolve_path_in_value_ns( - &mut self, - path: &Path, - hygiene_id: HygieneId, - on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic), - ) -> Option { - let (res, prefix_info) = self.resolver.resolve_path_in_value_ns_with_prefix_info( - self.db.upcast(), - path, - hygiene_id, - )?; - - let segments = path.segments(); - match path { - // `segments.is_empty()` can occur with `self`. - Path::Normal(..) if !segments.is_empty() => (), - _ => return Some(res), - }; - - let (mod_segments, enum_segment) = match res { - ResolveValueResult::Partial(_, unresolved_segment, _) => { - (segments.take(unresolved_segment - 1), None) - } - ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _) - if prefix_info.enum_variant => - { - (segments.strip_last_two(), segments.len().checked_sub(2)) - } - ResolveValueResult::ValueNs(..) => (segments.strip_last(), None), - }; - for (i, mod_segment) in mod_segments.iter().enumerate() { - if mod_segment.args_and_bindings.is_some() { - on_diagnostic( - self, - PathLoweringDiagnostic::GenericArgsProhibited { - segment: i as u32, - reason: GenericArgsProhibitedReason::Module, - }, - ); - } - } - - if let Some(enum_segment) = enum_segment { - if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) - && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) - { - on_diagnostic( - self, - PathLoweringDiagnostic::GenericArgsProhibited { - segment: (enum_segment + 1) as u32, - reason: GenericArgsProhibitedReason::EnumVariant, - }, - ); - } - } - - match &res { - ResolveValueResult::ValueNs(resolution, _) => { - let resolved_segment_idx = - segments.len().checked_sub(1).unwrap_or_else(|| panic!("{path:?}")); - let resolved_segment = segments.last().unwrap(); - - let mut prohibit_generics_on_resolved = |reason| { - if resolved_segment.args_and_bindings.is_some() { - on_diagnostic( - self, - PathLoweringDiagnostic::GenericArgsProhibited { - segment: resolved_segment_idx as u32, - reason, - }, - ); - } - }; - - match resolution { - ValueNs::ImplSelf(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) - } - // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not - // E0109 (generic arguments provided for a type that doesn't accept them) for - // consts and statics, presumably as a defense against future in which consts - // and statics can be generic, or just because it was easier for rustc implementors. - // That means we'll show the wrong error code. Because of us it's easier to do it - // this way :) - ValueNs::GenericParam(_) | ValueNs::ConstId(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const) - } - ValueNs::StaticId(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static) - } - ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => {} - ValueNs::LocalBinding(_) => {} - } - } - ResolveValueResult::Partial(resolution, unresolved_idx, _) => { - let resolved_segment_idx = unresolved_idx - 1; - let resolved_segment = segments.get(resolved_segment_idx).unwrap(); - self.handle_type_ns_resolution( - resolution, - resolved_segment, - resolved_segment_idx, - on_diagnostic, - ); - } - }; - Some(res) - } - - fn on_path_diagnostic_callback( - type_ref: TypeRefId, - ) -> impl FnMut(&mut Self, PathLoweringDiagnostic) { - move |this, diag| { - this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag)) - } + #[inline] + fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a> { + PathLoweringContext::new( + self, + Self::on_path_diagnostic_callback(path_id.type_ref()), + &self.types_map[path_id], + ) } pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option) { // Resolve the path (in type namespace) if let Some(type_ref) = path.type_anchor() { let (ty, res) = self.lower_ty_ext(type_ref); - return self.lower_ty_relative_path(ty, res, path.segments()); + let mut ctx = self.at_path(path_id); + return ctx.lower_ty_relative_path(ty, res); } - let (resolution, remaining_index) = match self.resolve_path_in_type_ns( - path, - &mut Self::on_path_diagnostic_callback(path_id.type_ref()), - ) { + let mut ctx = self.at_path(path_id); + let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() { Some(it) => it, None => return (TyKind::Error.intern(Interner), None), }; @@ -953,346 +580,21 @@ impl<'a> TyLoweringContext<'a> { return (ty, None); } - let (resolved_segment_idx, resolved_segment, remaining_segments) = match remaining_index { - None => ( - path.segments().len() - 1, - path.segments().last().expect("resolved path has at least one element"), - PathSegments::EMPTY, - ), - Some(i) => (i - 1, path.segments().get(i - 1).unwrap(), path.segments().skip(i)), - }; - - self.lower_partly_resolved_path( - resolution, - resolved_segment, - remaining_segments, - resolved_segment_idx as u32, - false, - &mut Self::on_path_diagnostic_callback(path_id.type_ref()), - ) - } - - fn select_associated_type(&mut self, res: Option, segment: PathSegment<'_>) -> Ty { - let Some((generics, res)) = self.generics().zip(res) else { - return TyKind::Error.intern(Interner); - }; - let ty = named_associated_type_shorthand_candidates( - self.db, - generics.def(), - res, - Some(segment.name.clone()), - move |name, t, associated_ty| { - let generics = self.generics().unwrap(); - - if name != segment.name { - return None; - } - - let parent_subst = t.substitution.clone(); - let parent_subst = match self.type_param_mode { - ParamLoweringMode::Placeholder => { - // if we're lowering to placeholders, we have to put them in now. - let s = generics.placeholder_subst(self.db); - s.apply(parent_subst, Interner) - } - ParamLoweringMode::Variable => { - // We need to shift in the bound vars, since - // `named_associated_type_shorthand_candidates` does not do that. - parent_subst.shifted_in_from(Interner, self.in_binders) - } - }; - - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`t.substitution`). - let substs = - self.substs_from_path_segment(segment, associated_ty.into(), false, None); - - let len_self = - crate::generics::generics(self.db.upcast(), associated_ty.into()).len_self(); - - let substs = Substitution::from_iter( - Interner, - substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)), - ); - - Some( - TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(associated_ty), - substitution: substs, - })) - .intern(Interner), - ) - }, - ); - - ty.unwrap_or_else(|| TyKind::Error.intern(Interner)) - } - - fn lower_path_inner( - &mut self, - segment: PathSegment<'_>, - typeable: TyDefId, - infer_args: bool, - ) -> Ty { - let generic_def = match typeable { - TyDefId::BuiltinType(builtin) => return TyBuilder::builtin(builtin), - TyDefId::AdtId(it) => it.into(), - TyDefId::TypeAliasId(it) => it.into(), - }; - let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); - self.db.ty(typeable).substitute(Interner, &substs) - } - - /// Collect generic arguments from a path into a `Substs`. See also - /// `create_substs_for_ast_path` and `def_to_ty` in rustc. - pub(super) fn substs_from_path( - &mut self, - path: &Path, - // Note that we don't call `db.value_type(resolved)` here, - // `ValueTyDefId` is just a convenient way to pass generics and - // special-case enum variants - resolved: ValueTyDefId, - infer_args: bool, - ) -> Substitution { - let last = path.segments().last(); - let (segment, generic_def) = match resolved { - ValueTyDefId::FunctionId(it) => (last, it.into()), - ValueTyDefId::StructId(it) => (last, it.into()), - ValueTyDefId::UnionId(it) => (last, it.into()), - ValueTyDefId::ConstId(it) => (last, it.into()), - ValueTyDefId::StaticId(_) => return Substitution::empty(Interner), - ValueTyDefId::EnumVariantId(var) => { - // the generic args for an enum variant may be either specified - // on the segment referring to the enum, or on the segment - // referring to the variant. So `Option::::None` and - // `Option::None::` are both allowed (though the former is - // preferred). See also `def_ids_for_path_segments` in rustc. - let len = path.segments().len(); - let penultimate = len.checked_sub(2).and_then(|idx| path.segments().get(idx)); - let segment = match penultimate { - Some(segment) if segment.args_and_bindings.is_some() => Some(segment), - _ => last, - }; - (segment, var.lookup(self.db.upcast()).parent.into()) - } - }; - let args_and_bindings = segment.and_then(|it| it.args_and_bindings); - self.substs_from_args_and_bindings(args_and_bindings, generic_def, infer_args, None) - } - - pub(super) fn substs_from_path_segment( - &mut self, - segment: PathSegment<'_>, - def: GenericDefId, - infer_args: bool, - explicit_self_ty: Option, - ) -> Substitution { - self.substs_from_args_and_bindings( - segment.args_and_bindings, - def, - infer_args, - explicit_self_ty, - ) - } - - fn substs_from_args_and_bindings( - &mut self, - args_and_bindings: Option<&GenericArgs>, - def: GenericDefId, - infer_args: bool, - explicit_self_ty: Option, - ) -> Substitution { - // Order is - // - Optional Self parameter - // - Lifetime parameters - // - Type or Const parameters - // - Parent parameters - let def_generics = generics(self.db.upcast(), def); - let ( - parent_params, - self_param, - type_params, - const_params, - impl_trait_params, - lifetime_params, - ) = def_generics.provenance_split(); - let item_len = - self_param as usize + type_params + const_params + impl_trait_params + lifetime_params; - let total_len = parent_params + item_len; - - let mut substs = Vec::new(); - - // we need to iterate the lifetime and type/const params separately as our order of them - // differs from the supplied syntax - - let ty_error = || TyKind::Error.intern(Interner).cast(Interner); - let mut def_toc_iter = def_generics.iter_self_type_or_consts_id(); - let fill_self_param = || { - if self_param { - let self_ty = explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(ty_error); - - if let Some(id) = def_toc_iter.next() { - assert!(matches!(id, GenericParamId::TypeParamId(_))); - substs.push(self_ty); - } - } - }; - let mut had_explicit_args = false; - - if let Some(&GenericArgs { ref args, has_self_type, .. }) = args_and_bindings { - // Fill in the self param first - if has_self_type && self_param { - had_explicit_args = true; - if let Some(id) = def_toc_iter.next() { - assert!(matches!(id, GenericParamId::TypeParamId(_))); - had_explicit_args = true; - if let GenericArg::Type(ty) = &args[0] { - substs.push(self.lower_ty(*ty).cast(Interner)); - } - } - } else { - fill_self_param() - }; - - // Then fill in the supplied lifetime args, or error lifetimes if there are too few - // (default lifetimes aren't a thing) - for arg in args - .iter() - .filter_map(|arg| match arg { - GenericArg::Lifetime(arg) => Some(self.lower_lifetime(arg)), - _ => None, - }) - .chain(iter::repeat(error_lifetime())) - .take(lifetime_params) - { - substs.push(arg.cast(Interner)); - } - - let skip = if has_self_type { 1 } else { 0 }; - // Fill in supplied type and const args - // Note if non-lifetime args are provided, it should be all of them, but we can't rely on that - for (arg, id) in args - .iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) - .skip(skip) - .take(type_params + const_params) - .zip(def_toc_iter) - { - had_explicit_args = true; - let arg = generic_arg_to_chalk( - self.db, - id, - arg, - self, - self.types_map, - |this, type_ref| this.lower_ty(type_ref), - |this, const_ref, ty| this.lower_const(const_ref, ty), - |this, lifetime_ref| this.lower_lifetime(lifetime_ref), - ); - substs.push(arg); - } - } else { - fill_self_param(); - } - - let param_to_err = |id| match id { - GenericParamId::ConstParamId(x) => unknown_const_as_generic(self.db.const_param_ty(x)), - GenericParamId::TypeParamId(_) => ty_error(), - GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), - }; - // handle defaults. In expression or pattern path segments without - // explicitly specified type arguments, missing type arguments are inferred - // (i.e. defaults aren't used). - // Generic parameters for associated types are not supposed to have defaults, so we just - // ignore them. - let is_assoc_ty = || match def { - GenericDefId::TypeAliasId(id) => { - matches!(id.lookup(self.db.upcast()).container, ItemContainerId::TraitId(_)) - } - _ => false, - }; - let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty(); - if fill_defaults { - let defaults = &*self.db.generic_defaults(def); - let (item, _parent) = defaults.split_at(item_len); - let parent_from = item_len - substs.len(); - - let mut rem = - def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::>(); - // Fill in defaults for type/const params - for (idx, default_ty) in item[substs.len()..].iter().enumerate() { - // each default can depend on the previous parameters - let substs_so_far = Substitution::from_iter( - Interner, - substs.iter().cloned().chain(rem[idx..].iter().cloned()), - ); - substs.push(default_ty.clone().substitute(Interner, &substs_so_far)); - } - // Fill in remaining parent params - substs.extend(rem.drain(parent_from..)); - } else { - // Fill in remaining def params and parent params - substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err)); - } - - assert_eq!(substs.len(), total_len, "expected {} substs, got {}", total_len, substs.len()); - Substitution::from_iter(Interner, substs) - } - - pub(crate) fn lower_trait_ref_from_resolved_path( - &mut self, - resolved: TraitId, - segment: PathSegment<'_>, - explicit_self_ty: Ty, - ) -> TraitRef { - let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); - TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } - } - - fn prohibit_generics( - &mut self, - path_id: PathId, - idx: u32, - segments: PathSegments<'_>, - reason: GenericArgsProhibitedReason, - ) { - segments.iter().zip(idx..).for_each(|(segment, idx)| { - if segment.args_and_bindings.is_some() { - self.push_diagnostic( - path_id.type_ref(), - TyLoweringDiagnosticKind::PathDiagnostic( - PathLoweringDiagnostic::GenericArgsProhibited { segment: idx, reason }, - ), - ); - } - }); + ctx.lower_partly_resolved_path(resolution, false) } fn lower_trait_ref_from_path( &mut self, path_id: PathId, explicit_self_ty: Ty, - ) -> Option { - let path = &self.types_map[path_id]; - let resolved = match self.resolve_path_in_type_ns_fully( - path, - &mut Self::on_path_diagnostic_callback(path_id.type_ref()), - )? { + ) -> Option<(TraitRef, PathLoweringContext<'_, 'a>)> { + let mut ctx = self.at_path(path_id); + let resolved = match ctx.resolve_path_in_type_ns_fully()? { // FIXME(trait_alias): We need to handle trait alias here. TypeNs::TraitId(tr) => tr, _ => return None, }; - // Do this after we verify it's indeed a trait to not confuse the user if they're not modules. - self.prohibit_generics( - path_id, - 0, - path.segments().strip_last(), - GenericArgsProhibitedReason::Module, - ); - let segment = path.segments().last().expect("path should have at least one segment"); - Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty)) + Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty), ctx)) } fn lower_trait_ref( @@ -1300,16 +602,7 @@ impl<'a> TyLoweringContext<'a> { trait_ref: &HirTraitRef, explicit_self_ty: Ty, ) -> Option { - self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty) - } - - fn trait_ref_substs_from_path( - &mut self, - segment: PathSegment<'_>, - resolved: TraitId, - explicit_self_ty: Ty, - ) -> Substitution { - self.substs_from_path_segment(segment, resolved.into(), false, Some(explicit_self_ty)) + self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0) } pub(crate) fn lower_where_predicate<'b>( @@ -1357,11 +650,18 @@ impl<'a> TyLoweringContext<'a> { self_ty: Ty, ignore_bindings: bool, ) -> impl Iterator + use<'b, 'a> { - let mut trait_ref = None; - let clause = match bound { - &TypeBound::Path(path, TraitBoundModifier::None) => { - trait_ref = self.lower_trait_ref_from_path(path, self_ty); - trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders) + let mut assoc_bounds = None; + let mut clause = None; + match bound { + &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => { + // FIXME Don't silently drop the hrtb lifetimes here + if let Some((trait_ref, ctx)) = self.lower_trait_ref_from_path(path, self_ty) { + if !ignore_bindings { + assoc_bounds = + ctx.assoc_type_bindings_from_type_bound(bound, trait_ref.clone()); + } + clause = Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref))); + } } &TypeBound::Path(path, TraitBoundModifier::Maybe) => { let sized_trait = self @@ -1373,170 +673,21 @@ impl<'a> TyLoweringContext<'a> { // If we got another trait here ignore the bound completely. let trait_id = self .lower_trait_ref_from_path(path, self_ty.clone()) - .map(|trait_ref| trait_ref.hir_trait_id()); + .map(|(trait_ref, _)| trait_ref.hir_trait_id()); if trait_id == sized_trait { self.unsized_types.insert(self_ty); } - None - } - &TypeBound::ForLifetime(_, path) => { - // FIXME Don't silently drop the hrtb lifetimes here - trait_ref = self.lower_trait_ref_from_path(path, self_ty); - trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders) } TypeBound::Lifetime(l) => { let lifetime = self.lower_lifetime(l); - Some(crate::wrap_empty_binders(WhereClause::TypeOutlives(TypeOutlives { + clause = Some(crate::wrap_empty_binders(WhereClause::TypeOutlives(TypeOutlives { ty: self_ty, lifetime, - }))) + }))); } - TypeBound::Use(_) | TypeBound::Error => None, - }; - clause.into_iter().chain( - trait_ref - .filter(move |_| !ignore_bindings) - .map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)) - .into_iter() - .flatten(), - ) - } - - fn assoc_type_bindings_from_type_bound<'b>( - &'b mut self, - bound: &'b TypeBound, - trait_ref: TraitRef, - ) -> impl Iterator + use<'b, 'a> { - let last_segment = match bound { - &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => { - self.types_map[path].segments().last() - } - TypeBound::Path(_, TraitBoundModifier::Maybe) - | TypeBound::Use(_) - | TypeBound::Error - | TypeBound::Lifetime(_) => None, - }; - last_segment - .into_iter() - .filter_map(|segment| segment.args_and_bindings) - .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) - .flat_map(move |binding| { - let found = associated_type_by_name_including_super_traits( - self.db, - trait_ref.clone(), - &binding.name, - ); - let (super_trait_ref, associated_ty) = match found { - None => return SmallVec::new(), - Some(t) => t, - }; - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`super_trait_ref.substitution`). - let substitution = self.substs_from_path_segment( - // FIXME: This is hack. We shouldn't really build `PathSegment` directly. - PathSegment { name: &binding.name, args_and_bindings: binding.args.as_ref() }, - associated_ty.into(), - false, // this is not relevant - Some(super_trait_ref.self_type_parameter(Interner)), - ); - let self_params = generics(self.db.upcast(), associated_ty.into()).len_self(); - let substitution = Substitution::from_iter( - Interner, - substitution - .iter(Interner) - .take(self_params) - .chain(super_trait_ref.substitution.iter(Interner)), - ); - let projection_ty = ProjectionTy { - associated_ty_id: to_assoc_type_id(associated_ty), - substitution, - }; - let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity( - binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), - ); - if let Some(type_ref) = binding.type_ref { - match (&self.types_map[type_ref], self.impl_trait_mode.mode) { - (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (), - (_, ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque) => { - let ty = self.lower_ty(type_ref); - let alias_eq = - AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; - predicates - .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); - } - (_, ImplTraitLoweringMode::Param | ImplTraitLoweringMode::Variable) => { - // Find the generic index for the target of our `bound` - let target_param_idx = self - .resolver - .where_predicates_in_scope() - .find_map(|(p, _)| match p { - WherePredicate::TypeBound { - target: WherePredicateTypeTarget::TypeOrConstParam(idx), - bound: b, - } if b == bound => Some(idx), - _ => None, - }); - let ty = if let Some(target_param_idx) = target_param_idx { - let mut counter = 0; - let generics = self.generics().expect("generics in scope"); - for (idx, data) in generics.iter_self_type_or_consts() { - // Count the number of `impl Trait` things that appear before - // the target of our `bound`. - // Our counter within `impl_trait_mode` should be that number - // to properly lower each types within `type_ref` - if data.type_param().is_some_and(|p| { - p.provenance == TypeParamProvenance::ArgumentImplTrait - }) { - counter += 1; - } - if idx == *target_param_idx { - break; - } - } - let mut ext = TyLoweringContext::new_maybe_unowned( - self.db, - self.resolver, - self.types_map, - self.types_source_map, - self.owner, - ) - .with_type_param_mode(self.type_param_mode); - match self.impl_trait_mode.mode { - ImplTraitLoweringMode::Param => { - ext.impl_trait_mode = - ImplTraitLoweringState::param(counter); - } - ImplTraitLoweringMode::Variable => { - ext.impl_trait_mode = - ImplTraitLoweringState::variable(counter); - } - _ => unreachable!(), - } - let ty = ext.lower_ty(type_ref); - self.diagnostics.extend(ext.diagnostics); - ty - } else { - self.lower_ty(type_ref) - }; - - let alias_eq = - AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; - predicates - .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); - } - } - } - for bound in binding.bounds.iter() { - predicates.extend(self.lower_type_bound( - bound, - TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(Interner), - false, - )); - } - predicates - }) + TypeBound::Use(_) | TypeBound::Error => {} + } + clause.into_iter().chain(assoc_bounds.into_iter().flatten()) } fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs index dac04307b740..5c77bcd0736a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs @@ -32,4 +32,5 @@ pub enum GenericArgsProhibitedReason { #[derive(Debug, PartialEq, Eq, Clone)] pub enum PathLoweringDiagnostic { GenericArgsProhibited { segment: u32, reason: GenericArgsProhibitedReason }, + ParenthesizedGenericArgsWithoutFnTrait { segment: u32 }, } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs new file mode 100644 index 000000000000..22c5bb9923f0 --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -0,0 +1,911 @@ +//! A wrapper around [`TyLoweringContext`] specifically for lowering paths. + +use std::iter; + +use chalk_ir::{cast::Cast, fold::Shift, BoundVar}; +use either::Either; +use hir_def::{ + data::TraitFlags, + expr_store::HygieneId, + generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, + path::{GenericArg, GenericArgs, Path, PathSegment, PathSegments}, + resolver::{ResolveValueResult, TypeNs, ValueNs}, + type_ref::{TypeBound, TypeRef}, + GenericDefId, GenericParamId, ItemContainerId, Lookup, TraitId, +}; +use smallvec::SmallVec; +use stdx::never; + +use crate::{ + consteval::unknown_const_as_generic, + error_lifetime, + generics::generics, + lower::{ + generic_arg_to_chalk, named_associated_type_shorthand_candidates, ImplTraitLoweringState, + }, + to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, + utils::associated_type_by_name_including_super_traits, + AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, Interner, + ParamLoweringMode, PathLoweringDiagnostic, ProjectionTy, QuantifiedWhereClause, Substitution, + TraitRef, Ty, TyBuilder, TyDefId, TyKind, TyLoweringContext, ValueTyDefId, WhereClause, +}; + +type CallbackData<'a> = Either< + super::PathDiagnosticCallbackData, + crate::infer::diagnostics::PathDiagnosticCallbackData<'a>, +>; + +// We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box` +// because of the allocation, so we create a lifetime-less callback, tailored for our needs. +pub(crate) struct PathDiagnosticCallback<'a> { + pub(crate) data: CallbackData<'a>, + pub(crate) callback: fn(&CallbackData<'_>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic), +} + +pub(crate) struct PathLoweringContext<'a, 'b> { + ctx: &'a mut TyLoweringContext<'b>, + on_diagnostic: PathDiagnosticCallback<'a>, + path: &'a Path, + segments: PathSegments<'a>, + current_segment_idx: usize, + /// Contains the previous segment if `current_segment_idx == segments.len()` + current_or_prev_segment: PathSegment<'a>, +} + +impl<'a, 'b> PathLoweringContext<'a, 'b> { + #[inline] + pub(crate) fn new( + ctx: &'a mut TyLoweringContext<'b>, + on_diagnostic: PathDiagnosticCallback<'a>, + path: &'a Path, + ) -> Self { + let segments = path.segments(); + let first_segment = segments.first().unwrap_or(PathSegment::MISSING); + Self { + ctx, + on_diagnostic, + path, + segments, + current_segment_idx: 0, + current_or_prev_segment: first_segment, + } + } + + #[inline] + #[cold] + fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) { + (self.on_diagnostic.callback)(&self.on_diagnostic.data, self.ctx, diag); + } + + #[inline] + pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'b> { + self.ctx + } + + #[inline] + fn current_segment_u32(&self) -> u32 { + self.current_segment_idx as u32 + } + + #[inline] + fn skip_resolved_segment(&mut self) { + if !matches!(self.path, Path::LangItem(..)) { + // In lang items, the resolved "segment" is not one of the segments. Perhaps we should've put it + // point at -1, but I don't feel this is clearer. + self.current_segment_idx += 1; + } + self.update_current_segment(); + } + + #[inline] + fn update_current_segment(&mut self) { + self.current_or_prev_segment = + self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment); + } + + #[inline] + pub(crate) fn ignore_last_segment(&mut self) { + self.segments = self.segments.strip_last(); + } + + #[inline] + pub(crate) fn set_current_segment(&mut self, segment: usize) { + self.current_segment_idx = segment; + self.current_or_prev_segment = self + .segments + .get(segment) + .expect("invalid segment passed to PathLoweringContext::set_current_segment()"); + } + + pub(crate) fn lower_ty_relative_path( + &mut self, + ty: Ty, + // We need the original resolution to lower `Self::AssocTy` correctly + res: Option, + ) -> (Ty, Option) { + match self.segments.len() - self.current_segment_idx { + 0 => (ty, res), + 1 => { + // resolve unselected assoc types + (self.select_associated_type(res), None) + } + _ => { + // FIXME report error (ambiguous associated type) + (TyKind::Error.intern(Interner), None) + } + } + } + + fn prohibit_parenthesized_generic_args(&mut self) -> bool { + if let Some(generic_args) = self.current_or_prev_segment.args_and_bindings { + if generic_args.desugared_from_fn { + let segment = self.current_segment_u32(); + self.on_diagnostic( + PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment }, + ); + return true; + } + } + false + } + + // When calling this, the current segment is the resolved segment (we don't advance it yet). + pub(crate) fn lower_partly_resolved_path( + &mut self, + resolution: TypeNs, + infer_args: bool, + ) -> (Ty, Option) { + let remaining_segments = self.segments.skip(self.current_segment_idx + 1); + + let ty = match resolution { + TypeNs::TraitId(trait_) => { + let ty = match remaining_segments.len() { + 1 => { + let trait_ref = self.lower_trait_ref_from_resolved_path( + trait_, + TyKind::Error.intern(Interner), + ); + + self.skip_resolved_segment(); + let segment = self.current_or_prev_segment; + let found = + self.ctx.db.trait_data(trait_).associated_type_by_name(segment.name); + + match found { + Some(associated_ty) => { + // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent + // generic params. It's inefficient to splice the `Substitution`s, so we may want + // that method to optionally take parent `Substitution` as we already know them at + // this point (`trait_ref.substitution`). + let substitution = self.substs_from_path_segment( + associated_ty.into(), + false, + None, + ); + let len_self = + generics(self.ctx.db.upcast(), associated_ty.into()).len_self(); + let substitution = Substitution::from_iter( + Interner, + substitution + .iter(Interner) + .take(len_self) + .chain(trait_ref.substitution.iter(Interner)), + ); + TyKind::Alias(AliasTy::Projection(ProjectionTy { + associated_ty_id: to_assoc_type_id(associated_ty), + substitution, + })) + .intern(Interner) + } + None => { + // FIXME: report error (associated type not found) + TyKind::Error.intern(Interner) + } + } + } + 0 => { + // Trait object type without dyn; this should be handled in upstream. See + // `lower_path()`. + stdx::never!("unexpected fully resolved trait path"); + TyKind::Error.intern(Interner) + } + _ => { + // FIXME report error (ambiguous associated type) + TyKind::Error.intern(Interner) + } + }; + return (ty, None); + } + TypeNs::TraitAliasId(_) => { + // FIXME(trait_alias): Implement trait alias. + return (TyKind::Error.intern(Interner), None); + } + TypeNs::GenericParam(param_id) => match self.ctx.type_param_mode { + ParamLoweringMode::Placeholder => { + TyKind::Placeholder(to_placeholder_idx(self.ctx.db, param_id.into())) + } + ParamLoweringMode::Variable => { + let idx = match self + .ctx + .generics() + .expect("generics in scope") + .type_or_const_param_idx(param_id.into()) + { + None => { + never!("no matching generics"); + return (TyKind::Error.intern(Interner), None); + } + Some(idx) => idx, + }; + + TyKind::BoundVar(BoundVar::new(self.ctx.in_binders, idx)) + } + } + .intern(Interner), + TypeNs::SelfType(impl_id) => { + let generics = self.ctx.generics().expect("impl should have generic param scope"); + + match self.ctx.type_param_mode { + ParamLoweringMode::Placeholder => { + // `def` can be either impl itself or item within, and we need impl itself + // now. + let generics = generics.parent_or_self(); + let subst = generics.placeholder_subst(self.ctx.db); + self.ctx.db.impl_self_ty(impl_id).substitute(Interner, &subst) + } + ParamLoweringMode::Variable => { + let starting_from = match generics.def() { + GenericDefId::ImplId(_) => 0, + // `def` is an item within impl. We need to substitute `BoundVar`s but + // remember that they are for parent (i.e. impl) generic params so they + // come after our own params. + _ => generics.len_self(), + }; + TyBuilder::impl_self_ty(self.ctx.db, impl_id) + .fill_with_bound_vars(self.ctx.in_binders, starting_from) + .build() + } + } + } + TypeNs::AdtSelfType(adt) => { + let generics = generics(self.ctx.db.upcast(), adt.into()); + let substs = match self.ctx.type_param_mode { + ParamLoweringMode::Placeholder => generics.placeholder_subst(self.ctx.db), + ParamLoweringMode::Variable => { + generics.bound_vars_subst(self.ctx.db, self.ctx.in_binders) + } + }; + self.ctx.db.ty(adt.into()).substitute(Interner, &substs) + } + + TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args), + TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args), + TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args), + // FIXME: report error + TypeNs::EnumVariantId(_) => return (TyKind::Error.intern(Interner), None), + }; + + self.skip_resolved_segment(); + self.lower_ty_relative_path(ty, Some(resolution)) + } + + fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) { + let mut prohibit_generics_on_resolved = |reason| { + if self.current_or_prev_segment.args_and_bindings.is_some() { + let segment = self.current_segment_u32(); + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment, + reason, + }); + } + }; + + match resolution { + TypeNs::SelfType(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) + } + TypeNs::GenericParam(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam) + } + TypeNs::AdtSelfType(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) + } + TypeNs::BuiltinType(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy) + } + TypeNs::AdtId(_) + | TypeNs::EnumVariantId(_) + | TypeNs::TypeAliasId(_) + | TypeNs::TraitId(_) + | TypeNs::TraitAliasId(_) => {} + } + } + + pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option { + let (res, unresolved) = self.resolve_path_in_type_ns()?; + if unresolved.is_some() { + return None; + } + Some(res) + } + + pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option)> { + let (resolution, remaining_index, _, prefix_info) = self + .ctx + .resolver + .resolve_path_in_type_ns_with_prefix_info(self.ctx.db.upcast(), self.path)?; + + let segments = self.segments; + if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { + // `segments.is_empty()` can occur with `self`. + return Some((resolution, remaining_index)); + } + + let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index { + None if prefix_info.enum_variant => { + (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2)) + } + None => (segments.strip_last(), segments.len() - 1, None), + Some(i) => (segments.take(i - 1), i - 1, None), + }; + + self.current_segment_idx = resolved_segment_idx; + self.current_or_prev_segment = + segments.get(resolved_segment_idx).expect("should have resolved segment"); + + if matches!(self.path, Path::BarePath(..)) { + // Bare paths cannot have generics, so skip them as an optimization. + return Some((resolution, remaining_index)); + } + + for (i, mod_segment) in module_segments.iter().enumerate() { + if mod_segment.args_and_bindings.is_some() { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: i as u32, + reason: GenericArgsProhibitedReason::Module, + }); + } + } + + if let Some(enum_segment) = enum_segment { + if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) + && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) + { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: (enum_segment + 1) as u32, + reason: GenericArgsProhibitedReason::EnumVariant, + }); + } + } + + self.handle_type_ns_resolution(&resolution); + + Some((resolution, remaining_index)) + } + + pub(crate) fn resolve_path_in_value_ns( + &mut self, + hygiene_id: HygieneId, + ) -> Option { + let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info( + self.ctx.db.upcast(), + self.path, + hygiene_id, + )?; + + let segments = self.segments; + if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { + // `segments.is_empty()` can occur with `self`. + return Some(res); + } + + let (mod_segments, enum_segment, resolved_segment_idx) = match res { + ResolveValueResult::Partial(_, unresolved_segment, _) => { + (segments.take(unresolved_segment - 1), None, unresolved_segment - 1) + } + ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _) + if prefix_info.enum_variant => + { + (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1) + } + ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1), + }; + + self.current_segment_idx = resolved_segment_idx; + self.current_or_prev_segment = + segments.get(resolved_segment_idx).expect("should have resolved segment"); + + for (i, mod_segment) in mod_segments.iter().enumerate() { + if mod_segment.args_and_bindings.is_some() { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: i as u32, + reason: GenericArgsProhibitedReason::Module, + }); + } + } + + if let Some(enum_segment) = enum_segment { + if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) + && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) + { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: (enum_segment + 1) as u32, + reason: GenericArgsProhibitedReason::EnumVariant, + }); + } + } + + match &res { + ResolveValueResult::ValueNs(resolution, _) => { + let resolved_segment_idx = self.current_segment_u32(); + let resolved_segment = self.current_or_prev_segment; + + let mut prohibit_generics_on_resolved = |reason| { + if resolved_segment.args_and_bindings.is_some() { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: resolved_segment_idx, + reason, + }); + } + }; + + match resolution { + ValueNs::ImplSelf(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) + } + // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not + // E0109 (generic arguments provided for a type that doesn't accept them) for + // consts and statics, presumably as a defense against future in which consts + // and statics can be generic, or just because it was easier for rustc implementors. + // That means we'll show the wrong error code. Because of us it's easier to do it + // this way :) + ValueNs::GenericParam(_) | ValueNs::ConstId(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const) + } + ValueNs::StaticId(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static) + } + ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => {} + ValueNs::LocalBinding(_) => {} + } + } + ResolveValueResult::Partial(resolution, _, _) => { + self.handle_type_ns_resolution(resolution); + } + }; + Some(res) + } + + fn select_associated_type(&mut self, res: Option) -> Ty { + let Some((generics, res)) = self.ctx.generics().zip(res) else { + return TyKind::Error.intern(Interner); + }; + let segment = self.current_or_prev_segment; + let ty = named_associated_type_shorthand_candidates( + self.ctx.db, + generics.def(), + res, + Some(segment.name.clone()), + move |name, t, associated_ty| { + let generics = self.ctx.generics().unwrap(); + + if name != segment.name { + return None; + } + + let parent_subst = t.substitution.clone(); + let parent_subst = match self.ctx.type_param_mode { + ParamLoweringMode::Placeholder => { + // if we're lowering to placeholders, we have to put them in now. + let s = generics.placeholder_subst(self.ctx.db); + s.apply(parent_subst, Interner) + } + ParamLoweringMode::Variable => { + // We need to shift in the bound vars, since + // `named_associated_type_shorthand_candidates` does not do that. + parent_subst.shifted_in_from(Interner, self.ctx.in_binders) + } + }; + + // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent + // generic params. It's inefficient to splice the `Substitution`s, so we may want + // that method to optionally take parent `Substitution` as we already know them at + // this point (`t.substitution`). + let substs = self.substs_from_path_segment(associated_ty.into(), false, None); + + let len_self = + crate::generics::generics(self.ctx.db.upcast(), associated_ty.into()) + .len_self(); + + let substs = Substitution::from_iter( + Interner, + substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)), + ); + + Some( + TyKind::Alias(AliasTy::Projection(ProjectionTy { + associated_ty_id: to_assoc_type_id(associated_ty), + substitution: substs, + })) + .intern(Interner), + ) + }, + ); + + ty.unwrap_or_else(|| TyKind::Error.intern(Interner)) + } + + fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty { + let generic_def = match typeable { + TyDefId::BuiltinType(builtin) => return TyBuilder::builtin(builtin), + TyDefId::AdtId(it) => it.into(), + TyDefId::TypeAliasId(it) => it.into(), + }; + let substs = self.substs_from_path_segment(generic_def, infer_args, None); + self.ctx.db.ty(typeable).substitute(Interner, &substs) + } + + /// Collect generic arguments from a path into a `Substs`. See also + /// `create_substs_for_ast_path` and `def_to_ty` in rustc. + pub(crate) fn substs_from_path( + &mut self, + // Note that we don't call `db.value_type(resolved)` here, + // `ValueTyDefId` is just a convenient way to pass generics and + // special-case enum variants + resolved: ValueTyDefId, + infer_args: bool, + ) -> Substitution { + let prev_current_segment_idx = self.current_segment_idx; + let prev_current_segment = self.current_or_prev_segment; + + let generic_def = match resolved { + ValueTyDefId::FunctionId(it) => it.into(), + ValueTyDefId::StructId(it) => it.into(), + ValueTyDefId::UnionId(it) => it.into(), + ValueTyDefId::ConstId(it) => it.into(), + ValueTyDefId::StaticId(_) => return Substitution::empty(Interner), + ValueTyDefId::EnumVariantId(var) => { + // the generic args for an enum variant may be either specified + // on the segment referring to the enum, or on the segment + // referring to the variant. So `Option::::None` and + // `Option::None::` are both allowed (though the former is + // FIXME: This isn't strictly correct, enum variants may be used not through the enum + // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result + // available here. The worst that can happen is that we will show some confusing diagnostics to the user, + // if generics exist on the module and they don't match with the variant. + // preferred). See also `def_ids_for_path_segments` in rustc. + // + // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2. + // This simplifies the code a bit. + let penultimate_idx = self.current_segment_idx.wrapping_sub(1); + let penultimate = self.segments.get(penultimate_idx); + if let Some(penultimate) = penultimate { + if self.current_or_prev_segment.args_and_bindings.is_none() + && penultimate.args_and_bindings.is_some() + { + self.current_segment_idx = penultimate_idx; + self.current_or_prev_segment = penultimate; + } + } + var.lookup(self.ctx.db.upcast()).parent.into() + } + }; + let result = self.substs_from_path_segment(generic_def, infer_args, None); + self.current_segment_idx = prev_current_segment_idx; + self.current_or_prev_segment = prev_current_segment; + result + } + + pub(crate) fn substs_from_path_segment( + &mut self, + def: GenericDefId, + infer_args: bool, + explicit_self_ty: Option, + ) -> Substitution { + let prohibit_parens = match def { + GenericDefId::TraitId(trait_) => { + let trait_data = self.ctx.db.trait_data(trait_); + !trait_data.flags.contains(TraitFlags::RUSTC_PAREN_SUGAR) + } + _ => true, + }; + if prohibit_parens && self.prohibit_parenthesized_generic_args() { + return TyBuilder::unknown_subst(self.ctx.db, def); + } + + self.substs_from_args_and_bindings( + self.current_or_prev_segment.args_and_bindings, + def, + infer_args, + explicit_self_ty, + ) + } + + pub(super) fn substs_from_args_and_bindings( + &mut self, + args_and_bindings: Option<&GenericArgs>, + def: GenericDefId, + infer_args: bool, + explicit_self_ty: Option, + ) -> Substitution { + // Order is + // - Optional Self parameter + // - Lifetime parameters + // - Type or Const parameters + // - Parent parameters + let def_generics = generics(self.ctx.db.upcast(), def); + let ( + parent_params, + self_param, + type_params, + const_params, + impl_trait_params, + lifetime_params, + ) = def_generics.provenance_split(); + let item_len = + self_param as usize + type_params + const_params + impl_trait_params + lifetime_params; + let total_len = parent_params + item_len; + + let mut substs = Vec::new(); + + // we need to iterate the lifetime and type/const params separately as our order of them + // differs from the supplied syntax + + let ty_error = || TyKind::Error.intern(Interner).cast(Interner); + let mut def_toc_iter = def_generics.iter_self_type_or_consts_id(); + let fill_self_param = || { + if self_param { + let self_ty = explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(ty_error); + + if let Some(id) = def_toc_iter.next() { + assert!(matches!(id, GenericParamId::TypeParamId(_))); + substs.push(self_ty); + } + } + }; + let mut had_explicit_args = false; + + if let Some(&GenericArgs { ref args, has_self_type, .. }) = args_and_bindings { + // Fill in the self param first + if has_self_type && self_param { + had_explicit_args = true; + if let Some(id) = def_toc_iter.next() { + assert!(matches!(id, GenericParamId::TypeParamId(_))); + had_explicit_args = true; + if let GenericArg::Type(ty) = &args[0] { + substs.push(self.ctx.lower_ty(*ty).cast(Interner)); + } + } + } else { + fill_self_param() + }; + + // Then fill in the supplied lifetime args, or error lifetimes if there are too few + // (default lifetimes aren't a thing) + for arg in args + .iter() + .filter_map(|arg| match arg { + GenericArg::Lifetime(arg) => Some(self.ctx.lower_lifetime(arg)), + _ => None, + }) + .chain(iter::repeat(error_lifetime())) + .take(lifetime_params) + { + substs.push(arg.cast(Interner)); + } + + let skip = if has_self_type { 1 } else { 0 }; + // Fill in supplied type and const args + // Note if non-lifetime args are provided, it should be all of them, but we can't rely on that + for (arg, id) in args + .iter() + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .skip(skip) + .take(type_params + const_params) + .zip(def_toc_iter) + { + had_explicit_args = true; + let arg = generic_arg_to_chalk( + self.ctx.db, + id, + arg, + self.ctx, + self.ctx.types_map, + |ctx, type_ref| ctx.lower_ty(type_ref), + |ctx, const_ref, ty| ctx.lower_const(const_ref, ty), + |ctx, lifetime_ref| ctx.lower_lifetime(lifetime_ref), + ); + substs.push(arg); + } + } else { + fill_self_param(); + } + + let param_to_err = |id| match id { + GenericParamId::ConstParamId(x) => { + unknown_const_as_generic(self.ctx.db.const_param_ty(x)) + } + GenericParamId::TypeParamId(_) => ty_error(), + GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), + }; + // handle defaults. In expression or pattern path segments without + // explicitly specified type arguments, missing type arguments are inferred + // (i.e. defaults aren't used). + // Generic parameters for associated types are not supposed to have defaults, so we just + // ignore them. + let is_assoc_ty = || match def { + GenericDefId::TypeAliasId(id) => { + matches!(id.lookup(self.ctx.db.upcast()).container, ItemContainerId::TraitId(_)) + } + _ => false, + }; + let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty(); + if fill_defaults { + let defaults = &*self.ctx.db.generic_defaults(def); + let (item, _parent) = defaults.split_at(item_len); + let parent_from = item_len - substs.len(); + + let mut rem = + def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::>(); + // Fill in defaults for type/const params + for (idx, default_ty) in item[substs.len()..].iter().enumerate() { + // each default can depend on the previous parameters + let substs_so_far = Substitution::from_iter( + Interner, + substs.iter().cloned().chain(rem[idx..].iter().cloned()), + ); + substs.push(default_ty.clone().substitute(Interner, &substs_so_far)); + } + // Fill in remaining parent params + substs.extend(rem.drain(parent_from..)); + } else { + // Fill in remaining def params and parent params + substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err)); + } + + assert_eq!(substs.len(), total_len, "expected {} substs, got {}", total_len, substs.len()); + Substitution::from_iter(Interner, substs) + } + + pub(crate) fn lower_trait_ref_from_resolved_path( + &mut self, + resolved: TraitId, + explicit_self_ty: Ty, + ) -> TraitRef { + let substs = self.trait_ref_substs_from_path(resolved, explicit_self_ty); + TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } + } + + fn trait_ref_substs_from_path( + &mut self, + resolved: TraitId, + explicit_self_ty: Ty, + ) -> Substitution { + self.substs_from_path_segment(resolved.into(), false, Some(explicit_self_ty)) + } + + pub(super) fn assoc_type_bindings_from_type_bound<'c>( + mut self, + bound: &'c TypeBound, + trait_ref: TraitRef, + ) -> Option + use<'a, 'b, 'c>> { + self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| { + args_and_bindings.bindings.iter().flat_map(move |binding| { + let found = associated_type_by_name_including_super_traits( + self.ctx.db, + trait_ref.clone(), + &binding.name, + ); + let (super_trait_ref, associated_ty) = match found { + None => return SmallVec::new(), + Some(t) => t, + }; + // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent + // generic params. It's inefficient to splice the `Substitution`s, so we may want + // that method to optionally take parent `Substitution` as we already know them at + // this point (`super_trait_ref.substitution`). + let substitution = self.substs_from_args_and_bindings( + binding.args.as_ref(), + associated_ty.into(), + false, // this is not relevant + Some(super_trait_ref.self_type_parameter(Interner)), + ); + let self_params = generics(self.ctx.db.upcast(), associated_ty.into()).len_self(); + let substitution = Substitution::from_iter( + Interner, + substitution + .iter(Interner) + .take(self_params) + .chain(super_trait_ref.substitution.iter(Interner)), + ); + let projection_ty = ProjectionTy { + associated_ty_id: to_assoc_type_id(associated_ty), + substitution, + }; + let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity( + binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), + ); + if let Some(type_ref) = binding.type_ref { + match (&self.ctx.types_map[type_ref], self.ctx.impl_trait_mode.mode) { + (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (), + (_, ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque) => { + let ty = self.ctx.lower_ty(type_ref); + let alias_eq = + AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; + predicates + .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); + } + (_, ImplTraitLoweringMode::Param | ImplTraitLoweringMode::Variable) => { + // Find the generic index for the target of our `bound` + let target_param_idx = + self.ctx.resolver.where_predicates_in_scope().find_map(|(p, _)| { + match p { + WherePredicate::TypeBound { + target: WherePredicateTypeTarget::TypeOrConstParam(idx), + bound: b, + } if b == bound => Some(idx), + _ => None, + } + }); + let ty = if let Some(target_param_idx) = target_param_idx { + let mut counter = 0; + let generics = self.ctx.generics().expect("generics in scope"); + for (idx, data) in generics.iter_self_type_or_consts() { + // Count the number of `impl Trait` things that appear before + // the target of our `bound`. + // Our counter within `impl_trait_mode` should be that number + // to properly lower each types within `type_ref` + if data.type_param().is_some_and(|p| { + p.provenance == TypeParamProvenance::ArgumentImplTrait + }) { + counter += 1; + } + if idx == *target_param_idx { + break; + } + } + let mut ext = TyLoweringContext::new_maybe_unowned( + self.ctx.db, + self.ctx.resolver, + self.ctx.types_map, + self.ctx.types_source_map, + self.ctx.owner, + ) + .with_type_param_mode(self.ctx.type_param_mode); + match self.ctx.impl_trait_mode.mode { + ImplTraitLoweringMode::Param => { + ext.impl_trait_mode = + ImplTraitLoweringState::param(counter); + } + ImplTraitLoweringMode::Variable => { + ext.impl_trait_mode = + ImplTraitLoweringState::variable(counter); + } + _ => unreachable!(), + } + let ty = ext.lower_ty(type_ref); + self.ctx.diagnostics.extend(ext.diagnostics); + ty + } else { + self.ctx.lower_ty(type_ref) + }; + + let alias_eq = + AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; + predicates + .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); + } + } + } + for bound in binding.bounds.iter() { + predicates.extend(self.ctx.lower_type_bound( + bound, + TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(Interner), + false, + )); + } + predicates + }) + }) + } +} diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 64e982c42d7f..f6c0bdc6a62c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -111,6 +111,7 @@ diagnostics![ UnusedMut, UnusedVariable, GenericArgsProhibited, + ParenthesizedGenericArgsWithoutFnTrait, ]; #[derive(Debug)] @@ -413,6 +414,11 @@ pub struct GenericArgsProhibited { pub reason: GenericArgsProhibitedReason, } +#[derive(Debug)] +pub struct ParenthesizedGenericArgsWithoutFnTrait { + pub args: InFile>, +} + impl AnyDiagnostic { pub(crate) fn body_validation_diagnostic( db: &dyn HirDatabase, @@ -702,8 +708,8 @@ impl AnyDiagnostic { diag: &PathLoweringDiagnostic, path: InFile, ) -> Option { - Some(match diag { - &PathLoweringDiagnostic::GenericArgsProhibited { segment, reason } => { + Some(match *diag { + PathLoweringDiagnostic::GenericArgsProhibited { segment, reason } => { let segment = hir_segment_to_ast_segment(&path.value, segment)?; let args = if let Some(generics) = segment.generic_arg_list() { AstPtr::new(&generics).wrap_left() @@ -713,6 +719,12 @@ impl AnyDiagnostic { let args = path.with_value(args); GenericArgsProhibited { args, reason }.into() } + PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment } => { + let segment = hir_segment_to_ast_segment(&path.value, segment)?; + let args = AstPtr::new(&segment.parenthesized_arg_list()?); + let args = path.with_value(args); + ParenthesizedGenericArgsWithoutFnTrait { args }.into() + } }) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs new file mode 100644 index 000000000000..ccf517234183 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs @@ -0,0 +1,59 @@ +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: parenthesized-generic-args-without-fn-trait +// +// This diagnostic is shown when a `Fn`-trait-style generic parameters (`Trait(A, B) -> C`) +// was used on non-`Fn` trait/type. +pub(crate) fn parenthesized_generic_args_without_fn_trait( + ctx: &DiagnosticsContext<'_>, + d: &hir::ParenthesizedGenericArgsWithoutFnTrait, +) -> Diagnostic { + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::RustcHardError("E0214"), + "parenthesized type parameters may only be used with a `Fn` trait", + d.args.map(Into::into), + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn fn_traits_work() { + check_diagnostics( + r#" +//- minicore: async_fn, fn +fn foo< + A: Fn(), + B: FnMut() -> i32, + C: FnOnce(&str, bool), + D: AsyncFn::(u32) -> u32, + E: AsyncFnMut(), + F: AsyncFnOnce() -> bool, +>() {} + "#, + ); + } + + #[test] + fn non_fn_trait() { + check_diagnostics( + r#" +struct Struct(T); +enum Enum { EnumVariant(T) } +type TypeAlias = bool; + +type Foo = TypeAlias() -> bool; + // ^^ error: parenthesized type parameters may only be used with a `Fn` trait + +fn foo(_a: Struct(i32)) { + // ^^^^^ error: parenthesized type parameters may only be used with a `Fn` trait + let _ = ::EnumVariant(0); + // ^^^^^^^ error: parenthesized type parameters may only be used with a `Fn` trait +} + "#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 50c91a69602c..3ea41aa7e859 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -43,6 +43,7 @@ mod handlers { pub(crate) mod mutability_errors; pub(crate) mod no_such_field; pub(crate) mod non_exhaustive_let; + pub(crate) mod parenthesized_generic_args_without_fn_trait; pub(crate) mod private_assoc_item; pub(crate) mod private_field; pub(crate) mod remove_trailing_return; @@ -466,7 +467,12 @@ pub fn semantic_diagnostics( Some(it) => it, None => continue, }, - AnyDiagnostic::GenericArgsProhibited(d) => handlers::generic_args_prohibited::generic_args_prohibited(&ctx, &d) + AnyDiagnostic::GenericArgsProhibited(d) => { + handlers::generic_args_prohibited::generic_args_prohibited(&ctx, &d) + } + AnyDiagnostic::ParenthesizedGenericArgsWithoutFnTrait(d) => { + handlers::parenthesized_generic_args_without_fn_trait::parenthesized_generic_args_without_fn_trait(&ctx, &d) + } }; res.push(d) } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html index 9be7c92fc798..9477d0d1b877 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html @@ -48,17 +48,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
use inner::{self as inner_mod};
 mod inner {}
 
-pub mod ops {
-    #[lang = "fn_once"]
-    pub trait FnOnce<Args> {}
-
-    #[lang = "fn_mut"]
-    pub trait FnMut<Args>: FnOnce<Args> {}
-
-    #[lang = "fn"]
-    pub trait Fn<Args>: FnMut<Args> {}
-}
-
 struct Foo {
     x: u32,
 }
@@ -125,8 +114,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     FOO
 }
 
-use ops::Fn;
-fn baz<F: Fn() -> ()>(f: F) {
+use core::ops::Fn;
+fn baz<F: Fn() -> ()>(f: F) {
     f()
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index b9520ae2bba2..75dc5235625b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -136,22 +136,11 @@ use self::foo as bar;
 fn test_highlighting() {
     check_highlighting(
         r#"
-//- minicore: derive, copy
+//- minicore: derive, copy, fn
 //- /main.rs crate:main deps:foo
 use inner::{self as inner_mod};
 mod inner {}
 
-pub mod ops {
-    #[lang = "fn_once"]
-    pub trait FnOnce {}
-
-    #[lang = "fn_mut"]
-    pub trait FnMut: FnOnce {}
-
-    #[lang = "fn"]
-    pub trait Fn: FnMut {}
-}
-
 struct Foo {
     x: u32,
 }
@@ -218,7 +207,7 @@ fn const_param() -> usize {
     FOO
 }
 
-use ops::Fn;
+use core::ops::Fn;
 fn baz ()>(f: F) {
     f()
 }
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index a53da69d9013..1958e3f7b1d8 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -13,15 +13,35 @@ use crate::{
 
 macro_rules! define_symbols {
     (@WITH_NAME: $($alias:ident = $value:literal,)* @PLAIN: $($name:ident,)*) => {
-        // Ideally we would be emitting `const` here, but then we no longer have stable addresses
-        // which is what we are relying on for equality! In the future if consts can refer to
-        // statics we should swap these for `const`s and have the string literal being pointed
-        // to be statics to refer to such that their address is stable.
+        // We define symbols as both `const`s and `static`s because some const code requires const symbols,
+        // but code from before the transition relies on the lifetime of the predefined symbols and making them
+        // `const`s make it error (because now they're temporaries). In the future we probably should only
+        // use consts.
+
+        /// Predefined symbols as `const`s (instead of the default `static`s).
+        pub mod consts {
+            use super::{Symbol, TaggedArcPtr};
+
+            // The strings should be in `static`s so that symbol equality holds.
+            $(
+                pub const $name: Symbol = {
+                    static SYMBOL_STR: &str = stringify!($name);
+                    Symbol { repr: TaggedArcPtr::non_arc(&SYMBOL_STR) }
+                };
+            )*
+            $(
+                pub const $alias: Symbol = {
+                    static SYMBOL_STR: &str = $value;
+                    Symbol { repr: TaggedArcPtr::non_arc(&SYMBOL_STR) }
+                };
+            )*
+        }
+
         $(
-            pub static $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) };
+            pub static $name: Symbol = consts::$name;
         )*
         $(
-            pub static $alias: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&$value) };
+            pub static $alias: Symbol = consts::$alias;
         )*
 
 
@@ -427,6 +447,7 @@ define_symbols! {
     rustc_layout_scalar_valid_range_start,
     rustc_legacy_const_generics,
     rustc_macro_transparency,
+    rustc_paren_sugar,
     rustc_reallocator,
     rustc_reservation_impl,
     rustc_safe_intrinsic,
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index 4ed68d18e807..202afebde70f 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -647,18 +647,21 @@ pub mod ops {
 
         #[lang = "fn"]
         #[fundamental]
+        #[rustc_paren_sugar]
         pub trait Fn: FnMut {
             extern "rust-call" fn call(&self, args: Args) -> Self::Output;
         }
 
         #[lang = "fn_mut"]
         #[fundamental]
+        #[rustc_paren_sugar]
         pub trait FnMut: FnOnce {
             extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
         }
 
         #[lang = "fn_once"]
         #[fundamental]
+        #[rustc_paren_sugar]
         pub trait FnOnce {
             #[lang = "fn_once_output"]
             type Output;
@@ -736,12 +739,14 @@ pub mod ops {
 
         #[lang = "async_fn"]
         #[fundamental]
+        #[rustc_paren_sugar]
         pub trait AsyncFn: AsyncFnMut {
             extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_>;
         }
 
         #[lang = "async_fn_mut"]
         #[fundamental]
+        #[rustc_paren_sugar]
         pub trait AsyncFnMut: AsyncFnOnce {
             #[lang = "call_ref_future"]
             type CallRefFuture<'a>: Future
@@ -752,6 +757,7 @@ pub mod ops {
 
         #[lang = "async_fn_once"]
         #[fundamental]
+        #[rustc_paren_sugar]
         pub trait AsyncFnOnce {
             #[lang = "async_fn_once_output"]
             type Output;

From 1c66d5bed9e6444923c04937f5a28bfcec427ec0 Mon Sep 17 00:00:00 2001
From: Noratrieb <48135649+Noratrieb@users.noreply.github.com>
Date: Sun, 16 Feb 2025 21:13:01 +0100
Subject: [PATCH 082/158] Remove SSE ABI from i586-pc-windows-msvc

As an i586 target, it should not have SSE. This caused the following
warning to be emitted:

```
warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
  |
  = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #116344 

warning: 1 warning emitted
```
---
 compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs
index dd38f86bced2..394e6f9e6bf6 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs
@@ -2,6 +2,7 @@ use crate::spec::Target;
 
 pub(crate) fn target() -> Target {
     let mut base = super::i686_pc_windows_msvc::target();
+    base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target
     base.cpu = "pentium".into();
     base.llvm_target = "i586-pc-windows-msvc".into();
     base

From 4cf21866e8f18449ea0c41ee1ba031c05419d94c Mon Sep 17 00:00:00 2001
From: Ben Kimock 
Date: Sat, 15 Feb 2025 15:18:19 -0500
Subject: [PATCH 083/158] Move hashes from rustc_data_structure to rustc_hashes
 so they can be shared with rust-analyzer

---
 Cargo.lock                                    | 21 +++++++++
 compiler/rustc_abi/Cargo.toml                 |  1 +
 compiler/rustc_abi/src/layout.rs              |  2 +-
 compiler/rustc_abi/src/lib.rs                 |  2 +-
 compiler/rustc_codegen_llvm/Cargo.toml        |  1 +
 compiler/rustc_codegen_llvm/src/common.rs     |  3 +-
 compiler/rustc_codegen_ssa/Cargo.toml         |  1 +
 .../src/debuginfo/type_names.rs               |  3 +-
 compiler/rustc_data_structures/Cargo.toml     |  1 +
 .../rustc_data_structures/src/fingerprint.rs  |  5 +--
 compiler/rustc_data_structures/src/lib.rs     |  1 -
 .../src/stable_hasher.rs                      |  3 +-
 .../src/tagged_ptr/tests.rs                   |  3 +-
 compiler/rustc_errors/Cargo.toml              |  1 +
 compiler/rustc_errors/src/lib.rs              |  3 +-
 compiler/rustc_hashes/Cargo.toml              |  9 ++++
 .../src/hashes.rs => rustc_hashes/src/lib.rs} | 43 +++++--------------
 compiler/rustc_hir/Cargo.toml                 |  1 +
 compiler/rustc_hir/src/def_path_hash_map.rs   |  2 +-
 compiler/rustc_hir/src/definitions.rs         |  3 +-
 compiler/rustc_hir/src/tests.rs               |  2 +-
 compiler/rustc_middle/Cargo.toml              |  1 +
 compiler/rustc_middle/src/mir/mono.rs         |  3 +-
 compiler/rustc_middle/src/ty/layout.rs        |  2 +-
 compiler/rustc_middle/src/ty/util.rs          |  3 +-
 compiler/rustc_query_impl/Cargo.toml          |  1 +
 compiler/rustc_query_impl/src/plumbing.rs     |  3 +-
 compiler/rustc_query_system/Cargo.toml        |  1 +
 compiler/rustc_query_system/src/query/mod.rs  |  2 +-
 compiler/rustc_serialize/Cargo.toml           |  1 +
 compiler/rustc_serialize/src/serialize.rs     | 29 +++++++++++++
 compiler/rustc_session/Cargo.toml             |  1 +
 compiler/rustc_session/src/config.rs          |  2 +-
 compiler/rustc_session/src/options.rs         |  2 +-
 compiler/rustc_span/Cargo.toml                |  1 +
 compiler/rustc_span/src/def_id.rs             |  5 +--
 compiler/rustc_span/src/hygiene.rs            |  3 +-
 compiler/rustc_span/src/lib.rs                |  3 +-
 compiler/rustc_symbol_mangling/Cargo.toml     |  1 +
 compiler/rustc_symbol_mangling/src/hashed.rs  |  3 +-
 compiler/rustc_symbol_mangling/src/legacy.rs  |  3 +-
 compiler/rustc_ty_utils/Cargo.toml            |  1 +
 compiler/rustc_ty_utils/src/layout.rs         |  2 +-
 compiler/rustc_type_ir/src/ty_kind.rs         |  1 +
 .../crates/hir-def/src/data/adt.rs            |  3 +-
 .../rust-analyzer/crates/hir-def/src/lib.rs   |  6 +++
 .../rust-analyzer/crates/hir-ty/src/layout.rs |  9 ++--
 .../rust-analyzer/crates/hir-ty/src/lib.rs    |  6 +++
 .../run-make/rustc-crates-on-stable/rmake.rs  |  2 +
 .../missing-rustc-driver-error.stderr         |  8 ++++
 50 files changed, 152 insertions(+), 67 deletions(-)
 create mode 100644 compiler/rustc_hashes/Cargo.toml
 rename compiler/{rustc_data_structures/src/hashes.rs => rustc_hashes/src/lib.rs} (79%)

diff --git a/Cargo.lock b/Cargo.lock
index d31ef9c4b17e..10492c0a4f3e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3317,6 +3317,7 @@ dependencies = [
  "rand 0.8.5",
  "rand_xoshiro",
  "rustc_data_structures",
+ "rustc_hashes",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -3544,6 +3545,7 @@ dependencies = [
  "rustc_errors",
  "rustc_fluent_macro",
  "rustc_fs_util",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_index",
  "rustc_llvm",
@@ -3586,6 +3588,7 @@ dependencies = [
  "rustc_errors",
  "rustc_fluent_macro",
  "rustc_fs_util",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_hir_pretty",
  "rustc_incremental",
@@ -3658,6 +3661,7 @@ dependencies = [
  "rustc-stable-hash",
  "rustc_arena",
  "rustc_graphviz",
+ "rustc_hashes",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -3768,6 +3772,7 @@ dependencies = [
  "rustc_error_codes",
  "rustc_error_messages",
  "rustc_fluent_macro",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_index",
  "rustc_lexer",
@@ -3840,6 +3845,13 @@ version = "0.0.0"
 name = "rustc_graphviz"
 version = "0.0.0"
 
+[[package]]
+name = "rustc_hashes"
+version = "0.0.0"
+dependencies = [
+ "rustc-stable-hash",
+]
+
 [[package]]
 name = "rustc_hir"
 version = "0.0.0"
@@ -3849,6 +3861,7 @@ dependencies = [
  "rustc_arena",
  "rustc_ast",
  "rustc_data_structures",
+ "rustc_hashes",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -4169,6 +4182,7 @@ dependencies = [
  "rustc_feature",
  "rustc_fluent_macro",
  "rustc_graphviz",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_hir_pretty",
  "rustc_index",
@@ -4405,6 +4419,7 @@ dependencies = [
  "measureme",
  "rustc_data_structures",
  "rustc_errors",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_index",
  "rustc_middle",
@@ -4428,6 +4443,7 @@ dependencies = [
  "rustc_errors",
  "rustc_feature",
  "rustc_fluent_macro",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_index",
  "rustc_macros",
@@ -4488,6 +4504,7 @@ name = "rustc_serialize"
 version = "0.0.0"
 dependencies = [
  "indexmap",
+ "rustc_hashes",
  "rustc_macros",
  "smallvec",
  "tempfile",
@@ -4508,6 +4525,7 @@ dependencies = [
  "rustc_feature",
  "rustc_fluent_macro",
  "rustc_fs_util",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_lint_defs",
  "rustc_macros",
@@ -4549,6 +4567,7 @@ dependencies = [
  "md-5",
  "rustc_arena",
  "rustc_data_structures",
+ "rustc_hashes",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -4568,6 +4587,7 @@ dependencies = [
  "rustc_abi",
  "rustc_data_structures",
  "rustc_errors",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_middle",
  "rustc_session",
@@ -4663,6 +4683,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
+ "rustc_hashes",
  "rustc_hir",
  "rustc_index",
  "rustc_infer",
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 1013f1d3958d..3d6f4a6a1092 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -9,6 +9,7 @@ bitflags = "2.4.1"
 rand = { version = "0.8.4", default-features = false, optional = true }
 rand_xoshiro = { version = "0.6.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true  }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true  }
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 9e33824afe20..45cd0b517f6c 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -2,7 +2,7 @@ use std::fmt::{self, Write};
 use std::ops::{Bound, Deref};
 use std::{cmp, iter};
 
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_hashes::Hash64;
 use rustc_index::Idx;
 use tracing::debug;
 
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index d3847e5f2722..dbb4bed5cdd9 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -48,9 +48,9 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
 use bitflags::bitflags;
-use rustc_data_structures::stable_hasher::Hash64;
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::StableOrd;
+use rustc_hashes::Hash64;
 use rustc_index::{Idx, IndexSlice, IndexVec};
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable_Generic, Encodable_Generic, HashStable_Generic};
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 94f21ac5f574..a81722705488 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -25,6 +25,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_llvm = { path = "../rustc_llvm" }
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 78b3a7f85417..f17d98fa242b 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -7,7 +7,8 @@ use rustc_abi::{AddressSpace, HasDataLayout};
 use rustc_ast::Mutability;
 use rustc_codegen_ssa::common::TypeKind;
 use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hashes::Hash128;
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 2afc1efc1b34..963d9258be67 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -25,6 +25,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_incremental = { path = "../rustc_incremental" }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 53953b089c61..84703a0a1569 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -15,7 +15,8 @@ use std::fmt::Write;
 
 use rustc_abi::Integer;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hashes::Hash64;
 use rustc_hir::def_id::DefId;
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability};
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index a8f83ca13e26..1705af1e210a 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -18,6 +18,7 @@ rustc-rayon = { version = "0.5.1", features = ["indexmap"] }
 rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
 rustc_arena = { path = "../rustc_arena" }
 rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 16c66824c5ba..c7c0d0ab0725 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,10 +1,9 @@
 use std::hash::{Hash, Hasher};
 
+use rustc_hashes::Hash64;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
-use crate::stable_hasher::{
-    FromStableHash, Hash64, StableHasherHash, impl_stable_traits_for_trivial_type,
-};
+use crate::stable_hasher::{FromStableHash, StableHasherHash, impl_stable_traits_for_trivial_type};
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 6ef73debadd5..66d3834d8578 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -84,7 +84,6 @@ pub mod vec_cache;
 pub mod work_queue;
 
 mod atomic_ref;
-mod hashes;
 
 /// This calls the passed function while ensuring it won't be inlined into the caller.
 #[inline(never)]
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 9cd0cc499ca3..ffbe54d62061 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -10,12 +10,11 @@ use smallvec::SmallVec;
 #[cfg(test)]
 mod tests;
 
+use rustc_hashes::{Hash64, Hash128};
 pub use rustc_stable_hash::{
     FromStableHash, SipHasher128Hash as StableHasherHash, StableSipHasher128 as StableHasher,
 };
 
-pub use crate::hashes::{Hash64, Hash128};
-
 /// Something that implements `HashStable` can be hashed in a way that is
 /// stable across multiple compilation sessions.
 ///
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
index b1bdee18d6d4..9c1e4cefa692 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
@@ -1,7 +1,8 @@
 use std::ptr;
 
+use rustc_hashes::Hash128;
+
 use super::*;
-use crate::hashes::Hash128;
 use crate::stable_hasher::{HashStable, StableHasher};
 
 /// A tag type used in [`TaggedRef`] tests.
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index fbb6a1cc4755..434f8c1c7675 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -14,6 +14,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8ff5dc125969..6fce1fade266 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -58,12 +58,13 @@ pub use emitter::ColorConfig;
 use emitter::{DynEmitter, Emitter, is_case_difference, is_different};
 use rustc_data_structures::AtomicRef;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
+use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{DynSend, Lock};
 pub use rustc_error_messages::{
     DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel,
     SubdiagMessage, fallback_fluent_bundle, fluent_bundle,
 };
+use rustc_hashes::Hash128;
 use rustc_lint_defs::LintExpectationId;
 pub use rustc_lint_defs::{Applicability, listify, pluralize};
 use rustc_macros::{Decodable, Encodable};
diff --git a/compiler/rustc_hashes/Cargo.toml b/compiler/rustc_hashes/Cargo.toml
new file mode 100644
index 000000000000..c2bae2fe8cb0
--- /dev/null
+++ b/compiler/rustc_hashes/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "rustc_hashes"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
+# tidy-alphabetical-start
+rustc-stable-hash = { version = "0.1.0" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_hashes/src/lib.rs
similarity index 79%
rename from compiler/rustc_data_structures/src/hashes.rs
rename to compiler/rustc_hashes/src/lib.rs
index b25758048bd3..3755caaaa296 100644
--- a/compiler/rustc_data_structures/src/hashes.rs
+++ b/compiler/rustc_hashes/src/lib.rs
@@ -1,6 +1,8 @@
 //! rustc encodes a lot of hashes. If hashes are stored as `u64` or `u128`, a `derive(Encodable)`
 //! will apply varint encoding to the hashes, which is less efficient than directly encoding the 8
-//! or 16 bytes of the hash.
+//! or 16 bytes of the hash. And if that hash depends on the `StableCrateHash` (which most in rustc
+//! do), the varint encoding will make the number of bytes encoded fluctuate between compiler
+//! versions.
 //!
 //! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`.
 //! `Hash64` and `Hash128` expose some utility functions to encourage users to not extract the inner
@@ -14,10 +16,9 @@
 use std::fmt;
 use std::ops::BitXorAssign;
 
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
-use crate::stable_hasher::{FromStableHash, StableHasherHash};
+use rustc_stable_hash::{FromStableHash, SipHasher128Hash as StableHasherHash};
 
+/// A `u64` but encoded with a fixed size; for hashes this encoding is more compact than `u64`.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
 pub struct Hash64 {
     inner: u64,
@@ -49,20 +50,6 @@ impl BitXorAssign for Hash64 {
     }
 }
 
-impl Encodable for Hash64 {
-    #[inline]
-    fn encode(&self, s: &mut S) {
-        s.emit_raw_bytes(&self.inner.to_le_bytes());
-    }
-}
-
-impl Decodable for Hash64 {
-    #[inline]
-    fn decode(d: &mut D) -> Self {
-        Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) }
-    }
-}
-
 impl FromStableHash for Hash64 {
     type Hash = StableHasherHash;
 
@@ -84,6 +71,7 @@ impl fmt::LowerHex for Hash64 {
     }
 }
 
+/// A `u128` but encoded with a fixed size; for hashes this encoding is more compact than `u128`.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
 pub struct Hash128 {
     inner: u128,
@@ -100,6 +88,11 @@ impl std::hash::Hash for Hash128 {
 }
 
 impl Hash128 {
+    #[inline]
+    pub fn new(n: u128) -> Self {
+        Self { inner: n }
+    }
+
     #[inline]
     pub fn truncate(self) -> Hash64 {
         Hash64 { inner: self.inner as u64 }
@@ -116,20 +109,6 @@ impl Hash128 {
     }
 }
 
-impl Encodable for Hash128 {
-    #[inline]
-    fn encode(&self, s: &mut S) {
-        s.emit_raw_bytes(&self.inner.to_le_bytes());
-    }
-}
-
-impl Decodable for Hash128 {
-    #[inline]
-    fn decode(d: &mut D) -> Self {
-        Self { inner: u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) }
-    }
-}
-
 impl FromStableHash for Hash128 {
     type Hash = StableHasherHash;
 
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 5bfc4756ec6a..b1516e53173b 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -10,6 +10,7 @@ rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_hir/src/def_path_hash_map.rs b/compiler/rustc_hir/src/def_path_hash_map.rs
index 9a6dee1e511d..35c6e57b8770 100644
--- a/compiler/rustc_hir/src/def_path_hash_map.rs
+++ b/compiler/rustc_hir/src/def_path_hash_map.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_hashes::Hash64;
 use rustc_span::def_id::DefIndex;
 
 #[derive(Clone, Default)]
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index dc527240f742..08a0a5225e74 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -7,8 +7,9 @@
 use std::fmt::{self, Write};
 use std::hash::Hash;
 
-use rustc_data_structures::stable_hasher::{Hash64, StableHasher};
+use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::unord::UnordMap;
+use rustc_hashes::Hash64;
 use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::{Symbol, kw, sym};
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index e0e63d183c63..0837444ffdbe 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,6 +1,6 @@
 #![allow(rustc::symbol_intern_string_literal)]
 
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_hashes::Hash64;
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 use rustc_span::edition::Edition;
 use rustc_span::{Symbol, create_session_globals_then};
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index de722e62043c..1b6a174c0932 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -22,6 +22,7 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index d4a9aac3733f..4a21b6ad2370 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -6,8 +6,9 @@ use rustc_attr_parsing::InlineAttr;
 use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::unord::UnordMap;
+use rustc_hashes::Hash128;
 use rustc_hir::ItemId;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
 use rustc_index::Idx;
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 2e90e5251e2b..bbb8a9fa6714 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -7,11 +7,11 @@ use rustc_abi::{
     PointeeInfo, PointerKind, Primitive, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout,
     TyAbiInterface, VariantIdx, Variants,
 };
-use rustc_data_structures::stable_hasher::Hash64;
 use rustc_error_messages::DiagMessage;
 use rustc_errors::{
     Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
 };
+use rustc_hashes::Hash64;
 use rustc_hir::LangItem;
 use rustc_hir::def_id::DefId;
 use rustc_index::IndexVec;
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 94bd359f6eb0..88d574985423 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -5,9 +5,10 @@ use std::{fmt, iter};
 use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size};
 use rustc_apfloat::Float as _;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorGuaranteed;
+use rustc_hashes::Hash128;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index 8b0cc9d726b8..fd1d21b6a892 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2021"
 measureme = "11"
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index e95c186f6b68..f98d6421307a 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -4,10 +4,11 @@
 
 use std::num::NonZero;
 
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::unord::UnordMap;
 use rustc_errors::DiagInner;
+use rustc_hashes::Hash64;
 use rustc_index::Idx;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::{
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index a42329b4614f..d9560f3eb0fa 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -13,6 +13,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 82c51193a19d..7490a3f35032 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -11,9 +11,9 @@ mod caches;
 pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
 
 mod config;
-use rustc_data_structures::stable_hasher::Hash64;
 use rustc_data_structures::sync::Lock;
 use rustc_errors::DiagInner;
+use rustc_hashes::Hash64;
 use rustc_hir::def::DefKind;
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::Span;
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index 8bf98c16361e..a6815c7a4476 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 indexmap = "2.0.0"
+rustc_hashes = { path = "../rustc_hashes" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index db8555edd0f8..1eefd76f92b4 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -10,6 +10,7 @@ use std::path;
 use std::rc::Rc;
 use std::sync::Arc;
 
+use rustc_hashes::{Hash64, Hash128};
 use smallvec::{Array, SmallVec};
 use thin_vec::ThinVec;
 
@@ -716,3 +717,31 @@ impl> Decodable for Arc<[T]> {
         vec.into()
     }
 }
+
+impl Encodable for Hash64 {
+    #[inline]
+    fn encode(&self, s: &mut S) {
+        s.emit_raw_bytes(&self.as_u64().to_le_bytes());
+    }
+}
+
+impl Encodable for Hash128 {
+    #[inline]
+    fn encode(&self, s: &mut S) {
+        s.emit_raw_bytes(&self.as_u128().to_le_bytes());
+    }
+}
+
+impl Decodable for Hash64 {
+    #[inline]
+    fn decode(d: &mut D) -> Self {
+        Self::new(u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()))
+    }
+}
+
+impl Decodable for Hash128 {
+    #[inline]
+    fn decode(d: &mut D) -> Self {
+        Self::new(u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()))
+    }
+}
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index b9c535df4bd0..31892c134380 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -14,6 +14,7 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7d473b86ff58..85ef69ea2b74 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2934,9 +2934,9 @@ pub(crate) mod dep_tracking {
 
     use rustc_abi::Align;
     use rustc_data_structures::fx::FxIndexMap;
-    use rustc_data_structures::stable_hasher::Hash64;
     use rustc_errors::LanguageIdentifier;
     use rustc_feature::UnstableFeatures;
+    use rustc_hashes::Hash64;
     use rustc_span::RealFileName;
     use rustc_span::edition::Edition;
     use rustc_target::spec::{
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 35819f896c5b..351dad3f3e42 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -7,9 +7,9 @@ use std::str;
 use rustc_abi::Align;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::profiling::TimePassesFormat;
-use rustc_data_structures::stable_hasher::Hash64;
 use rustc_errors::{ColorConfig, LanguageIdentifier, TerminalUrl};
 use rustc_feature::UnstableFeatures;
+use rustc_hashes::Hash64;
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::edition::Edition;
 use rustc_span::{RealFileName, SourceFileHashAlgorithm};
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 781fe6a11fe8..991c75cc98df 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -12,6 +12,7 @@ itoa = "1.0"
 md5 = { package = "md-5", version = "0.10.0" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index f61ce37131eb..641bac88ad02 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -3,10 +3,9 @@ use std::hash::{BuildHasherDefault, Hash, Hasher};
 
 use rustc_data_structures::AtomicRef;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::{
-    Hash64, HashStable, StableHasher, StableOrd, ToStableHashKey,
-};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
 use rustc_data_structures::unhash::Unhasher;
+use rustc_hashes::Hash64;
 use rustc_index::Idx;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_serialize::{Decodable, Encodable};
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 2910bcdf51d9..9bf1d305e541 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -33,9 +33,10 @@ use std::sync::Arc;
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
 use rustc_data_structures::sync::{Lock, WorkerLocal};
 use rustc_data_structures::unhash::UnhashMap;
+use rustc_hashes::Hash64;
 use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 0e146baef375..695edc956cdb 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -87,9 +87,10 @@ use std::sync::Arc;
 use std::{fmt, iter};
 
 use md5::{Digest, Md5};
-use rustc_data_structures::stable_hasher::{Hash64, Hash128, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock};
 use rustc_data_structures::unord::UnordMap;
+use rustc_hashes::{Hash64, Hash128};
 use sha1::Sha1;
 use sha2::Sha256;
 
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 1fb647cab5b5..4c51c908f541 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -11,6 +11,7 @@ rustc-demangle = "0.1.21"
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_symbol_mangling/src/hashed.rs b/compiler/rustc_symbol_mangling/src/hashed.rs
index 07c5f5447923..e965e6a7d53a 100644
--- a/compiler/rustc_symbol_mangling/src/hashed.rs
+++ b/compiler/rustc_symbol_mangling/src/hashed.rs
@@ -1,6 +1,7 @@
 use std::fmt::Write;
 
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hashes::Hash64;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::ty::{Instance, TyCtxt};
 
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 8ae35572d012..88754f1f15b4 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -1,7 +1,8 @@
 use std::fmt::{self, Write};
 use std::mem::{self, discriminant};
 
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hashes::Hash64;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::bug;
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 40356e0c9785..f88f8c38d508 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -11,6 +11,7 @@ rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hashes = { path = "../rustc_hashes" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 6a67009fe90c..8429e68b600d 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -9,7 +9,7 @@ use rustc_abi::{
     HasDataLayout, Layout, LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size,
     StructKind, TagEncoding, VariantIdx, Variants, WrappingRange,
 };
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_hashes::Hash64;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::bug;
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 52e4fa19cb02..83631f7fe343 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -14,6 +14,7 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
 use self::TyKind::*;
 pub use self::closure::*;
 use crate::inherent::*;
+#[cfg(feature = "nightly")]
 use crate::visit::TypeVisitable;
 use crate::{self as ty, DebruijnIndex, Interner};
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
index 8fc19854033c..5d1834a86424 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
@@ -9,6 +9,7 @@ use hir_expand::name::Name;
 use intern::sym;
 use la_arena::Arena;
 use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
+use rustc_hashes::Hash64;
 use triomphe::Arc;
 use tt::iter::TtElement;
 
@@ -172,7 +173,7 @@ fn parse_repr_tt(tt: &TopSubtree) -> Option {
         }
     }
 
-    Some(ReprOptions { int, align: max_align, pack: min_pack, flags, field_shuffle_seed: 0 })
+    Some(ReprOptions { int, align: max_align, pack: min_pack, flags, field_shuffle_seed: Hash64::ZERO })
 }
 
 impl StructData {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index c8efd9043203..9c947df35e99 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -18,9 +18,15 @@ extern crate ra_ap_rustc_parse_format as rustc_parse_format;
 #[cfg(feature = "in-rust-tree")]
 extern crate rustc_abi;
 
+#[cfg(feature = "in-rust-tree")]
+extern crate rustc_hashes;
+
 #[cfg(not(feature = "in-rust-tree"))]
 extern crate ra_ap_rustc_abi as rustc_abi;
 
+#[cfg(not(feature = "in-rust-tree"))]
+extern crate ra_ap_rustc_hashes as rustc_hashes;
+
 pub mod db;
 
 pub mod attr;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 108171586ea8..b6f7c44c2aee 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -15,6 +15,7 @@ use hir_def::{
 use la_arena::{Idx, RawIdx};
 use rustc_abi::AddressSpace;
 use rustc_index::{IndexSlice, IndexVec};
+use rustc_hashes::Hash64;
 
 use triomphe::Arc;
 
@@ -197,7 +198,7 @@ fn layout_of_simd_ty(
         align,
         max_repr_align: None,
         unadjusted_abi_align: align.abi,
-        randomization_seed: 0,
+        randomization_seed: Hash64::ZERO,
     }))
 }
 
@@ -314,7 +315,7 @@ pub fn layout_of_ty_query(
                 size,
                 max_repr_align: None,
                 unadjusted_abi_align: element.align.abi,
-                randomization_seed: 0,
+                randomization_seed: Hash64::ZERO,
             }
         }
         TyKind::Slice(element) => {
@@ -328,7 +329,7 @@ pub fn layout_of_ty_query(
                 size: Size::ZERO,
                 max_repr_align: None,
                 unadjusted_abi_align: element.align.abi,
-                randomization_seed: 0,
+                randomization_seed: Hash64::ZERO,
             }
         }
         TyKind::Str => Layout {
@@ -340,7 +341,7 @@ pub fn layout_of_ty_query(
             size: Size::ZERO,
             max_repr_align: None,
             unadjusted_abi_align: dl.i8_align.abi,
-            randomization_seed: 0,
+            randomization_seed: Hash64::ZERO,
         },
         // Potentially-wide pointers.
         TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 55d81875a2be..daddcf0b2424 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -12,6 +12,9 @@ extern crate ra_ap_rustc_index as rustc_index;
 #[cfg(feature = "in-rust-tree")]
 extern crate rustc_abi;
 
+#[cfg(feature = "in-rust-tree")]
+extern crate rustc_hashes;
+
 #[cfg(not(feature = "in-rust-tree"))]
 extern crate ra_ap_rustc_abi as rustc_abi;
 
@@ -21,6 +24,9 @@ extern crate rustc_pattern_analysis;
 #[cfg(not(feature = "in-rust-tree"))]
 extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
 
+#[cfg(not(feature = "in-rust-tree"))]
+extern crate ra_ap_rustc_hashes as rustc_hashes;
+
 mod builder;
 mod chalk_db;
 mod chalk_ext;
diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs
index 9fbc675cc9a3..cbc1f24b8c16 100644
--- a/tests/run-make/rustc-crates-on-stable/rmake.rs
+++ b/tests/run-make/rustc-crates-on-stable/rmake.rs
@@ -35,6 +35,8 @@ fn main() {
             "rustc_abi",
             "-p",
             "rustc_parse_format",
+            "-p",
+            "rustc_hashes",
         ])
         .run();
 }
diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.stderr b/tests/ui-fulldeps/missing-rustc-driver-error.stderr
index d7bf27d63491..faad62645222 100644
--- a/tests/ui-fulldeps/missing-rustc-driver-error.stderr
+++ b/tests/ui-fulldeps/missing-rustc-driver-error.stderr
@@ -2,5 +2,13 @@ error: crate `rustc_serialize` required to be available in rlib format, but was
    |
    = help: try adding `extern crate rustc_driver;` at the top level of this crate
 
+error: crate `rustc_hashes` required to be available in rlib format, but was not found in this form
+   |
+   = help: try adding `extern crate rustc_driver;` at the top level of this crate
+
+error: crate `rustc_stable_hash` required to be available in rlib format, but was not found in this form
+   |
+   = help: try adding `extern crate rustc_driver;` at the top level of this crate
+
 error: aborting due to NUMBER previous errors
 

From b023671ce2019cdc1768d4acfb148c86ab70183a Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 10:57:14 +1100
Subject: [PATCH 084/158] Add `pattern_complexity_limit` to `Limits`.

It's similar to the other limits, e.g. obtained via `get_limit`. So it
makes sense to handle it consistently with the other limits. We now use
`Limit`/`usize` in most places instead of `Option`, so we use
`Limit::new(usize::MAX)`/`usize::MAX` to emulate how `None` used to work.

The commit also adds `Limit::unlimited`.
---
 compiler/rustc_middle/src/middle/limits.rs    | 16 ++++++++++-----
 compiler/rustc_middle/src/ty/context.rs       |  4 ++++
 .../src/thir/pattern/check_match.rs           | 20 ++++++-------------
 compiler/rustc_pattern_analysis/src/rustc.rs  | 10 +++++++---
 .../rustc_pattern_analysis/src/usefulness.rs  | 17 ++++++++--------
 .../tests/common/mod.rs                       |  2 +-
 .../tests/complexity.rs                       |  2 +-
 .../tests/exhaustiveness.rs                   |  3 ++-
 .../tests/intersection.rs                     |  3 ++-
 compiler/rustc_session/src/session.rs         |  7 +++++++
 .../diagnostics/match_check/pat_analysis.rs   |  2 +-
 11 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 8a367a947d16..7dc1db5a22df 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -24,30 +24,36 @@ pub fn provide(providers: &mut Providers) {
             tcx.hir().krate_attrs(),
             tcx.sess,
             sym::move_size_limit,
-            tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0),
+            Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0)),
         ),
         type_length_limit: get_limit(
             tcx.hir().krate_attrs(),
             tcx.sess,
             sym::type_length_limit,
-            2usize.pow(24),
+            Limit::new(2usize.pow(24)),
+        ),
+        pattern_complexity_limit: get_limit(
+            tcx.hir().krate_attrs(),
+            tcx.sess,
+            sym::pattern_complexity,
+            Limit::unlimited(),
         ),
     }
 }
 
 pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
-    get_limit(krate_attrs, sess, sym::recursion_limit, 128)
+    get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128))
 }
 
 fn get_limit(
     krate_attrs: &[impl AttributeExt],
     sess: &Session,
     name: Symbol,
-    default: usize,
+    default: Limit,
 ) -> Limit {
     match get_limit_size(krate_attrs, sess, name) {
         Some(size) => Limit::new(size),
-        None => Limit::new(default),
+        None => default,
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index cb8dc6921487..ea2b610a727b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2168,6 +2168,10 @@ impl<'tcx> TyCtxt<'tcx> {
         self.limits(()).move_size_limit
     }
 
+    pub fn pattern_complexity_limit(self) -> Limit {
+        self.limits(()).pattern_complexity_limit
+    }
+
     /// All traits in the crate graph, including those not visible to the user.
     pub fn all_traits(self) -> impl Iterator + 'tcx {
         iter::once(LOCAL_CRATE)
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 697cb7cf37a3..7dd2ed7bbdf6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -10,7 +10,6 @@ use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::Level;
 use rustc_middle::bug;
-use rustc_middle::middle::limits::get_limit_size;
 use rustc_middle::thir::visit::Visitor;
 use rustc_middle::thir::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -25,7 +24,7 @@ use rustc_session::lint::builtin::{
 };
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::DesugaringKind;
-use rustc_span::{Ident, Span, sym};
+use rustc_span::{Ident, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
 use tracing::instrument;
 
@@ -404,18 +403,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
         arms: &[MatchArm<'p, 'tcx>],
         scrut_ty: Ty<'tcx>,
     ) -> Result, ErrorGuaranteed> {
-        let pattern_complexity_limit =
-            get_limit_size(cx.tcx.hir().krate_attrs(), cx.tcx.sess, sym::pattern_complexity);
-        let report = rustc_pattern_analysis::rustc::analyze_match(
-            &cx,
-            &arms,
-            scrut_ty,
-            pattern_complexity_limit,
-        )
-        .map_err(|err| {
-            self.error = Err(err);
-            err
-        })?;
+        let report =
+            rustc_pattern_analysis::rustc::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
+                self.error = Err(err);
+                err
+            })?;
 
         // Warn unreachable subpatterns.
         for (arm, is_useful) in report.arm_usefulness.iter() {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 2694cf472f48..0b1e954d64d4 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1084,12 +1084,16 @@ pub fn analyze_match<'p, 'tcx>(
     tycx: &RustcPatCtxt<'p, 'tcx>,
     arms: &[MatchArm<'p, 'tcx>],
     scrut_ty: Ty<'tcx>,
-    pattern_complexity_limit: Option,
 ) -> Result, ErrorGuaranteed> {
     let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
     let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee);
-    let report =
-        compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?;
+    let report = compute_match_usefulness(
+        tycx,
+        arms,
+        scrut_ty,
+        scrut_validity,
+        tycx.tcx.pattern_complexity_limit().0,
+    )?;
 
     // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
     // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index cc09cd491af1..1dff76141da5 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -795,20 +795,21 @@ struct UsefulnessCtxt<'a, 'p, Cx: PatCx> {
     /// Track information about the usefulness of branch patterns (see definition of "branch
     /// pattern" at [`BranchPatUsefulness`]).
     branch_usefulness: FxHashMap>,
-    complexity_limit: Option,
+    // Ideally this field would have type `Limit`, but this crate is used by
+    // rust-analyzer which cannot have a dependency on `Limit`, because `Limit`
+    // is from crate `rustc_session` which uses unstable Rust features.
+    complexity_limit: usize,
     complexity_level: usize,
 }
 
 impl<'a, 'p, Cx: PatCx> UsefulnessCtxt<'a, 'p, Cx> {
     fn increase_complexity_level(&mut self, complexity_add: usize) -> Result<(), Cx::Error> {
         self.complexity_level += complexity_add;
-        if self
-            .complexity_limit
-            .is_some_and(|complexity_limit| complexity_limit < self.complexity_level)
-        {
-            return self.tycx.complexity_exceeded();
+        if self.complexity_level <= self.complexity_limit {
+            Ok(())
+        } else {
+            self.tycx.complexity_exceeded()
         }
-        Ok(())
     }
 }
 
@@ -1834,7 +1835,7 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>(
     arms: &[MatchArm<'p, Cx>],
     scrut_ty: Cx::Ty,
     scrut_validity: PlaceValidity,
-    complexity_limit: Option,
+    complexity_limit: usize,
 ) -> Result, Cx::Error> {
     let mut cx = UsefulnessCtxt {
         tycx,
diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs
index cd697632d1b1..23560ad64190 100644
--- a/compiler/rustc_pattern_analysis/tests/common/mod.rs
+++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs
@@ -124,7 +124,7 @@ pub fn compute_match_usefulness<'p>(
     arms: &[MatchArm<'p, Cx>],
     ty: Ty,
     scrut_validity: PlaceValidity,
-    complexity_limit: Option,
+    complexity_limit: usize,
 ) -> Result, ()> {
     init_tracing();
     rustc_pattern_analysis::usefulness::compute_match_usefulness(
diff --git a/compiler/rustc_pattern_analysis/tests/complexity.rs b/compiler/rustc_pattern_analysis/tests/complexity.rs
index 43b585bc533a..abd1ec24d938 100644
--- a/compiler/rustc_pattern_analysis/tests/complexity.rs
+++ b/compiler/rustc_pattern_analysis/tests/complexity.rs
@@ -14,7 +14,7 @@ fn check(patterns: &[DeconstructedPat], complexity_limit: usize) -> Result<(
     let ty = *patterns[0].ty();
     let arms: Vec<_> =
         patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
-    compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, Some(complexity_limit))
+    compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, complexity_limit)
         .map(|_report| ())
 }
 
diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
index 0d80042a850f..61ce0fd11e77 100644
--- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
+++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
@@ -14,7 +14,8 @@ fn check(patterns: Vec>) -> Vec> {
     let arms: Vec<_> =
         patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
     let report =
-        compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, None).unwrap();
+        compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, usize::MAX)
+            .unwrap();
     report.non_exhaustiveness_witnesses
 }
 
diff --git a/compiler/rustc_pattern_analysis/tests/intersection.rs b/compiler/rustc_pattern_analysis/tests/intersection.rs
index a852056b6a6c..45674338efd4 100644
--- a/compiler/rustc_pattern_analysis/tests/intersection.rs
+++ b/compiler/rustc_pattern_analysis/tests/intersection.rs
@@ -14,7 +14,8 @@ fn check(patterns: Vec>) -> Vec> {
     let arms: Vec<_> =
         patterns.iter().map(|pat| MatchArm { pat, has_guard: false, arm_data: () }).collect();
     let report =
-        compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, None).unwrap();
+        compute_match_usefulness(arms.as_slice(), ty, PlaceValidity::ValidOnly, usize::MAX)
+            .unwrap();
     report.arm_intersections.into_iter().map(|bitset| bitset.iter().collect()).collect()
 }
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index f795ad1ee17d..c4d45ee02eea 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -67,6 +67,11 @@ impl Limit {
         Limit(value)
     }
 
+    /// Create a new unlimited limit.
+    pub fn unlimited() -> Self {
+        Limit(usize::MAX)
+    }
+
     /// Check that `value` is within the limit. Ensures that the same comparisons are used
     /// throughout the compiler, as mismatches can cause ICEs, see #72540.
     #[inline]
@@ -119,6 +124,8 @@ pub struct Limits {
     pub move_size_limit: Limit,
     /// The maximum length of types during monomorphization.
     pub type_length_limit: Limit,
+    /// The maximum pattern complexity allowed (internal only).
+    pub pattern_complexity_limit: Limit,
 }
 
 pub struct CompilerIO {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 2b854310a15e..3312da470c03 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -95,7 +95,7 @@ impl<'db> MatchCheckCtx<'db> {
 
         let place_validity = PlaceValidity::from_bool(known_valid_scrutinee.unwrap_or(true));
         // Measured to take ~100ms on modern hardware.
-        let complexity_limit = Some(500000);
+        let complexity_limit = 500000;
         compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit)
     }
 

From 30b8c84de693885a9645add17c0e0e6a7c391db3 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 14:16:59 +1100
Subject: [PATCH 085/158] Merge `get_limit` and `get_limit_size`.

Thanks to the previous commit, they no longer need to be separate.
---
 compiler/rustc_middle/src/middle/limits.rs | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 7dc1db5a22df..53590eee9271 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -51,17 +51,6 @@ fn get_limit(
     name: Symbol,
     default: Limit,
 ) -> Limit {
-    match get_limit_size(krate_attrs, sess, name) {
-        Some(size) => Limit::new(size),
-        None => default,
-    }
-}
-
-pub fn get_limit_size(
-    krate_attrs: &[impl AttributeExt],
-    sess: &Session,
-    name: Symbol,
-) -> Option {
     for attr in krate_attrs {
         if !attr.has_name(name) {
             continue;
@@ -69,7 +58,7 @@ pub fn get_limit_size(
 
         if let Some(sym) = attr.value_str() {
             match sym.as_str().parse() {
-                Ok(n) => return Some(n),
+                Ok(n) => return Limit::new(n),
                 Err(e) => {
                     let error_str = match e.kind() {
                         IntErrorKind::PosOverflow => "`limit` is too large",
@@ -90,5 +79,5 @@ pub fn get_limit_size(
             }
         }
     }
-    None
+    default
 }

From 13280eed6a04b94efa3702733d733f5496f60d27 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 14:28:52 +1100
Subject: [PATCH 086/158] Improve comments about limits.

---
 compiler/rustc_middle/src/middle/limits.rs | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 53590eee9271..bc5d629c9abb 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -1,12 +1,12 @@
 //! Registering limits:
-//! * recursion_limit,
-//! * move_size_limit, and
-//! * type_length_limit
+//! - recursion_limit: there are various parts of the compiler that must impose arbitrary limits
+//!   on how deeply they recurse to prevent stack overflow.
+//! - move_size_limit
+//! - type_length_limit
+//! - pattern_complexity_limit
 //!
-//! There are various parts of the compiler that must impose arbitrary limits
-//! on how deeply they recurse to prevent stack overflow. Users can override
-//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
-//! just peeks and looks for that attribute.
+//! Users can override these limits via an attribute on the crate like
+//! `#![recursion_limit="22"]`. This pass just looks for those attributes.
 
 use std::num::IntErrorKind;
 
@@ -41,6 +41,7 @@ pub fn provide(providers: &mut Providers) {
     }
 }
 
+// This one is separate because it must be read prior to macro expansion.
 pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
     get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128))
 }

From 223c95fd59f361ff482bf26434900fc8f72fbe04 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 16:19:05 +1100
Subject: [PATCH 087/158] Move `rustc_middle::limits` to `rustc_interface`.

It's always good to make `rustc_middle` smaller. `rustc_interface` is
the best destination, because it's the only crate that calls
`get_recursive_limit`.
---
 compiler/rustc_interface/messages.ftl                  |  4 ++++
 compiler/rustc_interface/src/errors.rs                 | 10 ++++++++++
 compiler/rustc_interface/src/lib.rs                    |  1 +
 .../src/middle => rustc_interface/src}/limits.rs       |  9 +++++----
 compiler/rustc_interface/src/passes.rs                 |  5 +++--
 compiler/rustc_middle/messages.ftl                     |  4 ----
 compiler/rustc_middle/src/error.rs                     | 10 ----------
 compiler/rustc_middle/src/middle/mod.rs                |  5 -----
 compiler/rustc_middle/src/ty/mod.rs                    |  1 -
 9 files changed, 23 insertions(+), 26 deletions(-)
 rename compiler/{rustc_middle/src/middle => rustc_interface/src}/limits.rs (91%)

diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 43c69c8e5718..adc7ed54e147 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -33,6 +33,10 @@ interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
 interface_input_file_would_be_overwritten =
     the input file "{$path}" would be overwritten by the generated executable
 
+interface_limit_invalid =
+    `limit` must be a non-negative integer
+    .label = {$error_str}
+
 interface_mixed_bin_crate =
     cannot mix `bin` crate type with others
 
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index c3b858d4f2ec..ca4e556dcdb8 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -127,3 +127,13 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
     pub feature: &'a str,
     pub enabled: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(interface_limit_invalid)]
+pub(crate) struct LimitInvalid<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub value_span: Span,
+    pub error_str: &'a str,
+}
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index a2a29612e489..54cd341698f0 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -10,6 +10,7 @@
 mod callbacks;
 pub mod errors;
 pub mod interface;
+mod limits;
 pub mod passes;
 mod proc_macro_decls;
 mod queries;
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_interface/src/limits.rs
similarity index 91%
rename from compiler/rustc_middle/src/middle/limits.rs
rename to compiler/rustc_interface/src/limits.rs
index bc5d629c9abb..08d155a2c23d 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_interface/src/limits.rs
@@ -11,13 +11,14 @@
 use std::num::IntErrorKind;
 
 use rustc_ast::attr::AttributeExt;
+use rustc_middle::bug;
+use rustc_middle::query::Providers;
 use rustc_session::{Limit, Limits, Session};
 use rustc_span::{Symbol, sym};
 
-use crate::error::LimitInvalid;
-use crate::query::Providers;
+use crate::errors::LimitInvalid;
 
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
     providers.limits = |tcx, ()| Limits {
         recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
         move_size_limit: get_limit(
@@ -42,7 +43,7 @@ pub fn provide(providers: &mut Providers) {
 }
 
 // This one is separate because it must be read prior to macro expansion.
-pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
+pub(crate) fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
     get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128))
 }
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index fcebca3ecc91..d7d183e17edb 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -39,7 +39,7 @@ use rustc_trait_selection::traits;
 use tracing::{info, instrument};
 
 use crate::interface::Compiler;
-use crate::{errors, proc_macro_decls, util};
+use crate::{errors, limits, proc_macro_decls, util};
 
 pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
     let krate = sess
@@ -687,6 +687,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| {
         |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
     providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
     providers.early_lint_checks = early_lint_checks;
+    limits::provide(providers);
     proc_macro_decls::provide(providers);
     rustc_const_eval::provide(providers);
     rustc_middle::hir::provide(providers);
@@ -1134,7 +1135,7 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit
     // because that would require expanding this while in the middle of expansion, which needs to
     // know the limit before expanding.
     let _ = validate_and_find_value_str_builtin_attr(sym::recursion_limit, sess, krate_attrs);
-    rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
+    crate::limits::get_recursion_limit(krate_attrs, sess)
 }
 
 /// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find.
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 09c16222be19..dcfa81dab252 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -81,10 +81,6 @@ middle_failed_writing_file =
 middle_layout_references_error =
     the type has an unknown layout
 
-middle_limit_invalid =
-    `limit` must be a non-negative integer
-    .label = {$error_str}
-
 middle_opaque_hidden_type_mismatch =
     concrete type differs from previous defining opaque type use
     .label = expected `{$self_ty}`, got `{$other_ty}`
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 91b18295b43b..c53e3d54cc49 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -67,16 +67,6 @@ pub enum TypeMismatchReason {
     },
 }
 
-#[derive(Diagnostic)]
-#[diag(middle_limit_invalid)]
-pub(crate) struct LimitInvalid<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[label]
-    pub value_span: Span,
-    pub error_str: &'a str,
-}
-
 #[derive(Diagnostic)]
 #[diag(middle_recursion_limit_reached)]
 #[help]
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 692fe027c490..9f71971ea08b 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -30,12 +30,7 @@ pub mod lib_features {
         }
     }
 }
-pub mod limits;
 pub mod privacy;
 pub mod region;
 pub mod resolve_bound_vars;
 pub mod stability;
-
-pub fn provide(providers: &mut crate::query::Providers) {
-    limits::provide(providers);
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 52cb8f57a88a..04519008711b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2168,7 +2168,6 @@ pub fn provide(providers: &mut Providers) {
     util::provide(providers);
     print::provide(providers);
     super::util::bug::provide(providers);
-    super::middle::provide(providers);
     *providers = Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         incoherent_impls: trait_def::incoherent_impls_provider,

From 7a8c0fc117a4d866ea0c362cc173f90c7bf14dd6 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 15:58:00 +1100
Subject: [PATCH 088/158] Rename `pattern_complexity` attr as
 `pattern_complexity_limit`.

For consistency with `recursion_limit`, `move_size_limit`, and
`type_length_limit`.
---
 compiler/rustc_feature/src/builtin_attrs.rs               | 2 +-
 compiler/rustc_feature/src/unstable.rs                    | 2 +-
 compiler/rustc_interface/src/limits.rs                    | 2 +-
 compiler/rustc_span/src/symbol.rs                         | 2 +-
 .../rust-analyzer/crates/ide-db/src/generated/lints.rs    | 4 ++--
 .../feature-gate-pattern-complexity-limit.rs              | 6 ++++++
 ...tderr => feature-gate-pattern-complexity-limit.stderr} | 8 ++++----
 tests/ui/feature-gates/feature-gate-pattern-complexity.rs | 6 ------
 tests/ui/pattern/complexity_limit.rs                      | 2 +-
 .../issue-118437-exponential-time-on-diagonal-match.rs    | 2 +-
 10 files changed, 18 insertions(+), 18 deletions(-)
 create mode 100644 tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs
 rename tests/ui/feature-gates/{feature-gate-pattern-complexity.stderr => feature-gate-pattern-complexity-limit.stderr} (53%)
 delete mode 100644 tests/ui/feature-gates/feature-gate-pattern-complexity.rs

diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index eb5fac96af27..8eb9bf158290 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1149,7 +1149,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
     ),
     rustc_attr!(
-        TEST, pattern_complexity, CrateLevel, template!(NameValueStr: "N"),
+        TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"),
         ErrorFollowing, EncodeCrossCrate::No,
     ),
 ];
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index a638a845c07e..e852f239aa27 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -227,7 +227,7 @@ declare_features! (
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (internal, omit_gdb_pretty_printer_section, "1.5.0", None),
     /// Set the maximum pattern complexity allowed (not limited by default).
-    (internal, pattern_complexity, "1.78.0", None),
+    (internal, pattern_complexity_limit, "1.78.0", None),
     /// Allows using pattern types.
     (internal, pattern_types, "1.79.0", Some(123646)),
     /// Allows using `#[prelude_import]` on glob `use` items.
diff --git a/compiler/rustc_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs
index 08d155a2c23d..3de513797e3e 100644
--- a/compiler/rustc_interface/src/limits.rs
+++ b/compiler/rustc_interface/src/limits.rs
@@ -36,7 +36,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         pattern_complexity_limit: get_limit(
             tcx.hir().krate_attrs(),
             tcx.sess,
-            sym::pattern_complexity,
+            sym::pattern_complexity_limit,
             Limit::unlimited(),
         ),
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 62723e385cf6..1bd97916d1ca 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1512,7 +1512,7 @@ symbols! {
         path_main_separator,
         path_to_pathbuf,
         pathbuf_as_path,
-        pattern_complexity,
+        pattern_complexity_limit,
         pattern_parentheses,
         pattern_type,
         pattern_types,
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index 14af22c31931..ed9d6c67501e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -9107,8 +9107,8 @@ The tracking issue for this feature is: [#27721]
         deny_since: None,
     },
     Lint {
-        label: "pattern_complexity",
-        description: r##"# `pattern_complexity`
+        label: "pattern_complexity_limit",
+        description: r##"# `pattern_complexity_limit`
 
 This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
 
diff --git a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs
new file mode 100644
index 000000000000..d1f6f4755f08
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs
@@ -0,0 +1,6 @@
+// check that `pattern_complexity_limit` is feature-gated
+
+#![pattern_complexity_limit = "42"]
+//~^ ERROR: the `#[pattern_complexity_limit]` attribute is just used for rustc unit tests
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-pattern-complexity.stderr b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr
similarity index 53%
rename from tests/ui/feature-gates/feature-gate-pattern-complexity.stderr
rename to tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr
index c05e6abb0176..e6f17710e096 100644
--- a/tests/ui/feature-gates/feature-gate-pattern-complexity.stderr
+++ b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr
@@ -1,8 +1,8 @@
-error[E0658]: the `#[pattern_complexity]` attribute is just used for rustc unit tests and will never be stable
-  --> $DIR/feature-gate-pattern-complexity.rs:3:1
+error[E0658]: the `#[pattern_complexity_limit]` attribute is just used for rustc unit tests and will never be stable
+  --> $DIR/feature-gate-pattern-complexity-limit.rs:3:1
    |
-LL | #![pattern_complexity = "42"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![pattern_complexity_limit = "42"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/feature-gates/feature-gate-pattern-complexity.rs b/tests/ui/feature-gates/feature-gate-pattern-complexity.rs
deleted file mode 100644
index 43e9a00c9a7e..000000000000
--- a/tests/ui/feature-gates/feature-gate-pattern-complexity.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// check that `pattern_complexity` is feature-gated
-
-#![pattern_complexity = "42"]
-//~^ ERROR: the `#[pattern_complexity]` attribute is just used for rustc unit tests
-
-fn main() {}
diff --git a/tests/ui/pattern/complexity_limit.rs b/tests/ui/pattern/complexity_limit.rs
index c9a3f99bccd1..7c1278205115 100644
--- a/tests/ui/pattern/complexity_limit.rs
+++ b/tests/ui/pattern/complexity_limit.rs
@@ -1,5 +1,5 @@
 #![feature(rustc_attrs)]
-#![pattern_complexity = "10000"]
+#![pattern_complexity_limit = "10000"]
 
 #[derive(Default)]
 struct BaseCommand {
diff --git a/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs b/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs
index 783512d5cca3..44d1586ce4fc 100644
--- a/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs
+++ b/tests/ui/pattern/usefulness/issue-118437-exponential-time-on-diagonal-match.rs
@@ -1,5 +1,5 @@
 #![feature(rustc_attrs)]
-#![pattern_complexity = "61"]
+#![pattern_complexity_limit = "61"]
 
 //@ check-pass
 struct BaseCommand {

From 13003100f803419307ada53620d00aa51ea678db Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Tue, 11 Feb 2025 16:33:17 +1100
Subject: [PATCH 089/158] Refactor `apply_effects_in_block`.

Very minor changes that will make the next few commits easier to follow.
---
 .../src/framework/direction.rs                | 20 +++++++------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 07517d7edab0..528debcaba34 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -112,14 +112,11 @@ impl Direction for Backward {
 
                 mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
                     if let Some(mut data) = analysis.get_switch_int_data(block, discr) {
-                        let values = &body.basic_blocks.switch_sources()[&(block, pred)];
-                        let targets =
-                            values.iter().map(|&value| SwitchIntTarget { value, target: block });
-
                         let mut tmp = analysis.bottom_value(body);
-                        for target in targets {
-                            tmp.clone_from(&exit_state);
-                            analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, target);
+                        for &value in &body.basic_blocks.switch_sources()[&(block, pred)] {
+                            tmp.clone_from(exit_state);
+                            let si_target = SwitchIntTarget { value, target: block };
+                            analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, si_target);
                             propagate(pred, &tmp);
                         }
                     } else {
@@ -292,12 +289,9 @@ impl Direction for Forward {
                 if let Some(mut data) = analysis.get_switch_int_data(block, discr) {
                     let mut tmp = analysis.bottom_value(body);
                     for (value, target) in targets.iter() {
-                        tmp.clone_from(&exit_state);
-                        analysis.apply_switch_int_edge_effect(
-                            &mut data,
-                            &mut tmp,
-                            SwitchIntTarget { value: Some(value), target },
-                        );
+                        tmp.clone_from(exit_state);
+                        let si_target = SwitchIntTarget { value: Some(value), target };
+                        analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, si_target);
                         propagate(target, &tmp);
                     }
 

From 23dbff88f6ecf7b92129ec3cfc41971b5cd9579c Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Thu, 13 Feb 2025 10:46:34 +1100
Subject: [PATCH 090/158] Add a useful comment.

---
 compiler/rustc_middle/src/mir/basic_blocks.rs | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index c32cf5f82533..5c6708303760 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -20,6 +20,13 @@ pub struct BasicBlocks<'tcx> {
 // Typically 95%+ of basic blocks have 4 or fewer predecessors.
 type Predecessors = IndexVec>;
 
+/// Each `(target, switch)` entry in the map contains a list of switch values
+/// that lead to a `target` block from a `switch` block.
+///
+/// Note: this type is currently never instantiated, because it's only used for
+/// `BasicBlocks::switch_sources`, which is only called by backwards analyses
+/// that do `SwitchInt` handling, and we don't have any of those, not even in
+/// tests. See #95120 and #94576.
 type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option; 1]>>;
 
 #[derive(Clone, Default, Debug)]
@@ -70,8 +77,8 @@ impl<'tcx> BasicBlocks<'tcx> {
         })
     }
 
-    /// `switch_sources()[&(target, switch)]` returns a list of switch
-    /// values that lead to a `target` block from a `switch` block.
+    /// Returns info about switch values that lead from one block to another
+    /// block. See `SwitchSources`.
     #[inline]
     pub fn switch_sources(&self) -> &SwitchSources {
         self.cache.switch_sources.get_or_init(|| {

From 8403d39dce2b6875381974a3f413c0c610f2ca1a Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 14 Feb 2025 09:54:01 +1100
Subject: [PATCH 091/158] Add `SwitchTargetValue`.

This is much clearer than `Option`.
---
 compiler/rustc_middle/src/mir/basic_blocks.rs | 20 ++++++++++++++++---
 compiler/rustc_middle/src/mir/mod.rs          |  2 +-
 .../src/framework/direction.rs                |  9 ++++++---
 .../rustc_mir_dataflow/src/framework/mod.rs   |  6 ++++--
 .../src/impls/initialized.rs                  |  8 +++++---
 5 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 5c6708303760..107c3198525a 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -27,7 +27,15 @@ type Predecessors = IndexVec>;
 /// `BasicBlocks::switch_sources`, which is only called by backwards analyses
 /// that do `SwitchInt` handling, and we don't have any of those, not even in
 /// tests. See #95120 and #94576.
-type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option; 1]>>;
+type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[SwitchTargetValue; 1]>>;
+
+#[derive(Debug, Clone, Copy)]
+pub enum SwitchTargetValue {
+    // A normal switch value.
+    Normal(u128),
+    // The final "otherwise" fallback value.
+    Otherwise,
+}
 
 #[derive(Clone, Default, Debug)]
 struct Cache {
@@ -89,9 +97,15 @@ impl<'tcx> BasicBlocks<'tcx> {
                 }) = &data.terminator
                 {
                     for (value, target) in targets.iter() {
-                        switch_sources.entry((target, bb)).or_default().push(Some(value));
+                        switch_sources
+                            .entry((target, bb))
+                            .or_default()
+                            .push(SwitchTargetValue::Normal(value));
                     }
-                    switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
+                    switch_sources
+                        .entry((targets.otherwise(), bb))
+                        .or_default()
+                        .push(SwitchTargetValue::Otherwise);
                 }
             }
             switch_sources
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 795cfcef2d36..cc22cabcb3e8 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -7,7 +7,7 @@ use std::fmt::{self, Debug, Formatter};
 use std::ops::{Index, IndexMut};
 use std::{iter, mem};
 
-pub use basic_blocks::BasicBlocks;
+pub use basic_blocks::{BasicBlocks, SwitchTargetValue};
 use either::Either;
 use polonius_engine::Atom;
 use rustc_abi::{FieldIdx, VariantIdx};
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 528debcaba34..02b2bbb35076 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,6 +1,8 @@
 use std::ops::RangeInclusive;
 
-use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
+use rustc_middle::mir::{
+    self, BasicBlock, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges,
+};
 
 use super::visitor::ResultsVisitor;
 use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
@@ -290,7 +292,8 @@ impl Direction for Forward {
                     let mut tmp = analysis.bottom_value(body);
                     for (value, target) in targets.iter() {
                         tmp.clone_from(exit_state);
-                        let si_target = SwitchIntTarget { value: Some(value), target };
+                        let si_target =
+                            SwitchIntTarget { value: SwitchTargetValue::Normal(value), target };
                         analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, si_target);
                         propagate(target, &tmp);
                     }
@@ -302,7 +305,7 @@ impl Direction for Forward {
                     analysis.apply_switch_int_edge_effect(
                         &mut data,
                         exit_state,
-                        SwitchIntTarget { value: None, target: otherwise },
+                        SwitchIntTarget { value: SwitchTargetValue::Otherwise, target: otherwise },
                     );
                     propagate(otherwise, exit_state);
                 } else {
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 60c5cb0cae8a..14630991cd6c 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -38,7 +38,9 @@ use rustc_data_structures::work_queue::WorkQueue;
 use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::bug;
-use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal};
+use rustc_middle::mir::{
+    self, BasicBlock, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges, traversal,
+};
 use rustc_middle::ty::TyCtxt;
 use tracing::error;
 
@@ -431,7 +433,7 @@ impl EffectIndex {
 }
 
 pub struct SwitchIntTarget {
-    pub value: Option,
+    pub value: SwitchTargetValue,
     pub target: BasicBlock,
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 3be450a0b3f4..f2fbadaac09d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -4,7 +4,9 @@ use rustc_abi::VariantIdx;
 use rustc_index::Idx;
 use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
 use rustc_middle::bug;
-use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges};
+use rustc_middle::mir::{
+    self, Body, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges,
+};
 use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::{self, TyCtxt};
 use tracing::{debug, instrument};
@@ -424,7 +426,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         state: &mut Self::Domain,
         edge: SwitchIntTarget,
     ) {
-        if let Some(value) = edge.value {
+        if let SwitchTargetValue::Normal(value) = edge.value {
             // Kill all move paths that correspond to variants we know to be inactive along this
             // particular outgoing edge of a `SwitchInt`.
             drop_flag_effects::on_all_inactive_variants(
@@ -537,7 +539,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
         state: &mut Self::Domain,
         edge: SwitchIntTarget,
     ) {
-        if let Some(value) = edge.value {
+        if let SwitchTargetValue::Normal(value) = edge.value {
             // Mark all move paths that correspond to variants other than this one as maybe
             // uninitialized (in reality, they are *definitely* uninitialized).
             drop_flag_effects::on_all_inactive_variants(

From db1ca60470d3d9bcb533ad1130e669dcd8c7ffd2 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 14 Feb 2025 10:57:06 +1100
Subject: [PATCH 092/158] Update and clarify the comment on `SwitchTargets`.

---
 compiler/rustc_middle/src/mir/syntax.rs | 30 ++++++++++++++++---------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 9cec8d832dd1..dfd40a9535ba 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1015,22 +1015,30 @@ impl TerminatorKind<'_> {
 
 #[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
 pub struct SwitchTargets {
-    /// Possible values. The locations to branch to in each case
-    /// are found in the corresponding indices from the `targets` vector.
+    /// Possible values. For each value, the location to branch to is found in
+    /// the corresponding element in the `targets` vector.
     pub(super) values: SmallVec<[Pu128; 1]>,
 
-    /// Possible branch sites. The last element of this vector is used
-    /// for the otherwise branch, so targets.len() == values.len() + 1
-    /// should hold.
+    /// Possible branch targets. The last element of this vector is used for
+    /// the "otherwise" branch, so `targets.len() == values.len() + 1` always
+    /// holds.
     //
-    // This invariant is quite non-obvious and also could be improved.
-    // One way to make this invariant is to have something like this instead:
+    // Note: This invariant is non-obvious and easy to violate. This would be a
+    // more rigorous representation:
     //
-    // branches: Vec<(ConstInt, BasicBlock)>,
-    // otherwise: Option // exhaustive if None
+    //   normal: SmallVec<[(Pu128, BasicBlock); 1]>,
+    //   otherwise: BasicBlock,
     //
-    // However we’ve decided to keep this as-is until we figure a case
-    // where some other approach seems to be strictly better than other.
+    // But it's important to have the targets in a sliceable type, because
+    // target slices show up elsewhere. E.g. `TerminatorKind::InlineAsm` has a
+    // boxed slice, and `TerminatorKind::FalseEdge` has a single target that
+    // can be converted to a slice with `slice::from_ref`.
+    //
+    // Why does this matter? In functions like `TerminatorKind::successors` we
+    // return `impl Iterator` and a non-slice-of-targets representation here
+    // causes problems because multiple different concrete iterator types would
+    // be involved and we would need a boxed trait object, which requires an
+    // allocation, which is expensive if done frequently.
     pub(super) targets: SmallVec<[BasicBlock; 2]>,
 }
 

From 3b81d9d42d07d3e2c4f9f0c714fb16d2527758fe Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 14 Feb 2025 13:23:00 +1100
Subject: [PATCH 093/158] Remove `SwitchIntTarget`.

It's only passed to `Analysis::apply_switch_int_edge_effect`, and the
existing impls of that method only use the `value` field. So pass that
instead.
---
 .../rustc_mir_dataflow/src/framework/direction.rs    | 12 +++++-------
 compiler/rustc_mir_dataflow/src/framework/mod.rs     |  7 +------
 compiler/rustc_mir_dataflow/src/impls/initialized.rs |  9 ++++-----
 3 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 02b2bbb35076..3d7f9e2d8e71 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -5,7 +5,7 @@ use rustc_middle::mir::{
 };
 
 use super::visitor::ResultsVisitor;
-use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
+use super::{Analysis, Effect, EffectIndex, Results};
 
 pub trait Direction {
     const IS_FORWARD: bool;
@@ -117,8 +117,7 @@ impl Direction for Backward {
                         let mut tmp = analysis.bottom_value(body);
                         for &value in &body.basic_blocks.switch_sources()[&(block, pred)] {
                             tmp.clone_from(exit_state);
-                            let si_target = SwitchIntTarget { value, target: block };
-                            analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, si_target);
+                            analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, value);
                             propagate(pred, &tmp);
                         }
                     } else {
@@ -292,9 +291,8 @@ impl Direction for Forward {
                     let mut tmp = analysis.bottom_value(body);
                     for (value, target) in targets.iter() {
                         tmp.clone_from(exit_state);
-                        let si_target =
-                            SwitchIntTarget { value: SwitchTargetValue::Normal(value), target };
-                        analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, si_target);
+                        let value = SwitchTargetValue::Normal(value);
+                        analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, value);
                         propagate(target, &tmp);
                     }
 
@@ -305,7 +303,7 @@ impl Direction for Forward {
                     analysis.apply_switch_int_edge_effect(
                         &mut data,
                         exit_state,
-                        SwitchIntTarget { value: SwitchTargetValue::Otherwise, target: otherwise },
+                        SwitchTargetValue::Otherwise,
                     );
                     propagate(otherwise, exit_state);
                 } else {
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 14630991cd6c..09f6cdb5c4a7 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -222,7 +222,7 @@ pub trait Analysis<'tcx> {
         &mut self,
         _data: &mut Self::SwitchIntData,
         _state: &mut Self::Domain,
-        _edge: SwitchIntTarget,
+        _value: SwitchTargetValue,
     ) {
         unreachable!();
     }
@@ -432,10 +432,5 @@ impl EffectIndex {
     }
 }
 
-pub struct SwitchIntTarget {
-    pub value: SwitchTargetValue,
-    pub target: BasicBlock,
-}
-
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index f2fbadaac09d..f5ffc42d52ab 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -12,7 +12,6 @@ use rustc_middle::ty::{self, TyCtxt};
 use tracing::{debug, instrument};
 
 use crate::drop_flag_effects::DropFlagState;
-use crate::framework::SwitchIntTarget;
 use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
 use crate::{
     Analysis, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry,
@@ -424,9 +423,9 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         &mut self,
         data: &mut Self::SwitchIntData,
         state: &mut Self::Domain,
-        edge: SwitchIntTarget,
+        value: SwitchTargetValue,
     ) {
-        if let SwitchTargetValue::Normal(value) = edge.value {
+        if let SwitchTargetValue::Normal(value) = value {
             // Kill all move paths that correspond to variants we know to be inactive along this
             // particular outgoing edge of a `SwitchInt`.
             drop_flag_effects::on_all_inactive_variants(
@@ -537,9 +536,9 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
         &mut self,
         data: &mut Self::SwitchIntData,
         state: &mut Self::Domain,
-        edge: SwitchIntTarget,
+        value: SwitchTargetValue,
     ) {
-        if let SwitchTargetValue::Normal(value) = edge.value {
+        if let SwitchTargetValue::Normal(value) = value {
             // Mark all move paths that correspond to variants other than this one as maybe
             // uninitialized (in reality, they are *definitely* uninitialized).
             drop_flag_effects::on_all_inactive_variants(

From 7ff67901acd7dd0669a2f41a618d5e539b6d3663 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 16:08:48 +1100
Subject: [PATCH 094/158] Avoid unnecessary use of the `Map` trait.

The `Map` trait is there for cases where `tcx` isn't available. This
isn't one of those cases, so it's simpler to just call through `tcx`
directly.
---
 compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6269728e67f7..8fa409f4e381 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -14,7 +14,7 @@ use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, MultiSpan, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{Map, Visitor, walk_block, walk_expr};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter::OnlyBodies;
@@ -1082,7 +1082,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 ] {
                     for (destination, sp) in elements {
                         if let Ok(hir_id) = destination.target_id
-                            && let hir::Node::Expr(expr) = tcx.hir().hir_node(hir_id)
+                            && let hir::Node::Expr(expr) = tcx.hir_node(hir_id)
                             && !matches!(
                                 sp.desugaring_kind(),
                                 Some(DesugaringKind::ForLoop | DesugaringKind::WhileLoop)

From b51ab7d9be51ad70addf7ddb62dfa85e2bac1e2e Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 15:29:12 +1100
Subject: [PATCH 095/158] Clarify `impl Map for !`.

All the methods are unreachable, so make that clearer.
---
 compiler/rustc_hir/src/intravisit.rs | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index f632041dba9f..01e6fb890534 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -121,25 +121,25 @@ pub trait Map<'hir> {
 // Used when no map is actually available, forcing manual implementation of nested visitors.
 impl<'hir> Map<'hir> for ! {
     fn hir_node(&self, _: HirId) -> Node<'hir> {
-        *self;
+        unreachable!();
     }
     fn hir_node_by_def_id(&self, _: LocalDefId) -> Node<'hir> {
         *self;
     }
     fn body(&self, _: BodyId) -> &'hir Body<'hir> {
-        *self;
+        unreachable!();
     }
     fn item(&self, _: ItemId) -> &'hir Item<'hir> {
-        *self;
+        unreachable!();
     }
     fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
-        *self;
+        unreachable!();
     }
     fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
-        *self;
+        unreachable!();
     }
     fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        *self;
+        unreachable!();
     }
 }
 
@@ -203,7 +203,7 @@ use nested_filter::NestedFilter;
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
 pub trait Visitor<'v>: Sized {
-    // this type should not be overridden, it exists for convenient usage as `Self::Map`
+    // This type should not be overridden, it exists for convenient usage as `Self::Map`.
     type Map: Map<'v> = >::Map;
 
     ///////////////////////////////////////////////////////////////////////////

From 6021ba0668a00fde339936f32a4f58fa4dace876 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 10:24:10 +1100
Subject: [PATCH 096/158] Rename `rustc_middle/src/hir/map/mod.rs` as `map.rs`.

There is no need for the extra subdirectory, and this makes the `map`
module consistent with its sibling modules `nested_filter` and `place`.
---
 compiler/rustc_middle/src/hir/{map/mod.rs => map.rs} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename compiler/rustc_middle/src/hir/{map/mod.rs => map.rs} (100%)

diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map.rs
similarity index 100%
rename from compiler/rustc_middle/src/hir/map/mod.rs
rename to compiler/rustc_middle/src/hir/map.rs

From cd1d84cdf76e86f2647eb7fd157047b73e76bdf5 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 10:54:00 +1100
Subject: [PATCH 097/158] Remove unused `Map::hir_node_by_def_id` method.

---
 compiler/rustc_hir/src/intravisit.rs | 4 ----
 compiler/rustc_middle/src/hir/map.rs | 4 ----
 2 files changed, 8 deletions(-)

diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 01e6fb890534..f57d1a5cc2ca 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -110,7 +110,6 @@ impl<'a> FnKind<'a> {
 pub trait Map<'hir> {
     /// Retrieves the `Node` corresponding to `id`.
     fn hir_node(&self, hir_id: HirId) -> Node<'hir>;
-    fn hir_node_by_def_id(&self, def_id: LocalDefId) -> Node<'hir>;
     fn body(&self, id: BodyId) -> &'hir Body<'hir>;
     fn item(&self, id: ItemId) -> &'hir Item<'hir>;
     fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
@@ -123,9 +122,6 @@ impl<'hir> Map<'hir> for ! {
     fn hir_node(&self, _: HirId) -> Node<'hir> {
         unreachable!();
     }
-    fn hir_node_by_def_id(&self, _: LocalDefId) -> Node<'hir> {
-        *self;
-    }
     fn body(&self, _: BodyId) -> &'hir Body<'hir> {
         unreachable!();
     }
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 83c7bb0f52f4..2c5deecd7461 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -1019,10 +1019,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
         self.tcx.hir_node(hir_id)
     }
 
-    fn hir_node_by_def_id(&self, def_id: LocalDefId) -> Node<'hir> {
-        self.tcx.hir_node_by_def_id(def_id)
-    }
-
     fn body(&self, id: BodyId) -> &'hir Body<'hir> {
         (*self).body(id)
     }

From b660382f120054309bd441ad32b6e1e3041c9402 Mon Sep 17 00:00:00 2001
From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com>
Date: Wed, 12 Feb 2025 19:54:05 -0500
Subject: [PATCH 098/158] rustc_target: import TargetMetadata

---
 .../src/spec/targets/aarch64_apple_darwin.rs             | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_apple_ios.rs   | 4 ++--
 .../src/spec/targets/aarch64_apple_ios_macabi.rs         | 4 ++--
 .../src/spec/targets/aarch64_apple_ios_sim.rs            | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_apple_tvos.rs  | 4 ++--
 .../src/spec/targets/aarch64_apple_tvos_sim.rs           | 4 ++--
 .../src/spec/targets/aarch64_apple_visionos.rs           | 4 ++--
 .../src/spec/targets/aarch64_apple_visionos_sim.rs       | 4 ++--
 .../src/spec/targets/aarch64_apple_watchos.rs            | 4 ++--
 .../src/spec/targets/aarch64_apple_watchos_sim.rs        | 4 ++--
 .../src/spec/targets/aarch64_be_unknown_linux_gnu.rs     | 4 ++--
 .../spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs   | 4 ++--
 .../src/spec/targets/aarch64_be_unknown_netbsd.rs        | 4 ++--
 .../src/spec/targets/aarch64_kmc_solid_asp3.rs           | 4 ++--
 .../src/spec/targets/aarch64_linux_android.rs            | 4 ++--
 .../spec/targets/aarch64_nintendo_switch_freestanding.rs | 5 +++--
 .../src/spec/targets/aarch64_pc_windows_gnullvm.rs       | 4 ++--
 .../src/spec/targets/aarch64_pc_windows_msvc.rs          | 4 ++--
 .../src/spec/targets/aarch64_unknown_freebsd.rs          | 4 ++--
 .../src/spec/targets/aarch64_unknown_fuchsia.rs          | 4 ++--
 .../src/spec/targets/aarch64_unknown_hermit.rs           | 4 ++--
 .../src/spec/targets/aarch64_unknown_illumos.rs          | 4 ++--
 .../src/spec/targets/aarch64_unknown_linux_gnu.rs        | 4 ++--
 .../src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs  | 4 ++--
 .../src/spec/targets/aarch64_unknown_linux_musl.rs       | 4 ++--
 .../src/spec/targets/aarch64_unknown_linux_ohos.rs       | 4 ++--
 .../src/spec/targets/aarch64_unknown_netbsd.rs           | 4 ++--
 .../src/spec/targets/aarch64_unknown_none.rs             | 4 ++--
 .../src/spec/targets/aarch64_unknown_none_softfloat.rs   | 4 ++--
 .../src/spec/targets/aarch64_unknown_nuttx.rs            | 4 ++--
 .../src/spec/targets/aarch64_unknown_openbsd.rs          | 4 ++--
 .../src/spec/targets/aarch64_unknown_redox.rs            | 4 ++--
 .../src/spec/targets/aarch64_unknown_teeos.rs            | 4 ++--
 .../src/spec/targets/aarch64_unknown_trusty.rs           | 6 ++++--
 .../src/spec/targets/aarch64_unknown_uefi.rs             | 4 ++--
 .../src/spec/targets/aarch64_uwp_windows_msvc.rs         | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs | 4 ++--
 .../rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs   | 4 ++--
 .../src/spec/targets/arm64_32_apple_watchos.rs           | 4 ++--
 .../rustc_target/src/spec/targets/arm64e_apple_darwin.rs | 4 ++--
 .../rustc_target/src/spec/targets/arm64e_apple_ios.rs    | 4 ++--
 .../rustc_target/src/spec/targets/arm64e_apple_tvos.rs   | 4 ++--
 .../src/spec/targets/arm64ec_pc_windows_msvc.rs          | 4 ++--
 .../src/spec/targets/arm_linux_androideabi.rs            | 4 ++--
 .../src/spec/targets/arm_unknown_linux_gnueabi.rs        | 4 ++--
 .../src/spec/targets/arm_unknown_linux_gnueabihf.rs      | 4 ++--
 .../src/spec/targets/arm_unknown_linux_musleabi.rs       | 4 ++--
 .../src/spec/targets/arm_unknown_linux_musleabihf.rs     | 4 ++--
 .../src/spec/targets/armeb_unknown_linux_gnueabi.rs      | 4 ++--
 .../rustc_target/src/spec/targets/armebv7r_none_eabi.rs  | 5 +++--
 .../src/spec/targets/armebv7r_none_eabihf.rs             | 5 +++--
 .../rustc_target/src/spec/targets/armv4t_none_eabi.rs    | 5 +++--
 .../src/spec/targets/armv4t_unknown_linux_gnueabi.rs     | 4 ++--
 .../rustc_target/src/spec/targets/armv5te_none_eabi.rs   | 4 ++--
 .../src/spec/targets/armv5te_unknown_linux_gnueabi.rs    | 4 ++--
 .../src/spec/targets/armv5te_unknown_linux_musleabi.rs   | 4 ++--
 .../src/spec/targets/armv5te_unknown_linux_uclibceabi.rs | 4 ++--
 .../src/spec/targets/armv6_unknown_freebsd.rs            | 4 ++--
 .../src/spec/targets/armv6_unknown_netbsd_eabihf.rs      | 4 ++--
 .../rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs | 6 ++++--
 .../src/spec/targets/armv7_linux_androideabi.rs          | 6 ++++--
 .../rustc_target/src/spec/targets/armv7_rtems_eabihf.rs  | 5 +++--
 .../src/spec/targets/armv7_sony_vita_newlibeabihf.rs     | 6 ++++--
 .../src/spec/targets/armv7_unknown_freebsd.rs            | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_gnueabi.rs      | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_gnueabihf.rs    | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_musleabi.rs     | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_musleabihf.rs   | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_ohos.rs         | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_uclibceabi.rs   | 4 ++--
 .../src/spec/targets/armv7_unknown_linux_uclibceabihf.rs | 4 ++--
 .../src/spec/targets/armv7_unknown_netbsd_eabihf.rs      | 4 ++--
 .../src/spec/targets/armv7_unknown_trusty.rs             | 5 +++--
 .../src/spec/targets/armv7_wrs_vxworks_eabihf.rs         | 4 ++--
 .../src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs       | 4 ++--
 .../src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs     | 4 ++--
 .../rustc_target/src/spec/targets/armv7a_none_eabi.rs    | 5 +++--
 .../rustc_target/src/spec/targets/armv7a_none_eabihf.rs  | 5 +++--
 .../rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs   | 5 +++--
 .../rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs | 5 +++--
 .../src/spec/targets/armv7k_apple_watchos.rs             | 4 ++--
 .../rustc_target/src/spec/targets/armv7r_none_eabi.rs    | 5 +++--
 .../rustc_target/src/spec/targets/armv7r_none_eabihf.rs  | 5 +++--
 .../rustc_target/src/spec/targets/armv7s_apple_ios.rs    | 4 ++--
 .../rustc_target/src/spec/targets/armv8r_none_eabihf.rs  | 5 +++--
 .../rustc_target/src/spec/targets/bpfeb_unknown_none.rs  | 4 ++--
 .../rustc_target/src/spec/targets/bpfel_unknown_none.rs  | 4 ++--
 .../src/spec/targets/csky_unknown_linux_gnuabiv2.rs      | 4 ++--
 .../src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs    | 4 ++--
 .../src/spec/targets/hexagon_unknown_linux_musl.rs       | 4 ++--
 .../src/spec/targets/hexagon_unknown_none_elf.rs         | 4 ++--
 compiler/rustc_target/src/spec/targets/i386_apple_ios.rs | 4 ++--
 .../rustc_target/src/spec/targets/i586_unknown_netbsd.rs | 4 ++--
 .../rustc_target/src/spec/targets/i586_unknown_redox.rs  | 9 ++-------
 .../rustc_target/src/spec/targets/i686_apple_darwin.rs   | 4 ++--
 .../rustc_target/src/spec/targets/i686_linux_android.rs  | 6 ++++--
 .../rustc_target/src/spec/targets/i686_pc_windows_gnu.rs | 4 ++--
 .../src/spec/targets/i686_pc_windows_gnullvm.rs          | 4 ++--
 .../src/spec/targets/i686_pc_windows_msvc.rs             | 4 ++--
 .../src/spec/targets/i686_unknown_freebsd.rs             | 4 ++--
 .../rustc_target/src/spec/targets/i686_unknown_haiku.rs  | 4 ++--
 .../src/spec/targets/i686_unknown_hurd_gnu.rs            | 4 ++--
 .../src/spec/targets/i686_unknown_linux_gnu.rs           | 6 ++++--
 .../src/spec/targets/i686_unknown_linux_musl.rs          | 6 ++++--
 .../rustc_target/src/spec/targets/i686_unknown_netbsd.rs | 6 ++++--
 .../src/spec/targets/i686_unknown_openbsd.rs             | 4 ++--
 .../rustc_target/src/spec/targets/i686_unknown_uefi.rs   | 4 ++--
 .../src/spec/targets/i686_uwp_windows_gnu.rs             | 4 ++--
 .../src/spec/targets/i686_uwp_windows_msvc.rs            | 4 ++--
 .../src/spec/targets/i686_win7_windows_gnu.rs            | 4 ++--
 .../src/spec/targets/i686_win7_windows_msvc.rs           | 4 ++--
 .../rustc_target/src/spec/targets/i686_wrs_vxworks.rs    | 4 ++--
 .../src/spec/targets/loongarch64_unknown_linux_gnu.rs    | 4 ++--
 .../src/spec/targets/loongarch64_unknown_linux_musl.rs   | 4 ++--
 .../src/spec/targets/loongarch64_unknown_linux_ohos.rs   | 4 ++--
 .../src/spec/targets/loongarch64_unknown_none.rs         | 5 +++--
 .../spec/targets/loongarch64_unknown_none_softfloat.rs   | 5 +++--
 .../src/spec/targets/m68k_unknown_linux_gnu.rs           | 4 ++--
 .../src/spec/targets/m68k_unknown_none_elf.rs            | 4 ++--
 .../src/spec/targets/mips64_openwrt_linux_musl.rs        | 4 ++--
 .../src/spec/targets/mips64_unknown_linux_gnuabi64.rs    | 4 ++--
 .../src/spec/targets/mips64_unknown_linux_muslabi64.rs   | 4 ++--
 .../src/spec/targets/mips64el_unknown_linux_gnuabi64.rs  | 4 ++--
 .../src/spec/targets/mips64el_unknown_linux_muslabi64.rs | 4 ++--
 .../rustc_target/src/spec/targets/mips_mti_none_elf.rs   | 6 ++++--
 .../src/spec/targets/mips_unknown_linux_gnu.rs           | 4 ++--
 .../src/spec/targets/mips_unknown_linux_musl.rs          | 4 ++--
 .../src/spec/targets/mips_unknown_linux_uclibc.rs        | 4 ++--
 .../rustc_target/src/spec/targets/mipsel_mti_none_elf.rs | 6 ++++--
 .../rustc_target/src/spec/targets/mipsel_sony_psp.rs     | 4 ++--
 .../rustc_target/src/spec/targets/mipsel_sony_psx.rs     | 6 ++++--
 .../src/spec/targets/mipsel_unknown_linux_gnu.rs         | 4 ++--
 .../src/spec/targets/mipsel_unknown_linux_musl.rs        | 4 ++--
 .../src/spec/targets/mipsel_unknown_linux_uclibc.rs      | 4 ++--
 .../src/spec/targets/mipsel_unknown_netbsd.rs            | 4 ++--
 .../rustc_target/src/spec/targets/mipsel_unknown_none.rs | 6 ++++--
 .../src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs    | 4 ++--
 .../src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs  | 4 ++--
 .../spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs   | 4 ++--
 .../spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs | 4 ++--
 .../rustc_target/src/spec/targets/msp430_none_elf.rs     | 6 ++++--
 .../rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs | 5 +++--
 .../rustc_target/src/spec/targets/powerpc64_ibm_aix.rs   | 4 ++--
 .../src/spec/targets/powerpc64_unknown_freebsd.rs        | 6 ++++--
 .../src/spec/targets/powerpc64_unknown_linux_gnu.rs      | 6 ++++--
 .../src/spec/targets/powerpc64_unknown_linux_musl.rs     | 6 ++++--
 .../src/spec/targets/powerpc64_unknown_openbsd.rs        | 6 ++++--
 .../src/spec/targets/powerpc64_wrs_vxworks.rs            | 6 ++++--
 .../src/spec/targets/powerpc64le_unknown_freebsd.rs      | 6 ++++--
 .../src/spec/targets/powerpc64le_unknown_linux_gnu.rs    | 6 ++++--
 .../src/spec/targets/powerpc64le_unknown_linux_musl.rs   | 6 ++++--
 .../src/spec/targets/powerpc_unknown_freebsd.rs          | 6 ++++--
 .../src/spec/targets/powerpc_unknown_linux_gnu.rs        | 6 ++++--
 .../src/spec/targets/powerpc_unknown_linux_gnuspe.rs     | 6 ++++--
 .../src/spec/targets/powerpc_unknown_linux_musl.rs       | 6 ++++--
 .../src/spec/targets/powerpc_unknown_linux_muslspe.rs    | 6 ++++--
 .../src/spec/targets/powerpc_unknown_netbsd.rs           | 6 ++++--
 .../src/spec/targets/powerpc_unknown_openbsd.rs          | 4 ++--
 .../rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs | 6 ++++--
 .../src/spec/targets/powerpc_wrs_vxworks_spe.rs          | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs | 4 ++--
 .../src/spec/targets/riscv32e_unknown_none_elf.rs        | 6 ++++--
 .../src/spec/targets/riscv32em_unknown_none_elf.rs       | 6 ++++--
 .../src/spec/targets/riscv32emc_unknown_none_elf.rs      | 6 ++++--
 .../src/spec/targets/riscv32gc_unknown_linux_gnu.rs      | 4 ++--
 .../src/spec/targets/riscv32gc_unknown_linux_musl.rs     | 4 ++--
 .../src/spec/targets/riscv32i_unknown_none_elf.rs        | 6 ++++--
 .../src/spec/targets/riscv32im_risc0_zkvm_elf.rs         | 6 ++++--
 .../src/spec/targets/riscv32im_unknown_none_elf.rs       | 6 ++++--
 .../src/spec/targets/riscv32ima_unknown_none_elf.rs      | 6 ++++--
 .../src/spec/targets/riscv32imac_esp_espidf.rs           | 4 ++--
 .../src/spec/targets/riscv32imac_unknown_none_elf.rs     | 6 ++++--
 .../src/spec/targets/riscv32imac_unknown_nuttx_elf.rs    | 6 ++++--
 .../src/spec/targets/riscv32imac_unknown_xous_elf.rs     | 6 ++++--
 .../src/spec/targets/riscv32imafc_esp_espidf.rs          | 4 ++--
 .../src/spec/targets/riscv32imafc_unknown_none_elf.rs    | 6 ++++--
 .../src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs   | 6 ++++--
 .../src/spec/targets/riscv32imc_esp_espidf.rs            | 4 ++--
 .../src/spec/targets/riscv32imc_unknown_none_elf.rs      | 6 ++++--
 .../src/spec/targets/riscv32imc_unknown_nuttx_elf.rs     | 6 ++++--
 .../src/spec/targets/riscv64_linux_android.rs            | 6 ++++--
 .../rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_freebsd.rs        | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_fuchsia.rs        | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_hermit.rs         | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_linux_gnu.rs      | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_linux_musl.rs     | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_netbsd.rs         | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_none_elf.rs       | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_nuttx_elf.rs      | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_openbsd.rs        | 4 ++--
 .../src/spec/targets/riscv64imac_unknown_none_elf.rs     | 4 ++--
 .../src/spec/targets/riscv64imac_unknown_nuttx_elf.rs    | 4 ++--
 .../src/spec/targets/s390x_unknown_linux_gnu.rs          | 4 ++--
 .../src/spec/targets/s390x_unknown_linux_musl.rs         | 4 ++--
 .../src/spec/targets/sparc64_unknown_linux_gnu.rs        | 4 ++--
 .../src/spec/targets/sparc64_unknown_netbsd.rs           | 4 ++--
 .../src/spec/targets/sparc64_unknown_openbsd.rs          | 4 ++--
 .../src/spec/targets/sparc_unknown_linux_gnu.rs          | 4 ++--
 .../src/spec/targets/sparc_unknown_none_elf.rs           | 6 ++++--
 .../rustc_target/src/spec/targets/sparcv9_sun_solaris.rs | 4 ++--
 .../rustc_target/src/spec/targets/thumbv4t_none_eabi.rs  | 5 +++--
 .../rustc_target/src/spec/targets/thumbv5te_none_eabi.rs | 4 ++--
 .../rustc_target/src/spec/targets/thumbv6m_none_eabi.rs  | 4 ++--
 .../rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs | 4 ++--
 .../rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs | 4 ++--
 .../src/spec/targets/thumbv7a_nuttx_eabihf.rs            | 4 ++--
 .../src/spec/targets/thumbv7a_pc_windows_msvc.rs         | 6 ++++--
 .../src/spec/targets/thumbv7a_uwp_windows_msvc.rs        | 4 ++--
 .../rustc_target/src/spec/targets/thumbv7em_none_eabi.rs | 4 ++--
 .../src/spec/targets/thumbv7em_none_eabihf.rs            | 4 ++--
 .../src/spec/targets/thumbv7em_nuttx_eabi.rs             | 4 ++--
 .../src/spec/targets/thumbv7em_nuttx_eabihf.rs           | 4 ++--
 .../rustc_target/src/spec/targets/thumbv7m_none_eabi.rs  | 4 ++--
 .../rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs | 4 ++--
 .../src/spec/targets/thumbv7neon_linux_androideabi.rs    | 4 ++--
 .../spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs  | 4 ++--
 .../spec/targets/thumbv7neon_unknown_linux_musleabihf.rs | 4 ++--
 .../src/spec/targets/thumbv8m_base_none_eabi.rs          | 4 ++--
 .../src/spec/targets/thumbv8m_base_nuttx_eabi.rs         | 4 ++--
 .../src/spec/targets/thumbv8m_main_none_eabi.rs          | 4 ++--
 .../src/spec/targets/thumbv8m_main_none_eabihf.rs        | 4 ++--
 .../src/spec/targets/thumbv8m_main_nuttx_eabi.rs         | 4 ++--
 .../src/spec/targets/thumbv8m_main_nuttx_eabihf.rs       | 4 ++--
 .../src/spec/targets/wasm32_unknown_emscripten.rs        | 5 +++--
 .../src/spec/targets/wasm32_unknown_unknown.rs           | 4 ++--
 compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs  | 6 ++++--
 .../src/spec/targets/wasm32_wasip1_threads.rs            | 6 ++++--
 compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs  | 6 ++++--
 compiler/rustc_target/src/spec/targets/wasm32v1_none.rs  | 4 ++--
 .../src/spec/targets/wasm64_unknown_unknown.rs           | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_apple_darwin.rs | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_apple_ios.rs    | 4 ++--
 .../src/spec/targets/x86_64_apple_ios_macabi.rs          | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_apple_tvos.rs   | 4 ++--
 .../src/spec/targets/x86_64_apple_watchos_sim.rs         | 4 ++--
 .../src/spec/targets/x86_64_fortanix_unknown_sgx.rs      | 4 ++--
 .../src/spec/targets/x86_64_linux_android.rs             | 5 +++--
 .../rustc_target/src/spec/targets/x86_64_pc_solaris.rs   | 4 ++--
 .../src/spec/targets/x86_64_pc_windows_gnu.rs            | 4 ++--
 .../src/spec/targets/x86_64_pc_windows_gnullvm.rs        | 4 ++--
 .../src/spec/targets/x86_64_pc_windows_msvc.rs           | 4 ++--
 .../src/spec/targets/x86_64_unikraft_linux_musl.rs       | 6 ++++--
 .../src/spec/targets/x86_64_unknown_dragonfly.rs         | 4 ++--
 .../src/spec/targets/x86_64_unknown_freebsd.rs           | 6 ++++--
 .../src/spec/targets/x86_64_unknown_fuchsia.rs           | 4 ++--
 .../src/spec/targets/x86_64_unknown_haiku.rs             | 4 ++--
 .../src/spec/targets/x86_64_unknown_hermit.rs            | 4 ++--
 .../src/spec/targets/x86_64_unknown_hurd_gnu.rs          | 4 ++--
 .../src/spec/targets/x86_64_unknown_illumos.rs           | 4 ++--
 .../src/spec/targets/x86_64_unknown_l4re_uclibc.rs       | 4 ++--
 .../src/spec/targets/x86_64_unknown_linux_gnu.rs         | 6 ++++--
 .../src/spec/targets/x86_64_unknown_linux_gnux32.rs      | 4 ++--
 .../src/spec/targets/x86_64_unknown_linux_musl.rs        | 6 ++++--
 .../src/spec/targets/x86_64_unknown_linux_none.rs        | 6 ++++--
 .../src/spec/targets/x86_64_unknown_linux_ohos.rs        | 6 ++++--
 .../src/spec/targets/x86_64_unknown_netbsd.rs            | 5 +++--
 .../rustc_target/src/spec/targets/x86_64_unknown_none.rs | 4 ++--
 .../src/spec/targets/x86_64_unknown_openbsd.rs           | 4 ++--
 .../src/spec/targets/x86_64_unknown_redox.rs             | 4 ++--
 .../src/spec/targets/x86_64_unknown_trusty.rs            | 5 +++--
 .../rustc_target/src/spec/targets/x86_64_unknown_uefi.rs | 4 ++--
 .../src/spec/targets/x86_64_uwp_windows_gnu.rs           | 4 ++--
 .../src/spec/targets/x86_64_uwp_windows_msvc.rs          | 4 ++--
 .../src/spec/targets/x86_64_win7_windows_gnu.rs          | 4 ++--
 .../src/spec/targets/x86_64_win7_windows_msvc.rs         | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs  | 4 ++--
 .../src/spec/targets/x86_64h_apple_darwin.rs             | 4 ++--
 .../rustc_target/src/spec/targets/xtensa_esp32_espidf.rs | 9 ++-------
 .../src/spec/targets/xtensa_esp32_none_elf.rs            | 4 ++--
 .../src/spec/targets/xtensa_esp32s2_espidf.rs            | 9 ++-------
 .../src/spec/targets/xtensa_esp32s2_none_elf.rs          | 4 ++--
 .../src/spec/targets/xtensa_esp32s3_espidf.rs            | 9 ++-------
 .../src/spec/targets/xtensa_esp32s3_none_elf.rs          | 4 ++--
 274 files changed, 679 insertions(+), 568 deletions(-)

diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index adee6f5fe994..d3e0a32c8b8f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple macOS (11.0+, Big Sur+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index efc42b909e4e..183a6c6f2d72 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple iOS".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index be503d18bf15..ce9ae03e6999 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple Mac Catalyst".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index 04bbee45cd32..4405e3fec028 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple iOS Simulator".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index fa0bc130e1c7..037685db1b38 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple tvOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index 428045da4930..a386220e6fc5 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple tvOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index 9817c5a8eb0d..2c1dfdd55ed1 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple visionOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index d411f7105408..c0b8b409797b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple visionOS simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index abd924b5934a..235962711072 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple watchOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index ba85647fddcc..62968f5b5555 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple watchOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
index de6fe991460a..87c07cd31090 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Linux (big-endian)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
index 8fdaff822fe7..e785069c78a1 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Linux (big-endian, ILP32 ABI)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
index 4e1e95ab7516..97742403c78f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64_be-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 NetBSD (big-endian)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
index 58fc703946e5..f58aa1ac043c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
@@ -1,10 +1,10 @@
-use crate::spec::{RelocModel, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{RelocModel, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 SOLID with TOPPERS/ASP3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
index a021d317cc83..41c25393e129 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
 // for target ABI requirements.
@@ -6,7 +6,7 @@ use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-linux-android".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Android".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
index 6ac69e0f57f3..9b81362b27db 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, StackProbeType, Target, TargetOptions,
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, StackProbeType, Target, TargetMetadata,
+    TargetOptions,
 };
 
 const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding_linker_script.ld");
@@ -8,7 +9,7 @@ const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Nintendo Switch, Horizon".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
index 8b96f589c74d..a8b133d19bb0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 MinGW (Windows 10+), LLVM ABI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index 14ce5edd2f3c..98d78520c983 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Windows MSVC".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
index dd90161f4408..7306a75aa227 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-freebsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 FreeBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
index df13d52a2236..23ed92e62b8e 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
@@ -1,9 +1,9 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-fuchsia".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Fuchsia".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
index 459e888eb943..580a36cb2e92 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-hermit".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Hermit".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
index 699376a7928b..1ed4fdb465d3 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target, base};
+use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::illumos::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
         llvm_target: "aarch64-unknown-solaris2.11".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 illumos".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index 18711cb399d7..c6be2c20ea23 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -1,9 +1,9 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Linux (kernel 4.1, glibc 2.17+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
index 7b0df7d1130d..166bb1ed2151 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu_ilp32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Linux (ILP32 ABI)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index 4fefdfa5c5e1..58ba06e124c7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Linux with musl 1.2.3".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index 14a22988a091..f2994b1232e6 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_ohos::opts();
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-linux-ohos".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 OpenHarmony".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
index 0ec76e4b42fd..461730457aa4 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 NetBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
index 27dd713cc533..6c14f5df4660 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
@@ -8,7 +8,7 @@
 
 use crate::spec::{
     Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target,
-    TargetOptions,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -31,7 +31,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARM64, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
index 3b719ebaf07e..35a4dd72b862 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
@@ -8,7 +8,7 @@
 
 use crate::spec::{
     Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target,
-    TargetOptions,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -27,7 +27,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARM64, softfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs
index f7f8dc1e1efb..243d84a12ece 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs
@@ -8,7 +8,7 @@
 
 use crate::spec::{
     Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target,
-    TargetOptions, cvs,
+    TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -33,7 +33,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("AArch64 NuttX".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
index 0fcf5c34bb0e..c23006adad6d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 OpenBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
index 7ff99c574ad8..39fe71528d38 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::redox::opts();
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-redox".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 RedoxOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
index fb8b59f77291..799ff1a806ee 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::teeos::opts();
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 TEEOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs
index cebd8ff2f684..126f02512391 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs
@@ -1,11 +1,13 @@
 // Trusty OS target for AArch64.
 
-use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions};
+use crate::spec::{
+    LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-unknown-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Trusty".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
index 9656024ddaa1..327b52389b93 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
@@ -1,7 +1,7 @@
 // This defines the aarch64 target for UEFI systems as described in the UEFI specification. See the
 // uefi-base module for generic UEFI options.
 
-use crate::spec::{LinkerFlavor, Lld, Target, base};
+use crate::spec::{LinkerFlavor, Lld, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::uefi_msvc::opts();
@@ -12,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-windows".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 UEFI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
index 3d7c02698080..a40c8c3a3f26 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_msvc::opts();
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
index ac53cbaecceb..b68267601838 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
index bb488c350c23..f20782cabb87 100644
--- a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
+++ b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
@@ -1,11 +1,11 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     Target {
         arch: "amdgpu".into(),
         data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
         llvm_target: "amdgcn-amd-amdhsa".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("AMD GPU".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index a5a6f772ac84..4c3a2f437438 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64 Apple watchOS with 32-bit pointers".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index 744d95445b8e..79b95dbde52d 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64e Apple Darwin".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index dace11dae24d..848dbeec199a 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64e Apple iOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
index 2ccdc76c52e6..3dbe169e826b 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARM64e Apple tvOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
index 5026c52429e5..bb3e3e544cba 100644
--- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Lld, Target, add_link_args, base};
+use crate::spec::{LinkerFlavor, Lld, Target, TargetMetadata, add_link_args, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -12,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "arm64ec-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Arm64EC Windows MSVC".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
index 73fb02c67310..d74468899f56 100644
--- a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, SanitizerSet, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "arm-linux-androideabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 Android".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
index 87e790a1f39e..3b6c97167cf4 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 Linux (kernel 3.2, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
index 6470bf6b6115..a3f5389f0aa7 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 Linux, hardfloat (kernel 3.2, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
index 26241dd0bd48..3919a5e0771b 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-musleabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 Linux with musl 1.2.3".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
index 4bbde7667b97..ca52e5b3ca6c 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-musleabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 Linux with musl 1.2.3, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
index 60ec4edbb0d2..afb17fd82032 100644
--- a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armeb-unknown-linux-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Arm BE8 the default Arm big-endian architecture since Armv6".into()),
             tier: Some(3),
             host_tools: None, // ?
diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
index 18b93f6cbc4f..d227d63c4a34 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
@@ -3,13 +3,14 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armebv7r-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv7-R, Big Endian".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
index 6c22cd34fc3a..c373afb914e3 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
@@ -3,13 +3,14 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armebv7r-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv7-R, Big Endian, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
index dc8cb4fb187e..9571821656c8 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
@@ -10,13 +10,14 @@
 //! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv4t-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv4T".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
index 081132b0e68c..beaec71093cb 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv4t-unknown-linux-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv4T Linux".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
index e0a4f26f0a6f..75ab941c5cf2 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
@@ -1,11 +1,11 @@
 //! Targets the ARMv5TE, with code as `a32` code by default.
 
-use crate::spec::{FloatAbi, FramePointer, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, FramePointer, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv5te-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv5TE".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
index ce7060b38479..52e786de3ed9 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv5TE Linux (kernel 4.4, glibc 2.23)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
index 62619546891d..e675739629b5 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-musleabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv5TE Linux with musl 1.2.3".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
index 73013bf00b10..dbe1540364ad 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv5TE Linux with uClibc".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
index 4bbc514f2b3d..1625a6b84bbc 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv6-unknown-freebsd-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 FreeBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
index 6b9d3ccd2152..af9a43595651 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv6-unknown-netbsdelf-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6 NetBSD w/hard-float".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
index 5438811803b4..4c32a5e62161 100644
--- a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, FloatAbi, LinkerFlavor, Lld, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, FloatAbi, LinkerFlavor, Lld, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 /// A base target for Nintendo 3DS devices using the devkitARM toolchain.
 ///
@@ -12,7 +14,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "armv6k-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
index e1cead9e0b7b..706fb12a524a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, FloatAbi, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, FloatAbi, LinkerFlavor, Lld, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
+};
 
 // This target if is for the baseline of the Android v7a ABI
 // in thumb mode. It's named armv7-* instead of thumbv7-*
@@ -13,7 +15,7 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Android".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
index 4e8a9d55f9a9..c17db36ee611 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
@@ -1,11 +1,12 @@
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7 RTEMS (Requires RTEMS toolchain and kernel".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
index 4b2ab8b8f20b..5d292bbf8adf 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, FloatAbi, LinkerFlavor, Lld, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, FloatAbi, LinkerFlavor, Lld, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 /// A base target for PlayStation Vita devices using the VITASDK toolchain (using newlib).
 ///
@@ -14,7 +16,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-vita-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some(
                 "Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)".into(),
             ),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
index 34f118d4f5dd..56f2e090e071 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-freebsd-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A FreeBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
index bb28427c99bf..603afe2c48bb 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on ARMv7 without thumb-mode, NEON or
 // hardfloat.
@@ -6,7 +6,7 @@ use crate::spec::{FloatAbi, Target, TargetOptions, base};
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Linux (kernel 4.15, glibc 2.27)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
index 6bffc0da87b0..3b5a337b4f13 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on ARMv7 without NEON or
 // thumb-mode. See the thumbv7neon variant for enabling both.
@@ -6,7 +6,7 @@ use crate::spec::{FloatAbi, Target, TargetOptions, base};
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Linux, hardfloat (kernel 3.2, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
index 0436e0d8df4c..42fbf6f48619 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for musl Linux on ARMv7 without thumb-mode, NEON or
 // hardfloat.
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
     // target.
     Target {
         llvm_target: "armv7-unknown-linux-musleabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Linux with musl 1.2.3".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
index 22e49f2f1b0b..a3ac0223c84b 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
@@ -1,11 +1,11 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for musl Linux on ARMv7 without thumb-mode or NEON.
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-musleabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Linux with musl 1.2.3, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
index d1261202124c..f31dedb04e6c 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for OpenHarmony on ARMv7 Linux with thumb-mode, but no NEON or
 // hardfloat.
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
     // target.
     Target {
         llvm_target: "armv7-unknown-linux-ohos".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A OpenHarmony".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
index ffcd8876eb4c..a9e9f4651bb2 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for uclibc Linux on ARMv7 without NEON,
 // thumb-mode or hardfloat.
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
     let base = base::linux_uclibc::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Linux with uClibc, softfloat".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
index 586bd8d3d883..a95f12d0230d 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for uclibc Linux on ARMv7 without NEON or
 // thumb-mode. See the thumbv7neon variant for enabling both.
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
     let base = base::linux_uclibc::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Linux with uClibc, hardfloat".into()),
             tier: Some(3),
             host_tools: None, // ?
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
index 28d3d572bf35..d155dc58e511 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-netbsdelf-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A NetBSD w/hard-float".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs
index b86c788df15f..31d492e83cda 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    FloatAbi, LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions,
+    FloatAbi, LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -8,7 +9,7 @@ pub(crate) fn target() -> Target {
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
         llvm_target: "armv7-unknown-unknown-gnueabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Trusty".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
index 212c45424dbb..05be389b57c3 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A for VxWorks".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
index 2ed100454126..26c251399891 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
@@ -1,10 +1,10 @@
-use crate::spec::{FloatAbi, RelocModel, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, RelocModel, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "armv7a-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Arm SOLID with TOPPERS/ASP3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
index c9c15b402ae8..7032444bea4c 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
@@ -1,10 +1,10 @@
-use crate::spec::{FloatAbi, RelocModel, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, RelocModel, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Arm SOLID with TOPPERS/ASP3, hardfloat".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
index d59849ec2c4b..fb1d7d6c39d7 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
@@ -15,7 +15,8 @@
 // linking. rationale: matches `thumb` targets
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -35,7 +36,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv7-A".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
index 06481e6f8825..df3a76599a75 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
@@ -6,7 +6,8 @@
 // `thumb` & `aarch64` targets.
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -27,7 +28,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv7-A, hardfloat".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs
index 08cbfc743968..052285b98dc8 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs
@@ -5,7 +5,8 @@
 // configuration without hardware floating point support.
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -27,7 +28,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARMv7-A Cortex-A with NuttX".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs
index f68c11a9c687..85543e95616b 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs
@@ -5,7 +5,8 @@
 // configuration with hardware floating point support.
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -27,7 +28,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARMv7-A Cortex-A with NuttX (hard float)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index e232f54f9b38..8103d132cea8 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-A Apple WatchOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
index 1eda05451691..334be483daa0 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
@@ -1,13 +1,14 @@
 // Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7r-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-R".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
index d4e85bc9b0ae..2bb3e70483ae 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
@@ -1,13 +1,14 @@
 // Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7r-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Armv7-R, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index 1c3040de06e2..ba9edd714612 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("ARMv7-A Apple-A6 Apple iOS".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
index 3df42a1482c1..8cf1ff957516 100644
--- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
@@ -1,13 +1,14 @@
 // Targets the Little-endian Cortex-R52 processor (ARMv8-R)
 
 use crate::spec::{
-    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv8r-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Armv8-R, hardfloat".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
index b95f93c3553c..3d39cd26c650 100644
--- a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "bpfeb".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("BPF (big endian)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
index 711bbb04b195..51f45b012449 100644
--- a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "bpfel".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("BPF (little endian)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
index c90d3bcc6ae9..6142c1541f0b 100644
--- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
+++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on Csky
 
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
         llvm_target: "csky-unknown-linux-gnuabiv2".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("C-SKY abiv2 Linux (little endian)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
index d0583b7866b9..c233ec3ada73 100644
--- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
+++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on Csky
 
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
         llvm_target: "csky-unknown-linux-gnuabiv2".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("C-SKY abiv2 Linux, hardfloat (little endian)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
index 003600c26cc7..f7416a7e0fde 100644
--- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "hexagon-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Hexagon Linux with musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
index 730b19abd2bd..e5a927d0953a 100644
--- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
@@ -1,9 +1,9 @@
-use crate::spec::{PanicStrategy, Target, TargetOptions};
+use crate::spec::{PanicStrategy, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "hexagon-unknown-none-elf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare Hexagon (v60+, HVX)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index 41c5fafe3418..29865fcd4c4e 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // i386-apple-ios is a simulator target, even though it isn't declared
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86 Apple iOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
index 6aa34f157ab4..39a71cf17812 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i586-unknown-netbsdelf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit x86, resricted to Pentium".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs
index 29ef8b883a11..08281eda42e0 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::redox::opts();
@@ -11,12 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i586-unknown-redox".into(),
-        metadata: crate::spec::TargetMetadata {
-            description: None,
-            tier: None,
-            host_tools: None,
-            std: None,
-        },
+        metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None },
         pointer_width: 32,
         data_layout:
             "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 6adf690e0dd8..161db9a08bb0 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86 Apple macOS (10.12+, Sierra+)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index 7d61d5ca257c..f2d7ec664439 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -1,4 +1,6 @@
-use crate::spec::{RustcAbi, SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    RustcAbi, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
 // for target ABI requirements.
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-linux-android".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit x86 Android".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
index 06dbf1e3a165..2a26323e5147 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MinGW (Windows 10+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
index 05d848e03931..2e2ea8f81be0 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit x86 MinGW (Windows 10+), LLVM ABI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index e0e471130874..6a95afa1d0d3 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MSVC (Windows 10+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index 71c26041a50a..1dfea64ebed6 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-freebsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit FreeBSD".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index 464ac46b07c0..ab329170a4f3 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::haiku::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-haiku".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit Haiku".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
index 2f93e97d9fc3..b01f93f74042 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::hurd_gnu::opts();
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-hurd-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit GNU/Hurd".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index fe699dbcb510..c70c026f9f71 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, RustcAbi, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -22,7 +24,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit Linux (kernel 3.2, glibc 2.17+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index 3d25c951e813..47a7eb3d597b 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -28,7 +30,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit Linux with musl 1.2.3".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index 4bc6eee1ac27..cbd61cadb360 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
@@ -10,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-netbsdelf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("NetBSD/i386 with SSE2".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index a3bdf66a14d8..48f7be7dc2b5 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit OpenBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
index 736b91310224..1a7923ca89bd 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
@@ -5,7 +5,7 @@
 // The cdecl ABI is used. It differs from the stdcall or fastcall ABI.
 // "i686-unknown-windows" is used to get the minimal subset of windows-specific features.
 
-use crate::spec::{LinkerFlavor, Lld, RustcAbi, Target, add_link_args, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, add_link_args, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::uefi_msvc::opts();
@@ -86,7 +86,7 @@ pub(crate) fn target() -> Target {
     // remove -gnu and use the default one.
     Target {
         llvm_target: "i686-unknown-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit UEFI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
index 0e1b65ef598c..d95f779774f1 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_gnu::opts();
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
index 44cf9b1adda1..fa7a103df797 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{RustcAbi, Target, base};
+use crate::spec::{RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_msvc::opts();
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
index e9100da14cba..f364c2cb0327 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MinGW (Windows 7+)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 94284a2fe72b..233a1c4fd7a5 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -23,7 +23,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MSVC (Windows 7+)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index 4e801955d0cb..63ede7b4ab89 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
index 603c0f99314b..9e743a355296 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
index d7044dde0f17..d9010b1e4eeb 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.5".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
index 11d05db6b0a0..c1c859ef25c8 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-ohos".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("LoongArch64 OpenHarmony".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
index db527c8b6369..91e3064aaede 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -1,11 +1,12 @@
 use crate::spec::{
-    Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Freestanding/bare-metal LoongArch64".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
index 221ca02fe3e3..24983900683e 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
@@ -1,11 +1,12 @@
 use crate::spec::{
-    Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+    Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Freestanding/bare-metal LoongArch64 softfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
index d3584a1be743..9bd02e842c24 100644
--- a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{LinkSelfContainedDefault, Target, TargetOptions, base};
+use crate::spec::{LinkSelfContainedDefault, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "m68k-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Motorola 680x0 Linux".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/m68k_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_none_elf.rs
index 8b8693b55c5c..6b66052692a4 100644
--- a/compiler/rustc_target/src/spec/targets/m68k_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/m68k_unknown_none_elf.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{CodeModel, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{CodeModel, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let options = TargetOptions {
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "m68k".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Motorola 680x0".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index 4880e993722f..1300280e35b0 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -2,7 +2,7 @@
 
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS64 for OpenWrt Linux musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
index daf6d5de4c03..b130ca29c7f0 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mips64-unknown-linux-gnuabi64".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
index 03c8fa924504..4ea7c7bff44a 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS64 Linux, N64 ABI, musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
index c7d248712252..a9afea27ef34 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
@@ -1,9 +1,9 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mips64el-unknown-linux-gnuabi64".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
index 5e7c37fd46c3..7bdd9edda70c 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64el-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS64 Linux, N64 ABI, musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs b/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs
index 2815d995c315..def12122416a 100644
--- a/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs
@@ -1,12 +1,14 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         llvm_target: "mips".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS32r2 BE Baremetal Softfloat".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
index 19cf62d19f6e..29a451b31a65 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mips-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS Linux (kernel 4.4, glibc 2.23)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
index dbca90ba569c..82f2fda7fff0 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
     base.max_atomic_width = Some(32);
     Target {
         llvm_target: "mips-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS Linux with musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
index c26c7867ec7a..0955b3debea0 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mips-unknown-linux-uclibc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS Linux with uClibc".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs b/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs
index f532643b56ae..cc9c19e4a0b5 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs
@@ -1,12 +1,14 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         llvm_target: "mipsel".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS32r2 LE Baremetal Softfloat".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
index 2c63b0f2f384..37ebb3d174b3 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetMetadata, TargetOptions, cvs};
 
 // The PSP has custom linker requirements.
 const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "mipsel-sony-psp".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS (LE) Sony PlatStation Portable (PSP)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
index 1b8f9b71e930..8475a43ea633 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
@@ -1,9 +1,11 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsel-sony-psx".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS (LE) Sony PlayStation 1 (PSX)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
index 08226449358a..6c7ea5c56889 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
@@ -1,9 +1,9 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS (little endian) Linux (kernel 4.4, glibc 2.23)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
index 339b32b63399..d008bb55189b 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
     base.max_atomic_width = Some(32);
     Target {
         llvm_target: "mipsel-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS (little endian) Linux with musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
index 88474e71848c..08c4347fe014 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
@@ -1,9 +1,9 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-linux-uclibc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("MIPS (LE) Linux with uClibc".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
index 400e05f14783..502d7382b3cf 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "mipsel-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MIPS (LE), requires mips32 cpu support".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
index bb8eb24908c2..6a201c56475e 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
@@ -2,12 +2,14 @@
 //!
 //! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
 
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare MIPS (LE) softfloat".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
index c7b0a05d8899..0716f2e483b4 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MIPS Release 6 Big Endian".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
index c75023385c22..81f2424e4dea 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
@@ -1,9 +1,9 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit MIPS Release 6 Little Endian".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
index 49bec90022c5..3eefa27ea04b 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit MIPS Release 6 Big Endian".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
index 60bda7a5996c..0887180791c7 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -1,9 +1,9 @@
-use crate::spec::{Target, TargetOptions, base};
+use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit MIPS Release 6 Little Endian".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
index 80cb740450a8..b067ac1e54a1 100644
--- a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
@@ -1,9 +1,11 @@
-use crate::spec::{Cc, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "msp430-none-elf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("16-bit MSP430 microcontrollers".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
index 80bfa3582438..598f0f19f0de 100644
--- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    LinkSelfContainedDefault, LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions,
+    LinkSelfContainedDefault, LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -7,7 +8,7 @@ pub(crate) fn target() -> Target {
         arch: "nvptx64".into(),
         data_layout: "e-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
         llvm_target: "nvptx64-nvidia-cuda".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("--emit=asm generates PTX code that runs on NVIDIA GPUs".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
index 2125c95e2664..a14051889997 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::aix::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-ibm-aix".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit AIX (7.2 and newer)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
index 201ab0d534f5..dba45776c949 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
@@ -11,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-freebsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PPC64 FreeBSD (ELFv2)".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
index 1a2f21259429..1f67bc7f3c28 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -11,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PowerPC Linux (kernel 3.2, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
index 417c8b63c86b..49413d27a455 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -13,7 +15,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit PowerPC Linux with musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
index 15947fdb0ac2..f5ca54291c69 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
@@ -11,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("OpenBSD/powerpc64".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
index d48c2f5e744b..3e4a58f568af 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
@@ -11,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
index 13885c7326a7..4640d537e8ea 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
@@ -9,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-freebsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PPC64LE FreeBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
index 06ae54063cef..dd3f660d81e4 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -9,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PPC64LE Linux (kernel 3.10, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
index f763c37f535e..9e2bfe2c56fe 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -11,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit PowerPC Linux with musl 1.2.3, Little Endian".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
index d6a84f55f5ee..5e1161e2f7d6 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
@@ -14,7 +16,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-freebsd13.0".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PowerPC FreeBSD".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
index 6f3a2baf4056..6cde4bd98ac1 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -10,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PowerPC Linux (kernel 3.2, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
index c4d894823e6a..03bae9b59777 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -10,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PowerPC SPE Linux".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
index 5b5fea666bb9..316b62d941b4 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -12,7 +14,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PowerPC Linux with musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
index dfd99635ddd0..df4fd75b0bde 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -12,7 +14,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-muslspe".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("PowerPC SPE Linux with musl".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
index 7492077bb88b..47a61a1aff24 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
@@ -10,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("NetBSD 32-bit powerpc systems".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
index dd82a6a71cda..bc5a50a05399 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
index c4f93c60d3ea..ca78be2b2b23 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
@@ -10,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
index 0284c50bd650..e6345629f039 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
@@ -10,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
index 4d3df78a5636..55dc6a70627c 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs
index 771ffac7d804..00e8532d2384 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     let abi = "ilp32e";
@@ -7,7 +9,7 @@ pub(crate) fn target() -> Target {
         // `options.llvm_abiname`.
         data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32E ISA)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs
index 3b81c278d3af..f814201601fc 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     let abi = "ilp32e";
@@ -7,7 +9,7 @@ pub(crate) fn target() -> Target {
         // `options.llvm_abiname`.
         data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32EM ISA)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs
index c18b51ad46e8..33df429db725 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     let abi = "ilp32e";
@@ -7,7 +9,7 @@ pub(crate) fn target() -> Target {
         // `options.llvm_abiname`.
         data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32EMC ISA)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
index e9c57b99b927..6dda346aaaf5 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
@@ -1,11 +1,11 @@
 use std::borrow::Cow;
 
-use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv32-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V Linux (kernel 5.4, glibc 2.33)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
index a07429bb0c5a..ba10e3c68818 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
@@ -1,11 +1,11 @@
 use std::borrow::Cow;
 
-use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv32-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some(
                 "RISC-V Linux (kernel 5.4, musl 1.2.3 + RISCV32 support patches".into(),
             ),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
index 0e0e13fd1d8e..f9a3b2172205 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32I ISA)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
index 669c1702fda8..162f21c42ba2 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
index 477a6c0e9eb9..47b408a12d17 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs
index 68146788d207..a173fb00b329 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32IMA ISA)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
index e12c3af6f8f3..48db9f44eacd 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
@@ -1,10 +1,10 @@
-use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V ESP-IDF".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
index adc76f3cdb58..1608f051ea82 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32IMAC ISA)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
index 3eb3d18faf44..4ee02c6b2956 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
index 88d112a012d0..0893bd5ad6dc 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V Xous (RV32IMAC ISA)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
index 0d5eda708d10..0929af7bb75f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
@@ -1,10 +1,10 @@
-use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V ESP-IDF".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
index 7395e1a6aad2..44a84d9082cd 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32IMAFC ISA)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
index 7864f7f8f9a3..8908c0c53d9f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
index cec97f865389..82a4d58a3986 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
@@ -1,10 +1,10 @@
-use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V ESP-IDF".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
index 0e00fc69b41a..755ffc6154a1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV32IMC ISA)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
index 60d8ec576af6..8da0b0e3e6b2 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
@@ -1,10 +1,12 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
index f694a1cb60dd..c8ef737b9e73 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -1,11 +1,13 @@
 use std::borrow::Cow;
 
-use crate::spec::{CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetOptions, base};
+use crate::spec::{
+    CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-linux-android".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V 64-bit Android".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
index 720549e6a017..58ded24b9c59 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
index 905bed76db4d..ecf656775311 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, Target, TargetOptions, base};
+use crate::spec::{CodeModel, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-freebsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V FreeBSD".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
index 7a887b604c50..d673936f5f85 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-fuchsia".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V Fuchsia".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
index a24e24edc59d..88b5dca284ae 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, RelocModel, Target, TargetOptions, TlsModel, base};
+use crate::spec::{CodeModel, RelocModel, Target, TargetMetadata, TargetOptions, TlsModel, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-hermit".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V Hermit".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
index da2c272005d7..8ffb622511db 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
@@ -1,11 +1,11 @@
 use std::borrow::Cow;
 
-use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V Linux (kernel 4.20, glibc 2.29)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index 0a4cc3b8be6c..33b08fdcb051 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -1,11 +1,11 @@
 use std::borrow::Cow;
 
-use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetOptions, base};
+use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V Linux (kernel 4.20, musl 1.2.3)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
index 9edec38f6528..2b647e36f18a 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, Target, TargetOptions, base};
+use crate::spec::{CodeModel, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("RISC-V NetBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index c32c57d92f75..d6f0a5499b99 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -1,12 +1,12 @@
 use crate::spec::{
     Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetOptions,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV64IMAFDC ISA)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
index 2cbb8c19b849..bc6829897a42 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
@@ -1,12 +1,12 @@
 use crate::spec::{
     Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetOptions, cvs,
+    TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
index 6aacb04418e2..75f508d8e933 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
@@ -1,9 +1,9 @@
-use crate::spec::{CodeModel, Target, TargetOptions, base};
+use crate::spec::{CodeModel, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("OpenBSD/riscv64".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
index d62ecc07a5d4..5c5d4aa32a2c 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
@@ -1,13 +1,13 @@
 use crate::spec::{
     Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetOptions,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         llvm_target: "riscv64".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare RISC-V (RV64IMAC ISA)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
index 306b23d27876..0928250dba64 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
@@ -1,12 +1,12 @@
 use crate::spec::{
     Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetOptions, cvs,
+    TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
index 41aa400f3e09..e0d16a7bfa55 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "s390x-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("S390x Linux (kernel 3.2, glibc 2.17)".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
index 61c01eba70d4..47050c1f769e 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "s390x-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("S390x Linux (kernel 3.2, musl 1.2.3)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
index 3317fe51c334..a52dadba5a51 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("SPARC Linux (kernel 4.4, glibc 2.23)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
index 4c2b971c0f13..21eedc5b6bc0 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("NetBSD/sparc64".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
index 81d7bf9a6284..b573bdf80a96 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("OpenBSD/sparc64".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
index 6abef79be96a..ffef69679125 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
@@ -1,11 +1,11 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "sparc-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("32-bit SPARC Linux".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
index 00cd7438f7ec..c2f64998dddb 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
@@ -1,6 +1,8 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+};
 
 pub(crate) fn target() -> Target {
     let options = TargetOptions {
@@ -20,7 +22,7 @@ pub(crate) fn target() -> Target {
     Target {
         data_layout: "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64".into(),
         llvm_target: "sparc-unknown-none-elf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare 32-bit SPARC V7+".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
index 5b7d560a8e09..1c53e15837cf 100644
--- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Cc, LinkerFlavor, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::solaris::opts();
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "sparcv9-sun-solaris".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("SPARC Solaris 11.4".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
index b0eefcab209e..7221bd8d4aef 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
@@ -10,13 +10,14 @@
 //! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
 
 use crate::spec::{
-    FloatAbi, FramePointer, PanicStrategy, RelocModel, Target, TargetOptions, base, cvs,
+    FloatAbi, FramePointer, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, base,
+    cvs,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv4t-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Thumb-mode Bare ARMv4T".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
index 1439e4a939f0..155e25211c1f 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
@@ -1,11 +1,11 @@
 //! Targets the ARMv5TE, with code as `t32` code by default.
 
-use crate::spec::{FloatAbi, FramePointer, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, FramePointer, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv5te-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Thumb-mode Bare ARMv5TE".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
index 4333a9c631c8..3b4b94da0577 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
@@ -1,11 +1,11 @@
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv6m-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv6-M".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
index dcf98acc41f8..3c6133dc7ceb 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
@@ -1,11 +1,11 @@
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv6m-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs
index b5cb393f4b00..5660f97c8b57 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs
@@ -4,12 +4,12 @@
 // and will use software floating point operations. This matches the NuttX EABI
 // configuration without hardware floating point support.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7a-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs
index 1aa44a8cc939..d79970b0a0dd 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs
@@ -7,12 +7,12 @@
 // This target uses the "hard" floating convention (ABI) where floating point values
 // are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7a-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
index a62d03ba0d32..33da885cc1a5 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
@@ -1,4 +1,6 @@
-use crate::spec::{FloatAbi, LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions, base};
+use crate::spec::{
+    FloatAbi, LinkerFlavor, Lld, PanicStrategy, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -13,7 +15,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
index c9df66253b36..b4cc960939e9 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
@@ -1,9 +1,9 @@
-use crate::spec::{FloatAbi, PanicStrategy, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, PanicStrategy, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
index b5cf8ce74f4c..c747d721b671 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
@@ -9,12 +9,12 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv7E-M".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
index c7b54b94efa7..309d32042a03 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
@@ -8,12 +8,12 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv7E-M, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
index a3bc4013e530..57ef4e75e640 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
@@ -9,12 +9,12 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
index 14bbe38257d3..0518872dd62d 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
@@ -8,12 +8,12 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
index 50f7bc1f810a..f261009d854e 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
@@ -1,11 +1,11 @@
 // Targets the Cortex-M3 processor (ARMv7-M)
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7m-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv7-M".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
index 2a77f48a9cd3..611795e58f1f 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
@@ -1,11 +1,11 @@
 // Targets the Cortex-M3 processor (ARMv7-M)
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv7m-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
index de3ac26a2bd9..d3a25163c53f 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, FloatAbi, LinkerFlavor, Lld, Target, TargetOptions, base};
+use crate::spec::{Cc, FloatAbi, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
 
 // This target if is for the Android v7a ABI in thumb mode with
 // NEON unconditionally enabled and, therefore, with 32 FPU registers
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Thumb2-mode ARMv7-A Android with NEON".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
index 120f13ae56d7..cce49f274aca 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on ARMv7 with thumb mode enabled
 // (for consistency with Android and Debian-based distributions)
@@ -9,7 +9,7 @@ use crate::spec::{FloatAbi, Target, TargetOptions, base};
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some(
                 "Thumb2-mode ARMv7-A Linux with NEON (kernel 4.4, glibc 2.23)".into(),
             ),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
index 1149b6d16eb2..81c502bfeada 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for musl Linux on ARMv7 with thumb mode enabled
 // (for consistency with Android and Debian-based distributions)
@@ -9,7 +9,7 @@ use crate::spec::{FloatAbi, Target, TargetOptions, base};
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-musleabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Thumb2-mode ARMv7-A Linux with NEON, musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
index 823fb828e4df..b35f7bac93b4 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
@@ -1,11 +1,11 @@
 // Targets the Cortex-M23 processor (Baseline ARMv8-M)
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.base-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv8-M Baseline".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
index 25a100e9c7e5..4e5f6898651a 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
@@ -1,11 +1,11 @@
 // Targets the Cortex-M23 processor (Baseline ARMv8-M)
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.base-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
index 47304e3027d9..38143904efd1 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
@@ -1,12 +1,12 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // without the Floating Point extension.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv8-M Mainline".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
index ddb5132ba605..55b7561da84c 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
@@ -1,12 +1,12 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // with the Floating Point extension.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Bare ARMv8-M Mainline, hardfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
index 0bfe2b32ad4a..56aca0a88297 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
@@ -1,12 +1,12 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // without the Floating Point extension.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
index 9f75f23aa93e..47525e704daf 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
@@ -1,12 +1,12 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // with the Floating Point extension.
 
-use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs};
+use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabihf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
index bdb1fc557112..4624c0fd5cba 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, base, cvs,
+    LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, base,
+    cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -25,7 +26,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "wasm32-unknown-emscripten".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("WebAssembly via Emscripten".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
index bcf7b69fe74a..b5792731a900 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
@@ -10,7 +10,7 @@
 //! This target is more or less managed by the Rust and WebAssembly Working
 //! Group nowadays at .
 
-use crate::spec::{Cc, LinkerFlavor, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut options = base::wasm::options();
@@ -36,7 +36,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("WebAssembly".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
index 0862958d05da..26add451ed25 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -10,7 +10,9 @@
 //! was since renamed to `wasm32-wasip1` after the preview2 target was
 //! introduced.
 
-use crate::spec::{Cc, LinkSelfContainedDefault, LinkerFlavor, Target, base, crt_objects};
+use crate::spec::{
+    Cc, LinkSelfContainedDefault, LinkerFlavor, Target, TargetMetadata, base, crt_objects,
+};
 
 pub(crate) fn target() -> Target {
     let mut options = base::wasm::options();
@@ -48,7 +50,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-wasip1".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("WebAssembly with WASI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
index 2411d386f52f..44d906a507de 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
@@ -7,7 +7,9 @@
 //!
 //! Historically this target was known as `wasm32-wasi-preview1-threads`.
 
-use crate::spec::{Cc, LinkSelfContainedDefault, LinkerFlavor, Target, base, crt_objects};
+use crate::spec::{
+    Cc, LinkSelfContainedDefault, LinkerFlavor, Target, TargetMetadata, base, crt_objects,
+};
 
 pub(crate) fn target() -> Target {
     let mut options = base::wasm::options();
@@ -61,7 +63,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-wasi".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index 3f4618fad5aa..7ad675dc3cf1 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -16,7 +16,9 @@
 //! You can see more about wasi at  and the component model at
 //! .
 
-use crate::spec::{LinkSelfContainedDefault, RelocModel, Target, base, crt_objects};
+use crate::spec::{
+    LinkSelfContainedDefault, RelocModel, Target, TargetMetadata, base, crt_objects,
+};
 
 pub(crate) fn target() -> Target {
     let mut options = base::wasm::options();
@@ -59,7 +61,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-wasip2".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("WebAssembly".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs b/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs
index ab1dc21d125f..e554e2ac0768 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32v1_none.rs
@@ -12,7 +12,7 @@
 //! nightly Rust feature `-Zbuild-std`. This target is for people who want to
 //! use stable Rust, and target a stable set pf WebAssembly features.
 
-use crate::spec::{Cc, LinkerFlavor, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut options = base::wasm::options();
@@ -43,7 +43,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("WebAssembly".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
index 596e26d1e9da..e8ac93a87ca4 100644
--- a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
@@ -7,7 +7,7 @@
 //! the standard library is available, most of it returns an error immediately
 //! (e.g. trying to create a TCP stream or something like that).
 
-use crate::spec::{Cc, LinkerFlavor, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut options = base::wasm::options();
@@ -39,7 +39,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "wasm64-unknown-unknown".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("WebAssembly".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 52ef3fc88fd7..2f868e38f1a5 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Apple macOS (10.12+, Sierra+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index f421e6b8984a..df45f430ecbf 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{SanitizerSet, Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // x86_64-apple-ios is a simulator target, even though it isn't declared
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Apple iOS Simulator".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index 3687446b9397..ee0c2bf31cd4 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{SanitizerSet, Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::MacCatalyst);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Apple Mac Catalyst".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index 07338a364e81..80ca80013f05 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // x86_64-apple-tvos is a simulator target, even though it isn't declared
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Apple tvOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 4a03c250e6ff..c503baedb8b5 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -1,11 +1,11 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetAbi::Simulator);
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Apple watchOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
index 60d078371bb6..bbaee6c1f6d9 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
@@ -1,6 +1,6 @@
 use std::borrow::Cow;
 
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, cvs};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     let pre_link_args = TargetOptions::link_args(
@@ -74,7 +74,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "x86_64-elf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Fortanix ABI for 64-bit Intel SGX".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
index d8f74f66f70b..3a0acaa028cb 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, base,
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions,
+    base,
 };
 
 pub(crate) fn target() -> Target {
@@ -15,7 +16,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-linux-android".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit x86 Android".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
index 843568a47927..662bbc4a31c4 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::solaris::opts();
@@ -12,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-solaris".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit Solaris 11.4".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
index b10d4478d5ec..16bdd3ee6684 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit MinGW (Windows 10+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
index 46c233f1863d..1a03390c2b89 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit x86 MinGW (Windows 10+), LLVM ABI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
index baf0d8b0c8b3..d88aabaa6d33 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, Target, base};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit MSVC (Windows 10+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
index 8aa0128aaa37..a5723341fe64 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
@@ -1,9 +1,11 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit Unikraft with musl 1.2.3".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
index 6492d3d7d2f3..715c0db632b1 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::dragonfly::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-dragonfly".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit DragonFlyBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
index 62cafd502e44..4a074539aab7 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
@@ -13,7 +15,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-freebsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit FreeBSD".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
index a45f8159de01..d41c696ac23b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::fuchsia::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-fuchsia".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit x86 Fuchsia".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
index b70b38dbbfe7..ecb9fc80351e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::haiku::opts();
@@ -12,7 +12,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-haiku".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit Haiku".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
index 2e239cafe955..7abde7717981 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
@@ -1,9 +1,9 @@
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-hermit".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Hermit".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
index 34835a209568..57ce67af36d6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::hurd_gnu::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-hurd-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit GNU/Hurd".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
index 69715fc257f7..17f90db0c906 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target, base};
+use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::illumos::opts();
@@ -12,7 +12,7 @@ pub(crate) fn target() -> Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
         llvm_target: "x86_64-pc-solaris".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("illumos".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
index db7e402cc806..a034a9fb2445 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{PanicStrategy, Target, base};
+use crate::spec::{PanicStrategy, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::l4re::opts();
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-l4re-uclibc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
index 59ec6c7f9d5f..0c8353fad182 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -27,7 +29,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit Linux (kernel 3.2+, glibc 2.17+)".into()),
             tier: Some(1),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
index 8a613477940d..c5d556e5cc65 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnux32".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
index 8dcdc5be8a95..cc5f88862400 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -19,7 +21,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit Linux with musl 1.2.3".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs
index 2e63ff215728..896e8a78f863 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux::opts();
@@ -11,7 +13,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-none".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: None,
             host_tools: None,
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
index 522943c91a5e..de9027ba9622 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_ohos::opts();
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-ohos".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 OpenHarmony".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
index e49729419573..0403c220982d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, base,
+    Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions,
+    base,
 };
 
 pub(crate) fn target() -> Target {
@@ -18,7 +19,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-netbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("NetBSD/amd64".into()),
             tier: Some(2),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index e14a36735894..1a6343595f54 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -6,7 +6,7 @@
 
 use crate::spec::{
     Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelroLevel, RustcAbi, SanitizerSet,
-    StackProbeType, Target, TargetOptions,
+    StackProbeType, Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -30,7 +30,7 @@ pub(crate) fn target() -> Target {
     };
     Target {
         llvm_target: "x86_64-unknown-none-elf".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Freestanding/bare-metal x86_64 softfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
index 3135ecf45dc4..2eb09b8cbada 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-openbsd".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit OpenBSD".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
index 43a28fca09ab..65b8e2543a41 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::redox::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-redox".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Redox OS".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs
index a6af06b03db9..c7b002bc9bba 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs
@@ -1,13 +1,14 @@
 // Trusty OS target for X86_64.
 
 use crate::spec::{
-    LinkSelfContainedDefault, PanicStrategy, RelroLevel, StackProbeType, Target, TargetOptions,
+    LinkSelfContainedDefault, PanicStrategy, RelroLevel, StackProbeType, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-unknown-musl".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Trusty".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
index bce6aa0ebc6b..07f853dacaf2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
@@ -6,7 +6,7 @@
 // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
 
 use crate::callconv::Conv;
-use crate::spec::{RustcAbi, Target, base};
+use crate::spec::{RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::uefi_msvc::opts();
@@ -30,7 +30,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-windows".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit UEFI".into()),
             tier: Some(2),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
index 0ef41d315af1..bf6179cb6c38 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_gnu::opts();
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
index 31861c16099d..50b0578da357 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, base};
+use crate::spec::{Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_msvc::opts();
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
index 8f903934a90f..df1fe8e7853c 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit MinGW (Windows 7+)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
index 2eceb6881087..876ac0118792 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, Target, base};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("64-bit MSVC (Windows 7+)".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
index f003f939ad11..9ab62b3530fa 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: None,
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index 0f73a860821e..11010b7d92f8 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
@@ -28,7 +28,7 @@ pub(crate) fn target() -> Target {
 
     Target {
         llvm_target,
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("x86_64 Apple macOS with Intel Haswell+".into()),
             tier: Some(3),
             host_tools: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs
index b2a7c8551e4f..c5b4d472fad3 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs
@@ -1,7 +1,7 @@
 use rustc_abi::Endian;
 
 use crate::spec::base::xtensa;
-use crate::spec::{Target, TargetOptions, cvs};
+use crate::spec::{Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -9,12 +9,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
         arch: "xtensa".into(),
-        metadata: crate::spec::TargetMetadata {
-            description: None,
-            tier: None,
-            host_tools: None,
-            std: None,
-        },
+        metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None },
 
         options: TargetOptions {
             endian: Endian::Little,
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs
index 254ae54db21f..d8638e8ac805 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::xtensa;
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
         arch: "xtensa".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Xtensa ESP32".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs
index 4fab2bac8e2d..dd98f34d3239 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs
@@ -1,7 +1,7 @@
 use rustc_abi::Endian;
 
 use crate::spec::base::xtensa;
-use crate::spec::{Target, TargetOptions, cvs};
+use crate::spec::{Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -9,12 +9,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
         arch: "xtensa".into(),
-        metadata: crate::spec::TargetMetadata {
-            description: None,
-            tier: None,
-            host_tools: None,
-            std: None,
-        },
+        metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None },
 
         options: TargetOptions {
             endian: Endian::Little,
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs
index ae7bfbd03940..29bcf12cbaf6 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::xtensa;
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
         arch: "xtensa".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Xtensa ESP32-S2".into()),
             tier: Some(3),
             host_tools: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs
index 45d409a509f3..dd6e7b6c3e8c 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs
@@ -1,7 +1,7 @@
 use rustc_abi::Endian;
 
 use crate::spec::base::xtensa;
-use crate::spec::{Target, TargetOptions, cvs};
+use crate::spec::{Target, TargetMetadata, TargetOptions, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -9,12 +9,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
         arch: "xtensa".into(),
-        metadata: crate::spec::TargetMetadata {
-            description: None,
-            tier: None,
-            host_tools: None,
-            std: None,
-        },
+        metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None },
 
         options: TargetOptions {
             endian: Endian::Little,
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs
index 023a67f28719..ddc909f387e9 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::xtensa;
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
         arch: "xtensa".into(),
-        metadata: crate::spec::TargetMetadata {
+        metadata: TargetMetadata {
             description: Some("Xtensa ESP32-S3".into()),
             tier: Some(3),
             host_tools: Some(false),

From 04ab8373c89d143feca797dfd5d501a98f59a43f Mon Sep 17 00:00:00 2001
From: Chayim Refael Friedman 
Date: Mon, 17 Feb 2025 02:26:02 +0200
Subject: [PATCH 099/158] Fix sorting of runnables

There were two mistakes: first, tests were sorted before test modules, and second, we re-sorted based on the name only, which cancelled the sort based on the kind.
---
 src/tools/rust-analyzer/crates/ide/src/annotations.rs | 9 +--------
 src/tools/rust-analyzer/crates/ide/src/runnables.rs   | 6 +++---
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
index a0add4741f32..e47891bbdfe7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
@@ -173,14 +173,7 @@ pub(crate) fn annotations(
     annotations
         .into_iter()
         .sorted_by_key(|a| {
-            (
-                a.range.start(),
-                a.range.end(),
-                match &a.kind {
-                    AnnotationKind::Runnable(runnable) => Some(runnable.nav.name.clone()),
-                    _ => None,
-                },
-            )
+            (a.range.start(), a.range.end(), matches!(a.kind, AnnotationKind::Runnable(..)))
         })
         .collect()
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index 9e3b70fa8eae..509ae3204c36 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -61,8 +61,8 @@ pub enum RunnableKind {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
 enum RunnableDiscKind {
-    Test,
     TestMod,
+    Test,
     DocTest,
     Bench,
     Bin,
@@ -1233,8 +1233,8 @@ gen_main!();
                     "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..315, name: \"\", kind: Module })",
                     "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 267..292, focus_range: 271..276, name: \"tests\", kind: Module, description: \"mod tests\" })",
                     "(Test, NavigationTarget { file_id: FileId(0), full_range: 283..290, name: \"foo_test\", kind: Function })",
-                    "(Test, NavigationTarget { file_id: FileId(0), full_range: 293..301, name: \"foo_test2\", kind: Function }, true)",
                     "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 293..301, name: \"tests2\", kind: Module, description: \"mod tests2\" }, true)",
+                    "(Test, NavigationTarget { file_id: FileId(0), full_range: 293..301, name: \"foo_test2\", kind: Function }, true)",
                     "(Bin, NavigationTarget { file_id: FileId(0), full_range: 302..314, name: \"main\", kind: Function })",
                 ]
             "#]],
@@ -1263,10 +1263,10 @@ foo!();
 "#,
             expect![[r#"
                 [
+                    "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo_tests\", kind: Module, description: \"mod foo_tests\" }, true)",
                     "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo0\", kind: Function }, true)",
                     "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo1\", kind: Function }, true)",
                     "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo2\", kind: Function }, true)",
-                    "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo_tests\", kind: Module, description: \"mod foo_tests\" }, true)",
                 ]
             "#]],
         );

From f86f7ad5f2d3eb6631e5fab57630a4fee9a50d01 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 10:45:49 +1100
Subject: [PATCH 100/158] Move some `Map` methods onto `TyCtxt`.

The end goal is to eliminate `Map` altogether.

I added a `hir_` prefix to all of them, that seemed simplest. The
exceptions are `module_items` which became `hir_module_free_items` because
there was already a `hir_module_items`, and `items` which became
`hir_free_items` for consistency with `hir_module_free_items`.
---
 compiler/rustc_ast_lowering/src/lib.rs        |   4 +-
 .../src/diagnostics/conflict_errors.rs        |  16 ++-
 .../src/diagnostics/explain_borrow.rs         |   8 +-
 .../rustc_borrowck/src/diagnostics/mod.rs     |   2 +-
 .../src/diagnostics/move_errors.rs            |   4 +-
 .../src/diagnostics/mutability_errors.rs      |  19 +--
 .../src/diagnostics/region_errors.rs          |  17 ++-
 .../rustc_codegen_cranelift/src/driver/jit.rs |   2 +-
 .../rustc_codegen_cranelift/src/global_asm.rs |   2 +-
 compiler/rustc_codegen_ssa/src/mono_item.rs   |   2 +-
 compiler/rustc_driver_impl/src/pretty.rs      |   4 +-
 .../rustc_hir_analysis/src/check/check.rs     |   6 +-
 .../src/check/compare_impl_item.rs            |  10 +-
 .../src/check/compare_impl_item/refine.rs     |   4 +-
 compiler/rustc_hir_analysis/src/check/mod.rs  |   2 +-
 .../rustc_hir_analysis/src/check/region.rs    |   4 +-
 .../rustc_hir_analysis/src/check/wfcheck.rs   |   2 +-
 .../src/coherence/builtin.rs                  |   2 +-
 .../src/coherence/inherent_impls.rs           |   2 +-
 .../src/coherence/inherent_impls_overlap.rs   |   2 +-
 compiler/rustc_hir_analysis/src/collect.rs    |  10 +-
 .../rustc_hir_analysis/src/collect/dump.rs    |   8 +-
 .../src/collect/resolve_bound_vars.rs         |  10 +-
 .../rustc_hir_analysis/src/collect/type_of.rs |   4 +-
 .../errors/wrong_number_of_generic_args.rs    |   2 +-
 .../src/hir_ty_lowering/errors.rs             |   2 +-
 .../src/hir_ty_lowering/generics.rs           |   2 +-
 .../src/hir_ty_lowering/mod.rs                |   4 +-
 .../rustc_hir_analysis/src/outlives/dump.rs   |   2 +-
 .../src/outlives/implicit_infer.rs            |   2 +-
 compiler/rustc_hir_typeck/src/callee.rs       |   4 +-
 compiler/rustc_hir_typeck/src/closure.rs      |   2 +-
 compiler/rustc_hir_typeck/src/coercion.rs     |   2 +-
 compiler/rustc_hir_typeck/src/demand.rs       |   4 +-
 compiler/rustc_hir_typeck/src/expr.rs         |   2 +-
 compiler/rustc_hir_typeck/src/fallback.rs     |   2 +-
 .../rustc_hir_typeck/src/fn_ctxt/_impl.rs     |   2 +-
 .../rustc_hir_typeck/src/fn_ctxt/checks.rs    |  10 +-
 .../src/fn_ctxt/suggestions.rs                |   4 +-
 compiler/rustc_hir_typeck/src/lib.rs          |   2 +-
 .../rustc_hir_typeck/src/method/suggest.rs    |  44 ++++---
 compiler/rustc_hir_typeck/src/pat.rs          |   2 +-
 compiler/rustc_hir_typeck/src/upvar.rs        |   4 +-
 compiler/rustc_hir_typeck/src/writeback.rs    |   4 +-
 .../rustc_interface/src/proc_macro_decls.rs   |   2 +-
 compiler/rustc_lint/src/async_closures.rs     |   2 +-
 compiler/rustc_lint/src/builtin.rs            |   2 +-
 compiler/rustc_lint/src/context.rs            |   4 +-
 .../src/default_could_be_derived.rs           |   8 +-
 .../src/for_loops_over_fallibles.rs           |   2 +-
 compiler/rustc_lint/src/late.rs               |   4 +-
 .../rustc_metadata/src/foreign_modules.rs     |   4 +-
 compiler/rustc_metadata/src/rmeta/encoder.rs  |   4 +-
 compiler/rustc_middle/src/hir/map.rs          | 116 ++++++++++--------
 compiler/rustc_middle/src/ty/print/pretty.rs  |   5 +-
 compiler/rustc_middle/src/ty/trait_def.rs     |   4 +-
 compiler/rustc_middle/src/values.rs           |   2 +-
 .../rustc_mir_build/src/check_unsafety.rs     |   2 +-
 compiler/rustc_mir_build/src/errors.rs        |   3 +-
 .../src/thir/pattern/check_match.rs           |   2 +-
 .../rustc_mir_transform/src/coverage/mod.rs   |   2 +-
 compiler/rustc_monomorphize/src/collector.rs  |   2 +-
 compiler/rustc_passes/src/check_attr.rs       |   7 +-
 compiler/rustc_passes/src/dead.rs             |  12 +-
 compiler/rustc_passes/src/entry.rs            |   2 +-
 compiler/rustc_passes/src/hir_id_validator.rs |   6 +-
 compiler/rustc_passes/src/input_stats.rs      |  22 ++--
 compiler/rustc_passes/src/naked_functions.rs  |   2 +-
 compiler/rustc_passes/src/reachable.rs        |   2 +-
 compiler/rustc_privacy/src/lib.rs             |  20 +--
 .../src/error_reporting/infer/mod.rs          |   3 +-
 .../error_reporting/infer/need_type_info.rs   |   2 +-
 .../mismatched_static_lifetime.rs             |   2 +-
 .../nice_region_error/static_impl_trait.rs    |   6 +-
 .../error_reporting/infer/note_and_explain.rs |   4 +-
 .../src/error_reporting/infer/region.rs       |  12 +-
 .../src/error_reporting/infer/suggest.rs      |   5 +-
 .../traits/fulfillment_errors.rs              |  17 +--
 .../src/error_reporting/traits/mod.rs         |   2 +-
 .../src/error_reporting/traits/suggestions.rs |  29 ++---
 compiler/rustc_trait_selection/src/errors.rs  |   2 +-
 .../src/errors/note_and_explain.rs            |   5 +-
 .../src/traits/dyn_compatibility.rs           |  11 +-
 .../rustc_trait_selection/src/traits/misc.rs  |   2 +-
 .../rustc_trait_selection/src/traits/wf.rs    |   2 +-
 compiler/rustc_ty_utils/src/opaque_types.rs   |   2 +-
 .../rustc-driver-interacting-with-the-ast.rs  |   2 +-
 src/librustdoc/clean/inline.rs                |   2 +-
 src/librustdoc/clean/mod.rs                   |   6 +-
 src/librustdoc/clean/types.rs                 |  17 ++-
 src/librustdoc/core.rs                        |   2 +-
 src/librustdoc/json/conversions.rs            |   2 +-
 .../passes/calculate_doc_coverage.rs          |   2 +-
 src/librustdoc/visit_ast.rs                   |  12 +-
 .../src/arbitrary_source_item_ordering.rs     |   2 +-
 .../clippy_lints/src/async_yields_async.rs    |   4 +-
 .../clippy/clippy_lints/src/attrs/utils.rs    |   6 +-
 src/tools/clippy/clippy_lints/src/booleans.rs |   2 +-
 .../src/collection_is_never_read.rs           |   2 +-
 .../clippy_lints/src/derivable_impls.rs       |   2 +-
 .../clippy_lints/src/doc/missing_headers.rs   |   2 +-
 src/tools/clippy/clippy_lints/src/doc/mod.rs  |   4 +-
 .../clippy/clippy_lints/src/empty_drop.rs     |   2 +-
 .../clippy/clippy_lints/src/eta_reduction.rs  |   2 +-
 .../src/extra_unused_type_parameters.rs       |   2 +-
 .../clippy_lints/src/fallible_impl_from.rs    |   4 +-
 .../clippy/clippy_lints/src/format_impl.rs    |   2 +-
 .../clippy/clippy_lints/src/from_over_into.rs |   4 +-
 .../src/functions/impl_trait_in_params.rs     |   2 +-
 .../clippy_lints/src/functions/must_use.rs    |   6 +-
 .../src/functions/not_unsafe_ptr_arg_deref.rs |   2 +-
 .../clippy_lints/src/implicit_hasher.rs       |   4 +-
 .../clippy/clippy_lints/src/infinite_iter.rs  |   2 +-
 .../src/items_after_statements.rs             |   2 +-
 .../src/items_after_test_module.rs            |   4 +-
 .../src/iter_without_into_iter.rs             |   2 +-
 src/tools/clippy/clippy_lints/src/len_zero.rs |   2 +-
 .../clippy/clippy_lints/src/lifetimes.rs      |   2 +-
 .../clippy_lints/src/lines_filter_map_ok.rs   |   2 +-
 .../src/loops/needless_range_loop.rs          |   2 +-
 .../src/loops/while_let_on_iterator.rs        |   2 +-
 .../clippy_lints/src/manual_async_fn.rs       |   2 +-
 .../src/manual_option_as_slice.rs             |   2 +-
 .../clippy/clippy_lints/src/manual_retain.rs  |   6 +-
 .../clippy/clippy_lints/src/map_unit_fn.rs    |   2 +-
 .../src/methods/bind_instead_of_map.rs        |   2 +-
 .../clippy_lints/src/methods/bytecount.rs     |   2 +-
 .../clippy_lints/src/methods/filter_map.rs    |   6 +-
 .../src/methods/filter_map_bool_then.rs       |   4 +-
 .../src/methods/format_collect.rs             |   2 +-
 .../clippy_lints/src/methods/iter_filter.rs   |   2 +-
 .../clippy_lints/src/methods/iter_kv_map.rs   |   2 +-
 .../src/methods/iter_overeager_cloned.rs      |   2 +-
 .../src/methods/manual_inspect.rs             |   4 +-
 .../clippy_lints/src/methods/manual_ok_or.rs  |   2 +-
 .../clippy_lints/src/methods/map_clone.rs     |   2 +-
 .../src/methods/map_err_ignore.rs             |   2 +-
 .../map_with_unused_argument_over_ranges.rs   |   2 +-
 .../clippy/clippy_lints/src/methods/mod.rs    |   4 +-
 .../methods/needless_character_iteration.rs   |   2 +-
 .../src/methods/needless_collect.rs           |   2 +-
 .../src/methods/obfuscated_if_else.rs         |   2 +-
 .../src/methods/option_as_ref_deref.rs        |   2 +-
 .../src/methods/option_map_or_none.rs         |   2 +-
 .../clippy_lints/src/methods/or_fun_call.rs   |   2 +-
 .../src/methods/result_map_or_else_none.rs    |   2 +-
 .../src/methods/return_and_then.rs            |   2 +-
 .../src/methods/search_is_some.rs             |   2 +-
 .../src/methods/suspicious_map.rs             |   2 +-
 .../src/methods/unnecessary_filter_map.rs     |   2 +-
 .../src/methods/unnecessary_fold.rs           |   2 +-
 .../src/methods/unnecessary_lazy_eval.rs      |   2 +-
 .../src/methods/unnecessary_literal_unwrap.rs |   2 +-
 .../src/methods/unnecessary_map_or.rs         |   2 +-
 .../methods/unnecessary_result_map_or_else.rs |   2 +-
 .../src/methods/unnecessary_sort_by.rs        |   2 +-
 .../src/methods/unnecessary_to_owned.rs       |   2 +-
 .../src/methods/unused_enumerate_index.rs     |   2 +-
 .../clippy_lints/src/methods/useless_asref.rs |   2 +-
 .../src/missing_fields_in_debug.rs            |   4 +-
 .../clippy/clippy_lints/src/missing_inline.rs |   4 +-
 .../clippy_lints/src/needless_for_each.rs     |   2 +-
 .../src/needless_pass_by_ref_mut.rs           |   3 +-
 .../clippy_lints/src/new_without_default.rs   |   2 +-
 .../clippy_lints/src/non_canonical_impls.rs   |   4 +-
 .../clippy_lints/src/non_std_lazy_statics.rs  |   2 +-
 .../clippy_lints/src/pass_by_ref_or_value.rs  |   2 +-
 .../clippy_lints/src/redundant_async_block.rs |   2 +-
 .../src/redundant_closure_call.rs             |   4 +-
 src/tools/clippy/clippy_lints/src/returns.rs  |   2 +-
 .../clippy_lints/src/same_name_method.rs      |   4 +-
 .../clippy_lints/src/string_patterns.rs       |   2 +-
 .../clippy_lints/src/suspicious_trait_impl.rs |   2 +-
 .../clippy/clippy_lints/src/trait_bounds.rs   |   2 +-
 .../clippy_lints/src/types/borrowed_box.rs    |   4 +-
 .../src/unconditional_recursion.rs            |   4 +-
 .../src/undocumented_unsafe_blocks.rs         |   6 +-
 .../src/unit_return_expecting_ord.rs          |   2 +-
 .../src/unit_types/let_unit_value.rs          |   2 +-
 .../clippy/clippy_lints/src/unused_self.rs    |   2 +-
 .../clippy_lints/src/unwrap_in_result.rs      |   2 +-
 .../clippy/clippy_lints/src/utils/author.rs   |   4 +-
 .../utils/internal_lints/collapsible_calls.rs |   2 +-
 .../src/utils/internal_lints/invalid_paths.rs |   2 +-
 .../internal_lints/lint_without_lint_pass.rs  |   2 +-
 .../src/zero_repeat_side_effects.rs           |   3 +-
 .../clippy_utils/src/check_proc_macro.rs      |   2 +-
 src/tools/clippy/clippy_utils/src/consts.rs   |   8 +-
 .../clippy/clippy_utils/src/hir_utils.rs      |   8 +-
 src/tools/clippy/clippy_utils/src/lib.rs      |  22 ++--
 src/tools/clippy/clippy_utils/src/ptr.rs      |   2 +-
 src/tools/clippy/clippy_utils/src/sugg.rs     |   2 +-
 src/tools/clippy/clippy_utils/src/visitors.rs |   4 +-
 .../clippy/tests/ui/author/blocks.stdout      |   4 +-
 .../tests/ui/author/macro_in_closure.stdout   |   2 +-
 .../clippy/tests/ui/author/repeat.stdout      |   2 +-
 tests/ui-fulldeps/obtain-borrowck.rs          |   3 +-
 197 files changed, 465 insertions(+), 476 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index facc9414b20d..1c777111896d 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -407,7 +407,7 @@ fn compute_hir_hash(
         .iter_enumerated()
         .filter_map(|(def_id, info)| {
             let info = info.as_owner()?;
-            let def_path_hash = tcx.hir().def_path_hash(def_id);
+            let def_path_hash = tcx.hir_def_path_hash(def_id);
             Some((def_path_hash, info))
         })
         .collect();
@@ -497,7 +497,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
             node_id,
             def_kind,
-            self.tcx.hir().def_key(self.local_def_id(node_id)),
+            self.tcx.hir_def_key(self.local_def_id(node_id)),
         );
 
         let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8fa409f4e381..4428d2246a16 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1437,7 +1437,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let Some(hir_generics) = tcx
             .typeck_root_def_id(self.mir_def_id().to_def_id())
             .as_local()
-            .and_then(|def_id| tcx.hir().get_generics(def_id))
+            .and_then(|def_id| tcx.hir_get_generics(def_id))
         else {
             return;
         };
@@ -1889,7 +1889,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'infcx>, place: Place<'tcx>) {
         let tcx = self.infcx.tcx;
-        let hir = tcx.hir();
         let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
 
         struct FindUselessClone<'tcx> {
@@ -1917,7 +1916,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
         let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id());
 
-        let body = hir.body(body_id).value;
+        let body = tcx.hir_body(body_id).value;
         expr_finder.visit_expr(body);
 
         struct Holds<'tcx> {
@@ -2106,7 +2105,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let tcx = self.infcx.tcx;
         let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
         let mut expr_finder = FindExprBySpan::new(span, tcx);
-        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        expr_finder.visit_expr(tcx.hir_body(body_id).value);
         expr_finder.result
     }
 
@@ -2258,7 +2257,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     ) {
         let issue_span = issued_spans.args_or_use();
         let tcx = self.infcx.tcx;
-        let hir = tcx.hir();
 
         let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
         let typeck_results = tcx.typeck(self.mir_def_id());
@@ -2346,7 +2344,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             pat_span: None,
             head: None,
         };
-        finder.visit_expr(hir.body(body_id).value);
+        finder.visit_expr(tcx.hir_body(body_id).value);
 
         if let Some(body_expr) = finder.body_expr
             && let Some(loop_span) = finder.loop_span
@@ -2454,7 +2452,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         // Get the body the error happens in
         let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
 
-        let body_expr = hir.body(body_id).value;
+        let body_expr = tcx.hir_body(body_id).value;
 
         struct ClosureFinder<'hir> {
             hir: rustc_middle::hir::map::Map<'hir>,
@@ -2558,7 +2556,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             }
 
             let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
-            finder.visit_expr(hir.body(closure.body).value);
+            finder.visit_expr(tcx.hir_body(closure.body).value);
 
             spans = finder.spans;
         } else {
@@ -3211,7 +3209,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 if let Some(scope) = self.body.source_scopes.get(source_info.scope)
                     && let ClearCrossCrate::Set(scope_data) = &scope.local_data
                     && let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id()
-                    && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
+                    && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir_body(id).value.kind
                 {
                     for stmt in block.stmts {
                         let mut visitor = NestedStatementVisitor {
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 3e474225afdf..976d14bb245d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -75,10 +75,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
 
         if let Some(span) = borrow_span {
             let def_id = body.source.def_id();
-            if let Some(node) = tcx.hir().get_if_local(def_id)
+            if let Some(node) = tcx.hir_get_if_local(def_id)
                 && let Some(body_id) = node.body_id()
             {
-                let body = tcx.hir().body(body_id);
+                let body = tcx.hir_body(body_id);
                 let mut expr_finder = FindExprBySpan::new(span, tcx);
                 expr_finder.visit_expr(body.value);
                 if let Some(mut expr) = expr_finder.result {
@@ -308,9 +308,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
                             suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
                         } else if let Some((old, new)) = multiple_borrow_span
                             && let def_id = body.source.def_id()
-                            && let Some(node) = tcx.hir().get_if_local(def_id)
+                            && let Some(node) = tcx.hir_get_if_local(def_id)
                             && let Some(body_id) = node.body_id()
-                            && let hir_body = tcx.hir().body(body_id)
+                            && let hir_body = tcx.hir_body(body_id)
                             && let mut expr_finder = (FindLetExpr { span: old, result: None, tcx })
                             && let Some((let_expr_span, let_expr_pat, let_expr_init)) = {
                                 expr_finder.visit_expr(hir_body.value);
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index df83ac985c65..07ea369c5c7f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1220,7 +1220,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                             .tcx
                             .typeck_root_def_id(self.mir_def_id().to_def_id())
                             .as_local()
-                            .and_then(|def_id| self.infcx.tcx.hir().get_generics(def_id))
+                            .and_then(|def_id| self.infcx.tcx.hir_get_generics(def_id))
                         && let spans = hir_generics
                             .predicates
                             .iter()
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 58c5c2fd7742..c5449952f993 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -347,7 +347,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         // Find the closure that captured the binding.
         let mut expr_finder = FindExprBySpan::new(args_span, tcx);
         expr_finder.include_closures = true;
-        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        expr_finder.visit_expr(tcx.hir_body(body_id).value);
         let Some(closure_expr) = expr_finder.result else { return };
         let ExprKind::Closure(closure) = closure_expr.kind else { return };
         // We'll only suggest cloning the binding if it's a `move` closure.
@@ -357,7 +357,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let use_span = use_spans.var_or_use();
         let mut expr_finder = FindExprBySpan::new(use_span, tcx);
         expr_finder.include_closures = true;
-        expr_finder.visit_expr(tcx.hir().body(body_id).value);
+        expr_finder.visit_expr(tcx.hir_body(body_id).value);
         let Some(use_expr) = expr_finder.result else { return };
         let parent = tcx.parent_hir_node(use_expr.hir_id);
         if let Node::Expr(expr) = parent
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 706dd7135f73..fc782ce64249 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -936,11 +936,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str) {
         err.span_label(sp, format!("cannot {act}"));
 
-        let hir = self.infcx.tcx.hir();
+        let tcx = self.infcx.tcx;
+        let hir = tcx.hir();
         let closure_id = self.mir_hir_id();
-        let closure_span = self.infcx.tcx.def_span(self.mir_def_id());
-        let fn_call_id = self.infcx.tcx.parent_hir_id(closure_id);
-        let node = self.infcx.tcx.hir_node(fn_call_id);
+        let closure_span = tcx.def_span(self.mir_def_id());
+        let fn_call_id = tcx.parent_hir_id(closure_id);
+        let node = tcx.hir_node(fn_call_id);
         let def_id = hir.enclosing_body_owner(fn_call_id);
         let mut look_at_return = true;
 
@@ -951,7 +952,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 return None;
             };
 
-            let typeck_results = self.infcx.tcx.typeck(def_id);
+            let typeck_results = tcx.typeck(def_id);
 
             match kind {
                 hir::ExprKind::Call(expr, args) => {
@@ -980,7 +981,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 .map(|(pos, _)| pos)
                 .next();
 
-            let arg = match hir.get_if_local(callee_def_id) {
+            let arg = match tcx.hir_get_if_local(callee_def_id) {
                 Some(
                     hir::Node::Item(hir::Item {
                         ident, kind: hir::ItemKind::Fn { sig, .. }, ..
@@ -1022,7 +1023,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         if look_at_return && hir.get_fn_id_for_return_block(closure_id).is_some() {
             // ...otherwise we are probably in the tail expression of the function, point at the
             // return type.
-            match self.infcx.tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
+            match tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
                 hir::Node::Item(hir::Item {
                     ident, kind: hir::ItemKind::Fn { sig, .. }, ..
                 })
@@ -1050,9 +1051,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     fn suggest_using_iter_mut(&self, err: &mut Diag<'_>) {
         let source = self.body.source;
-        let hir = self.infcx.tcx.hir();
         if let InstanceKind::Item(def_id) = source.instance
-            && let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id)
+            && let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) =
+                self.infcx.tcx.hir_get_if_local(def_id)
             && let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind
             && let Node::Expr(expr) = self.infcx.tcx.parent_hir_node(*hir_id)
         {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index b7e2510e035a..9c1baf870e18 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -205,7 +205,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         lower_bound: RegionVid,
     ) {
         let mut suggestions = vec![];
-        let hir = self.infcx.tcx.hir();
+        let tcx = self.infcx.tcx;
 
         // find generic associated types in the given region 'lower_bound'
         let gat_id_and_generics = self
@@ -214,12 +214,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             .map(|placeholder| {
                 if let Some(id) = placeholder.bound.kind.get_id()
                     && let Some(placeholder_id) = id.as_local()
-                    && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id)
-                    && let Some(generics_impl) = self
-                        .infcx
-                        .tcx
-                        .parent_hir_node(self.infcx.tcx.parent_hir_id(gat_hir_id))
-                        .generics()
+                    && let gat_hir_id = tcx.local_def_id_to_hir_id(placeholder_id)
+                    && let Some(generics_impl) =
+                        tcx.parent_hir_node(tcx.parent_hir_id(gat_hir_id)).generics()
                 {
                     Some((gat_hir_id, generics_impl))
                 } else {
@@ -240,7 +237,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 };
                 if bound_generic_params
                     .iter()
-                    .rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
+                    .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
                     .is_some()
                 {
                     for bound in *bounds {
@@ -256,7 +253,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 return;
             };
             diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static);
-            let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local())
+            let Some(generics_fn) = tcx.hir_get_generics(self.body.source.def_id().expect_local())
             else {
                 return;
             };
@@ -1144,7 +1141,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
         if ocx.select_all_or_error().is_empty() && count > 0 {
             diag.span_suggestion_verbose(
-                tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
+                tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(),
                 fluent::borrowck_dereference_suggestion,
                 "*".repeat(count),
                 Applicability::MachineApplicable,
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 2e713171ae06..57c88f4b0f9f 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -124,7 +124,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
                     crate::constant::codegen_static(tcx, &mut jit_module, def_id);
                 }
                 MonoItem::GlobalAsm(item_id) => {
-                    let item = tcx.hir().item(item_id);
+                    let item = tcx.hir_item(item_id);
                     tcx.dcx().span_fatal(item.span, "Global asm is not supported in JIT mode");
                 }
             }
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index c0a3ce84d529..54745b0d8c10 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -15,7 +15,7 @@ use rustc_target::asm::InlineAsmArch;
 use crate::prelude::*;
 
 pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
-    let item = tcx.hir().item(item_id);
+    let item = tcx.hir_item(item_id);
     if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
         let is_x86 =
             matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 6749bc63327e..5f95b6615bd3 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -35,7 +35,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
                 cx.codegen_static(def_id);
             }
             MonoItem::GlobalAsm(item_id) => {
-                let item = cx.tcx().hir().item(item_id);
+                let item = cx.tcx().hir_item(item_id);
                 if let hir::ItemKind::GlobalAsm(asm) = item.kind {
                     let operands: Vec<_> = asm
                         .operands
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 576b1c76823f..ea17dd773c04 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -273,7 +273,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
                 let attrs = |id| hir_map.attrs(id);
                 pprust_hir::print_crate(
                     sm,
-                    hir_map.root_module(),
+                    tcx.hir_root_module(),
                     src_name,
                     src,
                     &attrs,
@@ -294,7 +294,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
         }
         HirTree => {
             debug!("pretty printing HIR tree");
-            format!("{:#?}", ex.tcx().hir().krate())
+            format!("{:#?}", ex.tcx().hir_krate())
         }
         Mir => {
             let mut out = Vec::new();
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 71a10ad3a0c1..0d33aaa5d84f 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -124,7 +124,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
 
     for field in &def.non_enum_variant().fields {
         if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
-            let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
+            let (field_span, ty_span) = match tcx.hir_get_if_local(field.did) {
                 // We are currently checking the type this field came from, so it must be local.
                 Some(Node::Field(field)) => (field.span, field.ty.span),
                 _ => unreachable!("mir field has to correspond to hir field"),
@@ -880,7 +880,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                             .emit();
                         }
 
-                        let item = tcx.hir().foreign_item(item.id);
+                        let item = tcx.hir_foreign_item(item.id);
                         match &item.kind {
                             hir::ForeignItemKind::Fn(sig, _, _) => {
                                 require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
@@ -1494,7 +1494,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
                 // In the case the discriminant is both a duplicate and overflowed, let the user know
                 if let hir::Node::AnonConst(expr) =
                     tcx.hir_node_by_def_id(discr_def_id.expect_local())
-                    && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
+                    && let hir::ExprKind::Lit(lit) = &tcx.hir_body(expr.body).value.kind
                     && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
                     && *lit_value != dis.val
                 {
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index bb5087e864cb..84d5ec4a1e5b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -658,11 +658,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                 "method `{}` has an incompatible return type for trait",
                 trait_m.name
             );
-            let hir = tcx.hir();
             infcx.err_ctxt().note_type_err(
                 &mut diag,
                 &cause,
-                hir.get_if_local(impl_m.def_id)
+                tcx.hir_get_if_local(impl_m.def_id)
                     .and_then(|node| node.fn_decl())
                     .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)),
                 Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
@@ -1123,15 +1122,14 @@ fn check_region_bounds_on_impl_item<'tcx>(
     // the moment, give a kind of vague error message.
     if trait_params != impl_params {
         let span = tcx
-            .hir()
-            .get_generics(impl_m.def_id.expect_local())
+            .hir_get_generics(impl_m.def_id.expect_local())
             .expect("expected impl item to have generics or else we can't compare them")
             .span;
 
         let mut generics_span = None;
         let mut bounds_span = vec![];
         let mut where_span = None;
-        if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
+        if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
             && let Some(trait_generics) = trait_node.generics()
         {
             generics_span = Some(trait_generics.span);
@@ -1146,7 +1144,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
                     }
                 }
             }
-            if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
+            if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
                 && let Some(impl_generics) = impl_node.generics()
             {
                 let mut impl_bounds = 0;
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 0e9e9b48ab30..4973d8489597 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -96,7 +96,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
 
         // This opaque also needs to be from the impl method -- otherwise,
         // it's a refinement to a TAIT.
-        if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| {
+        if !tcx.hir_get_if_local(impl_opaque.def_id).is_some_and(|node| {
             matches!(
                 node.expect_opaque_ty().origin,
                 hir::OpaqueTyOrigin::AsyncFn { parent, .. }  | hir::OpaqueTyOrigin::FnReturn { parent, .. }
@@ -327,7 +327,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
             hir::FnRetTy::Return(ty) => (ty.span, ty.span, "", ""),
         };
     let trait_return_span =
-        tcx.hir().get_if_local(trait_m_def_id).map(|node| match node.fn_decl().unwrap().output {
+        tcx.hir_get_if_local(trait_m_def_id).map(|node| match node.fn_decl().unwrap().output {
             hir::FnRetTy::DefaultReturn(_) => tcx.def_span(trait_m_def_id),
             hir::FnRetTy::Return(ty) => ty.span,
         });
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 96b33bdd2506..7b3c3ea2bb46 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -129,7 +129,7 @@ fn get_owner_return_paths(
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
     let parent_id = tcx.hir().get_parent_item(hir_id).def_id;
     tcx.hir_node_by_def_id(parent_id).body_id().map(|body_id| {
-        let body = tcx.hir().body(body_id);
+        let body = tcx.hir_body(body_id);
         let mut visitor = ReturnsVisitor::default();
         visitor.visit_body(body);
         (parent_id, visitor)
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index d43c65c0023b..88dd40ba2898 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -424,7 +424,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
         // that share the parent environment. We handle const blocks in
         // `visit_inline_const`.
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
-            let body = visitor.tcx.hir().body(body);
+            let body = visitor.tcx.hir_body(body);
             visitor.visit_body(body);
         }
         hir::ExprKind::AssignOp(_, left_expr, right_expr) => {
@@ -906,7 +906,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
         resolve_local(self, Some(l.pat), l.init)
     }
     fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
-        let body = self.tcx.hir().body(c.body);
+        let body = self.tcx.hir_body(c.body);
         self.visit_body(body);
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 4218f4ef0c15..01b4a5649f14 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1163,7 +1163,7 @@ fn check_type_defn<'tcx>(
                     // be refactored to check the instantiate-ability of the code better.
                     if let Some(def_id) = def_id.as_local()
                         && let hir::Node::AnonConst(anon) = tcx.hir_node_by_def_id(def_id)
-                        && let expr = &tcx.hir().body(anon.body).value
+                        && let expr = &tcx.hir_body(anon.body).value
                         && let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
                         && let Res::Def(DefKind::ConstParam, _def_id) = path.res
                     {
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 9da57c330c5e..b46b805f0a9d 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -679,7 +679,7 @@ fn infringing_fields_error<'tcx>(
 
     suggest_constraining_type_params(
         tcx,
-        tcx.hir().get_generics(impl_did).expect("impls always have generics"),
+        tcx.hir_get_generics(impl_did).expect("impls always have generics"),
         &mut err,
         bounds
             .iter()
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index a86dede48bff..1805e2438afa 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -25,7 +25,7 @@ pub(crate) fn crate_inherent_impls(
     let mut collect = InherentCollect { tcx, impls_map: Default::default() };
 
     let mut res = Ok(());
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         res = res.and(collect.check_item(id));
     }
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index c72f6201831a..dc616576c9c1 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -18,7 +18,7 @@ pub(crate) fn crate_inherent_impls_overlap_check(
 ) -> Result<(), ErrorGuaranteed> {
     let mut inherent_overlap_checker = InherentOverlapChecker { tcx };
     let mut res = Ok(());
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         res = res.and(inherent_overlap_checker.check_item(id));
     }
     res
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 126237799562..6b430df8ed2c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -669,7 +669,7 @@ fn get_new_lifetime_name<'tcx>(
 
 #[instrument(level = "debug", skip_all)]
 fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
-    let it = tcx.hir().item(item_id);
+    let it = tcx.hir_item(item_id);
     debug!(item = %it.ident, id = %it.hir_id());
     let def_id = item_id.owner_id.def_id;
     let icx = ItemCtxt::new(tcx, def_id);
@@ -683,7 +683,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
         | hir::ItemKind::GlobalAsm(_) => {}
         hir::ItemKind::ForeignMod { items, .. } => {
             for item in *items {
-                let item = tcx.hir().foreign_item(item.id);
+                let item = tcx.hir_foreign_item(item.id);
                 tcx.ensure_ok().generics_of(item.owner_id);
                 tcx.ensure_ok().type_of(item.owner_id);
                 tcx.ensure_ok().predicates_of(item.owner_id);
@@ -790,7 +790,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
 }
 
 fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
-    let trait_item = tcx.hir().trait_item(trait_item_id);
+    let trait_item = tcx.hir_trait_item(trait_item_id);
     let def_id = trait_item_id.owner_id;
     tcx.ensure_ok().generics_of(def_id);
     let icx = ItemCtxt::new(tcx, def_id.def_id);
@@ -865,7 +865,7 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
     tcx.ensure_ok().generics_of(def_id);
     tcx.ensure_ok().type_of(def_id);
     tcx.ensure_ok().predicates_of(def_id);
-    let impl_item = tcx.hir().impl_item(impl_item_id);
+    let impl_item = tcx.hir_impl_item(impl_item_id);
     let icx = ItemCtxt::new(tcx, def_id.def_id);
     match impl_item.kind {
         hir::ImplItemKind::Fn(..) => {
@@ -1769,7 +1769,7 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
                 ..
             }),
         ..
-    } = tcx.hir().body(body).value
+    } = tcx.hir_body(body).value
     else {
         bug!()
     };
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index 41f8465ae91f..b4ba4d11221d 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -52,7 +52,7 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
 }
 
 pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
-    for iid in tcx.hir().items() {
+    for iid in tcx.hir_free_items() {
         let did = iid.owner_id.def_id;
         if tcx.has_attr(did, sym::rustc_dump_def_parents) {
             struct AnonConstFinder<'tcx> {
@@ -77,7 +77,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
             // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
             // to see what its def parent is.
             let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
-            intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid));
+            intravisit::walk_item(&mut anon_ct_finder, tcx.hir_item(iid));
 
             for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
                 let span = tcx.def_span(did);
@@ -99,14 +99,14 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
 }
 
 pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         let def_id = id.owner_id.def_id;
 
         let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else {
             continue;
         };
 
-        let vtable_entries = match tcx.hir().item(id).kind {
+        let vtable_entries = match tcx.hir_item(id).kind {
             hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
                 let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity();
                 if trait_ref.has_non_region_param() {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index c03a1f6240fa..6bf0498a8b0c 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -427,7 +427,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     }
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
-        let body = self.tcx.hir().body(body);
+        let body = self.tcx.hir_body(body);
         self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
             this.visit_body(body);
         });
@@ -1049,7 +1049,7 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL
     match param.source {
         hir::GenericParamSource::Generics => {
             let parent_def_id = tcx.local_parent(param_def_id);
-            let generics = tcx.hir().get_generics(parent_def_id).unwrap();
+            let generics = tcx.hir_get_generics(parent_def_id).unwrap();
             let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
             let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
 
@@ -1250,7 +1250,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
                         && let hir::LifetimeName::Param(param_id) = lifetime_ref.res
                         && let Some(generics) =
-                            self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
+                            self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
                         && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
                         && param.is_elided_lifetime()
                         && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
@@ -1264,7 +1264,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         );
 
                         if let Some(generics) =
-                            self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
+                            self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
                         {
                             let new_param_sugg =
                                 if let Some(span) = generics.span_for_lifetime_suggestion() {
@@ -2266,7 +2266,7 @@ fn is_late_bound_map(
     owner_id: hir::OwnerId,
 ) -> Option<&FxIndexSet> {
     let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?;
-    let generics = tcx.hir().get_generics(owner_id.def_id)?;
+    let generics = tcx.hir_get_generics(owner_id.def_id)?;
 
     let mut late_bound = FxIndexSet::default();
 
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 4e12db190fd0..293a095b41d0 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -451,7 +451,7 @@ fn infer_placeholder_type<'tcx>(
                     );
                 } else {
                     with_forced_trimmed_paths!(err.span_note(
-                        tcx.hir().body(body_id).value.span,
+                        tcx.hir_body(body_id).value.span,
                         format!("however, the inferred type `{ty}` cannot be named"),
                     ));
                 }
@@ -494,7 +494,7 @@ fn infer_placeholder_type<'tcx>(
                     );
                 } else {
                     with_forced_trimmed_paths!(diag.span_note(
-                        tcx.hir().body(body_id).value.span,
+                        tcx.hir_body(body_id).value.span,
                         format!("however, the inferred type `{ty}` cannot be named"),
                     ));
                 }
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index b2501d647a55..681e8e36d589 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -451,7 +451,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 )
             });
 
-        let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
+        let fn_sig = self.tcx.hir_get_if_local(self.def_id).and_then(hir::Node::fn_sig);
         let is_used_in_input = |def_id| {
             fn_sig.is_some_and(|fn_sig| {
                 fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 7eb982a31798..d2789cc0fd62 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -225,7 +225,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     && let item_def_id =
                         tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
                     // FIXME: ...which obviously won't have any generics.
-                    && let Some(generics) = tcx.hir().get_generics(item_def_id.def_id)
+                    && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
                 {
                     // FIXME: Suggest adding supertrait bounds if we have a `Self` type param.
                     // FIXME(trait_alias): Suggest adding `Self: Trait` to
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 431373978701..cc28b8780c61 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -110,7 +110,7 @@ fn generic_arg_mismatch_err(
                 err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
                 err.help("function item types cannot be named directly");
             } else if let hir::ConstArgKind::Anon(anon) = cnst.kind
-                && let body = tcx.hir().body(anon.body)
+                && let body = tcx.hir_body(anon.body)
                 && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
                     body.value.kind
                 && let Res::Def(DefKind::Fn { .. }, id) = path.res
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 88323db6dda6..d5ccbdc11c82 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1976,7 +1976,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     if let Some(hir::Node::Item(&hir::Item {
                         kind: hir::ItemKind::Impl(impl_),
                         ..
-                    })) = tcx.hir().get_if_local(def_id)
+                    })) = tcx.hir_get_if_local(def_id)
                     {
                         err.span_note(impl_.self_ty.span, "not a concrete type");
                     }
@@ -2213,7 +2213,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> {
         let tcx = self.tcx();
 
-        let expr = &tcx.hir().body(anon.body).value;
+        let expr = &tcx.hir_body(anon.body).value;
         debug!(?expr);
 
         let ty = tcx
diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs
index ab50d9e86efb..4233896c3720 100644
--- a/compiler/rustc_hir_analysis/src/outlives/dump.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::sym;
 
 pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) {
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         if !tcx.has_attr(id.owner_id, sym::rustc_outlives) {
             continue;
         }
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 036163b9f140..a0faa5e8429e 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -28,7 +28,7 @@ pub(super) fn infer_predicates(
         let mut predicates_added = false;
 
         // Visit all the crates and infer predicates
-        for id in tcx.hir().items() {
+        for id in tcx.hir_free_items() {
             let item_did = id.owner_id;
 
             debug!("InferVisitor::visit_item(item={:?})", item_did);
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index f2d0b9117314..bccde7822645 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -708,8 +708,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && let Res::Local(_) = path.res
             && let [segment] = &path.segments
         {
-            for id in self.tcx.hir().items() {
-                if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into())
+            for id in self.tcx.hir_free_items() {
+                if let Some(node) = self.tcx.hir_get_if_local(id.owner_id.into())
                     && let hir::Node::Item(item) = node
                     && let hir::ItemKind::Fn { .. } = item.kind
                     && item.ident.name == segment.ident.name
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 43124f44ca60..71a0664bbdff 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -51,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let body = tcx.hir().body(closure.body);
+        let body = tcx.hir_body(closure.body);
         let expr_def_id = closure.def_id;
 
         // It's always helpful for inference if we know the kind of
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index ad378367e305..c8433d0cb5b1 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1891,7 +1891,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 kind: hir::ExprKind::Closure(&hir::Closure { body, .. }),
                 ..
             }) = parent
-            && !matches!(fcx.tcx.hir().body(body).value.kind, hir::ExprKind::Block(..))
+            && !matches!(fcx.tcx.hir_body(body).value.kind, hir::ExprKind::Block(..))
         {
             fcx.suggest_missing_semicolon(&mut err, expr, expected, true);
         }
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 85e949952f8d..2f7f91480233 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -727,7 +727,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ident,
                             kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..),
                             ..
-                        })) = self.tcx.hir().get_if_local(*def_id)
+                        })) = self.tcx.hir_get_if_local(*def_id)
                         {
                             primary_span = ty.span;
                             secondary_span = ident.span;
@@ -1173,7 +1173,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let Some(hir::Node::Item(hir::Item {
                     kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
                     ..
-                })) = self.tcx.hir().get_if_local(*alias_to)
+                })) = self.tcx.hir_get_if_local(*alias_to)
                 {
                     err.span_label(self_ty.span, "this is the type of the `Self` literal");
                 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 9ccd67460874..a41ad94f95e2 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1801,7 +1801,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         block: &'tcx hir::ConstBlock,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let body = self.tcx.hir().body(block.body);
+        let body = self.tcx.hir_body(block.body);
 
         // Create a new function context.
         let def_id = block.def_id;
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 4618c5d3849b..ce6f7420e5ba 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -687,7 +687,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
         if let hir::ExprKind::Closure(&hir::Closure { body, .. })
         | hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) = expr.kind
         {
-            self.visit_body(self.fcx.tcx.hir().body(body))?;
+            self.visit_body(self.fcx.tcx.hir_body(body))?;
         }
 
         // Try to suggest adding an explicit qself `()` to a trait method path.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 1113f7f70953..ff41a080d629 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -640,7 +640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let witness = Ty::new_coroutine_witness(self.tcx, expr_def_id.to_def_id(), args);
 
             // Unify `interior` with `witness` and collect all the resulting obligations.
-            let span = self.tcx.hir().body(body_id).value.span;
+            let span = self.tcx.hir_body(body_id).value.span;
             let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
                 span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
             };
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 77081548d115..7963688203a0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2056,7 +2056,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match node {
             Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
             | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
-                let body = self.tcx.hir().body(body_id);
+                let body = self.tcx.hir_body(body_id);
                 if let ExprKind::Block(block, _) = &body.value.kind {
                     return Some(block.span);
                 }
@@ -2512,11 +2512,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
-        } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
+        } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
             && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
         {
             let param = expected_idx
-                .and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx));
+                .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
             let (kind, span) = if let Some(param) = param {
                 // Try to find earlier invocations of this closure to find if the type mismatch
                 // is because of inference. If we find one, point at them.
@@ -2650,7 +2650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         is_method: bool,
     ) -> Option<(IndexVec, FnParam<'_>)>, &hir::Generics<'_>)>
     {
-        let (sig, generics, body_id, param_names) = match self.tcx.hir().get_if_local(def_id)? {
+        let (sig, generics, body_id, param_names) = match self.tcx.hir_get_if_local(def_id)? {
             hir::Node::TraitItem(&hir::TraitItem {
                 generics,
                 kind: hir::TraitItemKind::Fn(sig, trait_fn),
@@ -2695,7 +2695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match (body_id, param_names) {
             (Some(_), Some(_)) | (None, None) => unreachable!(),
             (Some(body), None) => {
-                let params = self.tcx.hir().body(body).params;
+                let params = self.tcx.hir_body(body).params;
                 let params =
                     params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
                 debug_assert_eq!(params.len(), fn_inputs.len());
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 4ec8d0b1f60a..05c76b3c5681 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1813,7 +1813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
             let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
             if let ty::Param(param) = expected_ty.kind()
-                && let Some(generics) = self.tcx.hir().get_generics(owner)
+                && let Some(generics) = self.tcx.hir_get_generics(owner)
             {
                 suggest_constraining_type_params(
                     self.tcx,
@@ -1933,7 +1933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ..
                     } = init
                 {
-                    let hir::Body { value: body_expr, .. } = self.tcx.hir().body(*body_id);
+                    let hir::Body { value: body_expr, .. } = self.tcx.hir_body(*body_id);
                     self.note_type_is_not_clone_inner_expr(body_expr)
                 } else {
                     expr
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 02fbd46173c4..9d5184acb3ca 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -123,7 +123,7 @@ fn typeck_with_inspect<'tcx>(
     let body_id = node.body_id().unwrap_or_else(|| {
         span_bug!(span, "can't type-check body of {:?}", def_id);
     });
-    let body = tcx.hir().body(body_id);
+    let body = tcx.hir_body(body_id);
 
     let param_env = tcx.param_env(def_id);
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 6c4ad65be6a6..1ca8b59db223 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1091,7 +1091,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     continue;
                 }
 
-                match self.tcx.hir().get_if_local(item_def_id) {
+                match self.tcx.hir_get_if_local(item_def_id) {
                     // Unmet obligation comes from a `derive` macro, point at it once to
                     // avoid multiple span labels pointing at the same place.
                     Some(Node::Item(hir::Item {
@@ -3753,19 +3753,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                         hir::TraitFn::Required([ident, ..]) => {
                                             ident.name == kw::SelfLower
                                         }
-                                        hir::TraitFn::Provided(body_id) => self
-                                            .tcx
-                                            .hir()
-                                            .body(*body_id)
-                                            .params
-                                            .first()
-                                            .is_some_and(|param| {
-                                                matches!(
-                                                    param.pat.kind,
-                                                    hir::PatKind::Binding(_, _, ident, _)
-                                                        if ident.name == kw::SelfLower
-                                                )
-                                            }),
+                                        hir::TraitFn::Provided(body_id) => {
+                                            self.tcx.hir_body(*body_id).params.first().is_some_and(
+                                                |param| {
+                                                    matches!(
+                                                        param.pat.kind,
+                                                        hir::PatKind::Binding(_, _, ident, _)
+                                                            if ident.name == kw::SelfLower
+                                                    )
+                                                },
+                                            )
+                                        }
                                         _ => false,
                                     };
 
@@ -3833,20 +3831,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if let Some(param) = param_type {
                 let generics = self.tcx.generics_of(self.body_id.to_def_id());
                 let type_param = generics.type_param(param, self.tcx);
-                let hir = self.tcx.hir();
+                let tcx = self.tcx;
                 if let Some(def_id) = type_param.def_id.as_local() {
-                    let id = self.tcx.local_def_id_to_hir_id(def_id);
+                    let id = tcx.local_def_id_to_hir_id(def_id);
                     // Get the `hir::Param` to verify whether it already has any bounds.
                     // We do this to avoid suggesting code that ends up as `T: FooBar`,
                     // instead we suggest `T: Foo + Bar` in that case.
-                    match self.tcx.hir_node(id) {
+                    match tcx.hir_node(id) {
                         Node::GenericParam(param) => {
                             enum Introducer {
                                 Plus,
                                 Colon,
                                 Nothing,
                             }
-                            let hir_generics = hir.get_generics(id.owner.def_id).unwrap();
+                            let hir_generics = tcx.hir_get_generics(id.owner.def_id).unwrap();
                             let trait_def_ids: DefIdSet = hir_generics
                                 .bounds_for_param(def_id)
                                 .flat_map(|bp| bp.bounds.iter())
@@ -3866,8 +3864,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             let candidate_strs: Vec<_> = candidates
                                 .iter()
                                 .map(|cand| {
-                                    let cand_path = self.tcx.def_path_str(cand.def_id);
-                                    let cand_params = &self.tcx.generics_of(cand.def_id).own_params;
+                                    let cand_path = tcx.def_path_str(cand.def_id);
+                                    let cand_params = &tcx.generics_of(cand.def_id).own_params;
                                     let cand_args: String = cand_params
                                         .iter()
                                         .skip(1)
@@ -3960,9 +3958,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             err.span_suggestions(
                                 sp,
                                 message(format!("add {article} supertrait for")),
-                                candidates.iter().map(|t| {
-                                    format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
-                                }),
+                                candidates
+                                    .iter()
+                                    .map(|t| format!("{} {}", sep, tcx.def_path_str(t.def_id),)),
                                 Applicability::MaybeIncorrect,
                             );
                             return;
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 7c2a2b3fdf7d..cd07666ca6c5 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1231,7 +1231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ident: Ident,
     ) -> bool {
         match opt_def_id {
-            Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
+            Some(def_id) => match self.tcx.hir_get_if_local(def_id) {
                 Some(hir::Node::Item(hir::Item {
                     kind: hir::ItemKind::Const(_, _, body_id),
                     ..
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index b54e430a9d9f..871d08137b34 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -143,7 +143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         match expr.kind {
             hir::ExprKind::Closure(&hir::Closure { capture_clause, body: body_id, .. }) => {
-                let body = self.fcx.tcx.hir().body(body_id);
+                let body = self.fcx.tcx.hir_body(body_id);
                 self.visit_body(body);
                 self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
             }
@@ -154,7 +154,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
     }
 
     fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
-        let body = self.fcx.tcx.hir().body(c.body);
+        let body = self.fcx.tcx.hir_body(c.body);
         self.visit_body(body);
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 1bf5b19d68d0..dbcf99157905 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -249,7 +249,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn visit_const_block(&mut self, span: Span, anon_const: &hir::ConstBlock) {
         self.visit_node_id(span, anon_const.hir_id);
 
-        let body = self.tcx().hir().body(anon_const.body);
+        let body = self.tcx().hir_body(anon_const.body);
         self.visit_body(body);
     }
 }
@@ -266,7 +266,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
     fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
         match e.kind {
             hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
-                let body = self.fcx.tcx.hir().body(body);
+                let body = self.fcx.tcx.hir_body(body);
                 for param in body.params {
                     self.visit_node_id(e.span, param.hir_id);
                 }
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 82593dbc2b7a..00600abb5f1e 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -7,7 +7,7 @@ use rustc_span::sym;
 fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option {
     let mut decls = None;
 
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         let attrs = tcx.hir().attrs(id.hir_id());
         if attr::contains_name(attrs, sym::rustc_proc_macro_decls) {
             decls = Some(id.owner_id.def_id);
diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs
index 5d40b8ab2eed..02fb22bf782e 100644
--- a/compiler/rustc_lint/src/async_closures.rs
+++ b/compiler/rustc_lint/src/async_closures.rs
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for AsyncClosureUsage {
             return;
         };
 
-        let mut body = cx.tcx.hir().body(body).value;
+        let mut body = cx.tcx.hir_body(body).value;
 
         // Only peel blocks that have no expressions.
         while let hir::ExprKind::Block(&hir::Block { stmts: [], expr: Some(tail), .. }, None) =
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ecd40a52e75f..e449f1106131 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1057,7 +1057,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                             check_no_mangle_on_generic_fn(
                                 no_mangle_attr,
                                 Some(generics),
-                                cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(),
+                                cx.tcx.hir_get_generics(it.id.owner_id.def_id).unwrap(),
                                 it.span,
                             );
                         }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index a67b404e6e16..c74158102c7a 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -928,7 +928,7 @@ impl<'tcx> LateContext<'tcx> {
         while let hir::ExprKind::Path(ref qpath) = expr.kind
             && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
                 Res::Local(hir_id) => Some(self.tcx.parent_hir_node(hir_id)),
-                Res::Def(_, def_id) => self.tcx.hir().get_if_local(def_id),
+                Res::Def(_, def_id) => self.tcx.hir_get_if_local(def_id),
                 _ => None,
             }
             && let Some(init) = match parent_node {
@@ -936,7 +936,7 @@ impl<'tcx> LateContext<'tcx> {
                 hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
                 hir::Node::Item(item) => match item.kind {
                     hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
-                        Some(self.tcx.hir().body(body_id).value)
+                        Some(self.tcx.hir_body(body_id).value)
                     }
                     _ => None,
                 },
diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs
index bae9defa6870..59e38a882dde 100644
--- a/compiler/rustc_lint/src/default_could_be_derived.rs
+++ b/compiler/rustc_lint/src/default_could_be_derived.rs
@@ -76,10 +76,8 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
 
         // We now know we have a manually written definition of a `::default()`.
 
-        let hir = cx.tcx.hir();
-
         let type_def_id = def.did();
-        let body = hir.body(body_id);
+        let body = cx.tcx.hir_body(body_id);
 
         // FIXME: evaluate bodies with statements and evaluate bindings to see if they would be
         // derivable.
@@ -92,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
         // Keep a mapping of field name to `hir::FieldDef` for every field in the type. We'll use
         // these to check for things like checking whether it has a default or using its span for
         // suggestions.
-        let orig_fields = match hir.get_if_local(type_def_id) {
+        let orig_fields = match cx.tcx.hir_get_if_local(type_def_id) {
             Some(hir::Node::Item(hir::Item {
                 kind:
                     hir::ItemKind::Struct(hir::VariantData::Struct { fields, recovered: _ }, _generics),
@@ -183,7 +181,7 @@ fn mk_lint(
     if removed_all_fields {
         let msg = "to avoid divergence in behavior between `Struct { .. }` and \
                    `::default()`, derive the `Default`";
-        if let Some(hir::Node::Item(impl_)) = tcx.hir().get_if_local(impl_def_id) {
+        if let Some(hir::Node::Item(impl_)) = tcx.hir_get_if_local(impl_def_id) {
             diag.multipart_suggestion_verbose(
                 msg,
                 vec![
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 0a5c52d65ec9..59390b7e4206 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -155,7 +155,7 @@ fn suggest_question_mark<'tcx>(
     // Check that the function/closure/constant we are in has a `Result` type.
     // Otherwise suggesting using `?` may not be a good idea.
     {
-        let ty = cx.typeck_results().expr_ty(cx.tcx.hir().body(body_id).value);
+        let ty = cx.typeck_results().expr_ty(cx.tcx.hir_body(body_id).value);
         let ty::Adt(ret_adt, ..) = ty.kind() else { return false };
         if !cx.tcx.is_diagnostic_item(sym::Result, ret_adt.did()) {
             return false;
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 3ee908ba9bf4..c0d3df17d77b 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -99,7 +99,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
             self.context.cached_typeck_results.set(None);
         }
 
-        let body = self.context.tcx.hir().body(body_id);
+        let body = self.context.tcx.hir_body(body_id);
         self.visit_body(body);
         self.context.enclosing_body = old_enclosing_body;
 
@@ -191,7 +191,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
         // in order for `check_fn` to be able to use them.
         let old_enclosing_body = self.context.enclosing_body.replace(body_id);
         let old_cached_typeck_results = self.context.cached_typeck_results.take();
-        let body = self.context.tcx.hir().body(body_id);
+        let body = self.context.tcx.hir_body(body_id);
         lint_callback!(self, check_fn, fk, decl, body, span, id);
         hir_visit::walk_fn(self, fk, decl, body_id, id);
         self.context.enclosing_body = old_enclosing_body;
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index 154eb684f119..24689ea61d03 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -10,13 +10,13 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> FxIndexMap EncodeContext<'a, 'tcx> {
                     bug!("Unknown proc-macro type for item {:?}", id);
                 };
 
-                let mut def_key = self.tcx.hir().def_key(id);
+                let mut def_key = self.tcx.hir_def_key(id);
                 def_key.disambiguated_data.data = DefPathData::MacroNs(name);
 
                 let def_id = id.to_def_id();
@@ -2076,7 +2076,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let mut trait_impls: FxIndexMap)>> =
             FxIndexMap::default();
 
-        for id in tcx.hir().items() {
+        for id in tcx.hir_free_items() {
             let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else {
                 continue;
             };
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 2c5deecd7461..737b491ef573 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -93,7 +93,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
             return None;
         }
 
-        let parent_id = self.map.def_key(self.current_id.owner.def_id).parent;
+        let parent_id = self.map.tcx.hir_def_key(self.current_id.owner.def_id).parent;
         let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| {
             let def_id = LocalDefId { local_def_index };
             self.map.tcx.local_def_id_to_hir_id(def_id).owner
@@ -164,76 +164,80 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn parent_hir_node(self, hir_id: HirId) -> Node<'tcx> {
         self.hir_node(self.parent_hir_id(hir_id))
     }
-}
 
-impl<'hir> Map<'hir> {
+    /// Best avoided in favour of more targeted methods. See the comment on the `hir_crate` query.
     #[inline]
-    pub fn krate(self) -> &'hir Crate<'hir> {
-        self.tcx.hir_crate(())
+    pub fn hir_krate(self) -> &'tcx Crate<'tcx> {
+        self.hir_crate(())
     }
 
     #[inline]
-    pub fn root_module(self) -> &'hir Mod<'hir> {
-        match self.tcx.hir_owner_node(CRATE_OWNER_ID) {
+    pub fn hir_root_module(self) -> &'tcx Mod<'tcx> {
+        match self.hir_owner_node(CRATE_OWNER_ID) {
             OwnerNode::Crate(item) => item,
             _ => bug!(),
         }
     }
 
     #[inline]
-    pub fn items(self) -> impl Iterator + 'hir {
-        self.tcx.hir_crate_items(()).free_items.iter().copied()
+    pub fn hir_free_items(self) -> impl Iterator + 'tcx {
+        self.hir_crate_items(()).free_items.iter().copied()
     }
 
     #[inline]
-    pub fn module_items(self, module: LocalModDefId) -> impl Iterator + 'hir {
-        self.tcx.hir_module_items(module).free_items()
+    pub fn hir_module_free_items(
+        self,
+        module: LocalModDefId,
+    ) -> impl Iterator + 'tcx {
+        self.hir_module_items(module).free_items()
     }
 
-    pub fn def_key(self, def_id: LocalDefId) -> DefKey {
+    pub fn hir_def_key(self, def_id: LocalDefId) -> DefKey {
         // Accessing the DefKey is ok, since it is part of DefPathHash.
-        self.tcx.definitions_untracked().def_key(def_id)
+        self.definitions_untracked().def_key(def_id)
     }
 
-    pub fn def_path(self, def_id: LocalDefId) -> DefPath {
+    pub fn hir_def_path(self, def_id: LocalDefId) -> DefPath {
         // Accessing the DefPath is ok, since it is part of DefPathHash.
-        self.tcx.definitions_untracked().def_path(def_id)
+        self.definitions_untracked().def_path(def_id)
     }
 
     #[inline]
-    pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
+    pub fn hir_def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
         // Accessing the DefPathHash is ok, it is incr. comp. stable.
-        self.tcx.definitions_untracked().def_path_hash(def_id)
+        self.definitions_untracked().def_path_hash(def_id)
     }
 
-    pub fn get_if_local(self, id: DefId) -> Option> {
-        id.as_local().map(|id| self.tcx.hir_node_by_def_id(id))
+    pub fn hir_get_if_local(self, id: DefId) -> Option> {
+        id.as_local().map(|id| self.hir_node_by_def_id(id))
     }
 
-    pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
-        self.tcx.opt_hir_owner_node(id)?.generics()
+    pub fn hir_get_generics(self, id: LocalDefId) -> Option<&'tcx Generics<'tcx>> {
+        self.opt_hir_owner_node(id)?.generics()
     }
 
-    pub fn item(self, id: ItemId) -> &'hir Item<'hir> {
-        self.tcx.hir_owner_node(id.owner_id).expect_item()
+    pub fn hir_item(self, id: ItemId) -> &'tcx Item<'tcx> {
+        self.hir_owner_node(id.owner_id).expect_item()
     }
 
-    pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        self.tcx.hir_owner_node(id.owner_id).expect_trait_item()
+    pub fn hir_trait_item(self, id: TraitItemId) -> &'tcx TraitItem<'tcx> {
+        self.hir_owner_node(id.owner_id).expect_trait_item()
     }
 
-    pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        self.tcx.hir_owner_node(id.owner_id).expect_impl_item()
+    pub fn hir_impl_item(self, id: ImplItemId) -> &'tcx ImplItem<'tcx> {
+        self.hir_owner_node(id.owner_id).expect_impl_item()
     }
 
-    pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        self.tcx.hir_owner_node(id.owner_id).expect_foreign_item()
+    pub fn hir_foreign_item(self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
+        self.hir_owner_node(id.owner_id).expect_foreign_item()
     }
 
-    pub fn body(self, id: BodyId) -> &'hir Body<'hir> {
-        self.tcx.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
+    pub fn hir_body(self, id: BodyId) -> &'tcx Body<'tcx> {
+        self.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
     }
+}
 
+impl<'hir> Map<'hir> {
     #[track_caller]
     pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
         self.tcx.hir_node(hir_id).fn_decl()
@@ -271,7 +275,7 @@ impl<'hir> Map<'hir> {
     /// Given a `LocalDefId`, returns the `BodyId` associated with it,
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<&'hir Body<'hir>> {
-        Some(self.body(self.tcx.hir_node_by_def_id(id).body_id()?))
+        Some(self.tcx.hir_body(self.tcx.hir_node_by_def_id(id).body_id()?))
     }
 
     /// Given a body owner's id, returns the `BodyId` associated with it.
@@ -288,7 +292,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn body_param_names(self, id: BodyId) -> impl Iterator + 'hir {
-        self.body(id).params.iter().map(|arg| match arg.pat.kind {
+        self.tcx.hir_body(id).params.iter().map(|arg| match arg.pat.kind {
             PatKind::Binding(_, _, ident, _) => ident,
             _ => Ident::empty(),
         })
@@ -410,7 +414,7 @@ impl<'hir> Map<'hir> {
     where
         V: Visitor<'hir>,
     {
-        let krate = self.krate();
+        let krate = self.tcx.hir_krate();
         for info in krate.owners.iter() {
             if let MaybeOwner::Owner(info) = info {
                 for attrs in info.attrs.map.values() {
@@ -436,13 +440,21 @@ impl<'hir> Map<'hir> {
         V: Visitor<'hir>,
     {
         let krate = self.tcx.hir_crate_items(());
-        walk_list!(visitor, visit_item, krate.free_items().map(|id| self.item(id)));
-        walk_list!(visitor, visit_trait_item, krate.trait_items().map(|id| self.trait_item(id)));
-        walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.impl_item(id)));
+        walk_list!(visitor, visit_item, krate.free_items().map(|id| self.tcx.hir_item(id)));
+        walk_list!(
+            visitor,
+            visit_trait_item,
+            krate.trait_items().map(|id| self.tcx.hir_trait_item(id))
+        );
+        walk_list!(
+            visitor,
+            visit_impl_item,
+            krate.impl_items().map(|id| self.tcx.hir_impl_item(id))
+        );
         walk_list!(
             visitor,
             visit_foreign_item,
-            krate.foreign_items().map(|id| self.foreign_item(id))
+            krate.foreign_items().map(|id| self.tcx.hir_foreign_item(id))
         );
         V::Result::output()
     }
@@ -454,13 +466,21 @@ impl<'hir> Map<'hir> {
         V: Visitor<'hir>,
     {
         let module = self.tcx.hir_module_items(module);
-        walk_list!(visitor, visit_item, module.free_items().map(|id| self.item(id)));
-        walk_list!(visitor, visit_trait_item, module.trait_items().map(|id| self.trait_item(id)));
-        walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.impl_item(id)));
+        walk_list!(visitor, visit_item, module.free_items().map(|id| self.tcx.hir_item(id)));
+        walk_list!(
+            visitor,
+            visit_trait_item,
+            module.trait_items().map(|id| self.tcx.hir_trait_item(id))
+        );
+        walk_list!(
+            visitor,
+            visit_impl_item,
+            module.impl_items().map(|id| self.tcx.hir_impl_item(id))
+        );
         walk_list!(
             visitor,
             visit_foreign_item,
-            module.foreign_items().map(|id| self.foreign_item(id))
+            module.foreign_items().map(|id| self.tcx.hir_foreign_item(id))
         );
         V::Result::output()
     }
@@ -921,7 +941,7 @@ impl<'hir> Map<'hir> {
             Node::Variant(variant) => variant.span,
             Node::Field(field) => field.span,
             Node::AnonConst(constant) => constant.span,
-            Node::ConstBlock(constant) => self.body(constant.body).value.span,
+            Node::ConstBlock(constant) => self.tcx.hir_body(constant.body).value.span,
             Node::ConstArg(const_arg) => const_arg.span(),
             Node::Expr(expr) => expr.span,
             Node::ExprField(field) => field.span,
@@ -1020,23 +1040,23 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     }
 
     fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        (*self).body(id)
+        self.tcx.hir_body(id)
     }
 
     fn item(&self, id: ItemId) -> &'hir Item<'hir> {
-        (*self).item(id)
+        self.tcx.hir_item(id)
     }
 
     fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        (*self).trait_item(id)
+        self.tcx.hir_trait_item(id)
     }
 
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        (*self).impl_item(id)
+        self.tcx.hir_impl_item(id)
     }
 
     fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        (*self).foreign_item(id)
+        self.tcx.hir_foreign_item(id)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 7166c284c3d7..11b430dd358d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3299,13 +3299,12 @@ define_print_and_forward_display! {
 
 fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
     // Iterate all local crate items no matter where they are defined.
-    let hir = tcx.hir();
-    for id in hir.items() {
+    for id in tcx.hir_free_items() {
         if matches!(tcx.def_kind(id.owner_id), DefKind::Use) {
             continue;
         }
 
-        let item = hir.item(id);
+        let item = tcx.hir_item(id);
         if item.ident.name == kw::Empty {
             continue;
         }
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 743ea33b20a2..b84cc57234f4 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -267,7 +267,7 @@ pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -
 
 pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
     let mut traits = Vec::new();
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
             traits.push(id.owner_id.to_def_id())
         }
@@ -278,7 +278,7 @@ pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
 
 pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
     let mut trait_impls = Vec::new();
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
             && tcx.impl_trait_ref(id.owner_id).is_some()
         {
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 433f7542bd70..9450ce7ec444 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -53,7 +53,7 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> {
         let arity = if let Some(frame) = cycle_error.cycle.get(0)
             && frame.query.dep_kind == dep_kinds::fn_sig
             && let Some(def_id) = frame.query.def_id
-            && let Some(node) = tcx.hir().get_if_local(def_id)
+            && let Some(node) = tcx.hir_get_if_local(def_id)
             && let Some(sig) = node.fn_sig()
         {
             sig.decl.inputs.len()
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 1bd33475e607..8b6fcec3837c 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -759,7 +759,7 @@ impl UnsafeOpKind {
         });
         let unsafe_not_inherited_note = if should_suggest {
             suggest_unsafe_block.then(|| {
-                let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span;
+                let body_span = tcx.hir_body(parent_owner.body_id().unwrap()).value.span;
                 UnsafeNotInheritedLintNote {
                     signature_span: tcx.def_span(parent_id.def_id),
                     body_span,
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 07bdc59756aa..18a9002627a3 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -601,8 +601,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo
             let def_span = self
                 .cx
                 .tcx
-                .hir()
-                .get_if_local(def.did())
+                .hir_get_if_local(def.did())
                 .and_then(|node| node.ident())
                 .map(|ident| ident.span)
                 .unwrap_or_else(|| self.cx.tcx.def_span(def.did()));
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 697cb7cf37a3..acc9a62326b7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1498,7 +1498,7 @@ fn report_adt_defined_here<'tcx>(
         return None;
     };
     let adt_def_span =
-        tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
+        tcx.hir_get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
     let adt_def_span = if point_at_non_local_ty {
         adt_def_span.unwrap_or_else(|| tcx.def_span(def.did()))
     } else {
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index e195681bc92c..081e7b1a43cd 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -291,7 +291,7 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir
 
     let hir_node = tcx.hir_node_by_def_id(def_id);
     let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
-    let hir_body = tcx.hir().body(fn_body_id);
+    let hir_body = tcx.hir_body(fn_body_id);
 
     let maybe_fn_sig = hir_node.fn_sig();
     let is_async_fn = maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async());
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index e4a733fcbce8..1195c25e1308 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -478,7 +478,7 @@ fn collect_items_rec<'tcx>(
             );
             recursion_depth_reset = None;
 
-            let item = tcx.hir().item(item_id);
+            let item = tcx.hir_item(item_id);
             if let hir::ItemKind::GlobalAsm(asm) = item.kind {
                 for (op, op_sp) in asm.operands {
                     match op {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index f578708b40cd..e96db885131f 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -627,7 +627,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     fn check_object_lifetime_default(&self, hir_id: HirId) {
         let tcx = self.tcx;
         if let Some(owner_id) = hir_id.as_owner()
-            && let Some(generics) = tcx.hir().get_generics(owner_id.def_id)
+            && let Some(generics) = tcx.hir_get_generics(owner_id.def_id)
         {
             for p in generics.params {
                 let hir::GenericParamKind::Type { .. } = p.kind else { continue };
@@ -2740,9 +2740,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
             for attr_to_check in ATTRS_TO_CHECK {
                 if attr.has_name(*attr_to_check) {
                     let item = tcx
-                        .hir()
-                        .items()
-                        .map(|id| tcx.hir().item(id))
+                        .hir_free_items()
+                        .map(|id| tcx.hir_item(id))
                         .find(|item| !item.span.is_dummy()) // Skip prelude `use`s
                         .map(|item| errors::ItemFollowingInnerAttr {
                             span: item.ident.span,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 95f18eaa7ef1..696cc79bfeb6 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -531,7 +531,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
 
     fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool {
         if let TyKind::Path(hir::QPath::Resolved(_, path)) =
-            self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
+            self.tcx.hir_item(impl_id).expect_impl().self_ty.kind
             && let Res::Def(def_kind, def_id) = path.res
             && let Some(local_def_id) = def_id.as_local()
             && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
@@ -559,7 +559,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         let old_maybe_typeck_results =
             self.maybe_typeck_results.replace(self.tcx.typeck_body(body));
-        let body = self.tcx.hir().body(body);
+        let body = self.tcx.hir_body(body);
         self.visit_body(body);
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
@@ -750,7 +750,7 @@ fn check_item<'tcx>(
 
     match tcx.def_kind(id.owner_id) {
         DefKind::Enum => {
-            let item = tcx.hir().item(id);
+            let item = tcx.hir_item(id);
             if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
                 if let Some(comes_from_allow) = allow_dead_code {
                     worklist.extend(
@@ -772,7 +772,7 @@ fn check_item<'tcx>(
                 .iter()
                 .filter_map(|def_id| def_id.as_local());
 
-            let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
+            let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir_item(id).expect_impl().self_ty);
 
             // And we access the Map here to get HirId from LocalDefId
             for local_def_id in local_def_ids {
@@ -805,7 +805,7 @@ fn check_item<'tcx>(
             }
         }
         DefKind::Struct => {
-            let item = tcx.hir().item(id);
+            let item = tcx.hir_item(id);
             if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
                 && let Some(ctor_def_id) = variant_data.ctor_def_id()
             {
@@ -827,7 +827,7 @@ fn check_trait_item(
 ) {
     use hir::TraitItemKind::{Const, Fn};
     if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
-        let trait_item = tcx.hir().trait_item(id);
+        let trait_item = tcx.hir_trait_item(id);
         if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
             && let Some(comes_from_allow) =
                 has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 22291c9282db..c2225ea1e642 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -37,7 +37,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
 
     let mut ctxt = EntryContext { tcx, rustc_main_fn: None, non_main_fns: Vec::new() };
 
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         check_and_search_item(id, &mut ctxt);
     }
 
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 74038b24dccd..34d60d90be5f 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -61,7 +61,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
 
         if max != self.hir_ids_seen.len() - 1 {
             let hir = self.tcx.hir();
-            let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
+            let pretty_owner = self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose();
 
             let missing_items: Vec<_> = (0..=max as u32)
                 .map(|i| ItemLocalId::from_u32(i))
@@ -138,8 +138,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
                 format!(
                     "HirIdValidator: The recorded owner of {} is {} instead of {}",
                     self.tcx.hir().node_to_string(hir_id),
-                    self.tcx.hir().def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
-                    self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
+                    self.tcx.hir_def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
+                    self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose()
                 )
             });
         }
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index f7cae89852e1..e60dcc807c96 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -7,7 +7,6 @@ use rustc_ast::{self as ast, NodeId, visit as ast_visit};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::thousands::format_with_underscores;
 use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
-use rustc_middle::hir::map::Map;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
@@ -56,17 +55,14 @@ impl Node {
 /// a `visit_*` method for, and so we cannot measure these, which is
 /// unfortunate.
 struct StatCollector<'k> {
-    krate: Option>,
+    tcx: Option>,
     nodes: FxHashMap<&'static str, Node>,
     seen: FxHashSet,
 }
 
 pub fn print_hir_stats(tcx: TyCtxt<'_>) {
-    let mut collector = StatCollector {
-        krate: Some(tcx.hir()),
-        nodes: FxHashMap::default(),
-        seen: FxHashSet::default(),
-    };
+    let mut collector =
+        StatCollector { tcx: Some(tcx), nodes: FxHashMap::default(), seen: FxHashSet::default() };
     tcx.hir().walk_toplevel_module(&mut collector);
     tcx.hir().walk_attributes(&mut collector);
     collector.print("HIR STATS", "hir-stats");
@@ -76,7 +72,7 @@ pub fn print_ast_stats(krate: &ast::Crate, title: &str, prefix: &str) {
     use rustc_ast::visit::Visitor;
 
     let mut collector =
-        StatCollector { krate: None, nodes: FxHashMap::default(), seen: FxHashSet::default() };
+        StatCollector { tcx: None, nodes: FxHashMap::default(), seen: FxHashSet::default() };
     collector.visit_crate(krate);
     collector.print(title, prefix);
 }
@@ -205,27 +201,27 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_nested_item(&mut self, id: hir::ItemId) {
-        let nested_item = self.krate.unwrap().item(id);
+        let nested_item = self.tcx.unwrap().hir_item(id);
         self.visit_item(nested_item)
     }
 
     fn visit_nested_trait_item(&mut self, trait_item_id: hir::TraitItemId) {
-        let nested_trait_item = self.krate.unwrap().trait_item(trait_item_id);
+        let nested_trait_item = self.tcx.unwrap().hir_trait_item(trait_item_id);
         self.visit_trait_item(nested_trait_item)
     }
 
     fn visit_nested_impl_item(&mut self, impl_item_id: hir::ImplItemId) {
-        let nested_impl_item = self.krate.unwrap().impl_item(impl_item_id);
+        let nested_impl_item = self.tcx.unwrap().hir_impl_item(impl_item_id);
         self.visit_impl_item(nested_impl_item)
     }
 
     fn visit_nested_foreign_item(&mut self, id: hir::ForeignItemId) {
-        let nested_foreign_item = self.krate.unwrap().foreign_item(id);
+        let nested_foreign_item = self.tcx.unwrap().hir_foreign_item(id);
         self.visit_foreign_item(nested_foreign_item);
     }
 
     fn visit_nested_body(&mut self, body_id: hir::BodyId) {
-        let nested_body = self.krate.unwrap().body(body_id);
+        let nested_body = self.tcx.unwrap().hir_body(body_id);
         self.visit_body(nested_body)
     }
 
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 875b6edb58cb..23322be8f559 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -45,7 +45,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
             _ => continue,
         };
 
-        let body = tcx.hir().body(body_id);
+        let body = tcx.hir_body(body_id);
 
         if tcx.has_attr(def_id, sym::naked) {
             check_abi(tcx, def_id, fn_header.abi);
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 7788adb6e17d..1fe44bd3d21a 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -66,7 +66,7 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         let old_maybe_typeck_results =
             self.maybe_typeck_results.replace(self.tcx.typeck_body(body));
-        let body = self.tcx.hir().body(body);
+        let body = self.tcx.hir_body(body);
         self.visit_body(body);
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 3842b7035e53..b8490da26f4e 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1036,7 +1036,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
             return;
         }
         let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
-        self.visit_body(self.tcx.hir().body(body_id));
+        self.visit_body(self.tcx.hir_body(body_id));
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
 
@@ -1161,7 +1161,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
     fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         let old_maybe_typeck_results =
             self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
-        self.visit_body(self.tcx.hir().body(body_id));
+        self.visit_body(self.tcx.hir_body(body_id));
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
 
@@ -1599,7 +1599,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
                 self.check(def_id, item_visibility, effective_vis).generics().bounds();
             }
             DefKind::Trait => {
-                let item = tcx.hir().item(id);
+                let item = tcx.hir_item(id);
                 if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind {
                     self.check_unnameable(item.owner_id.def_id, effective_vis);
 
@@ -1630,7 +1630,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
                 self.check(def_id, item_visibility, effective_vis).generics().predicates();
             }
             DefKind::Enum => {
-                let item = tcx.hir().item(id);
+                let item = tcx.hir_item(id);
                 if let hir::ItemKind::Enum(ref def, _) = item.kind {
                     self.check_unnameable(item.owner_id.def_id, effective_vis);
 
@@ -1647,10 +1647,10 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
             }
             // Subitems of foreign modules have their own publicity.
             DefKind::ForeignMod => {
-                let item = tcx.hir().item(id);
+                let item = tcx.hir_item(id);
                 if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
                     for foreign_item in items {
-                        let foreign_item = tcx.hir().foreign_item(foreign_item.id);
+                        let foreign_item = tcx.hir_foreign_item(foreign_item.id);
 
                         let ev = self.get(foreign_item.owner_id.def_id);
                         let vis = tcx.local_visibility(foreign_item.owner_id.def_id);
@@ -1668,7 +1668,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
             }
             // Subitems of structs and unions have their own publicity.
             DefKind::Struct | DefKind::Union => {
-                let item = tcx.hir().item(id);
+                let item = tcx.hir_item(id);
                 if let hir::ItemKind::Struct(ref struct_def, _)
                 | hir::ItemKind::Union(ref struct_def, _) = item.kind
                 {
@@ -1695,7 +1695,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity.
             DefKind::Impl { .. } => {
-                let item = tcx.hir().item(id);
+                let item = tcx.hir_item(id);
                 if let hir::ItemKind::Impl(impl_) = item.kind {
                     let impl_vis = ty::Visibility::of_impl::(
                         item.owner_id.def_id,
@@ -1788,7 +1788,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
     }
 
     for id in module.free_items() {
-        if let ItemKind::Impl(i) = tcx.hir().item(id).kind {
+        if let ItemKind::Impl(i) = tcx.hir_item(id).kind {
             if let Some(item) = i.of_trait {
                 let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap();
                 let trait_ref = trait_ref.instantiate_identity();
@@ -1885,7 +1885,7 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
     // Check for private types in public interfaces.
     let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities };
 
-    for id in tcx.hir().items() {
+    for id in tcx.hir_free_items() {
         checker.check_item(id);
     }
 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 091773009e98..a618bae269fa 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1989,7 +1989,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         trace: &TypeTrace<'tcx>,
         span: Span,
     ) -> Option {
-        let hir = self.tcx.hir();
         let TypeError::ArraySize(sz) = terr else {
             return None;
         };
@@ -1997,7 +1996,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             hir::Node::Item(hir::Item {
                 kind: hir::ItemKind::Fn { body: body_id, .. }, ..
             }) => {
-                let body = hir.body(*body_id);
+                let body = self.tcx.hir_body(*body_id);
                 struct LetVisitor {
                     span: Span,
                 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 9e7e96dddd7c..57b614833aff 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1320,7 +1320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             {
                 let output = args.as_closure().sig().output().skip_binder();
                 if self.generic_arg_contains_target(output.into()) {
-                    let body = self.tecx.tcx.hir().body(body);
+                    let body = self.tecx.tcx.hir_body(body);
                     let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
                         None
                     } else {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
index 886581bc35fd..ad2f7f00fa53 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
@@ -66,7 +66,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         );
         let mut impl_span = None;
         let mut implicit_static_lifetimes = Vec::new();
-        if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
+        if let Some(impl_node) = self.tcx().hir_get_if_local(*impl_def_id) {
             // If an impl is local, then maybe this isn't what they want. Try to
             // be as helpful as possible with implicit lifetimes.
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index 039e21cb5562..35fd4e588ef9 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -318,7 +318,7 @@ pub fn suggest_new_region_bound(
                 } else {
                     // get a lifetime name of existing named lifetimes if any
                     let existing_lt_name = if let Some(id) = scope_def_id
-                        && let Some(generics) = tcx.hir().get_generics(id)
+                        && let Some(generics) = tcx.hir_get_generics(id)
                         && let named_lifetimes = generics
                             .params
                             .iter()
@@ -349,7 +349,7 @@ pub fn suggest_new_region_bound(
                     // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used.
                     // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any
                     if let Some(id) = scope_def_id
-                        && let Some(generics) = tcx.hir().get_generics(id)
+                        && let Some(generics) = tcx.hir_get_generics(id)
                         && let mut spans_suggs =
                             make_elided_region_spans_suggs(name, generics.params.iter())
                         && spans_suggs.len() > 1
@@ -470,7 +470,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         def_id: DefId,
         trait_objects: &FxIndexSet,
     ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
-        match tcx.hir().get_if_local(def_id)? {
+        match tcx.hir_get_if_local(def_id)? {
             Node::ImplItem(impl_item) => {
                 let impl_did = tcx.hir().get_parent_item(impl_item.hir_id());
                 if let hir::OwnerNode::Item(Item {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index e8d14b89d698..37032b539018 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -543,7 +543,7 @@ impl Trait for X {
         let tcx = self.tcx;
         let assoc = tcx.associated_item(proj_ty.def_id);
         let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
-        let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else {
+        let Some(item) = tcx.hir_get_if_local(body_owner_def_id) else {
             return false;
         };
         let Some(hir_generics) = item.generics() else {
@@ -625,7 +625,7 @@ impl Trait for X {
             )
         };
 
-        let body_owner = tcx.hir().get_if_local(body_owner_def_id);
+        let body_owner = tcx.hir_get_if_local(body_owner_def_id);
         let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
 
         // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index f35a5349ecb3..d009687ef14d 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -487,7 +487,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     &format!("`{sup}: {sub}`"),
                 );
                 // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
-                if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id)
+                if let Some(generics) = self.tcx.hir_get_generics(impl_item_def_id)
                     && generics.where_clause_span.contains(span)
                 {
                     self.suggest_copy_trait_method_bounds(
@@ -590,7 +590,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             return;
         };
 
-        let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else {
+        let Some(generics) = self.tcx.hir_get_generics(impl_item_def_id) else {
             return;
         };
 
@@ -763,7 +763,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     // Get the `hir::Param` to verify whether it already has any bounds.
                     // We do this to avoid suggesting code that ends up as `T: 'a'b`,
                     // instead we suggest `T: 'a + 'b` in that case.
-                    let hir_generics = self.tcx.hir().get_generics(scope).unwrap();
+                    let hir_generics = self.tcx.hir_get_generics(scope).unwrap();
                     let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
                         Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
                         // If `param` corresponds to `Self`, no usable suggestion span.
@@ -822,7 +822,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             {
                 // The lifetime found in the `impl` is longer than the one on the RPITIT.
                 // Do not suggest `::{opaque}: 'static`.
-            } else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) {
+            } else if let Some(generics) = self.tcx.hir_get_generics(suggestion_scope) {
                 let pred = format!("{bound_kind}: {lt_name}");
                 let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred);
                 suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion))
@@ -907,7 +907,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             hir::OwnerNode::Synthetic => unreachable!(),
         }
 
-        let ast_generics = self.tcx.hir().get_generics(lifetime_scope).unwrap();
+        let ast_generics = self.tcx.hir_get_generics(lifetime_scope).unwrap();
         let sugg = ast_generics
             .span_for_lifetime_suggestion()
             .map(|span| (span, format!("{new_lt}, ")))
@@ -1382,7 +1382,7 @@ fn suggest_precise_capturing<'tcx>(
                 new_params += name_as_bounds;
             }
 
-            let Some(generics) = tcx.hir().get_generics(fn_def_id) else {
+            let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
                 // This shouldn't happen, but don't ICE.
                 return;
             };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index 562000e28aca..bb25c5e8bd1b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -649,7 +649,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         else {
             return;
         };
-        let hir::Body { params, .. } = self.tcx.hir().body(*body);
+        let hir::Body { params, .. } = self.tcx.hir_body(*body);
 
         // 1. Get the args of the closure.
         // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
@@ -846,7 +846,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             true
         };
 
-        let hir = self.tcx.hir();
         for stmt in blk.stmts.iter().rev() {
             let hir::StmtKind::Let(local) = &stmt.kind else {
                 continue;
@@ -871,7 +870,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
                     ..
                 }) => {
-                    for param in hir.body(*body).params {
+                    for param in self.tcx.hir_body(*body).params {
                         param.pat.walk(&mut find_compatible_candidates);
                     }
                 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 49fa21e50c05..ecfffb65fbc1 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -925,7 +925,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
         let Some(body_id) = self.tcx.hir_node(hir_id).body_id() else { return false };
         let ControlFlow::Break(expr) =
-            (FindMethodSubexprOfTry { search_span: span }).visit_body(self.tcx.hir().body(body_id))
+            (FindMethodSubexprOfTry { search_span: span }).visit_body(self.tcx.hir_body(body_id))
         else {
             return false;
         };
@@ -1012,7 +1012,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 && let [arg] = args
                 && let hir::ExprKind::Closure(closure) = arg.kind
                 // The closure has a block for its body with no tail expression
-                && let body = self.tcx.hir().body(closure.body)
+                && let body = self.tcx.hir_body(closure.body)
                 && let hir::ExprKind::Block(block, _) = body.value.kind
                 && let None = block.expr
                 // The last statement is of a type that can be converted to the return error type
@@ -1447,7 +1447,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
                     return None;
                 };
-                match self.tcx.hir().get_if_local(associated_item.def_id) {
+                match self.tcx.hir_get_if_local(associated_item.def_id) {
                     Some(
                         hir::Node::TraitItem(hir::TraitItem {
                             kind: hir::TraitItemKind::Type(_, Some(ty)),
@@ -1514,7 +1514,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         span = match fn_decl.output {
                             hir::FnRetTy::Return(ty) => ty.span,
                             hir::FnRetTy::DefaultReturn(_) => {
-                                let body = self.tcx.hir().body(id);
+                                let body = self.tcx.hir_body(id);
                                 match body.value.kind {
                                     hir::ExprKind::Block(
                                         hir::Block { expr: Some(expr), .. },
@@ -2850,7 +2850,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             _ => None,
         };
 
-        let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
+        let found_node = found_did.and_then(|did| self.tcx.hir_get_if_local(did));
         let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
 
         if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
@@ -2896,7 +2896,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         if found.len() != expected.len() {
             let (closure_span, closure_arg_span, found) = found_did
                 .and_then(|did| {
-                    let node = self.tcx.hir().get_if_local(did)?;
+                    let node = self.tcx.hir_get_if_local(did)?;
                     let (found_span, closure_arg_span, found) = self.get_fn_like_arguments(node)?;
                     Some((Some(found_span), closure_arg_span, found))
                 })
@@ -2946,7 +2946,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }) => (
                 fn_decl_span,
                 fn_arg_span,
-                hir.body(body)
+                self.tcx
+                    .hir_body(body)
                     .params
                     .iter()
                     .map(|arg| {
@@ -3208,7 +3209,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 Some(obligation.cause.body_id)
                             };
                             if let Some(def_id) = def_id
-                                && let Some(generics) = self.tcx.hir().get_generics(def_id)
+                                && let Some(generics) = self.tcx.hir_get_generics(def_id)
                             {
                                 err.span_suggestion_verbose(
                                     generics.tail_span_for_predicate_suggestion(),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index e4f250ca4f54..d786d04b8f6f 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -418,7 +418,7 @@ pub fn report_dyn_incompatibility<'tcx>(
     violations: &[DynCompatibilityViolation],
 ) -> Diag<'tcx> {
     let trait_str = tcx.def_path_str(trait_def_id);
-    let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
+    let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node {
         hir::Node::Item(item) => Some(item.ident.span),
         _ => None,
     });
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 527d2e54e432..ac1ced2ed3c3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -790,8 +790,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
 
         // Get the name of the callable and the arguments to be used in the suggestion.
-        let hir = self.tcx.hir();
-
         let msg = match def_id_or_name {
             DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
                 DefKind::Ctor(CtorOf::Struct, _) => {
@@ -834,7 +832,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 Applicability::HasPlaceholders,
             );
         } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
-            let name = match hir.get_if_local(def_id) {
+            let name = match self.tcx.hir_get_if_local(def_id) {
                 Some(hir::Node::Expr(hir::Expr {
                     kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
                     ..
@@ -950,7 +948,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     ) -> bool {
         let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
         self.enter_forall(self_ty, |ty: Ty<'_>| {
-            let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else {
+            let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_id) else {
                 return false;
             };
             let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
@@ -1595,7 +1593,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     && let ty = typeck_results.expr_ty_adjusted(base)
                     && let ty::FnDef(def_id, _args) = ty.kind()
                     && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
-                        hir.get_if_local(*def_id)
+                        self.tcx.hir_get_if_local(*def_id)
                 {
                     let msg = format!("alternatively, consider making `fn {ident}` asynchronous");
                     if vis_span.is_empty() {
@@ -1703,10 +1701,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         span: Span,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        let hir = self.tcx.hir();
         let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
         if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn {sig, body: body_id, .. }, .. }) = node
-            && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
+            && let hir::ExprKind::Block(blk, _) = &self.tcx.hir_body(*body_id).value.kind
             && sig.decl.output.span().overlaps(span)
             && blk.expr.is_none()
             && trait_pred.self_ty().skip_binder().is_unit()
@@ -2790,7 +2787,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                     generics,
                                     kind: hir::TraitItemKind::Type(bounds, None),
                                     ..
-                                })) = tcx.hir().get_if_local(item_def_id)
+                                })) = tcx.hir_get_if_local(item_def_id)
                                     // Do not suggest relaxing if there is an explicit `Sized` obligation.
                                     && !bounds.iter()
                                         .filter_map(|bound| bound.trait_ref())
@@ -3298,7 +3295,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
                 let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
                 let mut is_auto_trait = false;
-                match tcx.hir().get_if_local(data.impl_or_alias_def_id) {
+                match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
                     Some(Node::Item(hir::Item {
                         kind: hir::ItemKind::Trait(is_auto, ..),
                         ident,
@@ -3423,7 +3420,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         .map_bound(|pred| pred.trait_ref)
                         .print_only_trait_path(),
                 );
-                match tcx.hir().get_if_local(data.impl_def_id) {
+                match tcx.hir_get_if_local(data.impl_def_id) {
                     Some(Node::Item(hir::Item {
                         kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
                         ..
@@ -3564,7 +3561,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     let expr = tcx.hir().expect_expr(hir_id);
                     (expr_ty, expr)
                 } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
-                    && let body = tcx.hir().body(body_id)
+                    && let body = tcx.hir_body(body_id)
                     && let hir::ExprKind::Block(block, _) = body.value.kind
                     && let Some(expr) = block.expr
                     && let Some(expr_ty) = self
@@ -3841,7 +3838,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             && let hir::ExprKind::Closure(hir::Closure {
                                 body, fn_decl_span, ..
                             }) = value.kind
-                            && let body = tcx.hir().body(*body)
+                            && let body = tcx.hir_body(*body)
                             && !matches!(body.value.kind, hir::ExprKind::Block(..))
                         {
                             // Check if the failed predicate was an expectation of a closure type
@@ -4068,7 +4065,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     && let [arg] = args
                     && let hir::ExprKind::Closure(closure) = arg.kind
                 {
-                    let body = tcx.hir().body(closure.body);
+                    let body = tcx.hir_body(closure.body);
                     if let hir::ExprKind::Block(block, None) = body.value.kind
                         && let None = block.expr
                         && let [.., stmt] = block.stmts
@@ -4761,7 +4758,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         {
             let mut sugg_spans =
                 vec![(ret_span, " -> Result<(), Box>".to_string())];
-            let body = self.tcx.hir().body(body_id);
+            let body = self.tcx.hir_body(body_id);
             if let hir::ExprKind::Block(b, _) = body.value.kind
                 && b.expr.is_none()
             {
@@ -4807,7 +4804,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         debug!(?pred, ?item_def_id, ?span);
 
         let (Some(node), true) = (
-            self.tcx.hir().get_if_local(item_def_id),
+            self.tcx.hir_get_if_local(item_def_id),
             self.tcx.is_lang_item(pred.def_id(), LangItem::Sized),
         ) else {
             return;
@@ -5248,7 +5245,7 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
 
     // If there's a body, we also need to wrap it in `async {}`
     if let hir::TraitFn::Provided(body) = body {
-        let body = tcx.hir().body(body);
+        let body = tcx.hir_body(body);
         let body_span = body.value.span;
         let body_span_without_braces =
             body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1));
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 62cac5b17bd0..ac4399750f59 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1857,7 +1857,7 @@ pub fn impl_trait_overcapture_suggestion<'tcx>(
             new_params += name_as_bounds;
         }
 
-        let Some(generics) = tcx.hir().get_generics(fn_def_id) else {
+        let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
             // This shouldn't happen, but don't ICE.
             return None;
         };
diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
index b752dbf3093b..4601ddf678a0 100644
--- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
@@ -26,7 +26,7 @@ impl<'a> DescriptionCtx<'a> {
                     .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id)
                     .expect_local();
                 let span = if let Some(param) =
-                    tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
+                    tcx.hir_get_generics(scope).and_then(|generics| generics.get_named(br.name))
                 {
                     param.span
                 } else {
@@ -48,8 +48,7 @@ impl<'a> DescriptionCtx<'a> {
                     match fr.kind {
                         ty::LateParamRegionKind::Named(_, name) => {
                             let span = if let Some(param) = tcx
-                                .hir()
-                                .get_generics(scope)
+                                .hir_get_generics(scope)
                                 .and_then(|generics| generics.get_named(name))
                             {
                                 param.span
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index a0df74835bc1..efe2386d014b 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -128,8 +128,7 @@ fn sized_trait_bound_spans<'tcx>(
 }
 
 fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
-    tcx.hir()
-        .get_if_local(trait_def_id)
+    tcx.hir_get_if_local(trait_def_id)
         .and_then(|node| match node {
             hir::Node::Item(hir::Item {
                 kind: hir::ItemKind::Trait(.., generics, bounds, _),
@@ -304,7 +303,7 @@ pub fn dyn_compatibility_violations_for_assoc_item(
         ty::AssocKind::Fn => virtual_call_violations_for_method(tcx, trait_def_id, item)
             .into_iter()
             .map(|v| {
-                let node = tcx.hir().get_if_local(item.def_id);
+                let node = tcx.hir_get_if_local(item.def_id);
                 // Get an accurate span depending on the violation.
                 let span = match (&v, node) {
                     (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
@@ -349,7 +348,7 @@ fn virtual_call_violations_for_method<'tcx>(
             generics,
             kind: hir::TraitItemKind::Fn(sig, _),
             ..
-        })) = tcx.hir().get_if_local(method.def_id).as_ref()
+        })) = tcx.hir_get_if_local(method.def_id).as_ref()
         {
             let sm = tcx.sess.source_map();
             Some((
@@ -383,7 +382,7 @@ fn virtual_call_violations_for_method<'tcx>(
             let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(sig, _),
                 ..
-            })) = tcx.hir().get_if_local(method.def_id).as_ref()
+            })) = tcx.hir_get_if_local(method.def_id).as_ref()
             {
                 Some(sig.decl.inputs[i].span)
             } else {
@@ -421,7 +420,7 @@ fn virtual_call_violations_for_method<'tcx>(
             let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(sig, _),
                 ..
-            })) = tcx.hir().get_if_local(method.def_id).as_ref()
+            })) = tcx.hir_get_if_local(method.def_id).as_ref()
             {
                 Some(sig.decl.inputs[0].span)
             } else {
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 79e178150de3..a4b6f330b9d7 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -208,7 +208,7 @@ pub fn all_fields_implement_trait<'tcx>(
             }
 
             let field_span = tcx.def_span(field.did);
-            let field_ty_span = match tcx.hir().get_if_local(field.did) {
+            let field_ty_span = match tcx.hir_get_if_local(field.did) {
                 Some(hir::Node::Field(field_def)) => field_def.ty.span,
                 _ => field_span,
             };
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 2f72b44f6b62..7f3e3ce47816 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -289,7 +289,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             && let Some(impl_item) =
                 items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id)
         {
-            Some(tcx.hir().impl_item(impl_item.id).expect_type().span)
+            Some(tcx.hir_impl_item(impl_item.id).expect_type().span)
         } else {
             None
         }
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 34f461aac58a..32d9469c296c 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -125,7 +125,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
             #[instrument(level = "trace", skip(self))]
             // Recurse into these, as they are type checked with their parent
             fn visit_nested_body(&mut self, id: rustc_hir::BodyId) {
-                let body = self.collector.tcx.hir().body(id);
+                let body = self.collector.tcx.hir_body(id);
                 self.visit_body(body);
             }
         }
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
index 9fcb16b0fca3..dc63e1aa511b 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
@@ -75,7 +75,7 @@ impl rustc_driver::Callbacks for MyCallbacks {
             let item = hir_krate.item(id);
             // Use pattern-matching to find a specific node inside the main function.
             if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind {
-                let expr = &tcx.hir().body(body_id).value;
+                let expr = &tcx.hir_body(body_id).value;
                 if let rustc_hir::ExprKind::Block(block, _) = expr.kind {
                     if let rustc_hir::StmtKind::Let(let_stmt) = block.stmts[0].kind {
                         if let Some(expr) = let_stmt.init {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3d51ab1967d4..0cdf1b989158 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -488,7 +488,7 @@ pub(crate) fn build_impl(
             impl_
                 .items
                 .iter()
-                .map(|item| tcx.hir().impl_item(item.id))
+                .map(|item| tcx.hir_impl_item(item.id))
                 .filter(|item| {
                     // Filter out impl items whose corresponding trait item has `doc(hidden)`
                     // not to document such impl items.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 1d62a93e723a..92ef3ab7a1d4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1145,7 +1145,7 @@ fn clean_args_from_types_and_body_id<'tcx>(
     types: &[hir::Ty<'tcx>],
     body_id: hir::BodyId,
 ) -> Arguments {
-    let body = cx.tcx.hir().body(body_id);
+    let body = cx.tcx.hir_body(body_id);
 
     Arguments {
         values: types
@@ -2845,7 +2845,7 @@ fn clean_maybe_renamed_item<'tcx>(
             ItemKind::Trait(_, _, generics, bounds, item_ids) => {
                 let items = item_ids
                     .iter()
-                    .map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx))
+                    .map(|ti| clean_trait_item(cx.tcx.hir_trait_item(ti.id), cx))
                     .collect();
 
                 TraitItem(Box::new(Trait {
@@ -2891,7 +2891,7 @@ fn clean_impl<'tcx>(
     let items = impl_
         .items
         .iter()
-        .map(|ii| clean_impl_item(tcx.hir().impl_item(ii.id), cx))
+        .map(|ii| clean_impl_item(tcx.hir_impl_item(ii.id), cx))
         .collect::>();
 
     // If this impl block is an implementation of the Deref trait, then we
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 5f7c30a33ab8..8b424499724b 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -220,12 +220,11 @@ impl ExternalCrate {
             None
         };
         if root.is_local() {
-            tcx.hir()
-                .root_module()
+            tcx.hir_root_module()
                 .item_ids
                 .iter()
                 .filter_map(|&id| {
-                    let item = tcx.hir().item(id);
+                    let item = tcx.hir_item(id);
                     match item.kind {
                         hir::ItemKind::Mod(_) => {
                             as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
@@ -277,12 +276,11 @@ impl ExternalCrate {
         };
 
         if root.is_local() {
-            tcx.hir()
-                .root_module()
+            tcx.hir_root_module()
                 .item_ids
                 .iter()
                 .filter_map(|&id| {
-                    let item = tcx.hir().item(id);
+                    let item = tcx.hir_item(id);
                     match item.kind {
                         hir::ItemKind::Mod(_) => {
                             as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
@@ -2122,9 +2120,8 @@ impl Discriminant {
     /// Will be `None` in the case of cross-crate reexports, and may be
     /// simplified
     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option {
-        self.expr.map(|body| {
-            rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body))
-        })
+        self.expr
+            .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir().body_owner_def_id(body)))
     }
     pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
         print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
@@ -2420,7 +2417,7 @@ impl ConstantKind {
             ConstantKind::Path { ref path } => path.to_string(),
             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
-                rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body))
+                rendered_const(tcx, tcx.hir_body(body), tcx.hir().body_owner_def_id(body))
             }
             ConstantKind::Infer { .. } => "_".to_string(),
         }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 5c146da03acc..390ff3de2fa2 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -378,7 +378,7 @@ pub(crate) fn run_global_ctxt(
         ctxt.external_traits.insert(sized_trait_did, sized_trait);
     }
 
-    debug!("crate: {:?}", tcx.hir().krate());
+    debug!("crate: {:?}", tcx.hir_krate());
 
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index fcee29609797..bef59469179c 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -846,7 +846,7 @@ fn convert_static(
         is_unsafe: safety.is_unsafe(),
         expr: stat
             .expr
-            .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
+            .map(|e| rendered_const(tcx, tcx.hir_body(e), tcx.hir().body_owner_def_id(e)))
             .unwrap_or_default(),
     }
 }
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 135aa7990601..45b8dafa9079 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -232,7 +232,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> {
                     .item_id
                     .as_def_id()
                     .and_then(|def_id| self.ctx.tcx.opt_parent(def_id))
-                    .and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id))
+                    .and_then(|def_id| self.ctx.tcx.hir_get_if_local(def_id))
                     .map(|node| {
                         matches!(
                             node,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index e4628e4f8377..5884e018f6a9 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -96,7 +96,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let om = Module::new(
             cx.tcx.crate_name(LOCAL_CRATE),
             CRATE_DEF_ID,
-            cx.tcx.hir().root_module().spans.inner_span,
+            cx.tcx.hir_root_module().spans.inner_span,
             None,
             None,
         );
@@ -119,7 +119,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     pub(crate) fn visit(mut self) -> Module<'tcx> {
-        let root_module = self.cx.tcx.hir().root_module();
+        let root_module = self.cx.tcx.hir_root_module();
         self.visit_mod_contents(CRATE_DEF_ID, root_module);
 
         let mut top_level_module = self.modules.pop().unwrap();
@@ -193,13 +193,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
         // the second loop):
         for &i in m.item_ids {
-            let item = self.cx.tcx.hir().item(i);
+            let item = self.cx.tcx.hir_item(i);
             if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
                 self.visit_item(item);
             }
         }
         for &i in m.item_ids {
-            let item = self.cx.tcx.hir().item(i);
+            let item = self.cx.tcx.hir_item(i);
             // To match the way import precedence works, visit glob imports last.
             // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
             // imported items appear last, then they'll be the ones that get discarded.
@@ -315,7 +315,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             Node::Item(&hir::Item { kind: hir::ItemKind::Mod(m), .. }) if glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
-                    let i = tcx.hir().item(i);
+                    let i = tcx.hir_item(i);
                     self.visit_item_inner(i, None, Some(def_id));
                 }
                 self.inlining = prev;
@@ -433,7 +433,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         match item.kind {
             hir::ItemKind::ForeignMod { items, .. } => {
                 for item in items {
-                    let item = tcx.hir().foreign_item(item.id);
+                    let item = tcx.hir_foreign_item(item.id);
                     self.visit_foreign_item_inner(item, None);
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
index f519a65fc272..aff40fa846be 100644
--- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
+++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
@@ -338,7 +338,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
             return;
         }
 
-        let items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id));
+        let items = module.item_ids.iter().map(|&id| cx.tcx.hir_item(id));
 
         // Iterates over the items within a module.
         //
diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs
index eeaa3de3725f..013819b0da8a 100644
--- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs
+++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs
@@ -60,12 +60,12 @@ impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync {
                 // XXXkhuey maybe we should?
                 return;
             },
-            CoroutineSource::Block => cx.tcx.hir().body(*body_id).value,
+            CoroutineSource::Block => cx.tcx.hir_body(*body_id).value,
             CoroutineSource::Closure => {
                 // Like `async fn`, async closures are wrapped in an additional block
                 // to move all of the closure's arguments into the future.
 
-                let async_closure_body = cx.tcx.hir().body(*body_id).value;
+                let async_closure_body = cx.tcx.hir_body(*body_id).value;
                 let ExprKind::Block(block, _) = async_closure_body.kind else {
                     return;
                 };
diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
index 152e6ec70a18..a667649f7343 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
@@ -22,7 +22,7 @@ pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
 
 pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
     if let ItemKind::Fn { body: eid, .. } = item.kind {
-        is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
+        is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value)
     } else {
         true
     }
@@ -30,7 +30,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
 
 pub(super) fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool {
     match item.kind {
-        ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value),
+        ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value),
         _ => false,
     }
 }
@@ -39,7 +39,7 @@ pub(super) fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> b
     match item.kind {
         TraitItemKind::Fn(_, TraitFn::Required(_)) => true,
         TraitItemKind::Fn(_, TraitFn::Provided(eid)) => {
-            is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
+            is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value)
         },
         _ => false,
     }
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index f8c30d1c881d..f30f16997d76 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -452,7 +452,7 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: &Msrv, expr: &Expr<'_>) -> Opti
                 })
         },
         ExprKind::Closure(closure) => {
-            let body = cx.tcx.hir().body(closure.body);
+            let body = cx.tcx.hir_body(closure.body);
             let params = body
                 .params
                 .iter()
diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
index 8276e53648c0..1279be34ed8f 100644
--- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
+++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
@@ -118,7 +118,7 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI
             let is_read_in_closure_arg = args.iter().any(|arg| {
                 if let ExprKind::Closure(closure) = arg.kind
                     // To keep things simple, we only check the first param to see if its read.
-                    && let Body { params: [param, ..], value } = cx.tcx.hir().body(closure.body)
+                    && let Body { params: [param, ..], value } = cx.tcx.hir_body(closure.body)
                 {
                     !has_no_read_access(cx, param.hir_id, *value)
                 } else {
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 9569081ad088..bb445e0155f6 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -197,7 +197,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             && let impl_item_hir = child.id.hir_id()
             && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
-            && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
+            && let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
             && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
             && let attrs = cx.tcx.hir().attrs(item.hir_id())
             && !attrs.iter().any(|attr| attr.doc_str().is_some())
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index 8e2af6bf14a6..d1ffbb6ffe25 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -68,7 +68,7 @@ pub fn check(
         } else if let Some(body_id) = body_id
             && let Some(future) = cx.tcx.lang_items().future_trait()
             && let typeck = cx.tcx.typeck_body(body_id)
-            && let body = cx.tcx.hir().body(body_id)
+            && let body = cx.tcx.hir_body(body_id)
             && let ret_ty = typeck.expr_ty(body.value)
             && implements_trait_with_env(
                 cx.tcx,
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 42e1f7fd950d..36baf492a540 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -597,7 +597,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                         if !(is_entrypoint_fn(cx, item.owner_id.to_def_id())
                             || item.span.in_external_macro(cx.tcx.sess.source_map()))
                         {
-                            let body = cx.tcx.hir().body(body_id);
+                            let body = cx.tcx.hir_body(body_id);
 
                             let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
                             missing_headers::check(
@@ -649,7 +649,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                     && !impl_item.span.in_external_macro(cx.tcx.sess.source_map())
                     && !is_trait_impl_item(cx, impl_item.hir_id())
                 {
-                    let body = cx.tcx.hir().body(body_id);
+                    let body = cx.tcx.hir_body(body_id);
 
                     let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(impl_item.owner_id), body.value);
                     missing_headers::check(
diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs
index 10a84b1b2ff2..d557a36c7ac2 100644
--- a/src/tools/clippy/clippy_lints/src/empty_drop.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs
@@ -44,7 +44,7 @@ impl LateLintPass<'_> for EmptyDrop {
             && let impl_item_hir = child.id.hir_id()
             && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
-            && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
+            && let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
             && let func_expr = peel_blocks(func_expr)
             && let ExprKind::Block(block, _) = func_expr.kind
             && block.stmts.is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index ae3acc1c4b19..d1782d582f4d 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -97,7 +97,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
         && matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_))
         && !expr.span.from_expansion()
     {
-        cx.tcx.hir().body(c.body)
+        cx.tcx.hir_body(c.body)
     } else {
         return;
     };
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 5d93aceb33ff..6ccea22e191c 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -247,7 +247,7 @@ impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> {
 }
 
 fn is_empty_body(cx: &LateContext<'_>, body: BodyId) -> bool {
-    matches!(cx.tcx.hir().body(body).value.kind, ExprKind::Block(b, _) if b.stmts.is_empty() && b.expr.is_none())
+    matches!(cx.tcx.hir_body(body).value.kind, ExprKind::Block(b, _) if b.stmts.is_empty() && b.expr.is_none())
 }
 
 impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
index f822432cce63..f67d38d932b9 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -98,10 +98,10 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
 
     for impl_item in impl_items {
         if impl_item.ident.name == sym::from
-            && let ImplItemKind::Fn(_, body_id) = cx.tcx.hir().impl_item(impl_item.id).kind
+            && let ImplItemKind::Fn(_, body_id) = cx.tcx.hir_impl_item(impl_item.id).kind
         {
             // check the body for `begin_panic` or `unwrap`
-            let body = cx.tcx.hir().body(body_id);
+            let body = cx.tcx.hir_body(body_id);
             let mut fpu = FindPanicUnwrap {
                 lcx: cx,
                 typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id),
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index 5619cb0ab1b0..ff75fcf2b417 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -262,7 +262,7 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio
         && let Some(name) = cx.tcx.get_diagnostic_name(did)
         && matches!(name, sym::Debug | sym::Display)
     {
-        let body = cx.tcx.hir().body(body_id);
+        let body = cx.tcx.hir_body(body_id);
         let formatter_name = body
             .params
             .get(1)
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 9a73d0c0993f..167377972db9 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -175,11 +175,11 @@ fn convert_to_from(
         // bad suggestion/fix.
         return None;
     }
-    let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
+    let impl_item = cx.tcx.hir_impl_item(impl_item_ref.id);
     let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind else {
         return None;
     };
-    let body = cx.tcx.hir().body(body_id);
+    let body = cx.tcx.hir_body(body_id);
     let [input] = body.params else { return None };
     let PatKind::Binding(.., self_ident, None) = input.pat.kind else {
         return None;
diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
index 752dbc0db4db..6d1c55d06938 100644
--- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -56,7 +56,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
         && let hir::ItemKind::Impl(impl_) = item.kind
         && let hir::Impl { of_trait, .. } = *impl_
         && of_trait.is_none()
-        && let body = cx.tcx.hir().body(body_id)
+        && let body = cx.tcx.hir_body(body_id)
         && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public()
         && !is_in_test(cx.tcx, impl_item.hir_id())
     {
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index e480805cac2f..e6e3ea59a9f6 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -37,7 +37,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
             check_must_use_candidate(
                 cx,
                 sig.decl,
-                cx.tcx.hir().body(*body_id),
+                cx.tcx.hir_body(*body_id),
                 item.span,
                 item.owner_id,
                 item.span.with_hi(sig.decl.output.span().hi()),
@@ -59,7 +59,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
             check_must_use_candidate(
                 cx,
                 sig.decl,
-                cx.tcx.hir().body(*body_id),
+                cx.tcx.hir_body(*body_id),
                 item.span,
                 item.owner_id,
                 item.span.with_hi(sig.decl.output.span().hi()),
@@ -79,7 +79,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
         } else if let hir::TraitFn::Provided(eid) = *eid {
-            let body = cx.tcx.hir().body(eid);
+            let body = cx.tcx.hir_body(eid);
             if attr.is_none() && is_public && !is_proc_macro(attrs) {
                 check_must_use_candidate(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 8a74951ef63e..906bbd006d46 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -30,7 +30,7 @@ pub(super) fn check_fn<'tcx>(
 
 pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
     if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
-        let body = cx.tcx.hir().body(eid);
+        let body = cx.tcx.hir_body(eid);
         check_raw_ptr(cx, sig.header.safety(), sig.decl, body, item.owner_id.def_id);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 47a5c19215b8..1b39663f4f81 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                     });
 
                     let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
-                    for item in impl_.items.iter().map(|item| cx.tcx.hir().impl_item(item.id)) {
+                    for item in impl_.items.iter().map(|item| cx.tcx.hir_impl_item(item.id)) {
                         ctr_vis.visit_impl_item(item);
                     }
 
@@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                 body: body_id,
                 ..
             } => {
-                let body = cx.tcx.hir().body(body_id);
+                let body = cx.tcx.hir_body(body_id);
 
                 for ty in sig.decl.inputs {
                     let mut vis = ImplicitHasherTypeVisitor::new(cx);
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index d3aade31f14f..3cb47d8ef919 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -159,7 +159,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
             }
             if method.ident.name.as_str() == "flat_map" && args.len() == 1 {
                 if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind {
-                    let body = cx.tcx.hir().body(body);
+                    let body = cx.tcx.hir_body(body);
                     return is_infinite(cx, body.value);
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs
index f5ad79a00279..021d43cefdda 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs
@@ -59,7 +59,7 @@ impl LateLintPass<'_> for ItemsAfterStatements {
                 .iter()
                 .skip_while(|stmt| matches!(stmt.kind, StmtKind::Item(..)))
                 .filter_map(|stmt| match stmt.kind {
-                    StmtKind::Item(id) => Some(cx.tcx.hir().item(id)),
+                    StmtKind::Item(id) => Some(cx.tcx.hir_item(id)),
                     _ => None,
                 })
                 // Ignore macros since they can only see previously defined locals.
diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
index 1ac549b74ac6..9df044f25eb7 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
@@ -58,7 +58,7 @@ fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
 
 impl LateLintPass<'_> for ItemsAfterTestModule {
     fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: HirId) {
-        let mut items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id));
+        let mut items = module.item_ids.iter().map(|&id| cx.tcx.hir_item(id));
 
         let Some((mod_pos, test_mod)) = items.by_ref().enumerate().find(|(_, item)| cfg_test_module(cx, item)) else {
             return;
@@ -91,7 +91,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
                 "items after a test module",
                 |diag| {
                     if let Some(prev) = mod_pos.checked_sub(1)
-                        && let prev = cx.tcx.hir().item(module.item_ids[prev])
+                        && let prev = cx.tcx.hir_item(module.item_ids[prev])
                         && let items_span = last.span.with_lo(test_mod.span.hi())
                         && let Some(items) = items_span.get_source_text(cx)
                     {
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
index 238f66d66755..173232c511a5 100644
--- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -142,7 +142,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
             })
             && let Some(iter_assoc_span) = imp.items.iter().find_map(|item| {
                 if item.ident.name.as_str() == "IntoIter" {
-                    Some(cx.tcx.hir().impl_item(item.id).expect_type().span)
+                    Some(cx.tcx.hir_impl_item(item.id).expect_type().span)
                 } else {
                     None
                 }
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 26bea8d633a3..98ba52f12707 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -316,7 +316,7 @@ enum LenOutput {
 
 fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
     if let ty::Alias(_, alias_ty) = ty.kind()
-        && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir().get_if_local(alias_ty.def_id)
+        && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir_get_if_local(alias_ty.def_id)
         && let OpaqueTyOrigin::AsyncFn { .. } = opaque.origin
         && let [GenericBound::Trait(trait_ref)] = &opaque.bounds
         && let Some(segment) = trait_ref.trait_ref.path.segments.last()
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 860c0584accf..8eb45109d68c 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -275,7 +275,7 @@ fn could_use_elision<'tcx>(
     }
 
     if let Some(body_id) = body {
-        let body = cx.tcx.hir().body(body_id);
+        let body = cx.tcx.hir_body(body_id);
 
         let first_ident = body.params.first().and_then(|param| param.pat.simple_ident());
         if non_elidable_self_type(cx, func, first_ident, msrv) {
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index 8206c75927b7..f022598651b7 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -101,7 +101,7 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> boo
                 ExprKind::Closure(Closure { body, .. }) => {
                     if let Body {
                         params: [param], value, ..
-                    } = cx.tcx.hir().body(*body)
+                    } = cx.tcx.hir_body(*body)
                         && let ExprKind::MethodCall(method, receiver, [], _) = value.kind
                         && path_to_local_id(receiver, param.pat.hir_id)
                         && let Some(method_did) = cx.typeck_results().type_dependent_def_id(value.hir_id)
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 2e6442156ef6..e98c3c9698ba 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -370,7 +370,7 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> {
                 }
             },
             ExprKind::Closure(&Closure { body, .. }) => {
-                let body = self.cx.tcx.hir().body(body);
+                let body = self.cx.tcx.hir_body(body);
                 self.visit_expr(body.value);
             },
             _ => walk_expr(self, expr),
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index b7e37c1a876f..e31b474c83f6 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -351,7 +351,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
             loop_id: loop_expr.hir_id,
             after_loop: false,
         };
-        v.visit_expr(cx.tcx.hir().body(cx.enclosing_body.unwrap()).value)
+        v.visit_expr(cx.tcx.hir_body(cx.enclosing_body.unwrap()).value)
             .is_break()
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 9f3b0957eab1..6f3a7d8cccc8 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -168,7 +168,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
         && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) =
             kind
     {
-        return Some(cx.tcx.hir().body(body));
+        return Some(cx.tcx.hir_body(body));
     }
 
     None
diff --git a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
index 5c40c945c690..e4360518b66e 100644
--- a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
@@ -191,7 +191,7 @@ fn check_arms(cx: &LateContext<'_>, none_arm: &Arm<'_>, some_arm: &Arm<'_>) -> b
 fn returns_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match expr.kind {
         ExprKind::Path(_) => clippy_utils::is_path_diagnostic_item(cx, expr, sym::default_fn),
-        ExprKind::Closure(cl) => is_empty_slice(cx, cx.tcx.hir().body(cl.body).value),
+        ExprKind::Closure(cl) => is_empty_slice(cx, cx.tcx.hir_body(cl.body).value),
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 708980ac503d..0a4e756096e9 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -92,7 +92,7 @@ fn check_into_iter(
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr)
         && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = target_expr.kind
         && let hir::ExprKind::Closure(closure) = closure_expr.kind
-        && let filter_body = cx.tcx.hir().body(closure.body)
+        && let filter_body = cx.tcx.hir_body(closure.body)
         && let [filter_params] = filter_body.params
     {
         if match_map_type(cx, left_expr) {
@@ -139,7 +139,7 @@ fn check_iter(
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr)
         && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
         && let hir::ExprKind::Closure(closure) = closure_expr.kind
-        && let filter_body = cx.tcx.hir().body(closure.body)
+        && let filter_body = cx.tcx.hir_body(closure.body)
         && let [filter_params] = filter_body.params
     {
         match filter_params.pat.kind {
@@ -198,7 +198,7 @@ fn check_to_owned(
         && SpanlessEq::new(cx).eq_expr(left_expr, str_expr)
         && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
         && let hir::ExprKind::Closure(closure) = closure_expr.kind
-        && let filter_body = cx.tcx.hir().body(closure.body)
+        && let filter_body = cx.tcx.hir_body(closure.body)
         && let [filter_params] = filter_body.params
     {
         if let hir::PatKind::Ref(pat, _) = filter_params.pat.kind {
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index 3221a04d2d03..56aead85e7c4 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -163,7 +163,7 @@ fn unit_closure<'tcx>(
     expr: &hir::Expr<'_>,
 ) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
     if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind
-        && let body = cx.tcx.hir().body(body)
+        && let body = cx.tcx.hir_body(body)
         && let body_expr = &body.value
         && fn_decl.inputs.len() == 1
         && is_unit_expression(cx, body_expr)
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 91a5de16e967..1e9b29f567f4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -163,7 +163,7 @@ impl BindInsteadOfMap {
 
         match arg.kind {
             hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) => {
-                let closure_body = cx.tcx.hir().body(body);
+                let closure_body = cx.tcx.hir_body(body);
                 let closure_expr = peel_blocks(closure_body.value);
 
                 if self.lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs
index 687272e550bb..0498f317442a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs
@@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
     filter_arg: &'tcx Expr<'_>,
 ) {
     if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind
-        && let body = cx.tcx.hir().body(body)
+        && let body = cx.tcx.hir_body(body)
         && let [param] = body.params
         && let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind
         && let ExprKind::Binary(ref op, l, r) = body.value.kind
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index c1653b65e982..5b9df6c2bfdd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -22,7 +22,7 @@ fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool
         ExprKind::Path(QPath::Resolved(_, segments)) => segments.segments.last().unwrap().ident.name == method_name,
         ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name,
         ExprKind::Closure(Closure { body, .. }) => {
-            let body = cx.tcx.hir().body(*body);
+            let body = cx.tcx.hir_body(*body);
             let closure_expr = peel_blocks(body.value);
             match closure_expr.kind {
                 ExprKind::MethodCall(PathSegment { ident, .. }, receiver, ..) => {
@@ -404,7 +404,7 @@ fn is_find_or_filter<'a>(
     if is_trait_method(cx, map_recv, sym::Iterator)
         // filter(|x| ...is_some())...
         && let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind
-        && let filter_body = cx.tcx.hir().body(filter_body_id)
+        && let filter_body = cx.tcx.hir_body(filter_body_id)
         && let [filter_param] = filter_body.params
         // optional ref pattern: `filter(|&x| ..)`
         && let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
@@ -417,7 +417,7 @@ fn is_find_or_filter<'a>(
         && let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id)
 
         && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind
-        && let map_body = cx.tcx.hir().body(map_body_id)
+        && let map_body = cx.tcx.hir_body(map_body_id)
         && let [map_param] = map_body.params
         && let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
index d550c1454668..f7e116c5310e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
     if !expr.span.in_external_macro(cx.sess().source_map())
         && is_trait_method(cx, expr, sym::Iterator)
         && let ExprKind::Closure(closure) = arg.kind
-        && let body = cx.tcx.hir().body(closure.body)
+        && let body = cx.tcx.hir_body(closure.body)
         && let value = peel_blocks(body.value)
         // Indexing should be fine as `filter_map` always has 1 input, we unfortunately need both
         // `inputs` and `params` here as we need both the type and the span
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
         && is_copy(cx, param_ty)
         && let ExprKind::MethodCall(_, recv, [then_arg], _) = value.kind
         && let ExprKind::Closure(then_closure) = then_arg.kind
-        && let then_body = peel_blocks(cx.tcx.hir().body(then_closure.body).value)
+        && let then_body = peel_blocks(cx.tcx.hir_body(then_closure.body).value)
         && let Some(def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id)
         && cx.tcx.is_diagnostic_item(sym::bool_then, def_id)
         && !is_from_proc_macro(cx, expr)
diff --git a/src/tools/clippy/clippy_lints/src/methods/format_collect.rs b/src/tools/clippy/clippy_lints/src/methods/format_collect.rs
index 3e5162ef4580..1b28596d50da 100644
--- a/src/tools/clippy/clippy_lints/src/methods/format_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/format_collect.rs
@@ -19,7 +19,7 @@ fn peel_non_expn_blocks<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, map_arg: &Expr<'_>, map_span: Span) {
     if is_type_lang_item(cx, cx.typeck_results().expr_ty(expr), LangItem::String)
         && let ExprKind::Closure(closure) = map_arg.kind
-        && let body = cx.tcx.hir().body(closure.body)
+        && let body = cx.tcx.hir_body(closure.body)
         && let Some(value) = peel_non_expn_blocks(body.value)
         && let Some(mac) = root_macro_call_first_node(cx, value)
         && is_format_macro(cx, mac.def_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
index 30387ba62a73..76a0c0061e52 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
@@ -95,7 +95,7 @@ fn is_method(
             false
         },
         ExprKind::Closure(&hir::Closure { body, .. }) => {
-            let body = cx.tcx.hir().body(body);
+            let body = cx.tcx.hir_body(body);
             let closure_expr = peel_blocks(body.value);
             let params = body.params.iter().map(|param| param.pat).collect::>();
             is_method(cx, closure_expr, type_symbol, method_name, params.as_slice())
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 299f6d101123..518041177e92 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
         && let Body {
             params: [p],
             value: body_expr,
-        } = cx.tcx.hir().body(c.body)
+        } = cx.tcx.hir_body(c.body)
         && let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind
         && let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
             (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
index 5ccb5243e903..a80977459f21 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
             let ExprKind::Closure(closure) = expr.kind else {
                 return;
             };
-            let body @ Body { params: [p], .. } = cx.tcx.hir().body(closure.body) else {
+            let body @ Body { params: [p], .. } = cx.tcx.hir_body(closure.body) else {
                 return;
             };
             let mut delegate = MoveDelegate {
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
index 20e4d233525a..de37df2394d3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
@@ -22,7 +22,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
         && (is_diag_trait_item(cx, fn_id, sym::Iterator)
             || (msrv.meets(msrvs::OPTION_RESULT_INSPECT)
                 && (is_diag_item_method(cx, fn_id, sym::Option) || is_diag_item_method(cx, fn_id, sym::Result))))
-        && let body = cx.tcx.hir().body(c.body)
+        && let body = cx.tcx.hir_body(c.body)
         && let [param] = body.params
         && let PatKind::Binding(BindingMode(ByRef::No, Mutability::Not), arg_id, _, None) = param.pat.kind
         && let arg_ty = typeck.node_type(arg_id)
@@ -45,7 +45,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
         let can_lint = for_each_expr_without_closures(block.stmts, |e| {
             if let ExprKind::Closure(c) = e.kind {
                 // Nested closures don't need to treat returns specially.
-                let _: Option = for_each_expr(cx, cx.tcx.hir().body(c.body).value, |e| {
+                let _: Option = for_each_expr(cx, cx.tcx.hir_body(c.body).value, |e| {
                     if path_to_local_id(e, arg_id) {
                         let (kind, same_ctxt) = check_use(cx, e);
                         match (kind, same_ctxt && e.span.ctxt() == ctxt) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
index 4321dd6b0e09..8265c93bfe9f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
@@ -44,7 +44,7 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
     match map_expr.kind {
         ExprKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, map_expr.hir_id), ResultOk) => true,
         ExprKind::Closure(closure) => {
-            let body = cx.tcx.hir().body(closure.body);
+            let body = cx.tcx.hir_body(closure.body);
             if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind
                 && let ExprKind::Call(callee, [ok_arg]) = body.value.kind
                 && is_res_lang_ctor(cx, path_res(cx, callee), ResultOk)
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 1252f7ccd357..b2705e1ffc2d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -47,7 +47,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
     {
         match arg.kind {
             hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
-                let closure_body = cx.tcx.hir().body(body);
+                let closure_body = cx.tcx.hir_body(body);
                 let closure_expr = peel_blocks(closure_body.value);
                 match closure_body.params[0].pat.kind {
                     hir::PatKind::Ref(inner, Mutability::Not) => {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
index 162f0ac564d7..5d0d4dae35fa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) {
             fn_decl_span,
             ..
         }) = arg.kind
-        && let closure_body = cx.tcx.hir().body(body)
+        && let closure_body = cx.tcx.hir_body(body)
         && let [param] = closure_body.params
         && let PatKind::Wild = param.pat.kind
     {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
index 78656ace831d..35dd7c082c90 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
@@ -68,7 +68,7 @@ pub(super) fn check(
     let mut applicability = Applicability::MaybeIncorrect;
     if let Some(range) = higher::Range::hir(receiver)
         && let ExprKind::Closure(Closure { body, .. }) = arg.kind
-        && let body_hir = cx.tcx.hir().body(*body)
+        && let body_hir = cx.tcx.hir_body(*body)
         && let Body {
             params: [param],
             value: body_expr,
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 0a8eafad0e84..ccc5cd4fa417 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -4716,7 +4716,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             if sig.decl.implicit_self.has_implicit_self()
                 && !(self.avoid_breaking_exported_api
                     && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id))
-                && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next()
+                && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir_body(id)).next()
                 && let Some(first_arg_ty) = first_arg_ty_opt
             {
                 wrong_self_convention::check(
@@ -4852,7 +4852,7 @@ impl Methods {
                         ),
                         Some(("chars", recv, _, _, _))
                             if let ExprKind::Closure(arg) = arg.kind
-                                && let body = cx.tcx.hir().body(arg.body)
+                                && let body = cx.tcx.hir_body(arg.body)
                                 && let [param] = body.params =>
                         {
                             string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
index 6993150fb57a..743aacf05885 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
@@ -99,7 +99,7 @@ fn handle_expr(
 
 pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, closure_arg: &Expr<'_>, is_all: bool) {
     if let ExprKind::Closure(&Closure { body, .. }) = closure_arg.kind
-        && let body = cx.tcx.hir().body(body)
+        && let body = cx.tcx.hir_body(body)
         && let Some(first_param) = body.params.first()
         && let ExprKind::MethodCall(method, mut recv, [], _) = recv.kind
         && method.ident.name.as_str() == "chars"
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 2780c3f8af5c..5664ffba1a0e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -498,7 +498,7 @@ fn get_captured_ids(cx: &LateContext<'_>, ty: Ty<'_>) -> HirIdSet {
                 }
             },
             ty::Closure(def_id, _) => {
-                let closure_hir_node = cx.tcx.hir().get_if_local(*def_id).unwrap();
+                let closure_hir_node = cx.tcx.hir_get_if_local(*def_id).unwrap();
                 if let Node::Expr(closure_expr) = closure_hir_node {
                     can_move_expr_to_closure(cx, closure_expr)
                         .unwrap()
diff --git a/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs b/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
index b71f79f84824..e0905374ddaa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
@@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
 
         let if_then = match then_method_name {
             "then" if let ExprKind::Closure(closure) = then_arg.kind => {
-                let body = cx.tcx.hir().body(closure.body);
+                let body = cx.tcx.hir_body(closure.body);
                 snippet_with_applicability(cx, body.value.span, "..", &mut applicability)
             },
             "then_some" => snippet_with_applicability(cx, then_arg.span, "..", &mut applicability),
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 8d97d1c72a6b..469fcccbe4f6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -54,7 +54,7 @@ pub(super) fn check(
                 })
         },
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
-            let closure_body = cx.tcx.hir().body(body);
+            let closure_body = cx.tcx.hir_body(body);
             let closure_expr = peel_blocks(closure_body.value);
 
             match &closure_expr.kind {
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
index 193deafccf65..1a273f77fb7d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
@@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(
         let self_snippet = snippet(cx, recv.span, "..");
         if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind
             && let arg_snippet = snippet(cx, fn_decl_span, "..")
-            && let body = cx.tcx.hir().body(body)
+            && let body = cx.tcx.hir_body(body)
             && let Some((func, [arg_char])) = reduce_unit_expression(body.value)
             && let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id))
             && Some(id) == cx.tcx.lang_items().option_some_variant()
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index 6b39b753885e..f5f404070cab 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -253,7 +253,7 @@ pub(super) fn check<'tcx>(
 
 fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool {
     if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = e.kind {
-        let body = cx.tcx.hir().body(body);
+        let body = cx.tcx.hir_body(body);
 
         if body.params.is_empty()
             && let hir::Expr { kind, .. } = &body.value
diff --git a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs
index 3b0dc506305b..af619c9e3bb1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
         // We check that it is mapped as `Some`.
         && is_res_lang_ctor(cx, path_res(cx, map_arg), OptionSome)
         && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = def_arg.kind
-        && let body = cx.tcx.hir().body(body)
+        && let body = cx.tcx.hir_body(body)
         // And finally we check that we return a `None` in the "else case".
         && is_res_lang_ctor(cx, path_res(cx, peel_blocks(body.value)), OptionNone)
     {
diff --git a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs
index 7b1199ad1e2d..68ffa81a2781 100644
--- a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs
@@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
     };
 
     let closure_arg = fn_decl.inputs[0];
-    let closure_expr = peel_blocks(cx.tcx.hir().body(body).value);
+    let closure_expr = peel_blocks(cx.tcx.hir_body(body).value);
 
     let mut applicability = Applicability::MachineApplicable;
     let arg_snip = snippet_with_applicability(cx, closure_arg.span, "_", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index 4ab165a5528b..97c8ce2bcdd2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(
             let mut applicability = Applicability::MachineApplicable;
             let any_search_snippet = if search_method == "find"
                 && let ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
-                && let closure_body = cx.tcx.hir().body(body)
+                && let closure_body = cx.tcx.hir_body(body)
                 && let Some(closure_arg) = closure_body.params.first()
             {
                 if let PatKind::Ref(..) = closure_arg.pat.kind {
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
index ed49233acb7f..1bd48525f12d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
@@ -10,7 +10,7 @@ use super::SUSPICIOUS_MAP;
 pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
     if is_trait_method(cx, count_recv, sym::Iterator)
         && let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind
-        && let closure_body = cx.tcx.hir().body(closure.body)
+        && let closure_body = cx.tcx.hir_body(closure.body)
         && !cx.typeck_results().expr_ty(closure_body.value).is_unit()
     {
         if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index 5b9e9e70e477..ca42a9ac04e0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -20,7 +20,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
     }
 
     if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind {
-        let body = cx.tcx.hir().body(body);
+        let body = cx.tcx.hir_body(body);
         let arg_id = body.params[0].pat.hir_id;
         let mutates_arg = mutated_variables(body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id));
         let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index e7adf3b43ba5..8e3cc9abe832 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -62,7 +62,7 @@ fn check_fold_with_op(
 ) {
     if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind
         // Extract the body of the closure passed to fold
-        && let closure_body = cx.tcx.hir().body(body)
+        && let closure_body = cx.tcx.hir_body(body)
         && let closure_expr = peel_blocks(closure_body.value)
 
         // Check if the closure body is of the form `acc  some_expr(x)`
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 7af550fa7c68..9f4080100da2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
 
     if is_option || is_result || is_bool {
         if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind {
-            let body = cx.tcx.hir().body(body);
+            let body = cx.tcx.hir_body(body);
             let body_expr = &body.value;
 
             if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
index 10112b62878a..00690aca6d13 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -99,7 +99,7 @@ pub(super) fn check(
             ("None", "unwrap_or_else", _) => match args[0].kind {
                 hir::ExprKind::Closure(hir::Closure { body, .. }) => Some(vec![
                     (
-                        expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()),
+                        expr.span.with_hi(cx.tcx.hir_body(*body).value.span.lo()),
                         String::new(),
                     ),
                     (expr.span.with_lo(args[0].span.hi()), String::new()),
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
index 6dea1506d0e3..5f88a7fd31f2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
@@ -63,7 +63,7 @@ pub(super) fn check<'a>(
     let ext_def_span = def.span.until(map.span);
 
     let (sugg, method, applicability) = if let ExprKind::Closure(map_closure) = map.kind
-            && let closure_body = cx.tcx.hir().body(map_closure.body)
+            && let closure_body = cx.tcx.hir_body(map_closure.body)
             && let closure_body_value = closure_body.value.peel_blocks()
             && let ExprKind::Binary(op, l, r) = closure_body_value.kind
             && let Some(param) = closure_body.params.first()
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
index dc50717112d8..f84d0d6dff0a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
@@ -53,7 +53,7 @@ pub(super) fn check<'tcx>(
     // lint if the caller of `map_or_else()` is a `Result`
     if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
         && let ExprKind::Closure(&Closure { body, .. }) = map_arg.kind
-        && let body = cx.tcx.hir().body(body)
+        && let body = cx.tcx.hir_body(body)
         && let Some(first_param) = body.params.first()
     {
         let body_expr = peel_blocks(body.value);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index f0b29213e1e5..fb4984914eb0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -117,7 +117,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
         && cx.tcx.type_of(impl_id).instantiate_identity().is_slice()
         && let ExprKind::Closure(&Closure { body, .. }) = arg.kind
-        && let closure_body = cx.tcx.hir().body(body)
+        && let closure_body = cx.tcx.hir_body(body)
         && let &[
             Param {
                 pat:
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 7d72310c1c44..e80d99dca56d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -506,7 +506,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                     if has_lifetime(output_ty) && has_lifetime(ty) {
                         return false;
                     }
-                    let body = cx.tcx.hir().body(*body_id);
+                    let body = cx.tcx.hir_body(*body_id);
                     let body_expr = &body.value;
                     let mut count = 0;
                     return find_all_ret_expressions(cx, body_expr, |_| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
index 0aec26f10111..af466fe091c2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
@@ -46,7 +46,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
         && is_trait_method(cx, call_expr, sym::Iterator)
         // And the map argument is a closure
         && let ExprKind::Closure(closure) = closure_arg.kind
-        && let closure_body = cx.tcx.hir().body(closure.body)
+        && let closure_body = cx.tcx.hir_body(closure.body)
         // And that closure has one argument ...
         && let [closure_param] = closure_body.params
         // .. which is a tuple of 2 elements
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index 82313257e5c4..19152362fb5f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -113,7 +113,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
     match arg.kind {
         hir::ExprKind::Closure(&hir::Closure { body, .. })
             // If it's a closure, we need to check what is called.
-            if let closure_body = cx.tcx.hir().body(body)
+            if let closure_body = cx.tcx.hir_body(body)
                 && let [param] = closure_body.params
                 && let hir::PatKind::Binding(_, local_id, ..) = strip_pat_refs(param.pat).kind =>
         {
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index e9ec23b1efa6..675989156cad 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -213,8 +213,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
             && !item.span.from_expansion()
             // find `Debug::fmt` function
             && let Some(fmt_item) = items.iter().find(|i| i.ident.name == sym::fmt)
-            && let ImplItem { kind: ImplItemKind::Fn(_, body_id), .. } = cx.tcx.hir().impl_item(fmt_item.id)
-            && let body = cx.tcx.hir().body(*body_id)
+            && let ImplItem { kind: ImplItemKind::Fn(_, body_id), .. } = cx.tcx.hir_impl_item(fmt_item.id)
+            && let body = cx.tcx.hir_body(*body_id)
             && let ExprKind::Block(block, _) = body.value.kind
             // inspect `self`
             && let self_ty = cx.tcx.type_of(self_path_did).skip_binder().peel_refs()
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 18385ac92692..fdc0930e957a 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
                 // note: we need to check if the trait is exported so we can't use
                 // `LateLintPass::check_trait_item` here.
                 for tit in trait_items {
-                    let tit_ = cx.tcx.hir().trait_item(tit.id);
+                    let tit_ = cx.tcx.hir_trait_item(tit.id);
                     match tit_.kind {
                         hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
                         hir::TraitItemKind::Fn(..) => {
@@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
                                 // trait method with default body needs inline in case
                                 // an impl is not provided
                                 let desc = "a default trait method";
-                                let item = cx.tcx.hir().trait_item(tit.id);
+                                let item = cx.tcx.hir_trait_item(tit.id);
                                 let attrs = cx.tcx.hir().attrs(item.hir_id());
                                 check_missing_inline_attrs(cx, attrs, item.span, desc);
                             }
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 93e20f37ef8a..90b27f5dbac8 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
             // Skip the lint if the body is not block because this is simpler than `for` loop.
             // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop.
             && let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind
-            && let body = cx.tcx.hir().body(body)
+            && let body = cx.tcx.hir_body(body)
             // Skip the lint if the body is not safe, so as not to suggest `for … in … unsafe {}`
             // and suggesting `for … in … { unsafe { } }` is a little ugly.
             && let ExprKind::Block(Block { rules: BlockCheckMode::DefaultBlock, .. }, ..) = body.value.kind
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 996251fdf162..6a1dc5e41a07 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -103,7 +103,6 @@ fn check_closures<'tcx>(
     checked_closures: &mut FxHashSet,
     closures: FxIndexSet,
 ) {
-    let hir = cx.tcx.hir();
     for closure in closures {
         if !checked_closures.insert(closure) {
             continue;
@@ -114,7 +113,7 @@ fn check_closures<'tcx>(
             .tcx
             .hir_node_by_def_id(closure)
             .associated_body()
-            .map(|(_, body_id)| hir.body(body_id))
+            .map(|(_, body_id)| cx.tcx.hir_body(body_id))
         {
             euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx)
                 .consume_body(body)
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index cc56df3a23d7..cf407e51f7af 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
         {
             for assoc_item in *items {
                 if assoc_item.kind == (hir::AssocItemKind::Fn { has_self: false }) {
-                    let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
+                    let impl_item = cx.tcx.hir_impl_item(assoc_item.id);
                     if impl_item.span.in_external_macro(cx.sess().source_map()) {
                         return;
                     }
diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
index dad1e8a3d6a1..448bb603cf2c 100644
--- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
@@ -121,10 +121,10 @@ impl LateLintPass<'_> for NonCanonicalImpls {
         if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) {
             return;
         }
-        let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else {
+        let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir_impl_item(impl_item.impl_item_id()).kind else {
             return;
         };
-        let body = cx.tcx.hir().body(impl_item_id);
+        let body = cx.tcx.hir_body(impl_item_id);
         let ExprKind::Block(block, ..) = body.value.kind else {
             return;
         };
diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
index 22116505a1c1..774a182d089f 100644
--- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
+++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
@@ -214,7 +214,7 @@ impl LazyInfo {
             && state.once_cell_sync_lazy.contains(&path_def_id)
         {
             let ty_span_no_args = path_span_without_args(path);
-            let body = cx.tcx.hir().body(body_id);
+            let body = cx.tcx.hir_body(body_id);
 
             // visit body to collect `Lazy::new` calls
             let mut new_fn_calls = FxIndexMap::default();
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 95403403217a..73c31b83b51f 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -136,7 +136,7 @@ impl PassByRefOrValue {
         }
 
         let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity();
-        let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id));
+        let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir_body(id));
 
         // Gather all the lifetimes found in the output type which may affect whether
         // `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
index 65fd312b3a09..bc5e8fd2c258 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
@@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock {
 /// any variable by ref.
 fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::Closure(Closure { body, def_id, kind, .. }) = expr.kind
-        && let body = cx.tcx.hir().body(*body)
+        && let body = cx.tcx.hir_body(*body)
         && matches!(
             kind,
             ClosureKind::Coroutine(CoroutineKind::Desugared(
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 91d023500ca6..54e507655e9c 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -90,7 +90,7 @@ fn find_innermost_closure<'tcx>(
     let mut data = None;
 
     while let ExprKind::Closure(closure) = expr.kind
-        && let body = cx.tcx.hir().body(closure.body)
+        && let body = cx.tcx.hir_body(closure.body)
         && {
             let mut visitor = ReturnVisitor;
             !visitor.visit_expr(body.value).is_break()
@@ -179,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                             // Like `async fn`, async closures are wrapped in an additional block
                             // to move all of the closure's arguments into the future.
 
-                            let async_closure_body = cx.tcx.hir().body(closure.body).value;
+                            let async_closure_body = cx.tcx.hir_body(closure.body).value;
                             let ExprKind::Block(block, _) = async_closure_body.kind else {
                                 return;
                             };
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index a1cf16e6ce9f..9f0ea84246dd 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -205,7 +205,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
             // Ensure this is not the final stmt, otherwise removing it would cause a compile error
             && let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id))
             && let ItemKind::Fn { body, .. } = item.kind
-            && let block = cx.tcx.hir().body(body).value
+            && let block = cx.tcx.hir_body(body).value
             && let ExprKind::Block(block, _) = block.kind
             && !is_inside_let_else(cx.tcx, expr)
             && let [.., final_stmt] = block.stmts
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 29914d4379fe..552135b15fd8 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -50,9 +50,9 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
     fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
         let mut map = FxHashMap::::default();
 
-        for id in cx.tcx.hir().items() {
+        for id in cx.tcx.hir_free_items() {
             if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl { .. })
-                && let item = cx.tcx.hir().item(id)
+                && let item = cx.tcx.hir_item(id)
                 && let ItemKind::Impl(Impl {
                     items,
                     of_trait,
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
index 3834087f7977..694ad4f6347b 100644
--- a/src/tools/clippy/clippy_lints/src/string_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -138,7 +138,7 @@ fn get_char_span<'tcx>(cx: &'_ LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Optio
 
 fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<'_>, msrv: &Msrv) {
     if let ExprKind::Closure(closure) = method_arg.kind
-        && let body = cx.tcx.hir().body(closure.body)
+        && let body = cx.tcx.hir_body(closure.body)
         && let Some(PatKind::Binding(_, binding, ..)) = body.params.first().map(|p| p.pat.kind)
     {
         let mut set_char_spans: Vec = Vec::new();
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index e9779d437d43..9326b2adaffb 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
             && let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id
             && let hir::Node::ImplItem(impl_item) = cx.tcx.hir_node_by_def_id(parent_fn)
             && let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind
-            && let body = cx.tcx.hir().body(body_id)
+            && let body = cx.tcx.hir_body(body_id)
             && let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id
             && let Some(trait_ref) = trait_ref_of_method(cx, parent_fn)
             && let trait_id = trait_ref.path.res.def_id()
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index 790e0965198d..cbf7b126632e 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
                 && let Some(Node::Item(Item {
                     kind: ItemKind::Trait(_, _, _, self_bounds, _),
                     ..
-                })) = cx.tcx.hir().get_if_local(*def_id)
+                })) = cx.tcx.hir_get_if_local(*def_id)
             {
                 if self_bounds_map.is_empty() {
                     for bound in *self_bounds {
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 2e97772407fd..004ad03e7085 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -96,10 +96,10 @@ fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
 
 fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option> {
     if let Some(did) = cx.qpath_res(qpath, id).opt_def_id()
-        && let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did)
+        && let Some(Node::GenericParam(generic_param)) = cx.tcx.hir_get_if_local(did)
         && let GenericParamKind::Type { synthetic, .. } = generic_param.kind
         && synthetic
-        && let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id)
+        && let Some(generics) = cx.tcx.hir_get_generics(id.owner.def_id)
         && let Some(pred) = generics.bounds_for_param(did.expect_local()).next()
     {
         Some(pred.bounds)
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 207f2ef4563a..16fe035802fa 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -326,9 +326,9 @@ impl UnconditionalRecursion {
                             .find(|item| {
                                 item.kind == AssocKind::Fn && item.def_id.is_local() && item.name == kw::Default
                             })
-                        && let Some(body_node) = cx.tcx.hir().get_if_local(assoc_item.def_id)
+                        && let Some(body_node) = cx.tcx.hir_get_if_local(assoc_item.def_id)
                         && let Some(body_id) = body_node.body_id()
-                        && let body = cx.tcx.hir().body(body_id)
+                        && let body = cx.tcx.hir_body(body_id)
                         // We don't want to keep it if it has conditional return.
                         && let [return_expr] = get_return_calls_in_body(body).as_slice()
                         && let ExprKind::Call(call_expr, _) = return_expr.kind
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index b3d269080930..c8e3c46f2f6f 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -245,7 +245,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
             // const and static items only need a safety comment if their body is an unsafe block, lint otherwise
             (&ItemKind::Const(.., body) | &ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => {
                 if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, body.hir_id) {
-                    let body = cx.tcx.hir().body(body);
+                    let body = cx.tcx.hir_body(body);
                     if !matches!(
                         body.value.kind, hir::ExprKind::Block(block, _)
                         if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
@@ -558,7 +558,7 @@ fn comment_start_before_item_in_mod(
                 // some_item /* comment */ unsafe impl T {}
                 // ^-------^ returns the end of this span
                 //         ^---------------^ finally checks comments in this range
-                let prev_item = cx.tcx.hir().item(parent_mod.item_ids[idx - 1]);
+                let prev_item = cx.tcx.hir_item(parent_mod.item_ids[idx - 1]);
                 if let Some(sp) = walk_span_to_context(prev_item.span, SyntaxContext::root()) {
                     return Some(sp.hi());
                 }
@@ -605,7 +605,7 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span
 fn get_body_search_span(cx: &LateContext<'_>) -> Option {
     let body = cx.enclosing_body?;
     let map = cx.tcx.hir();
-    let mut span = map.body(body).value.span;
+    let mut span = cx.tcx.hir_body(body).value.span;
     let mut maybe_global_var = false;
     for (_, node) in map.parent_iter(body.hir_id) {
         match node {
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 87478a120dd0..67ceac92dbc0 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -123,7 +123,7 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
         && let ty = cx.tcx.instantiate_bound_regions_with_erased(ret_ty)
         && ty.is_unit()
     {
-        let body = cx.tcx.hir().body(body);
+        let body = cx.tcx.hir_body(body);
         if let ExprKind::Block(block, _) = body.value.kind
             && block.expr.is_none()
             && let Some(stmt) = block.stmts.last()
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index 00b80e827d8a..87f184e13ce1 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
                     if let PatKind::Binding(_, binding_hir_id, ..) = local.pat.kind
                         && let Some(body_id) = cx.enclosing_body.as_ref()
                     {
-                        let body = cx.tcx.hir().body(*body_id);
+                        let body = cx.tcx.hir_body(*body_id);
 
                         // Collect variable usages
                         let mut visitor = UnitVariableCollector::new(binding_hir_id);
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 781f51aa9b07..d8305a628290 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             && assoc_item.fn_has_self_parameter
             && let ImplItemKind::Fn(.., body_id) = &impl_item.kind
             && (!cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api)
-            && let body = cx.tcx.hir().body(*body_id)
+            && let body = cx.tcx.hir_body(*body_id)
             && let [self_param, ..] = body.params
             && !is_local_used(cx, body, self_param.pat.hir_id)
             && !contains_todo(cx, body)
diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
index 9b9a2ffbbc80..f870eb71e19b 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult {
 
 fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
     if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
-        let body = cx.tcx.hir().body(body_id);
+        let body = cx.tcx.hir_body(body_id);
         let typeck = cx.tcx.typeck(impl_item.owner_id.def_id);
         let mut result = Vec::new();
         let _: Option = for_each_expr(cx, body.value, |e| {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 6bad78cf8718..ce489054e16e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -637,9 +637,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
     }
 
     fn body(&self, body_id: &Binding) {
-        let expr = self.cx.tcx.hir().body(body_id.value).value;
+        let expr = self.cx.tcx.hir_body(body_id.value).value;
         bind!(self, expr);
-        chain!(self, "{expr} = &cx.tcx.hir().body({body_id}).value");
+        chain!(self, "{expr} = &cx.tcx.hir_body({body_id}).value");
         self.expr(expr);
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
index eaeb754a23f1..2e6fb7c4ce4d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
         if let ExprKind::Call(func, [call_cx, call_lint, call_sp, call_msg, call_f]) = expr.kind
             && is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"])
             && let ExprKind::Closure(&Closure { body, .. }) = call_f.kind
-            && let body = cx.tcx.hir().body(body)
+            && let body = cx.tcx.hir_body(body)
             && let only_expr = peel_blocks_with_stmt(body.value)
             && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind
             && let ExprKind::Path(..) = recv.kind
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 08c178ed229f..252ac5e67682 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -37,7 +37,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
                 ty::TypingEnv::post_analysis(cx.tcx, item.owner_id),
                 cx.tcx.typeck(item.owner_id),
             )
-            .eval_simple(cx.tcx.hir().body(body_id).value)
+            .eval_simple(cx.tcx.hir_body(body_id).value)
             && let Some(path) = path
                 .iter()
                 .map(|x| {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index dac1951489ca..315c83507d07 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
             if is_lint_ref_type(cx, ty) {
                 check_invalid_clippy_version_attribute(cx, item);
 
-                let expr = &cx.tcx.hir().body(body_id).value;
+                let expr = &cx.tcx.hir_body(body_id).value;
                 let fields = if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
                     && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind
                 {
diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
index 05f856507697..30fdf22fdbb0 100644
--- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
@@ -47,7 +47,6 @@ declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
 
 impl LateLintPass<'_> for ZeroRepeatSideEffects {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &rustc_hir::Expr<'_>) {
-        let hir_map = cx.tcx.hir();
         if let Some(args) = VecArgs::hir(cx, expr)
             && let VecArgs::Repeat(inner_expr, len) = args
             && let ExprKind::Lit(l) = len.kind
@@ -62,7 +61,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
         // sessions).
         else if let ExprKind::Repeat(inner_expr, const_arg) = expr.kind
             && let ConstArgKind::Anon(anon_const) = const_arg.kind
-            && let length_expr = hir_map.body(anon_const.body).value
+            && let length_expr = cx.tcx.hir_body(anon_const.body).value
             && !length_expr.span.from_expansion()
             && let ExprKind::Lit(literal) = length_expr.kind
             && let LitKind::Int(Pu128(0), _) = literal.node
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 59aaaa3d9fb7..4f48fb3b8a96 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -192,7 +192,7 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
             },
             ExprKind::Closure(&Closure { body, .. }) => (
                 Pat::Str(""),
-                expr_search_pat_inner(tcx, tcx.hir().body(body).value, outer_span).1,
+                expr_search_pat_inner(tcx, tcx.hir_body(body).value, outer_span).1,
             ),
             ExprKind::Block(
                 Block {
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index db82c458f703..4f707e34abf9 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -455,7 +455,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
                     Some(val)
                 }
             },
-            PatExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(*body).value),
+            PatExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir_body(*body).value),
             PatExprKind::Path(qpath) => self.qpath(qpath, pat_expr.hir_id),
         }
     }
@@ -483,7 +483,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
     /// Simple constant folding: Insert an expression, get a constant or none.
     fn expr(&self, e: &Expr<'_>) -> Option> {
         match e.kind {
-            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir_body(body).value),
             ExprKind::DropTemps(e) => self.expr(e),
             ExprKind::Path(ref qpath) => self.qpath(qpath, e.hir_id),
             ExprKind::Block(block, _) => self.block(block),
@@ -550,7 +550,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
     /// leaves the local crate.
     pub fn eval_is_empty(&self, e: &Expr<'_>) -> Option {
         match e.kind {
-            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.eval_is_empty(self.tcx.hir().body(body).value),
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.eval_is_empty(self.tcx.hir_body(body).value),
             ExprKind::DropTemps(e) => self.eval_is_empty(e),
             ExprKind::Path(ref qpath) => {
                 if !self
@@ -645,7 +645,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
             Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => {
                 // Check if this constant is based on `cfg!(..)`,
                 // which is NOT constant for our purposes.
-                if let Some(node) = self.tcx.hir().get_if_local(def_id)
+                if let Some(node) = self.tcx.hir_get_if_local(def_id)
                     && let Node::Item(Item {
                         kind: ItemKind::Const(.., body_id),
                         ..
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 4bbf28115a68..9ee30094d608 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -273,8 +273,8 @@ impl HirEqInterExpr<'_, '_, '_> {
             self.inner.cx.tcx.typeck_body(right),
         ));
         let res = self.eq_expr(
-            self.inner.cx.tcx.hir().body(left).value,
-            self.inner.cx.tcx.hir().body(right).value,
+            self.inner.cx.tcx.hir_body(left).value,
+            self.inner.cx.tcx.hir_body(right).value,
         );
         self.inner.maybe_typeck_results = old_maybe_typeck_results;
         res
@@ -906,7 +906,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             }) => {
                 std::mem::discriminant(&capture_clause).hash(&mut self.s);
                 // closures inherit TypeckResults
-                self.hash_expr(self.cx.tcx.hir().body(body).value);
+                self.hash_expr(self.cx.tcx.hir_body(body).value);
             },
             ExprKind::ConstBlock(ref l_id) => {
                 self.hash_body(l_id.body);
@@ -1316,7 +1316,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     pub fn hash_body(&mut self, body_id: BodyId) {
         // swap out TypeckResults when hashing a body
         let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id));
-        self.hash_expr(self.cx.tcx.hir().body(body_id).value);
+        self.hash_expr(self.cx.tcx.hir_body(body_id).value);
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 79cc50665800..c4ba4c94c946 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -652,8 +652,6 @@ fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol)
 }
 
 fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symbol) -> Vec {
-    let hir = tcx.hir();
-
     let root_mod;
     let item_kind = match tcx.hir_node_by_def_id(local_id) {
         Node::Crate(r#mod) => {
@@ -677,7 +675,7 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb
         ItemKind::Mod(r#mod) => r#mod
             .item_ids
             .iter()
-            .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
+            .filter_map(|&item_id| res(tcx.hir_item(item_id).ident, item_id.owner_id))
             .collect(),
         ItemKind::Impl(r#impl) => r#impl
             .items
@@ -944,7 +942,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
         ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
         ExprKind::Repeat(x, len) => {
             if let ConstArgKind::Anon(anon_const) = len.kind
-                && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
+                && let ExprKind::Lit(const_lit) = cx.tcx.hir_body(anon_const.body).value.kind
                 && let LitKind::Int(v, _) = const_lit.node
                 && v <= 32
                 && is_default_equivalent(cx, x)
@@ -974,7 +972,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
             ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
             ExprKind::Repeat(_, len) => {
                 if let ConstArgKind::Anon(anon_const) = len.kind
-                    && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
+                    && let ExprKind::Lit(const_lit) = cx.tcx.hir_body(anon_const.body).value.kind
                     && let LitKind::Int(v, _) = const_lit.node
                 {
                     return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
@@ -1424,7 +1422,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
         | Node::ImplItem(&ImplItem {
             kind: ImplItemKind::Fn(_, eid),
             ..
-        }) => match cx.tcx.hir().body(eid).value.kind {
+        }) => match cx.tcx.hir_body(eid).value.kind {
             ExprKind::Block(block, _) => Some(block),
             _ => None,
         },
@@ -2067,7 +2065,7 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t
                 ..
             },
             _,
-        ) = tcx.hir().body(body).value.kind
+        ) = tcx.hir_body(body).value.kind
         {
             return Some(expr);
         }
@@ -2175,7 +2173,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>)
         ExprKind::Closure(&Closure { body, fn_decl, .. })
             if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) =>
         {
-            is_body_identity_function(cx, cx.tcx.hir().body(body))
+            is_body_identity_function(cx, cx.tcx.hir_body(body))
         },
         ExprKind::Path(QPath::Resolved(_, path))
             if path.segments.iter().all(|seg| seg.infer_args)
@@ -2197,7 +2195,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>)
 /// errors.
 pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match expr.kind {
-        ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
+        ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir_body(body)),
         _ => path_def_id(cx, expr).is_some_and(|id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
     }
 }
@@ -2552,9 +2550,9 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
         Entry::Occupied(entry) => f(entry.get()),
         Entry::Vacant(entry) => {
             let mut names = Vec::new();
-            for id in tcx.hir().module_items(module) {
+            for id in tcx.hir_module_free_items(module) {
                 if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
-                    && let item = tcx.hir().item(id)
+                    && let item = tcx.hir_item(id)
                     && let ItemKind::Const(ty, _generics, _body) = item.kind
                 {
                     if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
@@ -2932,7 +2930,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU
         #[allow(unreachable_patterns)]
         Some(ControlFlow::Break(_)) => unreachable!("type of node is ControlFlow"),
         None => ExprUseCtxt {
-            node: Node::Crate(cx.tcx.hir().root_module()),
+            node: Node::Crate(cx.tcx.hir_root_module()),
             child_id: HirId::INVALID,
             adjustments: &[],
             is_ty_unified: true,
diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs
index 273c1b0defab..360c6251a57c 100644
--- a/src/tools/clippy/clippy_utils/src/ptr.rs
+++ b/src/tools/clippy/clippy_utils/src/ptr.rs
@@ -13,7 +13,7 @@ pub fn get_spans(
     idx: usize,
     replacements: &[(&'static str, &'static str)],
 ) -> Option)>> {
-    if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
+    if let Some(body) = opt_body_id.map(|id| cx.tcx.hir_body(id)) {
         if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(body.params[idx].pat).kind {
             extract_clone_suggestions(cx, binding_id, replacements, body)
         } else {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 088abd7c4791..d5e0e2e3436e 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -809,7 +809,7 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
         fn_decl, def_id, body, ..
     }) = closure.kind
     {
-        let closure_body = cx.tcx.hir().body(body);
+        let closure_body = cx.tcx.hir_body(body);
         // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
         // a type annotation is present if param `kind` is different from `TyKind::Infer`
         let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 70910f5bf52d..9b35ecee1dd1 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -296,7 +296,7 @@ where
 
 /// Checks if the given resolved path is used in the given body.
 pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
-    for_each_expr(cx, cx.tcx.hir().body(body).value, |e| {
+    for_each_expr(cx, cx.tcx.hir_body(body).value, |e| {
         if let ExprKind::Path(p) = &e.kind {
             if cx.qpath_res(p, e.hir_id) == res {
                 return ControlFlow::Break(());
@@ -456,7 +456,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
             }
         }
         fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
-            if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind
+            if let ItemKind::Impl(i) = &self.cx.tcx.hir_item(id).kind
                 && i.safety.is_unsafe()
             {
                 ControlFlow::Break(())
diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout
index 6bf48d5ba4ef..54325f9776c5 100644
--- a/src/tools/clippy/tests/ui/author/blocks.stdout
+++ b/src/tools/clippy/tests/ui/author/blocks.stdout
@@ -42,10 +42,10 @@ if let ExprKind::Block(block, None) = expr.kind
 }
 if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::CoroutineClosure(CoroutineDesugaring::Async), .. } = expr.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl.output
-    && expr1 = &cx.tcx.hir().body(body_id).value
+    && expr1 = &cx.tcx.hir_body(body_id).value
     && let ExprKind::Closure { capture_clause: CaptureBy::Ref, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl1.output
-    && expr2 = &cx.tcx.hir().body(body_id1).value
+    && expr2 = &cx.tcx.hir_body(body_id1).value
     && let ExprKind::Block(block, None) = expr2.kind
     && block.stmts.is_empty()
     && let Some(trailing_expr) = block.expr
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
index 66caf382d897..3186d0cbc276 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
+++ b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
@@ -2,7 +2,7 @@ if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::Closure { capture_clause: CaptureBy::Ref, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::Closure, .. } = init.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl.output
-    && expr = &cx.tcx.hir().body(body_id).value
+    && expr = &cx.tcx.hir_body(body_id).value
     && let ExprKind::Block(block, None) = expr.kind
     && block.stmts.len() == 1
     && let StmtKind::Semi(e) = block.stmts[0].kind
diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout
index 1a608734ada9..f2c6b3f807f1 100644
--- a/src/tools/clippy/tests/ui/author/repeat.stdout
+++ b/src/tools/clippy/tests/ui/author/repeat.stdout
@@ -2,7 +2,7 @@ if let ExprKind::Repeat(value, length) = expr.kind
     && let ExprKind::Lit(ref lit) = value.kind
     && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
     && let ConstArgKind::Anon(anon_const) = length.kind
-    && expr1 = &cx.tcx.hir().body(anon_const.body).value
+    && expr1 = &cx.tcx.hir_body(anon_const.body).value
     && let ExprKind::Lit(ref lit1) = expr1.kind
     && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node
 {
diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs
index c6bec4f77a06..84f6970c83a0 100644
--- a/tests/ui-fulldeps/obtain-borrowck.rs
+++ b/tests/ui-fulldeps/obtain-borrowck.rs
@@ -67,7 +67,6 @@ impl rustc_driver::Callbacks for CompilerCalls {
     fn after_analysis<'tcx>(&mut self, _compiler: &Compiler, tcx: TyCtxt<'tcx>) -> Compilation {
         tcx.sess.dcx().abort_if_errors();
         // Collect definition ids of MIR bodies.
-        let hir = tcx.hir();
         let mut bodies = Vec::new();
 
         let crate_items = tcx.hir_crate_items(());
@@ -79,7 +78,7 @@ impl rustc_driver::Callbacks for CompilerCalls {
 
         for id in crate_items.trait_items() {
             if matches!(tcx.def_kind(id.owner_id), DefKind::AssocFn) {
-                let trait_item = hir.trait_item(id);
+                let trait_item = tcx.hir_trait_item(id);
                 if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind {
                     if let rustc_hir::TraitFn::Provided(_) = trait_fn {
                         bodies.push(trait_item.owner_id);

From 661f99ba03738f1ee87888342aef920f3c0f7f48 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 14:42:01 +1100
Subject: [PATCH 101/158] Overhaul the `intravisit::Map` trait.

First of all, note that `Map` has three different relevant meanings.
- The `intravisit::Map` trait.
- The `map::Map` struct.
- The `NestedFilter::Map` associated type.

The `intravisit::Map` trait is impl'd twice.
- For `!`, where the methods are all unreachable.
- For `map::Map`, which gets HIR stuff from the `TyCtxt`.

As part of getting rid of `map::Map`, this commit changes `impl
intravisit::Map for map::Map` to `impl intravisit::Map for TyCtxt`. It's
fairly straightforward except various things are renamed, because the
existing names would no longer have made sense.

- `trait intravisit::Map` becomes `trait intravisit::HirTyCtxt`, so named
  because it gets some HIR stuff from a `TyCtxt`.
- `NestedFilter::Map` assoc type becomes `NestedFilter::MaybeTyCtxt`,
  because it's always `!` or `TyCtxt`.
- `Visitor::nested_visit_map` becomes `Visitor::maybe_tcx`.

I deliberately made the new trait and associated type names different to
avoid the old `type Map: Map` situation, which I found confusing. We now
have `type MaybeTyCtxt: HirTyCtxt`.
---
 .../src/diagnostics/conflict_errors.rs        | 16 ++---
 .../src/diagnostics/explain_borrow.rs         |  4 +-
 .../src/diagnostics/move_errors.rs            | 10 +--
 compiler/rustc_hir/src/intravisit.rs          | 66 ++++++++++---------
 .../rustc_hir_analysis/src/check/check.rs     |  4 +-
 compiler/rustc_hir_analysis/src/collect.rs    |  4 +-
 .../rustc_hir_analysis/src/collect/dump.rs    |  4 +-
 .../src/collect/resolve_bound_vars.rs         |  4 +-
 .../src/collect/type_of/opaque.rs             |  8 +--
 compiler/rustc_hir_pretty/src/lib.rs          | 18 ++---
 .../rustc_hir_typeck/src/fn_ctxt/checks.rs    |  4 +-
 .../rustc_incremental/src/assert_dep_graph.rs |  4 +-
 .../src/persist/dirty_clean.rs                |  4 +-
 compiler/rustc_lint/src/late.rs               |  4 +-
 compiler/rustc_lint/src/levels.rs             |  8 +--
 compiler/rustc_metadata/src/rmeta/encoder.rs  |  3 +-
 compiler/rustc_middle/src/hir/map.rs          | 32 ++++-----
 .../rustc_middle/src/hir/nested_filter.rs     | 10 +--
 .../rustc_mir_transform/src/coverage/mod.rs   |  9 ++-
 compiler/rustc_passes/src/check_attr.rs       |  4 +-
 compiler/rustc_passes/src/hir_id_validator.rs |  4 +-
 compiler/rustc_passes/src/lib_features.rs     |  4 +-
 compiler/rustc_passes/src/loops.rs            |  4 +-
 compiler/rustc_passes/src/naked_functions.rs  |  4 +-
 compiler/rustc_passes/src/stability.rs        | 12 ++--
 .../error_reporting/infer/need_type_info.rs   |  4 +-
 .../infer/nice_region_error/find_anon_type.rs |  9 ++-
 .../trait_impl_difference.rs                  |  4 +-
 .../src/error_reporting/traits/mod.rs         |  4 +-
 src/librustdoc/clean/inline.rs                |  2 +-
 src/librustdoc/core.rs                        |  4 +-
 src/librustdoc/doctest/rust.rs                |  6 +-
 src/librustdoc/html/render/span_map.rs        |  4 +-
 src/librustdoc/scrape_examples.rs             |  4 +-
 src/librustdoc/visit_ast.rs                   |  4 +-
 src/tools/clippy/clippy_lints/src/derive.rs   |  4 +-
 src/tools/clippy/clippy_lints/src/doc/mod.rs  |  4 +-
 .../src/extra_unused_type_parameters.rs       |  4 +-
 .../clippy/clippy_lints/src/from_over_into.rs |  4 +-
 .../clippy_lints/src/implicit_hasher.rs       |  4 +-
 .../clippy_lints/src/index_refutable_slice.rs |  4 +-
 .../clippy/clippy_lints/src/lifetimes.rs      |  8 +--
 .../clippy/clippy_lints/src/loops/utils.rs    |  4 +-
 .../src/loops/while_let_on_iterator.rs        |  8 +--
 .../src/methods/needless_collect.rs           |  4 +-
 .../src/methods/option_map_unwrap_or.rs       |  8 +--
 .../clippy/clippy_lints/src/methods/utils.rs  |  4 +-
 .../src/mutable_debug_assertion.rs            |  4 +-
 src/tools/clippy/clippy_lints/src/ptr.rs      |  4 +-
 .../src/redundant_closure_call.rs             |  4 +-
 .../src/unconditional_recursion.rs            |  7 +-
 .../clippy/clippy_lints/src/unused_async.rs   |  4 +-
 .../clippy_lints/src/unused_peekable.rs       |  4 +-
 src/tools/clippy/clippy_lints/src/unwrap.rs   |  4 +-
 .../internal_lints/lint_without_lint_pass.rs  |  2 +-
 .../clippy_lints/src/zombie_processes.rs      |  4 +-
 src/tools/clippy/clippy_utils/src/lib.rs      |  4 +-
 src/tools/clippy/clippy_utils/src/usage.rs    |  4 +-
 src/tools/clippy/clippy_utils/src/visitors.rs | 20 +++---
 59 files changed, 208 insertions(+), 210 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 4428d2246a16..59c76cb7f2bb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -348,13 +348,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             expr: Option<&'hir hir::Expr<'hir>>,
             pat: Option<&'hir hir::Pat<'hir>>,
             parent_pat: Option<&'hir hir::Pat<'hir>>,
-            hir: rustc_middle::hir::map::Map<'hir>,
+            tcx: TyCtxt<'hir>,
         }
         impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
             type NestedFilter = OnlyBodies;
 
-            fn nested_visit_map(&mut self) -> Self::Map {
-                self.hir
+            fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                self.tcx
             }
 
             fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
@@ -396,7 +396,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 expr: None,
                 pat: None,
                 parent_pat: None,
-                hir,
+                tcx: self.infcx.tcx,
             };
             finder.visit_expr(expr);
             if let Some(span) = span
@@ -2455,7 +2455,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let body_expr = tcx.hir_body(body_id).value;
 
         struct ClosureFinder<'hir> {
-            hir: rustc_middle::hir::map::Map<'hir>,
+            tcx: TyCtxt<'hir>,
             borrow_span: Span,
             res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
             /// The path expression with the `borrow_span` span
@@ -2464,8 +2464,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
             type NestedFilter = OnlyBodies;
 
-            fn nested_visit_map(&mut self) -> Self::Map {
-                self.hir
+            fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                self.tcx
             }
 
             fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
@@ -2491,7 +2491,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
         // Find the closure that most tightly wraps `capture_kind_span`
         let mut finder =
-            ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
+            ClosureFinder { tcx, borrow_span: capture_kind_span, res: None, error_path: None };
         finder.visit_expr(body_expr);
         let Some((closure_expr, closure)) = finder.res else { return };
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 976d14bb245d..a88b27f24767 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -256,8 +256,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
 
                         impl<'hir> rustc_hir::intravisit::Visitor<'hir> for FindLetExpr<'hir> {
                             type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
-                            fn nested_visit_map(&mut self) -> Self::Map {
-                                self.tcx.hir()
+                            fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                                self.tcx
                             }
                             fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
                                 if let hir::ExprKind::If(cond, _conseq, _alt)
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index c5449952f993..38f22473edfa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -7,7 +7,7 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::{self as hir, CaptureBy, ExprKind, HirId, Node};
 use rustc_middle::bug;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
 use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
 use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
@@ -690,7 +690,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         /// make it bind by reference instead (if possible)
         struct BindingFinder<'tcx> {
             typeck_results: &'tcx ty::TypeckResults<'tcx>,
-            hir: rustc_middle::hir::map::Map<'tcx>,
+            tcx: TyCtxt<'tcx>,
             /// Input: the span of the pattern we're finding bindings in
             pat_span: Span,
             /// Input: the spans of the bindings we're providing suggestions for
@@ -709,8 +709,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         impl<'tcx> Visitor<'tcx> for BindingFinder<'tcx> {
             type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
 
-            fn nested_visit_map(&mut self) -> Self::Map {
-                self.hir
+            fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                self.tcx
             }
 
             fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
@@ -782,7 +782,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
         let mut finder = BindingFinder {
             typeck_results,
-            hir,
+            tcx: self.infcx.tcx,
             pat_span,
             binding_spans,
             found_pat: false,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index f57d1a5cc2ca..949f8daa4dcf 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -18,7 +18,7 @@
 //!    within one another.
 //!    - Example: Examine each expression to look for its type and do some check or other.
 //!    - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
-//!      `nested_filter::OnlyBodies` (and implement `nested_visit_map`), and use
+//!      `nested_filter::OnlyBodies` (and implement `maybe_tcx`), and use
 //!      `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your
 //!      `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke
 //!      `intravisit::walk_expr()` to keep walking the subparts).
@@ -30,7 +30,7 @@
 //!    - Example: Lifetime resolution, which wants to bring lifetimes declared on the
 //!      impl into scope while visiting the impl-items, and then back out again.
 //!    - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
-//!      `nested_filter::All` (and implement `nested_visit_map`). Walk your crate with
+//!      `nested_filter::All` (and implement `maybe_tcx`). Walk your crate with
 //!      `tcx.hir().walk_toplevel_module(visitor)` invoked on `tcx.hir().krate()`.
 //!    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
 //!    - Pro: Preserves nesting information
@@ -106,41 +106,43 @@ impl<'a> FnKind<'a> {
     }
 }
 
-/// An abstract representation of the HIR `rustc_middle::hir::map::Map`.
-pub trait Map<'hir> {
+/// HIR things retrievable from `TyCtxt`, avoiding an explicit dependence on
+/// `TyCtxt`. The only impls are for `!` (where these functions are never
+/// called) and `TyCtxt` (in `rustc_middle`).
+pub trait HirTyCtxt<'hir> {
     /// Retrieves the `Node` corresponding to `id`.
     fn hir_node(&self, hir_id: HirId) -> Node<'hir>;
-    fn body(&self, id: BodyId) -> &'hir Body<'hir>;
-    fn item(&self, id: ItemId) -> &'hir Item<'hir>;
-    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
-    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
-    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
+    fn hir_body(&self, id: BodyId) -> &'hir Body<'hir>;
+    fn hir_item(&self, id: ItemId) -> &'hir Item<'hir>;
+    fn hir_trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
+    fn hir_impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+    fn hir_foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
 }
 
-// Used when no map is actually available, forcing manual implementation of nested visitors.
-impl<'hir> Map<'hir> for ! {
+// Used when no tcx is actually available, forcing manual implementation of nested visitors.
+impl<'hir> HirTyCtxt<'hir> for ! {
     fn hir_node(&self, _: HirId) -> Node<'hir> {
         unreachable!();
     }
-    fn body(&self, _: BodyId) -> &'hir Body<'hir> {
+    fn hir_body(&self, _: BodyId) -> &'hir Body<'hir> {
         unreachable!();
     }
-    fn item(&self, _: ItemId) -> &'hir Item<'hir> {
+    fn hir_item(&self, _: ItemId) -> &'hir Item<'hir> {
         unreachable!();
     }
-    fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
+    fn hir_trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
         unreachable!();
     }
-    fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
+    fn hir_impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
         unreachable!();
     }
-    fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
+    fn hir_foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
         unreachable!();
     }
 }
 
 pub mod nested_filter {
-    use super::Map;
+    use super::HirTyCtxt;
 
     /// Specifies what nested things a visitor wants to visit. By "nested
     /// things", we are referring to bits of HIR that are not directly embedded
@@ -155,7 +157,7 @@ pub mod nested_filter {
     /// See the comments at [`rustc_hir::intravisit`] for more details on the overall
     /// visit strategy.
     pub trait NestedFilter<'hir> {
-        type Map: Map<'hir>;
+        type MaybeTyCtxt: HirTyCtxt<'hir>;
 
         /// Whether the visitor visits nested "item-like" things.
         /// E.g., item, impl-item.
@@ -171,10 +173,10 @@ pub mod nested_filter {
     ///
     /// Use this if you are only walking some particular kind of tree
     /// (i.e., a type, or fn signature) and you don't want to thread a
-    /// HIR map around.
+    /// `tcx` around.
     pub struct None(());
     impl NestedFilter<'_> for None {
-        type Map = !;
+        type MaybeTyCtxt = !;
         const INTER: bool = false;
         const INTRA: bool = false;
     }
@@ -199,18 +201,18 @@ use nested_filter::NestedFilter;
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
 pub trait Visitor<'v>: Sized {
-    // This type should not be overridden, it exists for convenient usage as `Self::Map`.
-    type Map: Map<'v> = >::Map;
+    // This type should not be overridden, it exists for convenient usage as `Self::MaybeTyCtxt`.
+    type MaybeTyCtxt: HirTyCtxt<'v> = >::MaybeTyCtxt;
 
     ///////////////////////////////////////////////////////////////////////////
     // Nested items.
 
     /// Override this type to control which nested HIR are visited; see
     /// [`NestedFilter`] for details. If you override this type, you
-    /// must also override [`nested_visit_map`](Self::nested_visit_map).
+    /// must also override [`maybe_tcx`](Self::maybe_tcx).
     ///
     /// **If for some reason you want the nested behavior, but don't
-    /// have a `Map` at your disposal:** then override the
+    /// have a `tcx` at your disposal:** then override the
     /// `visit_nested_XXX` methods. If a new `visit_nested_XXX` variant is
     /// added in the future, it will cause a panic which can be detected
     /// and fixed appropriately.
@@ -222,9 +224,9 @@ pub trait Visitor<'v>: Sized {
 
     /// If `type NestedFilter` is set to visit nested items, this method
     /// must also be overridden to provide a map to retrieve nested items.
-    fn nested_visit_map(&mut self) -> Self::Map {
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
         panic!(
-            "nested_visit_map must be implemented or consider using \
+            "maybe_tcx must be implemented or consider using \
             `type NestedFilter = nested_filter::None` (the default)"
         );
     }
@@ -236,10 +238,10 @@ pub trait Visitor<'v>: Sized {
     /// "deep" visit patterns described at
     /// [`rustc_hir::intravisit`]. The only reason to override
     /// this method is if you want a nested pattern but cannot supply a
-    /// [`Map`]; see `nested_visit_map` for advice.
+    /// `TyCtxt`; see `maybe_tcx` for advice.
     fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
-            let item = self.nested_visit_map().item(id);
+            let item = self.maybe_tcx().hir_item(id);
             try_visit!(self.visit_item(item));
         }
         Self::Result::output()
@@ -250,7 +252,7 @@ pub trait Visitor<'v>: Sized {
     /// method.
     fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
-            let item = self.nested_visit_map().trait_item(id);
+            let item = self.maybe_tcx().hir_trait_item(id);
             try_visit!(self.visit_trait_item(item));
         }
         Self::Result::output()
@@ -261,7 +263,7 @@ pub trait Visitor<'v>: Sized {
     /// method.
     fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
-            let item = self.nested_visit_map().impl_item(id);
+            let item = self.maybe_tcx().hir_impl_item(id);
             try_visit!(self.visit_impl_item(item));
         }
         Self::Result::output()
@@ -272,7 +274,7 @@ pub trait Visitor<'v>: Sized {
     /// method.
     fn visit_nested_foreign_item(&mut self, id: ForeignItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
-            let item = self.nested_visit_map().foreign_item(id);
+            let item = self.maybe_tcx().hir_foreign_item(id);
             try_visit!(self.visit_foreign_item(item));
         }
         Self::Result::output()
@@ -283,7 +285,7 @@ pub trait Visitor<'v>: Sized {
     /// `Self::NestedFilter`.
     fn visit_nested_body(&mut self, id: BodyId) -> Self::Result {
         if Self::NestedFilter::INTRA {
-            let body = self.nested_visit_map().body(id);
+            let body = self.maybe_tcx().hir_body(id);
             try_visit!(self.visit_body(body));
         }
         Self::Result::output()
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0d33aaa5d84f..bc0fd4b705d0 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -435,8 +435,8 @@ fn best_definition_site_of_opaque<'tcx>(
     impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         type NestedFilter = nested_filter::All;
         type Result = ControlFlow<(Span, LocalDefId)>;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.tcx
         }
         fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
             if let hir::ExprKind::Closure(closure) = ex.kind {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 6b430df8ed2c..75ea207a06bb 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -277,8 +277,8 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
 impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index b4ba4d11221d..63c445fa6a3d 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -63,8 +63,8 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
             impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
                 type NestedFilter = nested_filter::All;
 
-                fn nested_visit_map(&mut self) -> Self::Map {
-                    self.tcx.hir()
+                fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                    self.tcx
                 }
 
                 fn visit_anon_const(&mut self, c: &'tcx rustc_hir::AnonConst) {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 6bf0498a8b0c..5a8a2f1fe28e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -422,8 +422,8 @@ enum NonLifetimeBinderAllowed {
 impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index e2b9fe0f9f72..88d4acbdd8dc 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -298,8 +298,8 @@ impl TaitConstraintLocator<'_> {
 impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         if let hir::ExprKind::Closure(closure) = ex.kind {
@@ -441,8 +441,8 @@ impl RpitConstraintChecker<'_> {
 impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         if let hir::ExprKind::Closure(closure) = ex.kind {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 57df3127a025..34124a6aa11a 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -24,8 +24,8 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::{FileName, Ident, Span, Symbol, kw};
 use {rustc_ast as ast, rustc_hir as hir};
 
-pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
-    to_string(&map, |s| s.print_node(map.hir_node(hir_id)))
+pub fn id_to_string(cx: &dyn rustc_hir::intravisit::HirTyCtxt<'_>, hir_id: HirId) -> String {
+    to_string(&cx, |s| s.print_node(cx.hir_node(hir_id)))
 }
 
 pub enum AnnNode<'a> {
@@ -54,15 +54,15 @@ pub trait PpAnn {
     fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
 }
 
-impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
+impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> {
     fn nested(&self, state: &mut State<'_>, nested: Nested) {
         match nested {
-            Nested::Item(id) => state.print_item(self.item(id)),
-            Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
-            Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
-            Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
-            Nested::Body(id) => state.print_expr(self.body(id).value),
-            Nested::BodyParamPat(id, i) => state.print_pat(self.body(id).params[i].pat),
+            Nested::Item(id) => state.print_item(self.hir_item(id)),
+            Nested::TraitItem(id) => state.print_trait_item(self.hir_trait_item(id)),
+            Nested::ImplItem(id) => state.print_impl_item(self.hir_impl_item(id)),
+            Nested::ForeignItem(id) => state.print_foreign_item(self.hir_foreign_item(id)),
+            Nested::Body(id) => state.print_expr(self.hir_body(id).value),
+            Nested::BodyParamPat(id, i) => state.print_pat(self.hir_body(id).params[i].pat),
         }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 7963688203a0..c0af5ea7bbff 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2725,8 +2725,8 @@ struct FindClosureArg<'tcx> {
 impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
     type NestedFilter = rustc_middle::hir::nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 569034954c3d..c2f9ebc5262a 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -174,8 +174,8 @@ impl<'tcx> IfThisChanged<'tcx> {
 impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 30590bf5d3cb..a95599e7a860 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -455,8 +455,8 @@ impl<'tcx> FindAllAttrs<'tcx> {
 impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_attribute(&mut self, attr: &'tcx Attribute) {
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index c0d3df17d77b..f17570e4a81f 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -84,8 +84,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
     /// Because lints are scoped lexically, we want to walk nested
     /// items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.context.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.context.tcx
     }
 
     fn visit_nested_body(&mut self, body_id: hir::BodyId) {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 5a4ed68440a3..7e13205bbf1e 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -270,8 +270,8 @@ impl<'tcx> LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
 impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.provider.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.provider.tcx
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
@@ -365,8 +365,8 @@ impl<'tcx> LintLevelMaximum<'tcx> {
 impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     /// FIXME(blyxyas): In a future revision, we should also graph #![allow]s,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 3ca4b3e235ff..1ac2f6e81e58 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2410,7 +2410,6 @@ pub(crate) fn provide(providers: &mut Providers) {
 /// use a different method for pretty-printing. Ideally this function
 /// should only ever be used as a fallback.
 pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: LocalDefId) -> String {
-    let hir = tcx.hir();
     let value = body.value;
 
     #[derive(PartialEq, Eq)]
@@ -2467,7 +2466,7 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: Loc
 
         // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
         // other formatting artifacts.
-        Literal | Simple => id_to_string(&hir, body.id().hir_id),
+        Literal | Simple => id_to_string(&tcx, body.id().hir_id),
 
         // FIXME: Omit the curly braces if the enclosing expression is an array literal
         //        with a repeated element (an `ExprKind::Repeat`) as in such case it
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 737b491ef573..9bd35fdd6f0b 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -1034,35 +1034,35 @@ impl<'hir> Map<'hir> {
     }
 }
 
-impl<'hir> intravisit::Map<'hir> for Map<'hir> {
-    fn hir_node(&self, hir_id: HirId) -> Node<'hir> {
-        self.tcx.hir_node(hir_id)
+impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> {
+    fn hir_node(&self, hir_id: HirId) -> Node<'tcx> {
+        (*self).hir_node(hir_id)
     }
 
-    fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        self.tcx.hir_body(id)
+    fn hir_body(&self, id: BodyId) -> &'tcx Body<'tcx> {
+        (*self).hir_body(id)
     }
 
-    fn item(&self, id: ItemId) -> &'hir Item<'hir> {
-        self.tcx.hir_item(id)
+    fn hir_item(&self, id: ItemId) -> &'tcx Item<'tcx> {
+        (*self).hir_item(id)
     }
 
-    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        self.tcx.hir_trait_item(id)
+    fn hir_trait_item(&self, id: TraitItemId) -> &'tcx TraitItem<'tcx> {
+        (*self).hir_trait_item(id)
     }
 
-    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        self.tcx.hir_impl_item(id)
+    fn hir_impl_item(&self, id: ImplItemId) -> &'tcx ImplItem<'tcx> {
+        (*self).hir_impl_item(id)
     }
 
-    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        self.tcx.hir_foreign_item(id)
+    fn hir_foreign_item(&self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
+        (*self).hir_foreign_item(id)
     }
 }
 
 impl<'tcx> pprust_hir::PpAnn for TyCtxt<'tcx> {
     fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
-        pprust_hir::PpAnn::nested(&(&self.hir() as &dyn intravisit::Map<'_>), state, nested)
+        pprust_hir::PpAnn::nested(&(self as &dyn intravisit::HirTyCtxt<'_>), state, nested)
     }
 }
 
@@ -1349,8 +1349,8 @@ impl<'tcx> ItemCollector<'tcx> {
 impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, item: &'hir Item<'hir>) {
diff --git a/compiler/rustc_middle/src/hir/nested_filter.rs b/compiler/rustc_middle/src/hir/nested_filter.rs
index adbe81bb22c7..e18c28a8eac0 100644
--- a/compiler/rustc_middle/src/hir/nested_filter.rs
+++ b/compiler/rustc_middle/src/hir/nested_filter.rs
@@ -1,5 +1,7 @@
 use rustc_hir::intravisit::nested_filter::NestedFilter;
 
+use crate::ty::TyCtxt;
+
 /// Do not visit nested item-like things, but visit nested things
 /// that are inside of an item-like.
 ///
@@ -12,8 +14,8 @@ use rustc_hir::intravisit::nested_filter::NestedFilter;
 /// and to have the visitor that visits the contents of each item
 /// using this setting.
 pub struct OnlyBodies(());
-impl<'hir> NestedFilter<'hir> for OnlyBodies {
-    type Map = crate::hir::map::Map<'hir>;
+impl<'tcx> NestedFilter<'tcx> for OnlyBodies {
+    type MaybeTyCtxt = TyCtxt<'tcx>;
     const INTER: bool = false;
     const INTRA: bool = true;
 }
@@ -24,8 +26,8 @@ impl<'hir> NestedFilter<'hir> for OnlyBodies {
 /// process everything within their lexical context. Typically you
 /// kick off the visit by doing `walk_krate()`.
 pub struct All(());
-impl<'hir> NestedFilter<'hir> for All {
-    type Map = crate::hir::map::Map<'hir>;
+impl<'tcx> NestedFilter<'tcx> for All {
+    type MaybeTyCtxt = TyCtxt<'tcx>;
     const INTER: bool = true;
     const INTRA: bool = true;
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 081e7b1a43cd..264995efe8fa 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -10,7 +10,6 @@ mod unexpand;
 
 use rustc_hir as hir;
 use rustc_hir::intravisit::{Visitor, walk_expr};
-use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::coverage::{
     CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind,
@@ -348,7 +347,7 @@ fn extract_hole_spans_from_hir<'tcx>(
     hir_body: &hir::Body<'tcx>,
 ) -> Vec {
     struct HolesVisitor<'hir, F> {
-        hir: Map<'hir>,
+        tcx: TyCtxt<'hir>,
         visit_hole_span: F,
     }
 
@@ -360,8 +359,8 @@ fn extract_hole_spans_from_hir<'tcx>(
         ///   items contained within them.
         type NestedFilter = nested_filter::All;
 
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.hir
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.tcx
         }
 
         fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
@@ -388,7 +387,7 @@ fn extract_hole_spans_from_hir<'tcx>(
 
     let mut hole_spans = vec![];
     let mut visitor = HolesVisitor {
-        hir: tcx.hir(),
+        tcx,
         visit_hole_span: |hole_span| {
             // Discard any holes that aren't directly visible within the body span.
             if body_span.contains(hole_span) && body_span.eq_ctxt(hole_span) {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e96db885131f..396a0cbc8895 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2606,8 +2606,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 34d60d90be5f..43f2f892e77d 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -105,8 +105,8 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_nested_item(&mut self, id: hir::ItemId) {
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 600c46eb3d07..09d59e1f7172 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -129,8 +129,8 @@ impl<'tcx> LibFeatureCollector<'tcx> {
 impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_attribute(&mut self, attr: &'tcx Attribute) {
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 6eef0b926a13..0fd980af0b54 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -87,8 +87,8 @@ pub(crate) fn provide(providers: &mut Providers) {
 impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 23322be8f559..cb17b0f6cf52 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -259,8 +259,8 @@ struct CheckNakedAsmInNakedFn<'tcx> {
 impl<'tcx> Visitor<'tcx> for CheckNakedAsmInNakedFn<'tcx> {
     type NestedFilter = OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index fd30d0d4867f..d045e61d1d4c 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -394,8 +394,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
     /// deep-walking.
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
@@ -616,8 +616,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
 impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
@@ -756,8 +756,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 57b614833aff..55eb3f777d6b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1202,8 +1202,8 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tecx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tecx.tcx
     }
 
     fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
index b9f3abc2534a..5a303c3cd03c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
@@ -3,7 +3,6 @@ use core::ops::ControlFlow;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor, VisitorExt};
 use rustc_hir::{self as hir, AmbigArg};
-use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::{self, Region, TyCtxt};
@@ -70,8 +69,8 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
     type Result = ControlFlow<&'tcx hir::Ty<'tcx>>;
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
@@ -176,8 +175,8 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
     type Result = ControlFlow<()>;
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Map<'tcx> {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
index bbcd28c08351..0695cc579787 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
@@ -133,8 +133,8 @@ struct TypeParamSpanVisitor<'tcx> {
 impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index d786d04b8f6f..22d219cd64d2 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -68,8 +68,8 @@ impl<'hir> FindExprBySpan<'hir> {
 impl<'v> Visitor<'v> for FindExprBySpan<'v> {
     type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 0cdf1b989158..e10a74221ae2 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -703,7 +703,7 @@ fn build_module_items(
 pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
     if let Some(did) = did.as_local() {
         let hir_id = tcx.local_def_id_to_hir_id(did);
-        rustc_hir_pretty::id_to_string(&tcx.hir(), hir_id)
+        rustc_hir_pretty::id_to_string(&tcx, hir_id)
     } else {
         tcx.rendered_const(did).clone()
     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 390ff3de2fa2..09e71f65c148 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -464,10 +464,10 @@ impl<'tcx> EmitIgnoredResolutionErrors<'tcx> {
 impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
         // We need to recurse into nested closures,
         // since those will fallback to the parent for type checking.
-        self.tcx.hir()
+        self.tcx
     }
 
     fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index c4956bfd2b4a..0d52e21419fc 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -147,14 +147,14 @@ impl HirCollector<'_> {
 impl<'tcx> intravisit::Visitor<'tcx> for HirCollector<'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'_>) {
         let name = match &item.kind {
             hir::ItemKind::Impl(impl_) => {
-                rustc_hir_pretty::id_to_string(&self.tcx.hir(), impl_.self_ty.hir_id)
+                rustc_hir_pretty::id_to_string(&self.tcx, impl_.self_ty.hir_id)
             }
             _ => item.ident.to_string(),
         };
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index a15ac155123d..fa2465c1926e 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -221,8 +221,8 @@ impl SpanMapVisitor<'_> {
 impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
     }
 
     fn visit_path(&mut self, path: &rustc_hir::Path<'tcx>, _id: HirId) {
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 599671bd4d48..dd9dbd7170e5 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -123,8 +123,8 @@ where
 {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx().hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx()
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 5884e018f6a9..f606a3d8a927 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -563,8 +563,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 
     fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 91ddbb44ff89..db3e6034c5ba 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -437,8 +437,8 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
         walk_expr(self, expr)
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 36baf492a540..93c2b7a2d182 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -1079,8 +1079,8 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> {
     // Panics in const blocks will cause compilation to fail.
     fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 6ccea22e191c..6a217b6182ce 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -241,8 +241,8 @@ impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 167377972db9..41bf6e81916a 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -134,8 +134,8 @@ impl<'tcx> Visitor<'tcx> for SelfFinder<'_, 'tcx> {
     type Result = ControlFlow<()>;
     type NestedFilter = OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 
     fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) -> Self::Result {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 1b39663f4f81..d2545e57652a 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -363,7 +363,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
         walk_expr(self, e);
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 15650c4f7329..deac51ab4c49 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -223,8 +223,8 @@ struct SliceIndexLintingVisitor<'a, 'tcx> {
 impl<'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'_, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 8eb45109d68c..f08812017b9c 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -19,8 +19,8 @@ use rustc_hir::{
     WherePredicateKind, lang_items,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter as middle_nested_filter;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
@@ -582,7 +582,7 @@ impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
 where
     F: NestedFilter<'tcx>,
 {
-    type Map = Map<'tcx>;
+    type MaybeTyCtxt = TyCtxt<'tcx>;
     type NestedFilter = F;
 
     // for lifetimes as parameters of generics
@@ -628,8 +628,8 @@ where
         self.lifetime_elision_impossible = false;
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 51fde5288ab9..a5185d38e7c3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -240,8 +240,8 @@ impl<'tcx> Visitor<'tcx> for InitializeVisitor<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index e31b474c83f6..6000ff7a3609 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -245,8 +245,8 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
     impl<'tcx> Visitor<'tcx> for AfterLoopVisitor<'_, '_, 'tcx> {
         type NestedFilter = OnlyBodies;
         type Result = ControlFlow<()>;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
 
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
@@ -288,8 +288,8 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
     }
     impl<'tcx> Visitor<'tcx> for NestedLoopVisitor<'_, '_, 'tcx> {
         type NestedFilter = OnlyBodies;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
 
         fn visit_local(&mut self, l: &'tcx LetStmt<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 5664ffba1a0e..45f79dd44f2a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -456,8 +456,8 @@ impl<'tcx> Visitor<'tcx> for UsedCountVisitor<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 7c4dc4ffb202..4a8a221e8c36 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -143,8 +143,8 @@ impl<'tcx> Visitor<'tcx> for UnwrapVisitor<'_, 'tcx> {
         walk_path(self, path);
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
@@ -174,7 +174,7 @@ impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> {
         rustc_hir::intravisit::walk_expr(self, expr)
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 6e39e7be2c43..3611b341897a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -89,8 +89,8 @@ struct CloneOrCopyVisitor<'cx, 'tcx> {
 impl<'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'_, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 152635a5c35c..13a23a13b9c2 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -119,7 +119,7 @@ impl<'tcx> Visitor<'tcx> for MutArgVisitor<'_, 'tcx> {
         walk_expr(self, expr);
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 7fba4b6a6c8b..9b241edf4ccf 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -583,8 +583,8 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[
     }
     impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
         type NestedFilter = nested_filter::OnlyBodies;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
 
         fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 54e507655e9c..1498a49a7a4a 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -241,8 +241,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                     hir_visit::walk_expr(self, expr);
                 }
 
-                fn nested_visit_map(&mut self) -> Self::Map {
-                    self.cx.tcx.hir()
+                fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+                    self.cx.tcx
                 }
             }
             let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 };
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 16fe035802fa..529f85be3720 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -9,7 +9,6 @@ use rustc_hir::intravisit::{FnKind, Visitor, walk_body, walk_expr};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath, TyKind};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, AssocKind, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
@@ -275,7 +274,6 @@ fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>,
 
 struct CheckCalls<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    map: Map<'tcx>,
     implemented_ty_id: DefId,
     method_span: Span,
 }
@@ -287,8 +285,8 @@ where
     type NestedFilter = nested_filter::OnlyBodies;
     type Result = ControlFlow<()>;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.map
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> {
@@ -380,7 +378,6 @@ impl UnconditionalRecursion {
         {
             let mut c = CheckCalls {
                 cx,
-                map: cx.tcx.hir(),
                 implemented_ty_id,
                 method_span,
             };
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index d00bd7f2b3db..1c1c841e9641 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -101,8 +101,8 @@ impl<'tcx> Visitor<'tcx> for AsyncFnVisitor<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index 71aa57e0a14c..0f9b05c84d4b 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -112,8 +112,8 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
     type NestedFilter = OnlyBodies;
     type Result = ControlFlow<()>;
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> ControlFlow<()> {
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 6a952c0d97aa..76b9bbbd32fd 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -374,8 +374,8 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 315c83507d07..e31da9e9f611 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -277,7 +277,7 @@ impl<'tcx> Visitor<'tcx> for LintCollector<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
         self.cx.tcx.hir()
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/zombie_processes.rs b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
index 4df34891a2b1..9bd00b1e5c8c 100644
--- a/src/tools/clippy/clippy_lints/src/zombie_processes.rs
+++ b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
@@ -249,8 +249,8 @@ impl<'tcx> Visitor<'tcx> for WaitFinder<'_, 'tcx> {
         walk_expr(self, ex)
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index c4ba4c94c946..ccf32f42a47b 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1370,8 +1370,8 @@ impl<'tcx> Visitor<'tcx> for ContainsName<'_, 'tcx> {
         }
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 37f729668925..3bf518f7fe70 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -133,8 +133,8 @@ impl<'tcx> Visitor<'tcx> for BindingUsageFinder<'_, 'tcx> {
         ControlFlow::Continue(())
     }
 
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.cx.tcx
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 9b35ecee1dd1..2ac0efd7e392 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -154,8 +154,8 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
         type NestedFilter = nested_filter::OnlyBodies;
         type Result = ControlFlow;
 
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.tcx
         }
 
         fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
@@ -412,8 +412,8 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
         type NestedFilter = nested_filter::OnlyBodies;
         type Result = ControlFlow<()>;
 
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
             match e.kind {
@@ -477,8 +477,8 @@ pub fn contains_unsafe_block<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>)
     impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
         type Result = ControlFlow<()>;
         type NestedFilter = nested_filter::OnlyBodies;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
 
         fn visit_block(&mut self, b: &'tcx Block<'_>) -> Self::Result {
@@ -544,8 +544,8 @@ pub fn for_each_local_use_after_expr<'tcx, B>(
     }
     impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow, B> Visitor<'tcx> for V<'_, 'tcx, F, B> {
         type NestedFilter = nested_filter::OnlyBodies;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
 
         fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
@@ -729,8 +729,8 @@ pub fn for_each_local_assignment<'tcx, B>(
     }
     impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow, B> Visitor<'tcx> for V<'_, 'tcx, F, B> {
         type NestedFilter = nested_filter::OnlyBodies;
-        fn nested_visit_map(&mut self) -> Self::Map {
-            self.cx.tcx.hir()
+        fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+            self.cx.tcx
         }
 
         fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {

From f666361caa963c3f41934d5b431af24d8894d159 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 17 Feb 2025 13:24:07 +1100
Subject: [PATCH 102/158] Remove `TyCtxt::hir_krate`.

It's a trivial wrapper around the `hir_crate` query with a small number
of uses.
---
 compiler/rustc_driver_impl/src/pretty.rs | 2 +-
 compiler/rustc_middle/src/hir/map.rs     | 8 +-------
 src/librustdoc/core.rs                   | 2 +-
 3 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index ea17dd773c04..093ee659bb42 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -294,7 +294,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
         }
         HirTree => {
             debug!("pretty printing HIR tree");
-            format!("{:#?}", ex.tcx().hir_krate())
+            format!("{:#?}", ex.tcx().hir_crate(()))
         }
         Mir => {
             let mut out = Vec::new();
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 9bd35fdd6f0b..b44f14315d75 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -165,12 +165,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.hir_node(self.parent_hir_id(hir_id))
     }
 
-    /// Best avoided in favour of more targeted methods. See the comment on the `hir_crate` query.
-    #[inline]
-    pub fn hir_krate(self) -> &'tcx Crate<'tcx> {
-        self.hir_crate(())
-    }
-
     #[inline]
     pub fn hir_root_module(self) -> &'tcx Mod<'tcx> {
         match self.hir_owner_node(CRATE_OWNER_ID) {
@@ -414,7 +408,7 @@ impl<'hir> Map<'hir> {
     where
         V: Visitor<'hir>,
     {
-        let krate = self.tcx.hir_krate();
+        let krate = self.tcx.hir_crate(());
         for info in krate.owners.iter() {
             if let MaybeOwner::Owner(info) = info {
                 for attrs in info.attrs.map.values() {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 09e71f65c148..1ead87fd69da 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -378,7 +378,7 @@ pub(crate) fn run_global_ctxt(
         ctxt.external_traits.insert(sized_trait_did, sized_trait);
     }
 
-    debug!("crate: {:?}", tcx.hir_krate());
+    debug!("crate: {:?}", tcx.hir_crate(()));
 
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 

From 9cbc31031444c1efee8ca9860f2b907c5c18d24e Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Mon, 17 Feb 2025 09:57:13 +0100
Subject: [PATCH 103/158] Update default loongarch code model in docs

Since https://github.com/rust-lang/rust/pull/130266 loongarch
defaults to medium code model.
---
 src/doc/rustc/src/platform-support/loongarch-none.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md
index 110a7cc3424d..bafa85c26e29 100644
--- a/src/doc/rustc/src/platform-support/loongarch-none.md
+++ b/src/doc/rustc/src/platform-support/loongarch-none.md
@@ -32,7 +32,7 @@ By default, code generated with the soft-float target should run on any
 LoongArch64 hardware, with the hard-float target additionally requiring an FPU;
 enabling additional target features may raise this baseline.
 
-Code generated with the targets will use the `small` code model by default.
+Code generated with the targets will use the `medium` code model by default.
 You can change this using the `-C code-model=` option to rustc.
 
 On `loongarch64-unknown-none*`, `extern "C"` uses the [architecture's standard calling convention][lapcs].

From 6fa3ad1e5e037d9b4f120573b852f06591bbe6f0 Mon Sep 17 00:00:00 2001
From: klensy 
Date: Mon, 17 Feb 2025 12:32:26 +0300
Subject: [PATCH 104/158] correct comment

---
 compiler/rustc_middle/src/ty/typeck_results.rs | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 1b5b791bb24a..b8c73d258437 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -147,9 +147,7 @@ pub struct TypeckResults<'tcx> {
     coercion_casts: ItemLocalSet,
 
     /// Set of trait imports actually used in the method resolution.
-    /// This is used for warning unused imports. During type
-    /// checking, this `Arc` should not be cloned: it must have a ref-count
-    /// of 1 so that we can insert things into the set mutably.
+    /// This is used for warning unused imports.
     pub used_trait_imports: UnordSet,
 
     /// If any errors occurred while type-checking this body,

From f46c7652d54168dc617861d195e3ef87c08bd9c4 Mon Sep 17 00:00:00 2001
From: Miguel Ojeda 
Date: Mon, 17 Feb 2025 10:41:59 +0100
Subject: [PATCH 105/158] CI: rfl: move job forward to Linux v6.14-rc3

Linux v6.14-rc3 contains commit 6273a058383e ("x86: rust: set
rustc-abi=x86-softfloat on rustc>=1.86.0"), which resolves the error
from https://github.com/rust-lang/rust/pull/136146.

Signed-off-by: Miguel Ojeda 
---
 src/ci/docker/scripts/rfl-build.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index 3eb85ab215e0..573821c3e59c 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,7 +2,7 @@
 
 set -euo pipefail
 
-LINUX_VERSION=50e57739141b41f731ab31f8380821c7969f9dc4
+LINUX_VERSION=v6.14-rc3
 
 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt
 ../x.py build --stage 2 library rustdoc clippy rustfmt
@@ -28,7 +28,7 @@ rm -rf linux || true
 # Download Linux at a specific commit
 mkdir -p linux
 git -C linux init
-git -C linux remote add origin https://github.com/Darksonn/linux.git
+git -C linux remote add origin https://github.com/Rust-for-Linux/linux.git
 git -C linux fetch --depth 1 origin ${LINUX_VERSION}
 git -C linux checkout FETCH_HEAD
 

From b7a9a321265c0e9a597762c7c8107d4b7eba378b Mon Sep 17 00:00:00 2001
From: Chayim Refael Friedman 
Date: Mon, 17 Feb 2025 11:51:29 +0200
Subject: [PATCH 106/158] Fix detection of ref patterns for path patterns

I was wrong on #19127, I thought hir-def resolver is enough for them, but it turns out not because of paths like `::Variant` and `Type::AssocThatIsEnum::Variant`.
---
 .../crates/hir-ty/src/infer/diagnostics.rs    | 21 +++++++++++++++
 .../crates/hir-ty/src/infer/pat.rs            | 13 +++-------
 .../crates/hir-ty/src/infer/path.rs           | 26 ++++++++++++++-----
 .../src/handlers/type_mismatch.rs             | 21 +++++++++++++++
 4 files changed, 64 insertions(+), 17 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
index 8c0446953a6b..e4f5b5ed378d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
@@ -7,6 +7,7 @@ use std::ops::{Deref, DerefMut};
 
 use either::Either;
 use hir_def::{hir::ExprOrPatId, path::Path, resolver::Resolver, type_ref::TypesMap, TypeOwnerId};
+use la_arena::{Idx, RawIdx};
 
 use crate::{
     db::HirDatabase,
@@ -81,6 +82,26 @@ impl<'a> InferenceTyLoweringContext<'a> {
         };
         PathLoweringContext::new(&mut self.ctx, on_diagnostic, path)
     }
+
+    #[inline]
+    pub(super) fn at_path_forget_diagnostics<'b>(
+        &'b mut self,
+        path: &'b Path,
+    ) -> PathLoweringContext<'b, 'a> {
+        let on_diagnostic = PathDiagnosticCallback {
+            data: Either::Right(PathDiagnosticCallbackData {
+                diagnostics: self.diagnostics,
+                node: ExprOrPatId::ExprId(Idx::from_raw(RawIdx::from_u32(0))),
+            }),
+            callback: |_data, _, _diag| {},
+        };
+        PathLoweringContext::new(&mut self.ctx, on_diagnostic, path)
+    }
+
+    #[inline]
+    pub(super) fn forget_diagnostics(&mut self) {
+        self.ctx.diagnostics.clear();
+    }
 }
 
 impl<'a> Deref for InferenceTyLoweringContext<'a> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
index d0fe00ecebdd..db93116f1071 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
@@ -565,16 +565,9 @@ impl InferenceContext<'_> {
             | Pat::Slice { .. } => true,
             Pat::Or(pats) => pats.iter().all(|p| self.is_non_ref_pat(body, *p)),
             Pat::Path(path) => {
-                // A const is a reference pattern, but other value ns things aren't (see #16131). We don't need more than
-                // the hir-def resolver for this, because if there are segments left, this can only be an (associated) const.
-                //
-                // Do not use `TyLoweringContext`'s resolution, we want to ignore errors here (they'll be reported elsewhere).
-                let resolution = self.resolver.resolve_path_in_value_ns_fully(
-                    self.db.upcast(),
-                    path,
-                    body.pat_path_hygiene(pat),
-                );
-                resolution.is_some_and(|it| !matches!(it, hir_def::resolver::ValueNs::ConstId(_)))
+                // A const is a reference pattern, but other value ns things aren't (see #16131).
+                let resolved = self.resolve_value_path_inner(path, pat.into(), true);
+                resolved.is_some_and(|it| !matches!(it.0, hir_def::resolver::ValueNs::ConstId(_)))
             }
             Pat::ConstBlock(..) => false,
             Pat::Lit(expr) => !matches!(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 3794912ee980..6254bc12392b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -40,7 +40,7 @@ impl InferenceContext<'_> {
     }
 
     fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option {
-        let (value, self_subst) = self.resolve_value_path_inner(path, id)?;
+        let (value, self_subst) = self.resolve_value_path_inner(path, id, false)?;
 
         let value_def: ValueTyDefId = match value {
             ValueNs::FunctionId(it) => it.into(),
@@ -152,6 +152,7 @@ impl InferenceContext<'_> {
         &mut self,
         path: &Path,
         id: ExprOrPatId,
+        no_diagnostics: bool,
     ) -> Option<(ValueNs, Option>)> {
         // Don't use `self.make_ty()` here as we need `orig_ns`.
         let mut ctx = TyLoweringContext::new(
@@ -162,7 +163,11 @@ impl InferenceContext<'_> {
             &self.diagnostics,
             InferenceTyDiagnosticSource::Body,
         );
-        let mut path_ctx = ctx.at_path(path, id);
+        let mut path_ctx = if no_diagnostics {
+            ctx.at_path_forget_diagnostics(path)
+        } else {
+            ctx.at_path(path, id)
+        };
         let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
             let last = path.segments().last()?;
 
@@ -172,7 +177,7 @@ impl InferenceContext<'_> {
 
             path_ctx.ignore_last_segment();
             let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns);
-            drop(ctx);
+            drop_ctx(ctx, no_diagnostics);
             let ty = self.table.insert_type_vars(ty);
             let ty = self.table.normalize_associated_types_in(ty);
             self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
@@ -183,7 +188,7 @@ impl InferenceContext<'_> {
 
             match value_or_partial {
                 ResolveValueResult::ValueNs(it, _) => {
-                    drop(ctx);
+                    drop_ctx(ctx, no_diagnostics);
                     (it, None)
                 }
                 ResolveValueResult::Partial(def, remaining_index, _) => {
@@ -202,7 +207,7 @@ impl InferenceContext<'_> {
                             let self_ty = self.table.new_type_var();
                             let trait_ref =
                                 path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty);
-                            drop(ctx);
+                            drop_ctx(ctx, no_diagnostics);
                             self.resolve_trait_assoc_item(trait_ref, last_segment, id)
                         }
                         (def, _) => {
@@ -212,7 +217,7 @@ impl InferenceContext<'_> {
                             // as Iterator>::Item::default`)
                             path_ctx.ignore_last_segment();
                             let (ty, _) = path_ctx.lower_partly_resolved_path(def, true);
-                            drop(ctx);
+                            drop_ctx(ctx, no_diagnostics);
                             if ty.is_unknown() {
                                 return None;
                             }
@@ -227,7 +232,14 @@ impl InferenceContext<'_> {
                 }
             }
         };
-        Some((value, self_subst))
+        return Some((value, self_subst));
+
+        #[inline]
+        fn drop_ctx(mut ctx: TyLoweringContext<'_>, no_diagnostics: bool) {
+            if no_diagnostics {
+                ctx.forget_diagnostics();
+            }
+        }
     }
 
     fn add_required_obligations_for_value_path(&mut self, def: GenericDefId, subst: &Substitution) {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 73dcbc13b79a..7cf8282d0529 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -1235,4 +1235,25 @@ fn f() {
 "#,
         );
     }
+
+    #[test]
+    fn complex_enum_variant_non_ref_pat() {
+        check_diagnostics(
+            r#"
+enum Enum { Variant }
+
+trait Trait {
+    type Assoc;
+}
+impl Trait for () {
+    type Assoc = Enum;
+}
+
+fn foo(v: &Enum) {
+    let ::Variant = v;
+    let <() as Trait>::Assoc::Variant = v;
+}
+    "#,
+        );
+    }
 }

From 33e7f9bc6681e32cc3b3b26ea85e21da225b89ee Mon Sep 17 00:00:00 2001
From: Pietro Albini 
Date: Mon, 17 Feb 2025 10:20:14 +0100
Subject: [PATCH 107/158] generate-copyright: pass the vendored sources from
 bootstrap

---
 src/bootstrap/src/core/build_steps/run.rs     | 17 +++++++-
 src/bootstrap/src/core/build_steps/vendor.rs  | 14 +++++--
 src/bootstrap/src/core/builder/cargo.rs       |  3 +-
 src/bootstrap/src/lib.rs                      |  7 ++++
 .../generate-copyright/src/cargo_metadata.rs  | 40 ++-----------------
 src/tools/generate-copyright/src/main.rs      | 12 ++----
 6 files changed, 41 insertions(+), 52 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index 3f5e701e7e17..2b17e02cae5a 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -9,7 +9,7 @@ use crate::Mode;
 use crate::core::build_steps::dist::distdir;
 use crate::core::build_steps::test;
 use crate::core::build_steps::tool::{self, SourceType, Tool};
-use crate::core::build_steps::vendor::default_paths_to_vendor;
+use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::core::config::flags::get_completion;
@@ -226,13 +226,26 @@ impl Step for GenerateCopyright {
             .collect::>()
             .join(",");
 
+        let vendored_sources = if let Some(path) = builder.vendored_crates_path() {
+            path
+        } else {
+            let cache_dir = builder.out.join("tmp").join("generate-copyright-vendor");
+            builder.ensure(Vendor {
+                sync_args: Vec::new(),
+                versioned_dirs: true,
+                root_dir: builder.src.clone(),
+                output_dir: cache_dir.clone(),
+            });
+            cache_dir
+        };
+
         let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
         cmd.env("CARGO_MANIFESTS", &cargo_manifests);
         cmd.env("LICENSE_METADATA", &license_metadata);
         cmd.env("DEST", &dest);
         cmd.env("DEST_LIBSTD", &dest_libstd);
-        cmd.env("OUT_DIR", &builder.out);
         cmd.env("SRC_DIR", &builder.src);
+        cmd.env("VENDOR_DIR", &vendored_sources);
         cmd.env("CARGO", &builder.initial_cargo);
         // it is important that generate-copyright runs from the root of the
         // source tree, because it uses relative paths
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 26d0f100ffd5..c68b55f35894 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -4,6 +4,8 @@ use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK;
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::utils::exec::command;
 
+pub const VENDOR_DIR: &str = "vendor";
+
 /// Returns the cargo workspaces to vendor for `x vendor` and dist tarballs.
 ///
 /// Returns a `Vec` of `(path_to_manifest, submodules_required)` where
@@ -29,9 +31,10 @@ pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'sta
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub(crate) struct Vendor {
-    sync_args: Vec,
-    versioned_dirs: bool,
-    root_dir: PathBuf,
+    pub(crate) sync_args: Vec,
+    pub(crate) versioned_dirs: bool,
+    pub(crate) root_dir: PathBuf,
+    pub(crate) output_dir: PathBuf,
 }
 
 impl Step for Vendor {
@@ -48,10 +51,13 @@ impl Step for Vendor {
             sync_args: run.builder.config.cmd.vendor_sync_args(),
             versioned_dirs: run.builder.config.cmd.vendor_versioned_dirs(),
             root_dir: run.builder.src.clone(),
+            output_dir: run.builder.src.join(VENDOR_DIR),
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> Self::Output {
+        builder.info(&format!("Vendoring sources to {:?}", self.root_dir));
+
         let mut cmd = command(&builder.initial_cargo);
         cmd.arg("vendor");
 
@@ -81,7 +87,7 @@ impl Step for Vendor {
         // which uses the unstable `public-dependency` feature.
         cmd.env("RUSTC_BOOTSTRAP", "1");
 
-        cmd.current_dir(self.root_dir);
+        cmd.current_dir(self.root_dir).arg(&self.output_dir);
 
         cmd.run(builder);
     }
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 59680af00622..1ec3e601cad1 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -924,8 +924,7 @@ impl Builder<'_> {
 
         if self.config.rust_remap_debuginfo {
             let mut env_var = OsString::new();
-            if self.config.vendor {
-                let vendor = self.build.src.join("vendor");
+            if let Some(vendor) = self.build.vendored_crates_path() {
                 env_var.push(vendor);
                 env_var.push("=/rust/deps");
             } else {
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 7cd8aacf0d6c..e4a6e2b55e73 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -50,6 +50,8 @@ pub use utils::change_tracker::{
     CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes,
 };
 
+use crate::core::build_steps::vendor::VENDOR_DIR;
+
 const LLVM_TOOLS: &[&str] = &[
     "llvm-cov",      // used to generate coverage report
     "llvm-nm",       // used to inspect binaries; it shows symbol names, their sizes and visibility
@@ -782,6 +784,11 @@ impl Build {
         self.out.join(target).join("md-doc")
     }
 
+    /// Path to the vendored Rust crates.
+    fn vendored_crates_path(&self) -> Option {
+        if self.config.vendor { Some(self.src.join(VENDOR_DIR)) } else { None }
+    }
+
     /// Returns `true` if this is an external version of LLVM not managed by bootstrap.
     /// In particular, we expect llvm sources to be available when this is false.
     ///
diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs
index 16c5b5e7104e..b717bd53eb1a 100644
--- a/src/tools/generate-copyright/src/cargo_metadata.rs
+++ b/src/tools/generate-copyright/src/cargo_metadata.rs
@@ -11,10 +11,6 @@ pub enum Error {
     Io(#[from] std::io::Error),
     #[error("Failed get output from cargo-metadata: {0:?}")]
     GettingMetadata(#[from] cargo_metadata::Error),
-    #[error("Failed to run cargo vendor: {0:?}")]
-    LaunchingVendor(std::io::Error),
-    #[error("Failed to complete cargo vendor")]
-    RunningVendor,
     #[error("Bad path {0:?} whilst scraping files")]
     Scraping(PathBuf),
 }
@@ -43,13 +39,11 @@ pub struct PackageMetadata {
     pub is_in_libstd: Option,
 }
 
-/// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data.
+/// Use `cargo metadata` to get a list of dependencies and their license data. License files will
+/// also be pulled from the vendor path (generated by bootstrap).
 ///
-/// This will involve running `cargo vendor` into `vendor_path` so we can
-/// grab the license files.
-///
-/// Any dependency with a path beginning with `root_path` is ignored, as we
-/// assume `reuse` has covered it already.
+/// Any dependency with a path beginning with `root_path` is ignored, as we assume `reuse` has
+/// covered it already.
 pub fn get_metadata_and_notices(
     cargo: &Path,
     vendor_path: &Path,
@@ -58,10 +52,6 @@ pub fn get_metadata_and_notices(
 ) -> Result, Error> {
     let mut output = get_metadata(cargo, root_path, manifest_paths)?;
 
-    // Now do a cargo-vendor and grab everything
-    println!("Vendoring deps into {}...", vendor_path.display());
-    run_cargo_vendor(cargo, &vendor_path, manifest_paths)?;
-
     // Now for each dependency we found, go and grab any important looking files
     for (package, metadata) in output.iter_mut() {
         load_important_files(package, metadata, &vendor_path)?;
@@ -113,28 +103,6 @@ pub fn get_metadata(
     Ok(output)
 }
 
-/// Run cargo-vendor, fetching into the given dir
-fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[PathBuf]) -> Result<(), Error> {
-    let mut vendor_command = std::process::Command::new(cargo);
-    vendor_command.env("RUSTC_BOOTSTRAP", "1");
-    vendor_command.arg("vendor");
-    vendor_command.arg("--quiet");
-    vendor_command.arg("--versioned-dirs");
-    for manifest_path in manifest_paths {
-        vendor_command.arg("-s");
-        vendor_command.arg(manifest_path);
-    }
-    vendor_command.arg(dest);
-
-    let vendor_status = vendor_command.status().map_err(Error::LaunchingVendor)?;
-
-    if !vendor_status.success() {
-        return Err(Error::RunningVendor);
-    }
-
-    Ok(())
-}
-
 /// Add important files off disk into this dependency.
 ///
 /// Maybe one-day Cargo.toml will contain enough information that we don't need
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
index 7b7cf0f4b699..79e90d88f444 100644
--- a/src/tools/generate-copyright/src/main.rs
+++ b/src/tools/generate-copyright/src/main.rs
@@ -17,8 +17,8 @@ mod cargo_metadata;
 fn main() -> Result<(), Error> {
     let dest_file = env_path("DEST")?;
     let libstd_dest_file = env_path("DEST_LIBSTD")?;
-    let out_dir = env_path("OUT_DIR")?;
     let src_dir = env_path("SRC_DIR")?;
+    let vendor_dir = env_path("VENDOR_DIR")?;
     let cargo = env_path("CARGO")?;
     let license_metadata = env_path("LICENSE_METADATA")?;
 
@@ -39,16 +39,12 @@ fn main() -> Result<(), Error> {
         .collect::>();
 
     // Scan Cargo dependencies
-    let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
-        &cargo,
-        &out_dir.join("vendor"),
-        &src_dir,
-        &cargo_manifests,
-    )?;
+    let mut collected_cargo_metadata =
+        cargo_metadata::get_metadata_and_notices(&cargo, &vendor_dir, &src_dir, &cargo_manifests)?;
 
     let library_collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
         &cargo,
-        &out_dir.join("library-vendor"),
+        &vendor_dir,
         &src_dir,
         &library_manifests,
     )?;

From a71de77ae9459e4f05ceb8695fce793b0ac00319 Mon Sep 17 00:00:00 2001
From: Pietro Albini 
Date: Mon, 17 Feb 2025 11:29:40 +0100
Subject: [PATCH 108/158] allow configuring jemalloc per target

---
 config.example.toml                           |  7 ++++++-
 src/bootstrap/src/core/build_steps/compile.rs |  2 +-
 src/bootstrap/src/core/build_steps/tool.rs    |  2 +-
 src/bootstrap/src/core/config/config.rs       | 10 ++++++++++
 src/bootstrap/src/lib.rs                      |  2 +-
 src/bootstrap/src/utils/change_tracker.rs     |  5 +++++
 6 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/config.example.toml b/config.example.toml
index f5395375afe4..fd27b24e4619 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -729,7 +729,8 @@
 #remap-debuginfo = false
 
 # Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
-# This option is only tested on Linux and OSX.
+# This option is only tested on Linux and OSX. It can also be configured per-target in the
+# [target.] section.
 #jemalloc = false
 
 # Run tests in various test suites with the "nll compare mode" in addition to
@@ -927,6 +928,10 @@
 # order to run `x check`.
 #optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
 
+# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
+# This overrides the global `rust.jemalloc` option. See that option for more info.
+#jemalloc = rust.jemalloc (bool)
+
 # =============================================================================
 # Distribution options
 #
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 479327d63695..64a9b51ed5d6 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1260,7 +1260,7 @@ pub fn rustc_cargo_env(
 
     // Build jemalloc on AArch64 with support for page sizes up to 64K
     // See: https://github.com/rust-lang/rust/pull/135081
-    if builder.config.jemalloc
+    if builder.config.jemalloc(target)
         && target.starts_with("aarch64")
         && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
     {
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 1291a634a6f6..9d08adaae6bd 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -643,7 +643,7 @@ impl Step for Rustdoc {
         // to build rustdoc.
         //
         let mut features = Vec::new();
-        if builder.config.jemalloc {
+        if builder.config.jemalloc(target) {
             features.push("jemalloc".to_string());
         }
 
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 62625fc3660f..9389bed8e550 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -325,6 +325,9 @@ pub struct Config {
     pub hosts: Vec,
     pub targets: Vec,
     pub local_rebuild: bool,
+    #[cfg(not(test))]
+    jemalloc: bool,
+    #[cfg(test)]
     pub jemalloc: bool,
     pub control_flow_guard: bool,
     pub ehcont_guard: bool,
@@ -643,6 +646,7 @@ pub struct Target {
     pub no_std: bool,
     pub codegen_backends: Option>,
     pub optimized_compiler_builtins: Option,
+    pub jemalloc: Option,
 }
 
 impl Target {
@@ -1234,6 +1238,7 @@ define_config! {
         codegen_backends: Option> = "codegen-backends",
         runner: Option = "runner",
         optimized_compiler_builtins: Option = "optimized-compiler-builtins",
+        jemalloc: Option = "jemalloc",
     }
 }
 
@@ -2161,6 +2166,7 @@ impl Config {
                 target.profiler = cfg.profiler;
                 target.rpath = cfg.rpath;
                 target.optimized_compiler_builtins = cfg.optimized_compiler_builtins;
+                target.jemalloc = cfg.jemalloc;
 
                 if let Some(ref backends) = cfg.codegen_backends {
                     let available_backends = ["llvm", "cranelift", "gcc"];
@@ -2726,6 +2732,10 @@ impl Config {
             .unwrap_or(&self.rust_codegen_backends)
     }
 
+    pub fn jemalloc(&self, target: TargetSelection) -> bool {
+        self.target_config.get(&target).and_then(|cfg| cfg.jemalloc).unwrap_or(self.jemalloc)
+    }
+
     pub fn default_codegen_backend(&self, target: TargetSelection) -> Option {
         self.codegen_backends(target).first().cloned()
     }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 7cd8aacf0d6c..2adb5993b4f0 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -677,7 +677,7 @@ impl Build {
             crates.is_empty() || possible_features_by_crates.contains(feature)
         };
         let mut features = vec![];
-        if self.config.jemalloc && check("jemalloc") {
+        if self.config.jemalloc(target) && check("jemalloc") {
             features.push("jemalloc");
         }
         if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") {
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 9b23cf1843ef..f215c3f6d0b3 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -350,4 +350,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "The llvm.ccache option has moved to build.ccache. llvm.ccache is now deprecated.",
     },
+    ChangeInfo {
+        change_id: 137170,
+        severity: ChangeSeverity::Info,
+        summary: "It is now possible to configure `jemalloc` for each target",
+    },
 ];

From f6485ff6173c1077c0c960361cbf64039f2b5c15 Mon Sep 17 00:00:00 2001
From: Martin Nordholts 
Date: Mon, 17 Feb 2025 08:00:37 +0100
Subject: [PATCH 109/158] tests: Also gate `f16::erfc()` doctest with
 `reliable_f16_math` cfg

In 136324 the doctest for `f16::erf()` was gated with
`reliable_f16_math`. Add the same gate on `f16::erfc()` to
avoid:

    rust_out.71e2e529d20ea47d-cgu.0:\
    (.text._ZN8rust_out4main43_doctest_main_library_std_src_f16_rs_1321_017h485f3ffe6bf2a981E+0x38): \
    undefined reference to `__gnu_h2f_ieee'

on MIPS (and maybe other architectures).
---
 library/std/src/f16.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index bdbe3e219946..0af69dff05ad 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -1321,12 +1321,14 @@ impl f16 {
     /// ```
     /// #![feature(f16)]
     /// #![feature(float_erf)]
+    /// # #[cfg(reliable_f16_math)] {
     /// let x: f16 = 0.123;
     ///
     /// let one = x.erf() + x.erfc();
     /// let abs_difference = (one - 1.0).abs();
     ///
     /// assert!(abs_difference <= f16::EPSILON);
+    /// # }
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]

From 19fa3deab30f89b0c5fb0b7144a074d95a35ab5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= 
Date: Mon, 17 Feb 2025 13:20:07 +0200
Subject: [PATCH 110/158] Preparing for merge from rust-lang/rust

---
 src/tools/rust-analyzer/rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index f414893b6cdf..4006d06e4fe3 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-d9a4a47b8b3dc0bdff83360cea2013200d60d49c
+273465e1f2932a30a5b56ac95859cdc86f3f33fa

From 1873bd37201f1b9086fddab7a1a9b0acded7f10f Mon Sep 17 00:00:00 2001
From: WANG Rui 
Date: Mon, 17 Feb 2025 17:45:47 +0800
Subject: [PATCH 111/158] Default to the medium code model for the
 loongarch64-linux toolchains

The medium code model is already the default on the Rust side.
Make sure that linked in C objects (e.g. from glibc) also use
medium code model.
---
 .../loongarch64-unknown-linux-gnu.defconfig                     | 2 ++
 .../loongarch64-unknown-linux-musl.defconfig                    | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
index 576f3631cd53..aa33f72268e4 100644
--- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
@@ -7,6 +7,8 @@ CT_ARCH_LOONGARCH=y
 # CT_DEMULTILIB is not set
 CT_ARCH_USE_MMU=y
 CT_ARCH_ARCH="loongarch64"
+CT_TARGET_CFLAGS="-mcmodel=medium"
+CT_TARGET_LDFLAGS="-mcmodel=medium"
 CT_KERNEL_LINUX=y
 CT_LINUX_V_5_19=y
 CT_GLIBC_V_2_36=y
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig
index 3ab676ed9717..3ccbc583c1bd 100644
--- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig
@@ -7,6 +7,8 @@ CT_ARCH_LOONGARCH=y
 # CT_DEMULTILIB is not set
 CT_ARCH_USE_MMU=y
 CT_ARCH_ARCH="loongarch64"
+CT_TARGET_CFLAGS="-mcmodel=medium"
+CT_TARGET_LDFLAGS="-mcmodel=medium"
 CT_KERNEL_LINUX=y
 CT_LINUX_V_5_19=y
 CT_LIBC_MUSL=y

From 952bfae057206f01c3afd126752389eef353b56a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= 
Date: Mon, 17 Feb 2025 14:11:12 +0200
Subject: [PATCH 112/158] Bump rustc crates

---
 src/tools/rust-analyzer/Cargo.toml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 44c628e8294d..924ffb8dd21d 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -87,11 +87,11 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 edition = { path = "./crates/edition", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.94", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.94", default-features = false }
-ra-ap-rustc_index = { version = "0.94", default-features = false }
-ra-ap-rustc_abi = { version = "0.94", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.94", default-features = false }
+ra-ap-rustc_lexer = { version = "0.95", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.95", default-features = false }
+ra-ap-rustc_index = { version = "0.95", default-features = false }
+ra-ap-rustc_abi = { version = "0.95", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.95", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 

From bce3d0ff1cc4182b096a86d31e5944b55c1a8105 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= 
Date: Mon, 17 Feb 2025 14:50:39 +0200
Subject: [PATCH 113/158] Update lockfile

---
 src/tools/rust-analyzer/Cargo.lock | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 98268d8f8444..6d7f6042deca 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -1514,9 +1514,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fa4333df7b71217edb44a36702cafd2bcfc9850677bdf78b32c9f2c98e5df40"
+checksum = "b40c4e339b71a8f075a829b1acaf32f870a11b466d9b8623d50b0ce33e65af95"
 dependencies = [
  "bitflags 2.7.0",
  "ra-ap-rustc_index",
@@ -1525,9 +1525,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d200275ff3d952cc11108f4dc6a692473659758623d63f2bdcea6104a7f1cec8"
+checksum = "872072e2ba11d11147ebe9fde1608fe7f7d9b5c51dac524af28ee07c6dade468"
 dependencies = [
  "ra-ap-rustc_index_macros",
  "smallvec",
@@ -1535,9 +1535,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06eb63df8c1ce2dcb07647305bed811c9c5ebd157def01a81c1b9479b8592b3b"
+checksum = "ffcd77debcaf2ad690a57c2d041c11eb33fe66869754b2c5f35c52954b46af0c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1546,9 +1546,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7a4d402b2f85650e8c1f78e2e2defc241b03948d6e30d9f5254c9b82755cc4d"
+checksum = "49265cdf8823f8d246e476c79c60bd6e5b551c81ae76e1c8d6a5e0dc73df0bca"
 dependencies = [
  "memchr",
  "unicode-properties",
@@ -1557,9 +1557,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23a382dbe392beb26360c1a8ce9193155ef74eeac59bcda0fa0a233e047323a"
+checksum = "b3da239fdc971176de0db45cb631d71475b52033a3d0027d91964da7be89eee6"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1567,9 +1567,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d746955d67f315ab79767f1d0bbc17fee4f0970d4a00b9ad76bf09cc7d3cd17e"
+checksum = "56057d08fdfa0d95494e461bbdd5d4b3fdb349cca6be05ad7759bc964be1b8d4"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash 2.0.0",

From 711247413465fc015420574d6afe929186ab0bb4 Mon Sep 17 00:00:00 2001
From: Thalia Archibald 
Date: Sun, 16 Feb 2025 22:11:46 -0800
Subject: [PATCH 114/158] Use tell for ::stream_position

---
 library/std/src/fs.rs                     | 6 ++++++
 library/std/src/sys/pal/hermit/fs.rs      | 4 ++++
 library/std/src/sys/pal/solid/fs.rs       | 5 ++++-
 library/std/src/sys/pal/uefi/fs.rs        | 4 ++++
 library/std/src/sys/pal/unix/fs.rs        | 4 ++++
 library/std/src/sys/pal/unsupported/fs.rs | 4 ++++
 library/std/src/sys/pal/wasi/fs.rs        | 4 ++++
 library/std/src/sys/pal/windows/fs.rs     | 4 ++++
 8 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 83b009c86dc0..6001a2e2f391 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1229,6 +1229,9 @@ impl Seek for &File {
     fn seek(&mut self, pos: SeekFrom) -> io::Result {
         self.inner.seek(pos)
     }
+    fn stream_position(&mut self) -> io::Result {
+        self.inner.tell()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1275,6 +1278,9 @@ impl Seek for File {
     fn seek(&mut self, pos: SeekFrom) -> io::Result {
         (&*self).seek(pos)
     }
+    fn stream_position(&mut self) -> io::Result {
+        (&*self).stream_position()
+    }
 }
 
 #[stable(feature = "io_traits_arc", since = "1.73.0")]
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index 783623552bb1..45fe7e093cdc 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -425,6 +425,10 @@ impl File {
         Err(Error::from_raw_os_error(22))
     }
 
+    pub fn tell(&self) -> io::Result {
+        self.seek(SeekFrom::Current(0))
+    }
+
     pub fn duplicate(&self) -> io::Result {
         Err(Error::from_raw_os_error(22))
     }
diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs
index cc424141ea80..70b5400bde47 100644
--- a/library/std/src/sys/pal/solid/fs.rs
+++ b/library/std/src/sys/pal/solid/fs.rs
@@ -452,8 +452,11 @@ impl File {
             abi::SOLID_FS_Lseek(self.fd.raw(), pos, whence)
         })
         .map_err(|e| e.as_io_error())?;
-
         // Get the new offset
+        self.tell()
+    }
+
+    pub fn tell(&self) -> io::Result {
         unsafe {
             let mut out_offset = MaybeUninit::uninit();
             error::SolidError::err_if_negative(abi::SOLID_FS_Ftell(
diff --git a/library/std/src/sys/pal/uefi/fs.rs b/library/std/src/sys/pal/uefi/fs.rs
index 9585ec24f687..45e93deffa3a 100644
--- a/library/std/src/sys/pal/uefi/fs.rs
+++ b/library/std/src/sys/pal/uefi/fs.rs
@@ -258,6 +258,10 @@ impl File {
         self.0
     }
 
+    pub fn tell(&self) -> io::Result {
+        self.0
+    }
+
     pub fn duplicate(&self) -> io::Result {
         self.0
     }
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 00cfa7a7fcfd..e13ce580d451 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -1438,6 +1438,10 @@ impl File {
         Ok(n as u64)
     }
 
+    pub fn tell(&self) -> io::Result {
+        self.seek(SeekFrom::Current(0))
+    }
+
     pub fn duplicate(&self) -> io::Result {
         self.0.duplicate().map(File)
     }
diff --git a/library/std/src/sys/pal/unsupported/fs.rs b/library/std/src/sys/pal/unsupported/fs.rs
index 9585ec24f687..45e93deffa3a 100644
--- a/library/std/src/sys/pal/unsupported/fs.rs
+++ b/library/std/src/sys/pal/unsupported/fs.rs
@@ -258,6 +258,10 @@ impl File {
         self.0
     }
 
+    pub fn tell(&self) -> io::Result {
+        self.0
+    }
+
     pub fn duplicate(&self) -> io::Result {
         self.0
     }
diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs
index faf3edd5da6c..513f038b5545 100644
--- a/library/std/src/sys/pal/wasi/fs.rs
+++ b/library/std/src/sys/pal/wasi/fs.rs
@@ -517,6 +517,10 @@ impl File {
         self.fd.seek(pos)
     }
 
+    pub fn tell(&self) -> io::Result {
+        self.fd.tell()
+    }
+
     pub fn duplicate(&self) -> io::Result {
         // https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-rationale.md#why-no-dup
         unsupported()
diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs
index 62d4d727432c..9b283a7a117b 100644
--- a/library/std/src/sys/pal/windows/fs.rs
+++ b/library/std/src/sys/pal/windows/fs.rs
@@ -631,6 +631,10 @@ impl File {
         Ok(newpos as u64)
     }
 
+    pub fn tell(&self) -> io::Result {
+        self.seek(SeekFrom::Current(0))
+    }
+
     pub fn duplicate(&self) -> io::Result {
         Ok(Self { handle: self.handle.try_clone()? })
     }

From 92f31b95c92cb0a34413a52793a50c7d4334dbb2 Mon Sep 17 00:00:00 2001
From: Pietro Albini 
Date: Mon, 17 Feb 2025 10:29:51 +0100
Subject: [PATCH 115/158] use the shared vendor impl for plan source tarballs

---
 src/bootstrap/src/core/build_steps/dist.rs   | 28 +++++++-------------
 src/bootstrap/src/core/build_steps/vendor.rs | 10 +++++--
 2 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index ae3761a97e50..c33f11f684f4 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -19,7 +19,7 @@ use object::read::archive::ArchiveFile;
 
 use crate::core::build_steps::doc::DocumentationFormat;
 use crate::core::build_steps::tool::{self, Tool};
-use crate::core::build_steps::vendor::default_paths_to_vendor;
+use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
 use crate::core::build_steps::{compile, llvm};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
@@ -1050,19 +1050,6 @@ impl Step for PlainSourceTarball {
         if builder.config.dist_vendor {
             builder.require_and_update_all_submodules();
 
-            // Vendor all Cargo dependencies
-            let mut cmd = command(&builder.initial_cargo);
-            cmd.arg("vendor").arg("--versioned-dirs");
-
-            for (p, _) in default_paths_to_vendor(builder) {
-                cmd.arg("--sync").arg(p);
-            }
-
-            cmd
-                // Will read the libstd Cargo.toml which uses the unstable `public-dependency` feature.
-                .env("RUSTC_BOOTSTRAP", "1")
-                .current_dir(plain_dst_src);
-
             // Vendor packages that are required by opt-dist to collect PGO profiles.
             let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
                 .iter()
@@ -1074,15 +1061,18 @@ impl Step for PlainSourceTarball {
                     manifest_path.push("Cargo.toml");
                     manifest_path
                 });
-            for manifest_path in pkgs_for_pgo_training {
-                cmd.arg("--sync").arg(manifest_path);
-            }
 
-            let config = cmd.run_capture(builder).stdout();
+            // Vendor all Cargo dependencies
+            let vendor = builder.ensure(Vendor {
+                sync_args: pkgs_for_pgo_training.collect(),
+                versioned_dirs: true,
+                root_dir: plain_dst_src.into(),
+                output_dir: VENDOR_DIR.into(),
+            });
 
             let cargo_config_dir = plain_dst_src.join(".cargo");
             builder.create_dir(&cargo_config_dir);
-            builder.create(&cargo_config_dir.join("config.toml"), &config);
+            builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
         }
 
         // Delete extraneous directories
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index c68b55f35894..410dbc04f030 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -38,7 +38,7 @@ pub(crate) struct Vendor {
 }
 
 impl Step for Vendor {
-    type Output = ();
+    type Output = VendorOutput;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
@@ -89,6 +89,12 @@ impl Step for Vendor {
 
         cmd.current_dir(self.root_dir).arg(&self.output_dir);
 
-        cmd.run(builder);
+        let config = cmd.run_capture_stdout(builder);
+        VendorOutput { config: config.stdout() }
     }
 }
+
+#[derive(Debug, Clone)]
+pub(crate) struct VendorOutput {
+    pub(crate) config: String,
+}

From 30c7956aed5438547334aa8c91d2921f8ad390e8 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez 
Date: Mon, 17 Feb 2025 17:06:26 +0100
Subject: [PATCH 116/158] Update `minifier-rs` version to `0.3.5`

---
 Cargo.lock                | 4 ++--
 src/librustdoc/Cargo.toml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e9ee3c6b36ec..4731b3370672 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2303,9 +2303,9 @@ dependencies = [
 
 [[package]]
 name = "minifier"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cf47565b1430f5fe6c81d3afcb4b835271348d7eb35294a4d592e38dd09ea22"
+checksum = "9bfdc64e2f805f3d12965f10522000bae36e88d2cfea44112331f467d4f4bf68"
 
 [[package]]
 name = "minimal-lexical"
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index c593cdcbcd22..c07cc4dc347a 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -13,7 +13,7 @@ rinja = { version = "0.3", default-features = false, features = ["config"] }
 base64 = "0.21.7"
 itertools = "0.12"
 indexmap = "2"
-minifier = { version = "0.3.4", default-features = false }
+minifier = { version = "0.3.5", default-features = false }
 pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false }
 regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }

From 2cdb7fac959381a44a409ae39d8d5cb4af988bb9 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Fri, 14 Feb 2025 01:11:21 +0000
Subject: [PATCH 117/158] Prefer param-env candidates even when alias's trait
 bound isn't proven via param-env

---
 .../src/solve/assembly/mod.rs                 | 39 ++++++++++++++-----
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index b0f59ed1474c..bfb590e87679 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -791,7 +791,7 @@ where
             return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Ambiguity));
         };
 
-        let responses: Vec<_> = match proven_via {
+        match proven_via {
             // Even when a trait bound has been proven using a where-bound, we
             // still need to consider alias-bounds for normalization, see
             // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
@@ -800,7 +800,7 @@ where
             // constness checking. Doing so is *at least theoretically* breaking,
             // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
             TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
-                let mut candidates_from_env: Vec<_> = candidates
+                let mut candidates_from_env_and_bounds: Vec<_> = candidates
                     .iter()
                     .filter(|c| {
                         matches!(
@@ -813,16 +813,37 @@ where
 
                 // If the trait goal has been proven by using the environment, we want to treat
                 // aliases as rigid if there are no applicable projection bounds in the environment.
-                if candidates_from_env.is_empty() {
+                if candidates_from_env_and_bounds.is_empty() {
                     if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
-                        candidates_from_env.push(response);
+                        candidates_from_env_and_bounds.push(response);
                     }
                 }
-                candidates_from_env
-            }
-            TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(),
-        };
 
-        self.try_merge_responses(&responses).map_or_else(|| self.flounder(&responses), Ok)
+                if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
+                    Ok(response)
+                } else {
+                    self.flounder(&candidates_from_env_and_bounds)
+                }
+            }
+            TraitGoalProvenVia::Misc => {
+                // Prefer "orphaned" param-env normalization predicates, which are used
+                // (for example, and ideally only) when proving item bounds for an impl.
+                let candidates_from_env: Vec<_> = candidates
+                    .iter()
+                    .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
+                    .map(|c| c.result)
+                    .collect();
+                if let Some(response) = self.try_merge_responses(&candidates_from_env) {
+                    return Ok(response);
+                }
+
+                let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
+                if let Some(response) = self.try_merge_responses(&responses) {
+                    Ok(response)
+                } else {
+                    self.flounder(&responses)
+                }
+            }
+        }
     }
 }

From b002b5cc82b8138308c1aad791ae1f80ca6f5c44 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Fri, 14 Feb 2025 01:28:15 +0000
Subject: [PATCH 118/158] Deeply normalize associated type bounds before
 proving them

---
 .../src/check/compare_impl_item.rs            | 64 +++++++------------
 ...1883.stderr => issue-91883.current.stderr} |  6 +-
 .../issue-91883.next.stderr                   | 20 ++++++
 .../generic-associated-types/issue-91883.rs   |  4 ++
 .../in-trait/default-body-with-rpit.rs        |  3 +
 .../in-trait/nested-rpitit-bounds.rs          |  3 +
 .../predicate-entailment-passes.rs            | 11 ----
 ...trait_ref_is_knowable-norm-overflow.stderr | 12 +---
 tests/ui/traits/next-solver/gat-wf.rs         | 16 +++++
 tests/ui/traits/next-solver/gat-wf.stderr     | 15 +++++
 10 files changed, 87 insertions(+), 67 deletions(-)
 rename tests/ui/generic-associated-types/{issue-91883.stderr => issue-91883.current.stderr} (90%)
 create mode 100644 tests/ui/generic-associated-types/issue-91883.next.stderr
 create mode 100644 tests/ui/traits/next-solver/gat-wf.rs
 create mode 100644 tests/ui/traits/next-solver/gat-wf.stderr

diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 84d5ec4a1e5b..79cf86191e0d 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2105,18 +2105,21 @@ pub(super) fn check_type_bounds<'tcx>(
         ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
     };
 
-    let mut obligations: Vec<_> = tcx
-        .explicit_item_bounds(trait_ty.def_id)
-        .iter_instantiated_copied(tcx, rebased_args)
-        .map(|(concrete_ty_bound, span)| {
-            debug!(?concrete_ty_bound);
-            traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
-        })
-        .collect();
+    let mut obligations: Vec<_> = util::elaborate(
+        tcx,
+        tcx.explicit_item_bounds(trait_ty.def_id).iter_instantiated_copied(tcx, rebased_args).map(
+            |(concrete_ty_bound, span)| {
+                debug!(?concrete_ty_bound);
+                traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
+            },
+        ),
+    )
+    .collect();
 
     // Only in a const implementation do we need to check that the `~const` item bounds hold.
     if tcx.is_conditionally_const(impl_ty_def_id) {
-        obligations.extend(
+        obligations.extend(util::elaborate(
+            tcx,
             tcx.explicit_implied_const_bounds(trait_ty.def_id)
                 .iter_instantiated_copied(tcx, rebased_args)
                 .map(|(c, span)| {
@@ -2127,7 +2130,7 @@ pub(super) fn check_type_bounds<'tcx>(
                         c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
                     )
                 }),
-        );
+        ));
     }
     debug!(item_bounds=?obligations);
 
@@ -2135,26 +2138,19 @@ pub(super) fn check_type_bounds<'tcx>(
     // to its definition type. This should be the param-env we use to *prove* the
     // predicate too, but we don't do that because of performance issues.
     // See .
-    let trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args);
-    let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
     let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
-    for mut obligation in util::elaborate(tcx, obligations) {
-        let normalized_predicate = if infcx.next_trait_solver() {
-            obligation.predicate.fold_with(&mut ReplaceTy {
-                tcx,
-                from: trait_projection_ty,
-                to: impl_identity_ty,
-            })
-        } else {
-            ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
-        };
-        debug!(?normalized_predicate);
-        obligation.predicate = normalized_predicate;
-
-        ocx.register_obligation(obligation);
+    for obligation in &mut obligations {
+        match ocx.deeply_normalize(&normalize_cause, normalize_param_env, obligation.predicate) {
+            Ok(pred) => obligation.predicate = pred,
+            Err(e) => {
+                return Err(infcx.err_ctxt().report_fulfillment_errors(e));
+            }
+        }
     }
+
     // Check that all obligations are satisfied by the implementation's
     // version.
+    ocx.register_obligations(obligations);
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
         let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
@@ -2166,22 +2162,6 @@ pub(super) fn check_type_bounds<'tcx>(
     ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
 }
 
-struct ReplaceTy<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    from: Ty<'tcx>,
-    to: Ty<'tcx>,
-}
-
-impl<'tcx> TypeFolder> for ReplaceTy<'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if self.from == ty { self.to } else { ty.super_fold_with(self) }
-    }
-}
-
 /// Install projection predicates that allow GATs to project to their own
 /// definition types. This is not allowed in general in cases of default
 /// associated types in trait definitions, or when specialization is involved,
diff --git a/tests/ui/generic-associated-types/issue-91883.stderr b/tests/ui/generic-associated-types/issue-91883.current.stderr
similarity index 90%
rename from tests/ui/generic-associated-types/issue-91883.stderr
rename to tests/ui/generic-associated-types/issue-91883.current.stderr
index ac636ebb648c..0741cf9581d5 100644
--- a/tests/ui/generic-associated-types/issue-91883.stderr
+++ b/tests/ui/generic-associated-types/issue-91883.current.stderr
@@ -1,5 +1,5 @@
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/issue-91883.rs:30:24
+  --> $DIR/issue-91883.rs:34:24
    |
 LL |     type Cursor<'tx>: Cursor<'tx>
    |     ----------------------------- definition of `Cursor` from trait
@@ -8,12 +8,12 @@ LL |     type Cursor<'tx> = CursorImpl<'tx>;
    |                        ^^^^^^^^^^^^^^^
    |
 note: lifetime parameter instantiated with the lifetime `'db` as defined here
-  --> $DIR/issue-91883.rs:29:6
+  --> $DIR/issue-91883.rs:33:6
    |
 LL | impl<'db> Transaction<'db> for TransactionImpl<'db> {
    |      ^^^
 note: but lifetime parameter must outlive the lifetime `'tx` as defined here
-  --> $DIR/issue-91883.rs:30:17
+  --> $DIR/issue-91883.rs:34:17
    |
 LL |     type Cursor<'tx> = CursorImpl<'tx>;
    |                 ^^^
diff --git a/tests/ui/generic-associated-types/issue-91883.next.stderr b/tests/ui/generic-associated-types/issue-91883.next.stderr
new file mode 100644
index 000000000000..b3ed2d81b63e
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-91883.next.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-91883.rs:34:24
+   |
+LL |     type Cursor<'tx> = CursorImpl<'tx>;
+   |                        ^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'db` as defined here
+  --> $DIR/issue-91883.rs:33:6
+   |
+LL | impl<'db> Transaction<'db> for TransactionImpl<'db> {
+   |      ^^^
+note: but lifetime parameter must outlive the lifetime `'tx` as defined here
+  --> $DIR/issue-91883.rs:34:17
+   |
+LL |     type Cursor<'tx> = CursorImpl<'tx>;
+   |                 ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/tests/ui/generic-associated-types/issue-91883.rs b/tests/ui/generic-associated-types/issue-91883.rs
index e870e08a3a2b..d31e1736cf28 100644
--- a/tests/ui/generic-associated-types/issue-91883.rs
+++ b/tests/ui/generic-associated-types/issue-91883.rs
@@ -1,3 +1,7 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 use std::fmt::Debug;
 use std::marker::PhantomData;
 
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
index c1a78bc23885..1bbff839ffa5 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -1,5 +1,8 @@
 //@ edition:2021
 //@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 use std::fmt::Debug;
 
diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs b/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs
index 10c2a8112434..6954a7d80672 100644
--- a/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/nested-rpitit-bounds.rs
@@ -1,4 +1,7 @@
 //@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 use std::ops::Deref;
 
diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.rs b/tests/ui/traits/const-traits/predicate-entailment-passes.rs
index 9c8d5a5e3f6a..28ae21891f38 100644
--- a/tests/ui/traits/const-traits/predicate-entailment-passes.rs
+++ b/tests/ui/traits/const-traits/predicate-entailment-passes.rs
@@ -6,32 +6,21 @@
 #[const_trait] trait Bar {}
 impl const Bar for () {}
 
-
 #[const_trait] trait TildeConst {
-    type Bar where T: ~const Bar;
-
     fn foo() where T: ~const Bar;
 }
 impl TildeConst for () {
-    type Bar = () where T: Bar;
-
     fn foo() where T: Bar {}
 }
 
 
 #[const_trait] trait AlwaysConst {
-    type Bar where T: const Bar;
-
     fn foo() where T: const Bar;
 }
 impl AlwaysConst for i32 {
-    type Bar = () where T: Bar;
-
     fn foo() where T: Bar {}
 }
 impl const AlwaysConst for u32 {
-    type Bar = () where T: ~const Bar;
-
     fn foo() where T: ~const Bar {}
 }
 
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
index 1d42dbdfe00e..294fa0d7613c 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
@@ -1,18 +1,8 @@
-error[E0275]: overflow evaluating the requirement `::Assoc: Sized`
+error[E0275]: overflow evaluating the requirement `::Assoc == _`
   --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18
    |
 LL |     type Assoc = ::Assoc;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: required by a bound in `Overflow::Assoc`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:7:5
-   |
-LL |     type Assoc;
-   |     ^^^^^^^^^^^ required by this bound in `Overflow::Assoc`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL |     type Assoc: ?Sized;
-   |               ++++++++
 
 error[E0119]: conflicting implementations of trait `Trait`
   --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1
diff --git a/tests/ui/traits/next-solver/gat-wf.rs b/tests/ui/traits/next-solver/gat-wf.rs
new file mode 100644
index 000000000000..ff6e2665ef3e
--- /dev/null
+++ b/tests/ui/traits/next-solver/gat-wf.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Znext-solver
+
+// Make sure that, like the old trait solver, we end up requiring that the WC of
+// impl GAT matches that of the trait. This is not a restriction that we *need*,
+// but is a side-effect of registering the where clauses when normalizing the GAT
+// when proving it satisfies its item bounds.
+
+trait Foo {
+    type T<'a>: Sized where Self: 'a;
+}
+
+impl Foo for &() {
+    type T<'a> = (); //~ the type `&()` does not fulfill the required lifetime
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/gat-wf.stderr b/tests/ui/traits/next-solver/gat-wf.stderr
new file mode 100644
index 000000000000..620bca77e4b9
--- /dev/null
+++ b/tests/ui/traits/next-solver/gat-wf.stderr
@@ -0,0 +1,15 @@
+error[E0477]: the type `&()` does not fulfill the required lifetime
+  --> $DIR/gat-wf.rs:13:18
+   |
+LL |     type T<'a> = ();
+   |                  ^^
+   |
+note: type must outlive the lifetime `'a` as defined here
+  --> $DIR/gat-wf.rs:13:12
+   |
+LL |     type T<'a> = ();
+   |            ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0477`.

From a0a8e02e663fd62705630616f06b45a0bd3e5b6c Mon Sep 17 00:00:00 2001
From: Urgau 
Date: Sun, 16 Feb 2025 22:16:31 +0100
Subject: [PATCH 119/158] Install more signal stack trace handlers

---
 .../rustc_driver_impl/src/signal_handler.rs   | 50 +++++++++++++++----
 1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs
index 08b7d937661f..e7bc57c9749b 100644
--- a/compiler/rustc_driver_impl/src/signal_handler.rs
+++ b/compiler/rustc_driver_impl/src/signal_handler.rs
@@ -6,6 +6,15 @@ use std::{fmt, mem, ptr, slice};
 
 use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
 
+/// Signals that represent that we have a bug, and our prompt termination has
+/// been ordered.
+#[rustfmt::skip]
+const KILL_SIGNALS: [(libc::c_int, &str); 3] = [
+    (libc::SIGILL, "SIGILL"),
+    (libc::SIGBUS, "SIGBUS"),
+    (libc::SIGSEGV, "SIGSEGV")
+];
+
 unsafe extern "C" {
     fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int);
 }
@@ -39,8 +48,19 @@ macro raw_errln($tokens:tt) {
 /// # Safety
 ///
 /// Caller must ensure that this function is not re-entered.
-unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
+unsafe extern "C" fn print_stack_trace(signum: libc::c_int) {
     const MAX_FRAMES: usize = 256;
+
+    let signame = {
+        let mut signame = "";
+        for sig in KILL_SIGNALS {
+            if sig.0 == signum {
+                signame = sig.1;
+            }
+        }
+        signame
+    };
+
     let stack = unsafe {
         // Reserve data segment so we don't have to malloc in a signal handler, which might fail
         // in incredibly undesirable and unexpected ways due to e.g. the allocator deadlocking
@@ -54,7 +74,8 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
     };
 
     // Just a stack trace is cryptic. Explain what we're doing.
-    raw_errln!("error: rustc interrupted by SIGSEGV, printing backtrace\n");
+    raw_errln!("error: rustc interrupted by {signame}, printing backtrace\n");
+
     let mut written = 1;
     let mut consumed = 0;
     // Begin elaborating return addrs into symbols and writing them directly to stderr
@@ -94,7 +115,7 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
     written += rem.len() + 1;
 
     let random_depth = || 8 * 16; // chosen by random diceroll (2d20)
-    if cyclic || stack.len() > random_depth() {
+    if (cyclic || stack.len() > random_depth()) && signum == libc::SIGSEGV {
         // technically speculation, but assert it with confidence anyway.
         // rustc only arrived in this signal handler because bad things happened
         // and this message is for explaining it's not the programmer's fault
@@ -106,17 +127,22 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
         written += 1;
     }
     raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
-    // get the current stack size WITHOUT blocking and double it
-    let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
-    raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
-    written += 2;
+    written += 1;
+    if signum == libc::SIGSEGV {
+        // get the current stack size WITHOUT blocking and double it
+        let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
+        raw_errln!(
+            "help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}"
+        );
+        written += 1;
+    }
     if written > 24 {
-        // We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
-        raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
+        // We probably just scrolled the earlier "interrupted by {signame}" message off the terminal
+        raw_errln!("note: backtrace dumped due to {signame}! resuming signal");
     };
 }
 
-/// When SIGSEGV is delivered to the process, print a stack trace and then exit.
+/// When one of the KILL signals is delivered to the process, print a stack trace and then exit.
 pub(super) fn install() {
     unsafe {
         let alt_stack_size: usize = min_sigstack_size() + 64 * 1024;
@@ -129,7 +155,9 @@ pub(super) fn install() {
         sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
         sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
         libc::sigemptyset(&mut sa.sa_mask);
-        libc::sigaction(libc::SIGSEGV, &sa, ptr::null_mut());
+        for (signum, _signame) in KILL_SIGNALS {
+            libc::sigaction(signum, &sa, ptr::null_mut());
+        }
     }
 }
 

From a7a43cd37308b774e4d562f1dbaf2793461ae09e Mon Sep 17 00:00:00 2001
From: Yotam Ofek 
Date: Wed, 5 Feb 2025 12:54:31 +0000
Subject: [PATCH 120/158] use `Iterator::zip` instead of enumerating+indexing

---
 src/librustdoc/clean/mod.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 92ef3ab7a1d4..dcc5fd12d81b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1150,9 +1150,9 @@ fn clean_args_from_types_and_body_id<'tcx>(
     Arguments {
         values: types
             .iter()
-            .enumerate()
-            .map(|(i, ty)| Argument {
-                name: name_from_pat(body.params[i].pat),
+            .zip(body.params)
+            .map(|(ty, param)| Argument {
+                name: name_from_pat(param.pat),
                 type_: clean_ty(ty, cx),
                 is_const: false,
             })

From 4a76615054efaea8a7c0a77ec4b77277da7c64be Mon Sep 17 00:00:00 2001
From: Yotam Ofek 
Date: Wed, 5 Feb 2025 13:03:12 +0000
Subject: [PATCH 121/158] coalesce match patterns with identical bodies

---
 src/librustdoc/clean/utils.rs | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 8a7d140bb1a6..418e60fd9725 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -299,10 +299,15 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
 
     Symbol::intern(&match p.kind {
         // FIXME(never_patterns): does this make sense?
-        PatKind::Wild | PatKind::Err(_) | PatKind::Never | PatKind::Struct(..) => {
+        PatKind::Wild
+        | PatKind::Err(_)
+        | PatKind::Never
+        | PatKind::Struct(..)
+        | PatKind::Range(..) => {
             return kw::Underscore;
         }
         PatKind::Binding(_, _, ident, _) => return ident.name,
+        PatKind::Box(p) | PatKind::Ref(p, _) | PatKind::Guard(p, _) => return name_from_pat(p),
         PatKind::TupleStruct(ref p, ..)
         | PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref p), .. }) => qpath_to_string(p),
         PatKind::Or(pats) => {
@@ -312,17 +317,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
             "({})",
             elts.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(", ")
         ),
-        PatKind::Box(p) => return name_from_pat(p),
         PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)),
-        PatKind::Ref(p, _) => return name_from_pat(p),
         PatKind::Expr(..) => {
             warn!(
                 "tried to get argument name from PatKind::Expr, which is silly in function arguments"
             );
             return Symbol::intern("()");
         }
-        PatKind::Guard(p, _) => return name_from_pat(p),
-        PatKind::Range(..) => return kw::Underscore,
         PatKind::Slice(begin, ref mid, end) => {
             let begin = begin.iter().map(|p| name_from_pat(p).to_string());
             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(p))).into_iter();

From 32b1bffa11640f3ad88c4761e0ec9e5546940159 Mon Sep 17 00:00:00 2001
From: Eric Huss 
Date: Mon, 17 Feb 2025 10:47:48 -0800
Subject: [PATCH 122/158] Update mdbook to 0.4.45

Changelog: https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#mdbook-0445
---
 src/tools/rustbook/Cargo.lock | 4 ++--
 src/tools/rustbook/Cargo.toml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index b31bf61a6fba..91f72e0d007f 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -867,9 +867,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.44"
+version = "0.4.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9da1e54401fe5d45a664c57e112e70f18e8c5a73e268c179305b932ee864574"
+checksum = "b07d36d96ffe1b5b16ddf2bc80b3b26bb7a498b2a6591061250bf0af8e8095ad"
 dependencies = [
  "ammonia",
  "anyhow",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 9f9846cdee07..c9d4d41d1155 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -14,6 +14,6 @@ mdbook-i18n-helpers = "0.3.3"
 mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
 
 [dependencies.mdbook]
-version = "0.4.44"
+version = "0.4.45"
 default-features = false
 features = ["search"]

From 2773456f5f3560bb0590d32452ca58f21b0181d0 Mon Sep 17 00:00:00 2001
From: Eric Huss 
Date: Mon, 17 Feb 2025 10:57:51 -0800
Subject: [PATCH 123/158] Move error_index_generator to the rustbook workspace

I had forgotten that error_index_generator is using mdbook. This moves
it to be part of the rustbook workspace so that it can share the
dependency with rustbook.
---
 Cargo.lock                                 | 194 +--------------------
 Cargo.toml                                 |   1 -
 src/bootstrap/src/utils/proc_macro_deps.rs |  15 --
 src/tools/error_index_generator/Cargo.toml |   1 +
 src/tools/rustbook/Cargo.lock              |   7 +
 src/tools/rustbook/Cargo.toml              |   1 +
 src/tools/tidy/src/deps.rs                 |   1 -
 7 files changed, 10 insertions(+), 210 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e9ee3c6b36ec..bb17717aceb4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,19 +61,6 @@ version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
-[[package]]
-name = "ammonia"
-version = "4.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
-dependencies = [
- "html5ever",
- "maplit",
- "once_cell",
- "tendril",
- "url",
-]
-
 [[package]]
 name = "android-tzdata"
 version = "0.1.1"
@@ -513,16 +500,6 @@ dependencies = [
  "anstyle",
  "clap_lex",
  "strsim",
- "terminal_size",
-]
-
-[[package]]
-name = "clap_complete"
-version = "4.5.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33a7e468e750fa4b6be660e8b5651ad47372e8fb114030b594c2d75d48c5ffd0"
-dependencies = [
- "clap",
 ]
 
 [[package]]
@@ -1084,18 +1061,6 @@ version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
 
-[[package]]
-name = "elasticlunr-rs"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41e83863a500656dfa214fee6682de9c5b9f03de6860fec531235ed2ae9f6571"
-dependencies = [
- "regex",
- "serde",
- "serde_derive",
- "serde_json",
-]
-
 [[package]]
 name = "elsa"
 version = "1.11.0"
@@ -1159,13 +1124,6 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
-[[package]]
-name = "error_index_generator"
-version = "0.0.0"
-dependencies = [
- "mdbook",
-]
-
 [[package]]
 name = "expect-test"
 version = "1.5.1"
@@ -1517,22 +1475,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "handlebars"
-version = "6.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6b224b95c1e668ac0270325ad563b2eef1469fbbb8959bc7c692c844b813d9"
-dependencies = [
- "derive_builder",
- "log",
- "num-order",
- "pest",
- "pest_derive",
- "serde",
- "serde_json",
- "thiserror 2.0.11",
-]
-
 [[package]]
 name = "hashbrown"
 version = "0.14.5"
@@ -2189,12 +2131,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
-[[package]]
-name = "maplit"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
-
 [[package]]
 name = "markup5ever"
 version = "0.12.1"
@@ -2228,34 +2164,6 @@ dependencies = [
  "digest",
 ]
 
-[[package]]
-name = "mdbook"
-version = "0.4.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148"
-dependencies = [
- "ammonia",
- "anyhow",
- "chrono",
- "clap",
- "clap_complete",
- "elasticlunr-rs",
- "env_logger",
- "handlebars",
- "log",
- "memchr",
- "once_cell",
- "opener",
- "pulldown-cmark 0.10.3",
- "regex",
- "serde",
- "serde_json",
- "shlex",
- "tempfile",
- "toml 0.5.11",
- "topological-sort",
-]
-
 [[package]]
 name = "measureme"
 version = "11.0.1"
@@ -2483,21 +2391,6 @@ dependencies = [
  "num-traits",
 ]
 
-[[package]]
-name = "num-modular"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
-
-[[package]]
-name = "num-order"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
-dependencies = [
- "num-modular",
-]
-
 [[package]]
 name = "num-rational"
 version = "0.4.2"
@@ -2718,51 +2611,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "pest"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
-dependencies = [
- "memchr",
- "thiserror 2.0.11",
- "ucd-trie",
-]
-
-[[package]]
-name = "pest_derive"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e"
-dependencies = [
- "pest",
- "pest_generator",
-]
-
-[[package]]
-name = "pest_generator"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b"
-dependencies = [
- "pest",
- "pest_meta",
- "proc-macro2",
- "quote",
- "syn 2.0.96",
-]
-
-[[package]]
-name = "pest_meta"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea"
-dependencies = [
- "once_cell",
- "pest",
- "sha2",
-]
-
 [[package]]
 name = "phf"
 version = "0.11.3"
@@ -2921,18 +2769,6 @@ dependencies = [
  "unicase",
 ]
 
-[[package]]
-name = "pulldown-cmark"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
-dependencies = [
- "bitflags",
- "memchr",
- "pulldown-cmark-escape 0.10.1",
- "unicase",
-]
-
 [[package]]
 name = "pulldown-cmark"
 version = "0.11.3"
@@ -2941,16 +2777,10 @@ checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
 dependencies = [
  "bitflags",
  "memchr",
- "pulldown-cmark-escape 0.11.0",
+ "pulldown-cmark-escape",
  "unicase",
 ]
 
-[[package]]
-name = "pulldown-cmark-escape"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
-
 [[package]]
 name = "pulldown-cmark-escape"
 version = "0.11.0"
@@ -5310,16 +5140,6 @@ dependencies = [
  "winapi-util",
 ]
 
-[[package]]
-name = "terminal_size"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
-dependencies = [
- "rustix",
- "windows-sys 0.59.0",
-]
-
 [[package]]
 name = "termize"
 version = "0.1.1"
@@ -5560,12 +5380,6 @@ dependencies = [
  "winnow",
 ]
 
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
 [[package]]
 name = "tracing"
 version = "0.1.37"
@@ -5686,12 +5500,6 @@ dependencies = [
  "regex-lite",
 ]
 
-[[package]]
-name = "ucd-trie"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
-
 [[package]]
 name = "ui_test"
 version = "0.26.5"
diff --git a/Cargo.toml b/Cargo.toml
index 97e782d0df02..20a43aaaeeb3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,6 @@ members = [
   "src/tools/clippy/clippy_dev",
   "src/tools/compiletest",
   "src/tools/run-make-support",
-  "src/tools/error_index_generator",
   "src/tools/linkchecker",
   "src/tools/lint-docs",
   "src/tools/miropt-test-tools",
diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs
index dbfd6f47dc67..34bf6bb7013f 100644
--- a/src/bootstrap/src/utils/proc_macro_deps.rs
+++ b/src/bootstrap/src/utils/proc_macro_deps.rs
@@ -6,25 +6,18 @@ pub static CRATES: &[&str] = &[
     "annotate-snippets",
     "anstyle",
     "basic-toml",
-    "block-buffer",
     "bumpalo",
-    "cfg-if",
-    "cpufeatures",
-    "crypto-common",
     "darling",
     "darling_core",
     "derive_builder_core",
-    "digest",
     "fluent-bundle",
     "fluent-langneg",
     "fluent-syntax",
     "fnv",
-    "generic-array",
     "heck",
     "ident_case",
     "intl-memoizer",
     "intl_pluralrules",
-    "libc",
     "log",
     "memchr",
     "mime",
@@ -32,17 +25,12 @@ pub static CRATES: &[&str] = &[
     "minimal-lexical",
     "nom",
     "num-conv",
-    "once_cell",
-    "pest",
-    "pest_generator",
-    "pest_meta",
     "proc-macro2",
     "quote",
     "rinja_parser",
     "rustc-hash",
     "self_cell",
     "serde",
-    "sha2",
     "smallvec",
     "stable_deref_trait",
     "strsim",
@@ -52,15 +40,12 @@ pub static CRATES: &[&str] = &[
     "time-core",
     "tinystr",
     "type-map",
-    "typenum",
-    "ucd-trie",
     "unic-langid",
     "unic-langid-impl",
     "unic-langid-macros",
     "unicase",
     "unicode-ident",
     "unicode-width",
-    "version_check",
     "wasm-bindgen-backend",
     "wasm-bindgen-macro-support",
     "wasm-bindgen-shared",
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index f4dac6e947e3..54fe7f6eb5a9 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -2,6 +2,7 @@
 name = "error_index_generator"
 version = "0.0.0"
 edition = "2021"
+workspace = "../rustbook"
 
 [dependencies]
 mdbook = { version = "0.4", default-features = false, features = ["search"] }
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 91f72e0d007f..ddcf315a2672 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -446,6 +446,13 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "error_index_generator"
+version = "0.0.0"
+dependencies = [
+ "mdbook",
+]
+
 [[package]]
 name = "fastrand"
 version = "2.3.0"
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index c9d4d41d1155..6aec0bec0fa0 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -1,4 +1,5 @@
 [workspace]
+members = ["../error_index_generator"]
 
 [package]
 name = "rustbook"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e8e7dfe0d84c..bfff5a8e17e1 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -99,7 +99,6 @@ const EXCEPTIONS: ExceptionList = &[
     ("dissimilar", "Apache-2.0"),                            // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
     ("fluent-langneg", "Apache-2.0"),                        // rustc (fluent translations)
     ("foldhash", "Zlib"),                                    // rustc
-    ("mdbook", "MPL-2.0"),                                   // mdbook
     ("option-ext", "MPL-2.0"),                               // cargo-miri (via `directories`)
     ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),     // rustc (license is the same as LLVM uses)
     ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0                       // cargo/... (because of serde)

From 123217b3b8233ba0cc852f81fe6ca55c47bed8cc Mon Sep 17 00:00:00 2001
From: Eric Huss 
Date: Mon, 17 Feb 2025 10:58:57 -0800
Subject: [PATCH 124/158] Fix what looks like an inverted message

I believe this is trying to say there is something that is in the file,
but shouldn't be.
---
 src/tools/tidy/src/deps.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index bfff5a8e17e1..51e58b4e4fcf 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -666,7 +666,7 @@ pub static CRATES: &[&str] = &[
         for extra in expected.difference(&proc_macro_deps) {
             tidy_error!(
                 bad,
-                "`{extra}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
+                "`{extra}` is registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
             );
         }
         if *bad != old_bad {

From c0b1c6eed516ca39a88dcd7d6a11051fe645fd4a Mon Sep 17 00:00:00 2001
From: Yotam Ofek 
Date: Wed, 5 Feb 2025 17:48:26 +0000
Subject: [PATCH 125/158] librustdoc: more usages of `Joined::joined`

---
 src/librustdoc/clean/utils.rs            | 60 +++++++++++++++---------
 src/librustdoc/doctest/make.rs           | 16 ++++---
 src/librustdoc/html/render/print_item.rs | 28 +++++------
 3 files changed, 61 insertions(+), 43 deletions(-)

diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 418e60fd9725..c69d22001d9b 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -1,5 +1,5 @@
 use std::assert_matches::debug_assert_matches;
-use std::fmt::Write as _;
+use std::fmt::{self, Display, Write as _};
 use std::mem;
 use std::sync::LazyLock as Lazy;
 
@@ -24,6 +24,7 @@ use crate::clean::{
     clean_middle_ty, inline,
 };
 use crate::core::DocContext;
+use crate::display::Joined as _;
 
 #[cfg(test)]
 mod tests;
@@ -250,16 +251,20 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
         hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
     };
 
-    let mut s = String::new();
-    for (i, seg) in segments.iter().enumerate() {
-        if i > 0 {
-            s.push_str("::");
-        }
-        if seg.ident.name != kw::PathRoot {
-            s.push_str(seg.ident.as_str());
-        }
-    }
-    s
+    fmt::from_fn(|f| {
+        segments
+            .iter()
+            .map(|seg| {
+                fmt::from_fn(|f| {
+                    if seg.ident.name != kw::PathRoot {
+                        write!(f, "{}", seg.ident)?;
+                    }
+                    Ok(())
+                })
+            })
+            .joined("::", f)
+    })
+    .to_string()
 }
 
 pub(crate) fn build_deref_target_impls(
@@ -311,12 +316,11 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
         PatKind::TupleStruct(ref p, ..)
         | PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref p), .. }) => qpath_to_string(p),
         PatKind::Or(pats) => {
-            pats.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(" | ")
+            fmt::from_fn(|f| pats.iter().map(|p| name_from_pat(p)).joined(" | ", f)).to_string()
+        }
+        PatKind::Tuple(elts, _) => {
+            format!("({})", fmt::from_fn(|f| elts.iter().map(|p| name_from_pat(p)).joined(", ", f)))
         }
-        PatKind::Tuple(elts, _) => format!(
-            "({})",
-            elts.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(", ")
-        ),
         PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)),
         PatKind::Expr(..) => {
             warn!(
@@ -324,11 +328,25 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
             );
             return Symbol::intern("()");
         }
-        PatKind::Slice(begin, ref mid, end) => {
-            let begin = begin.iter().map(|p| name_from_pat(p).to_string());
-            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(p))).into_iter();
-            let end = end.iter().map(|p| name_from_pat(p).to_string());
-            format!("[{}]", begin.chain(mid).chain(end).collect::>().join(", "))
+        PatKind::Slice(begin, mid, end) => {
+            fn print_pat<'a>(pat: &'a Pat<'a>, wild: bool) -> impl Display + 'a {
+                fmt::from_fn(move |f| {
+                    if wild {
+                        f.write_str("..")?;
+                    }
+                    name_from_pat(pat).fmt(f)
+                })
+            }
+
+            format!(
+                "[{}]",
+                fmt::from_fn(|f| {
+                    let begin = begin.iter().map(|p| print_pat(p, false));
+                    let mid = mid.map(|p| print_pat(p, true));
+                    let end = end.iter().map(|p| print_pat(p, false));
+                    begin.chain(mid).chain(end).joined(", ", f)
+                })
+            )
         }
     })
 }
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index d89caabefe3e..4792bc525a59 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -1,6 +1,7 @@
 //! Logic for transforming the raw code given by the user into something actually
 //! runnable, e.g. by adding a `main` function if it doesn't already exist.
 
+use std::fmt::{self, Write as _};
 use std::io;
 use std::sync::Arc;
 
@@ -17,6 +18,7 @@ use rustc_span::symbol::sym;
 use tracing::debug;
 
 use super::GlobalTestOptions;
+use crate::display::Joined as _;
 use crate::html::markdown::LangString;
 
 /// This struct contains information about the doctest itself which is then used to generate
@@ -232,13 +234,15 @@ impl DocTestBuilder {
 
             // add extra 4 spaces for each line to offset the code block
             if opts.insert_indent_space {
-                prog.push_str(
-                    &everything_else
+                write!(
+                    prog,
+                    "{}",
+                    fmt::from_fn(|f| everything_else
                         .lines()
-                        .map(|line| format!("    {}", line))
-                        .collect::>()
-                        .join("\n"),
-                );
+                        .map(|line| fmt::from_fn(move |f| write!(f, "    {line}")))
+                        .joined("\n", f))
+                )
+                .unwrap();
             } else {
                 prog.push_str(everything_else);
             };
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index d2d7415261b9..f32011470399 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -2,7 +2,6 @@ use std::cmp::Ordering;
 use std::fmt;
 use std::fmt::Display;
 
-use itertools::Itertools;
 use rinja::Template;
 use rustc_abi::VariantIdx;
 use rustc_data_structures::captures::Captures;
@@ -514,11 +513,7 @@ fn item_module(w: &mut String, cx: &Context<'_>, item: &clean::Item, items: &[cl
                         class = myitem.type_(),
                         unsafety_flag = unsafety_flag,
                         href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
-                        title = [myitem.type_().to_string(), full_path(cx, myitem)]
-                            .iter()
-                            .filter_map(|s| if !s.is_empty() { Some(s.as_str()) } else { None })
-                            .collect::>()
-                            .join(" "),
+                        title = format_args!("{} {}", myitem.type_(), full_path(cx, myitem)),
                     ),
                 );
             }
@@ -915,7 +910,7 @@ fn item_trait(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                 w,
                 format_args!(
                     "
At least one of the `{}` methods is required.
", - list.iter().join("`, `") + fmt::from_fn(|f| list.iter().joined("`, `", f)) ), ); } @@ -1168,17 +1163,18 @@ fn item_trait(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra js_src_path.extend(cx.current.iter().copied()); js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap())); } - let extern_crates = extern_crates - .into_iter() - .map(|cnum| tcx.crate_name(cnum).to_string()) - .collect::>() - .join(","); - let (extern_before, extern_after) = - if extern_crates.is_empty() { ("", "") } else { (" data-ignore-extern-crates=\"", "\"") }; + let extern_crates = fmt::from_fn(|f| { + if !extern_crates.is_empty() { + f.write_str(" data-ignore-extern-crates=\"")?; + extern_crates.iter().map(|&cnum| tcx.crate_name(cnum)).joined(",", f)?; + f.write_str("\"")?; + } + Ok(()) + }); write_str( w, format_args!( - "", + "", src = js_src_path.finish() ), ); @@ -1400,7 +1396,7 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean .collect(); js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap())); - let self_path = self_fqp.iter().map(Symbol::as_str).collect::>().join("::"); + let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f)); write_str( w, format_args!( From 59e9eb9b2bce23fb948a3944adb127206e73d1e4 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 11 Feb 2025 22:33:18 -0800 Subject: [PATCH 126/158] cg_clif: use exclusively ABI alignment --- compiler/rustc_codegen_cranelift/src/abi/comments.rs | 5 ++--- compiler/rustc_codegen_cranelift/src/constant.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs index 521a250ab82c..e2c9f40d1479 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs @@ -65,7 +65,7 @@ pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { if fx.clif_comments.enabled() { fx.add_global_comment(String::new()); fx.add_global_comment( - "kind local ty size align (abi,pref)".to_string(), + "kind local ty size align (abi)".to_string(), ); } } @@ -84,13 +84,12 @@ pub(super) fn add_local_place_comments<'tcx>( let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( - "{:<5} {:5} {:30} {:4}b {}, {}{}{}", + "{:<5} {:5} {:30} {:4}b {}, {}{}", kind, format!("{:?}", local), format!("{:?}", ty), size.bytes(), align.abi.bytes(), - align.pref.bytes(), if extra.is_empty() { "" } else { " " }, extra, )); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 425b2adf32a3..bcc70f4567fb 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -272,7 +272,7 @@ fn data_id_for_static( .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .unwrap() .align - .pref + .abi .bytes(); let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak From fd7b4bf4e19b19ebf9b536790ec1668a3e50fe6f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Feb 2025 14:17:57 +1100 Subject: [PATCH 127/158] Move methods from `Map` to `TyCtxt`, part 2. Continuing the work started in #136466. Every method gains a `hir_` prefix, though for the ones that already have a `par_` or `try_par_` prefix I added the `hir_` after that. --- .../src/diagnostics/conflict_errors.rs | 16 +- .../src/diagnostics/move_errors.rs | 6 +- .../src/diagnostics/mutability_errors.rs | 23 +-- .../src/diagnostics/region_errors.rs | 3 +- .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- .../rustc_borrowck/src/universal_regions.rs | 2 +- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- .../rustc_const_eval/src/check_consts/mod.rs | 2 +- compiler/rustc_driver_impl/src/pretty.rs | 7 +- compiler/rustc_hir/src/intravisit.rs | 6 +- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 5 +- .../rustc_hir_analysis/src/check/region.rs | 6 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../rustc_hir_analysis/src/check_unused.rs | 4 +- .../src/coherence/inherent_impls.rs | 2 +- .../src/collect/predicates_of.rs | 4 +- .../src/collect/resolve_bound_vars.rs | 4 +- .../src/collect/type_of/opaque.rs | 2 +- .../src/hir_ty_lowering/generics.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 10 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 4 +- compiler/rustc_hir_analysis/src/lib.rs | 6 +- compiler/rustc_hir_typeck/src/_match.rs | 4 +- compiler/rustc_hir_typeck/src/callee.rs | 2 +- compiler/rustc_hir_typeck/src/check.rs | 6 +- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 4 +- compiler/rustc_hir_typeck/src/expr.rs | 6 +- .../rustc_hir_typeck/src/expr_use_visitor.rs | 5 +- compiler/rustc_hir_typeck/src/fallback.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 13 +- .../rustc_hir_typeck/src/method/suggest.rs | 6 +- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 8 +- .../rustc_incremental/src/assert_dep_graph.rs | 2 +- .../src/persist/dirty_clean.rs | 2 +- compiler/rustc_interface/src/limits.rs | 8 +- compiler/rustc_interface/src/passes.rs | 18 +- .../src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_lint/src/late.rs | 6 +- compiler/rustc_lint/src/levels.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- compiler/rustc_middle/src/hir/map.rs | 171 +++++++++--------- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 8 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 2 +- compiler/rustc_mir_build/src/builder/mod.rs | 7 +- .../rustc_mir_build/src/check_unsafety.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 7 +- .../src/thir/pattern/const_to_pat.rs | 2 +- .../rustc_mir_transform/src/check_inline.rs | 2 +- .../src/ffi_unwind_calls.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 2 +- .../rustc_mir_transform/src/instsimplify.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 8 +- compiler/rustc_passes/src/check_attr.rs | 6 +- compiler/rustc_passes/src/dead.rs | 4 +- compiler/rustc_passes/src/hir_id_validator.rs | 4 +- compiler/rustc_passes/src/input_stats.rs | 4 +- compiler/rustc_passes/src/lib_features.rs | 2 +- compiler/rustc_passes/src/liveness.rs | 7 +- compiler/rustc_passes/src/loops.rs | 2 +- compiler/rustc_passes/src/stability.rs | 8 +- compiler/rustc_passes/src/upvars.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 8 +- .../error_reporting/infer/need_type_info.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 4 +- .../trait_impl_difference.rs | 3 +- .../infer/nice_region_error/util.rs | 6 +- .../src/error_reporting/infer/suggest.rs | 2 +- .../src/error_reporting/traits/ambiguity.rs | 2 +- .../traits/fulfillment_errors.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 15 +- compiler/rustc_ty_utils/src/opaque_types.rs | 2 +- src/librustdoc/clean/types.rs | 4 +- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/core.rs | 7 +- src/librustdoc/doctest/rust.rs | 2 +- src/librustdoc/html/render/span_map.rs | 10 +- src/librustdoc/json/conversions.rs | 2 +- src/librustdoc/scrape_examples.rs | 5 +- .../src/default_numeric_fallback.rs | 3 +- .../clippy/clippy_lints/src/enum_clike.rs | 2 +- .../src/functions/impl_trait_in_params.rs | 4 +- .../src/functions/renamed_function_params.rs | 2 +- .../clippy_lints/src/manual_float_methods.rs | 2 +- .../src/methods/option_map_unwrap_or.rs | 3 +- .../src/needless_borrows_for_generic_args.rs | 4 +- .../src/needless_pass_by_ref_mut.rs | 2 +- .../src/operators/arithmetic_side_effects.rs | 8 +- .../src/operators/numeric_arithmetic.rs | 8 +- .../clippy_lints/src/redundant_locals.rs | 2 +- src/tools/clippy/clippy_lints/src/shadow.rs | 8 +- .../clippy/clippy_lints/src/single_call_fn.rs | 3 +- .../missing_transmute_annotations.rs | 4 +- .../src/unconditional_recursion.rs | 4 +- .../clippy/clippy_lints/src/utils/author.rs | 3 +- .../internal_lints/lint_without_lint_pass.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 10 +- src/tools/clippy/clippy_utils/src/mir/mod.rs | 4 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 4 +- 108 files changed, 314 insertions(+), 346 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 59c76cb7f2bb..e778340cb65d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -386,8 +386,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { hir::intravisit::walk_pat(self, p); } } + let tcx = self.infcx.tcx; let hir = self.infcx.tcx.hir(); - if let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) { + if let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) { let expr = body.value; let place = &self.move_data.move_paths[mpi].place; let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span); @@ -396,7 +397,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { expr: None, pat: None, parent_pat: None, - tcx: self.infcx.tcx, + tcx, }; finder.visit_expr(expr); if let Some(span) = span @@ -782,9 +783,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // We use the statements were the binding was initialized, and inspect the HIR to look // for the branching codepaths that aren't covered, to point at them. - let map = self.infcx.tcx.hir(); - let body = map.body_owned_by(self.mir_def_id()); - let mut visitor = ConditionVisitor { tcx: self.infcx.tcx, spans, name, errors: vec![] }; + let tcx = self.infcx.tcx; + let body = tcx.hir_body_owned_by(self.mir_def_id()); + let mut visitor = ConditionVisitor { tcx, spans, name, errors: vec![] }; visitor.visit_body(&body); let spans = visitor.spans; @@ -2443,7 +2444,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return }; let tcx = self.infcx.tcx; - let hir = tcx.hir(); // Get the type of the local that we are trying to borrow let local = borrowed_place.local; @@ -2522,7 +2522,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Find the first argument with a matching type, get its name let Some((_, this_name)) = - params.iter().zip(hir.body_param_names(closure.body)).find(|(param_ty, name)| { + params.iter().zip(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| { // FIXME: also support deref for stuff like `Rc` arguments param_ty.peel_refs() == local_ty && name != &Ident::empty() }) @@ -4178,7 +4178,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); let is_closure = self.infcx.tcx.is_closure_like(did.to_def_id()); let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did); - let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; + let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(fn_hir_id)?; // We need to work out which arguments to highlight. We do this by looking // at the return type, where there are three cases: diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 38f22473edfa..ddf6187a662e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -777,12 +777,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } let Some(pat_span) = pat_span else { return }; - let hir = self.infcx.tcx.hir(); - let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) else { return }; + let tcx = self.infcx.tcx; + let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) else { return }; let typeck_results = self.infcx.tcx.typeck(self.mir_def_id()); let mut finder = BindingFinder { typeck_results, - tcx: self.infcx.tcx, + tcx, pat_span, binding_spans, found_pat: false, diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index fc782ce64249..be83e61f75d8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -648,10 +648,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } } - let hir_map = self.infcx.tcx.hir(); let def_id = self.body.source.def_id(); let Some(local_def_id) = def_id.as_local() else { return }; - let Some(body) = hir_map.maybe_body_owned_by(local_def_id) else { return }; + let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id) else { return }; let mut v = SuggestIndexOperatorAlternativeVisitor { assign_span: span, @@ -749,7 +748,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)` let def_id = self.body.source.def_id(); if let Some(local_def_id) = def_id.as_local() - && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) + && let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id) && let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value() && let node = self.infcx.tcx.hir_node(hir_id) && let hir::Node::LetStmt(hir::LetStmt { @@ -856,7 +855,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { use hir::ExprKind::{AddrOf, Block, Call, MethodCall}; use hir::{BorrowKind, Expr}; - let hir_map = self.infcx.tcx.hir(); + let tcx = self.infcx.tcx; struct Finder { span: Span, } @@ -871,7 +870,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } } - if let Some(body) = hir_map.maybe_body_owned_by(self.mir_def_id()) + if let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) && let Block(block, _) = body.value.kind { // `span` corresponds to the expression being iterated, find the `for`-loop desugared @@ -884,17 +883,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { MethodCall(path_segment, _, _, span) => { // We have `for _ in iter.read_only_iter()`, try to // suggest `for _ in iter.mutable_iter()` instead. - let opt_suggestions = self - .infcx - .tcx + let opt_suggestions = tcx .typeck(path_segment.hir_id.owner.def_id) .type_dependent_def_id(expr.hir_id) - .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id)) - .map(|def_id| self.infcx.tcx.associated_items(def_id)) + .and_then(|def_id| tcx.impl_of_method(def_id)) + .map(|def_id| tcx.associated_items(def_id)) .map(|assoc_items| { assoc_items .in_definition_order() - .map(|assoc_item_def| assoc_item_def.ident(self.infcx.tcx)) + .map(|assoc_item_def| assoc_item_def.ident(tcx)) .filter(|&ident| { let original_method_ident = path_segment.ident; original_method_ident != ident @@ -942,7 +939,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let closure_span = tcx.def_span(self.mir_def_id()); let fn_call_id = tcx.parent_hir_id(closure_id); let node = tcx.hir_node(fn_call_id); - let def_id = hir.enclosing_body_owner(fn_call_id); + let def_id = tcx.hir_enclosing_body_owner(fn_call_id); let mut look_at_return = true; // If the HIR node is a function or method call gets the def ID @@ -1275,7 +1272,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }) => { let def_id = self.body.source.def_id(); let hir_id = if let Some(local_def_id) = def_id.as_local() - && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) + && let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id) { BindingFinder { span: err_label_span }.visit_body(&body).break_value() } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d3c91cbdee9c..55b6367f35ff 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1169,8 +1169,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { #[allow(rustc::diagnostic_outside_of_impl)] fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) { - let map = self.infcx.tcx.hir(); - let body = map.body_owned_by(self.mir_def_id()); + let body = self.infcx.tcx.hir_body_owned_by(self.mir_def_id()); let expr = &body.value.peel_blocks(); let mut closure_span = None::; match expr.kind { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index ccd13badad74..b036e6e950b9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -424,7 +424,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { &self, argument_index: usize, ) -> Option<&hir::Ty<'tcx>> { - let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(self.mir_hir_id())?; + let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(self.mir_hir_id())?; let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?; match argument_hir_ty.kind { // This indicates a variable with no type annotation, like diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 53cf4f34ae79..22ce0fd1ea79 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -188,7 +188,7 @@ fn do_mir_borrowck<'tcx>( .iterate_to_fixpoint(tcx, body, Some("borrowck")) .into_results_cursor(body); - let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure(); + let locals_are_invalidated_at_exit = tcx.hir_body_owner_kind(def).is_fn_or_closure(); let borrow_set = BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data); // Compute non-lexical lifetimes. diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index eb0079a3883f..4e6f82ac8492 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -576,7 +576,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let tcx = self.infcx.tcx; let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id()); - match tcx.hir().body_owner_kind(self.mir_def) { + match tcx.hir_body_owner_kind(self.mir_def) { BodyOwnerKind::Closure | BodyOwnerKind::Fn => { let defining_ty = tcx.type_of(self.mir_def).instantiate_identity(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 54c5d445f66b..4ffe551df09b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -87,7 +87,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { let omit_gdb_pretty_printer_section = - attr::contains_name(cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); + attr::contains_name(cx.tcx.hir_krate_attrs(), sym::omit_gdb_pretty_printer_section); // To ensure the section `__rustc_debug_gdb_scripts_section__` will not create // ODR violations at link time, this section will not be emitted for rlibs since diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index bfa0a0319c34..52e000858b4c 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -31,7 +31,7 @@ pub struct ConstCx<'mir, 'tcx> { impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self { let typing_env = body.typing_env(tcx); - let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local()); + let const_kind = tcx.hir_body_const_context(body.source.def_id().expect_local()); ConstCx { body, tcx, typing_env, const_kind } } diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 093ee659bb42..828a14e707c5 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -164,8 +164,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> { if let pprust_hir::AnnNode::Expr(expr) = node { let typeck_results = self.maybe_typeck_results.get().or_else(|| { self.tcx - .hir() - .maybe_body_owned_by(expr.hir_id.owner.def_id) + .hir_maybe_body_owned_by(expr.hir_id.owner.def_id) .map(|body_id| self.tcx.typeck_body(body_id.id())) }); @@ -317,7 +316,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { rustc_hir_analysis::check_crate(tcx); tcx.dcx().abort_if_errors(); debug!("pretty printing THIR tree"); - for did in tcx.hir().body_owners() { + for did in tcx.hir_body_owners() { let _ = writeln!(out, "{:?}:\n{}\n", did, thir_tree(tcx, did)); } out @@ -328,7 +327,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { rustc_hir_analysis::check_crate(tcx); tcx.dcx().abort_if_errors(); debug!("pretty printing THIR flat"); - for did in tcx.hir().body_owners() { + for did in tcx.hir_body_owners() { let _ = writeln!(out, "{:?}:\n{}\n", did, thir_flat(tcx, did)); } out diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 949f8daa4dcf..bd96fe9ee32c 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -19,7 +19,7 @@ //! - Example: Examine each expression to look for its type and do some check or other. //! - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to //! `nested_filter::OnlyBodies` (and implement `maybe_tcx`), and use -//! `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your +//! `tcx.hir_visit_all_item_likes_in_crate(&mut visitor)`. Within your //! `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke //! `intravisit::walk_expr()` to keep walking the subparts). //! - Pro: Visitor methods for any kind of HIR node, not just item-like things. @@ -31,7 +31,7 @@ //! impl into scope while visiting the impl-items, and then back out again. //! - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to //! `nested_filter::All` (and implement `maybe_tcx`). Walk your crate with -//! `tcx.hir().walk_toplevel_module(visitor)` invoked on `tcx.hir().krate()`. +//! `tcx.hir_walk_toplevel_module(visitor)`. //! - Pro: Visitor methods for any kind of HIR node, not just item-like things. //! - Pro: Preserves nesting information //! - Con: Does not integrate well into dependency tracking. @@ -193,7 +193,7 @@ use nested_filter::NestedFilter; /// (this is why the module is called `intravisit`, to distinguish it /// from the AST's `visit` module, which acts differently). If you /// simply want to visit all items in the crate in some order, you -/// should call `tcx.hir().visit_all_item_likes_in_crate`. Otherwise, see the comment +/// should call `tcx.hir_visit_all_item_likes_in_crate`. Otherwise, see the comment /// on `visit_nested_item` for details on how to visit nested items. /// /// If you want to ensure that your code handles every variant diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index bc0fd4b705d0..516ecbcfe0ef 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -484,7 +484,7 @@ fn best_definition_site_of_opaque<'tcx>( hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id)); let found = if scope == hir::CRATE_HIR_ID { - tcx.hir().walk_toplevel_module(&mut locator) + tcx.hir_walk_toplevel_module(&mut locator) } else { match tcx.hir_node(scope) { Node::Item(it) => locator.visit_item(it), diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 84d5ec4a1e5b..0dd8296e66c2 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -501,7 +501,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); - let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); + let return_span = tcx.hir_fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); let cause = ObligationCause::new( return_span, impl_m_def_id, @@ -1033,8 +1033,7 @@ fn report_trait_method_mismatch<'tcx>( // argument pattern and type. let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); let span = tcx - .hir() - .body_param_names(body) + .hir_body_param_names(body) .zip(sig.decl.inputs.iter()) .map(|(param, ty)| param.span.to(ty.span)) .next() diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 88dd40ba2898..255f5fee52a8 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -844,7 +844,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { fn visit_body(&mut self, body: &hir::Body<'tcx>) { let body_id = body.id(); - let owner_id = self.tcx.hir().body_owner_def_id(body_id); + let owner_id = self.tcx.hir_body_owner_def_id(body_id); debug!( "visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})", @@ -855,7 +855,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { ); self.enter_body(body.value.hir_id, |this| { - if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { + if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. this.cx.var_parent = this.cx.parent.take(); for param in body.params { @@ -924,7 +924,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { return tcx.region_scope_tree(typeck_root_def_id); } - let scope_tree = if let Some(body) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) { + let scope_tree = if let Some(body) = tcx.hir_maybe_body_owned_by(def_id.expect_local()) { let mut visitor = ScopeResolutionVisitor { tcx, scope_tree: ScopeTree::default(), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 01b4a5649f14..edfa897860b7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1710,7 +1710,7 @@ fn check_sized_if_body<'tcx>( maybe_span: Option, ) { let tcx = wfcx.tcx(); - if let Some(body) = tcx.hir().maybe_body_owned_by(def_id) { + if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) { let span = maybe_span.unwrap_or(body.value.span); wfcx.register_bound( diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 68b7b44c36d6..750c09887a1e 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -13,11 +13,11 @@ pub(crate) fn provide(providers: &mut Providers) { fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) { let mut used_trait_imports = UnordSet::::default(); - // FIXME: Use `tcx.hir().par_body_owners()` when we implement creating `DefId`s + // FIXME: Use `tcx.hir_par_body_owners()` when we implement creating `DefId`s // for anon constants during their parents' typeck. // Doing so at current will produce queries cycle errors because it may typeck // on anon constants directly. - for item_def_id in tcx.hir().body_owners() { + for item_def_id in tcx.hir_body_owners() { let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend_unord(imports.items().copied()); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 1805e2438afa..c9a9180c5c9d 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -113,7 +113,7 @@ impl<'tcx> InherentCollect<'tcx> { ty: Ty<'tcx>, ) -> Result<(), ErrorGuaranteed> { let items = self.tcx.associated_item_def_ids(impl_def_id); - if !self.tcx.hir().rustc_coherence_is_core() { + if !self.tcx.hir_rustc_coherence_is_core() { if self.tcx.features().rustc_attrs() { for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 70e7451a5fb0..7b1fff157b54 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -435,7 +435,7 @@ fn const_evaluatable_predicates_of<'tcx>( self_ty.instantiate_identity().visit_with(&mut collector); } - if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) { + if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) { debug!("visit fn sig"); let fn_sig = tcx.fn_sig(def_id); let fn_sig = fn_sig.instantiate_identity(); @@ -825,7 +825,7 @@ pub(super) fn type_param_predicates<'tcx>( // `where T: Foo`. let param_id = tcx.local_def_id_to_hir_id(def_id); - let param_owner = tcx.hir().ty_param_owner(def_id); + let param_owner = tcx.hir_ty_param_owner(def_id); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 5a8a2f1fe28e..759c981a8f76 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1340,7 +1340,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; def = ResolvedArg::Error(guar); } else if let Some(body_id) = outermost_body { - let fn_id = self.tcx.hir().body_owner(body_id); + let fn_id = self.tcx.hir_body_owner(body_id); match self.tcx.hir_node(fn_id) { Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. }) | Node::TraitItem(hir::TraitItem { @@ -2265,7 +2265,7 @@ fn is_late_bound_map( tcx: TyCtxt<'_>, owner_id: hir::OwnerId, ) -> Option<&FxIndexSet> { - let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?; + let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?; let generics = tcx.hir_get_generics(owner_id.def_id)?; let mut late_bound = FxIndexSet::default(); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 88d4acbdd8dc..0c36888f3639 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -89,7 +89,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local debug!(?scope); if scope == hir::CRATE_HIR_ID { - tcx.hir().walk_toplevel_module(&mut locator); + tcx.hir_walk_toplevel_module(&mut locator); } else { trace!("scope={:#?}", tcx.hir_node(scope)); match tcx.hir_node(scope) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index cc28b8780c61..17de64db6290 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -70,7 +70,7 @@ fn generic_arg_mismatch_err( } Res::Def(DefKind::TyParam, src_def_id) => { if let Some(param_local_id) = param.def_id.as_local() { - let param_name = tcx.hir().ty_param_name(param_local_id); + let param_name = tcx.hir_ty_param_name(param_local_id); let param_type = tcx.type_of(param.def_id).instantiate_identity(); if param_type.is_suggestable(tcx, false) { err.span_suggestion( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7dce8b9b60f8..ec8343bb2bfe 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -217,7 +217,7 @@ impl AssocItemQSelf { fn to_string(&self, tcx: TyCtxt<'_>) -> String { match *self { Self::Trait(def_id) => tcx.def_path_str(def_id), - Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(), + Self::TyParam(def_id, _) => tcx.hir_ty_param_name(def_id).to_string(), Self::SelfTyAlias => kw::SelfUpper.to_string(), } } @@ -342,8 +342,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } rbv::ResolvedArg::EarlyBound(def_id) => { - let name = tcx.hir().ty_param_name(def_id); - let item_def_id = tcx.hir().ty_param_owner(def_id); + let name = tcx.hir_ty_param_name(def_id); + let item_def_id = tcx.hir_ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name }) @@ -2070,10 +2070,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { - let item_def_id = tcx.hir().ty_param_owner(def_id); + let item_def_id = tcx.hir_ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)) + Ty::new_param(tcx, index, tcx.hir_ty_param_name(def_id)) } Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index f5abcd234401..0b1be8e4f7a9 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -22,8 +22,6 @@ fn diagnostic_hir_wf_check<'tcx>( tcx: TyCtxt<'tcx>, (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc), ) -> Option> { - let hir = tcx.hir(); - let def_id = match loc { WellFormedLoc::Ty(def_id) => def_id, WellFormedLoc::Param { function, param_idx: _ } => function, @@ -187,7 +185,7 @@ fn diagnostic_hir_wf_check<'tcx>( ref node => bug!("Unexpected node {:?}", node), }, WellFormedLoc::Param { function: _, param_idx } => { - let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap(); + let fn_decl = tcx.hir_fn_decl_by_hir_id(hir_id).unwrap(); // Get return type if param_idx as usize == fn_decl.inputs.len() { match fn_decl.output { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 886360dfb6cf..66d7c9377edd 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -183,7 +183,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // what we are intending to discard, to help future type-based refactoring. type R = Result<(), ErrorGuaranteed>; - tcx.hir().par_for_each_module(|module| { + tcx.par_hir_for_each_module(|module| { let _: R = tcx.ensure_ok().check_mod_type_wf(module); }); @@ -208,7 +208,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // Make sure we evaluate all static and (non-associated) const items, even if unused. // If any of these fail to evaluate, we do not want this crate to pass compilation. - tcx.hir().par_body_owners(|item_def_id| { + tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); match def_kind { DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id), @@ -226,7 +226,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // for anon constants during their parents' typeck. // Typeck all body owners in parallel will produce queries // cycle errors because it may typeck on anon constants directly. - tcx.hir().par_body_owners(|item_def_id| { + tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); if !matches!(def_kind, DefKind::AnonConst) { tcx.ensure_ok().typeck(item_def_id); diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 3d40c5ee8045..38319862334a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -213,10 +213,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arm_ty: Ty<'tcx>, prior_arm: Option<(Option, Ty<'tcx>, Span)>, ) { - let hir = self.tcx.hir(); - // First, check that we're actually in the tail of a function. - let Some(body) = hir.maybe_body_owned_by(self.body_id) else { + let Some(body) = self.tcx.hir_maybe_body_owned_by(self.body_id) else { return; }; let hir::ExprKind::Block(block, _) = body.value.kind else { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index bccde7822645..49ea2181b075 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -860,7 +860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let host = match self.tcx.hir().body_const_context(self.body_id) { + let host = match self.tcx.hir_body_const_context(self.body_id) { Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => { ty::BoundConstness::Const } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 6fb5f6af0913..dabae7b1d094 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -35,12 +35,8 @@ pub(super) fn check_fn<'a, 'tcx>( params_can_be_unsized: bool, ) -> Option> { let fn_id = fcx.tcx.local_def_id_to_hir_id(fn_def_id); - let tcx = fcx.tcx; - let hir = tcx.hir(); - let declared_ret_ty = fn_sig.output(); - let ret_ty = fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars( declared_ret_ty, @@ -69,7 +65,7 @@ pub(super) fn check_fn<'a, 'tcx>( }); // Add formal parameters. - let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs); + let inputs_hir = tcx.hir_fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs); let inputs_fn = fn_sig.inputs().iter().copied(); for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { // We checked the root's signature during wfcheck, but not the child. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index c8433d0cb5b1..cf11bccae0ac 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1943,7 +1943,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if due_to_block && let Some(expr) = expression && let Some(parent_fn_decl) = - fcx.tcx.hir().fn_decl_by_hir_id(fcx.tcx.local_def_id_to_hir_id(fcx.body_id)) + fcx.tcx.hir_fn_decl_by_hir_id(fcx.tcx.local_def_id_to_hir_id(fcx.body_id)) { fcx.suggest_missing_break_or_return_expr( &mut err, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2f7f91480233..4dc736f72cf8 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -293,8 +293,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, source: TypeMismatchSource<'tcx>, ) -> bool { - let hir = self.tcx.hir(); - let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; }; @@ -334,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() }; - let body = hir.body_owned_by(self.body_id); + let body = self.tcx.hir_body_owned_by(self.body_id); expr_finder.visit_expr(body.value); // Replaces all of the variables in the given type with a fresh inference variable. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a41ad94f95e2..b46d7c490639 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1150,13 +1150,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We are inside a function body, so reporting "return statement // outside of function body" needs an explanation. - let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id); + let encl_body_owner_id = self.tcx.hir_enclosing_body_owner(expr.hir_id); // If this didn't hold, we would not have to report an error in // the first place. assert_ne!(encl_item_id.def_id, encl_body_owner_id); - let encl_body = self.tcx.hir().body_owned_by(encl_body_owner_id); + let encl_body = self.tcx.hir_body_owned_by(encl_body_owner_id); err.encl_body_span = Some(encl_body.value.span); err.encl_fn_span = Some(*encl_fn_span); @@ -3229,7 +3229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => return, }; let param_span = self.tcx.hir().span(param_hir_id); - let param_name = self.tcx.hir().ty_param_name(param_def_id.expect_local()); + let param_name = self.tcx.hir_ty_param_name(param_def_id.expect_local()); err.span_label(param_span, format!("type parameter '{param_name}' declared here")); } diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 860e619be718..9b85b2aeec6e 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1001,11 +1001,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let closure_def_id = closure_expr.def_id; // For purposes of this function, coroutine and closures are equivalent. let body_owner_is_closure = matches!( - tcx.hir().body_owner_kind(self.cx.body_owner_def_id()), + tcx.hir_body_owner_kind(self.cx.body_owner_def_id()), hir::BodyOwnerKind::Closure ); - // If we have a nested closure, we want to include the fake reads present in the nested closure. + // If we have a nested closure, we want to include the fake reads present in the nested + // closure. if let Some(fake_reads) = self.cx.typeck_results().closure_fake_reads.get(&closure_def_id) { for (fake_read, cause, hir_id) in fake_reads.iter() { match fake_read.base { diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index ce6f7420e5ba..e051fc7ac6ca 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -573,7 +573,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { coercions: &VecGraph, ) -> errors::SuggestAnnotations { let body = - self.tcx.hir().maybe_body_owned_by(self.body_id).expect("body id must have an owner"); + self.tcx.hir_maybe_body_owned_by(self.body_id).expect("body id must have an owner"); // For each diverging var, look through the HIR for a place to give it // a type annotation. We do this per var because we only really need one // suggestion to influence a var to be `()`. @@ -764,7 +764,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, body_id: LocalDefId, ) -> UnordMap { - let body = fcx.tcx.hir().maybe_body_owned_by(body_id).expect("body id must have an owner"); + let body = fcx.tcx.hir_maybe_body_owned_by(body_id).expect("body id must have an owner"); let mut res = UnordMap::default(); struct UnsafeInferVarsVisitor<'a, 'tcx> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c0af5ea7bbff..7ca44d23e3ed 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut(); debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len()); for (asm, hir_id) in deferred_asm_checks.drain(..) { - let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id); + let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id); let get_operand_ty = |expr| { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index b77e6de52ff1..42236ac6d808 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -290,7 +290,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { _: Ident, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let tcx = self.tcx; - let item_def_id = tcx.hir().ty_param_owner(def_id); + let item_def_id = tcx.hir_ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; // HACK(eddyb) should get the original `Span`. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 05c76b3c5681..347a6557c2aa 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1811,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead" ), ); - let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id); + let owner = self.tcx.hir_enclosing_body_owner(expr.hir_id); if let ty::Param(param) = expected_ty.kind() && let Some(generics) = self.tcx.hir_get_generics(owner) { @@ -2094,9 +2094,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'tcx>, expected: Ty<'tcx>, ) -> bool { - let hir = self.tcx.hir(); + let tcx = self.tcx; + let hir = tcx.hir(); let enclosing_scope = - hir.get_enclosing_scope(expr.hir_id).map(|hir_id| self.tcx.hir_node(hir_id)); + hir.get_enclosing_scope(expr.hir_id).map(|hir_id| tcx.hir_node(hir_id)); // Get tail expr of the enclosing block or body let tail_expr = if let Some(Node::Block(hir::Block { expr, .. })) = enclosing_scope @@ -2104,8 +2105,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { *expr } else { - let body_def_id = hir.enclosing_body_owner(expr.hir_id); - let body = hir.body_owned_by(body_def_id); + let body_def_id = tcx.hir_enclosing_body_owner(expr.hir_id); + let body = tcx.hir_body_owned_by(body_def_id); // Get tail expr of the body match body.value.kind { @@ -2147,7 +2148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ("consider returning a value here", format!("`{expected}` value")) }; - let src_map = self.tcx.sess.source_map(); + let src_map = tcx.sess.source_map(); let suggestion = if src_map.is_multiline(expr.span) { let indentation = src_map.indentation_before(span).unwrap_or_else(String::new); format!("\n{indentation}/* {suggestion} */") diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1ca8b59db223..780ab8c18334 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -531,7 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::def::Res::Local(recv_id) = path.res && let Some(segment) = path.segments.first() { - let body = self.tcx.hir().body_owned_by(self.body_id); + let body = self.tcx.hir_body_owned_by(self.body_id); if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) { let mut let_visitor = LetVisitor { @@ -2599,7 +2599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { seg1.ident.span, StashKey::CallAssocMethod, |err| { - let body = self.tcx.hir().body_owned_by(self.body_id); + let body = self.tcx.hir_body_owned_by(self.body_id); struct LetVisitor { ident_name: Symbol, } @@ -3336,7 +3336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_sugg = sugg(accessible_candidates, true); let inaccessible_sugg = sugg(inaccessible_candidates, false); - let (module, _, _) = self.tcx.hir().get_module(scope); + let (module, _, _) = self.tcx.hir_get_module(scope); let span = module.spans.inject_use_span; handle_candidates(accessible_sugg, inaccessible_sugg, span); } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 871d08137b34..762d04fdedd4 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let args = self.resolve_vars_if_possible(args); let closure_def_id = closure_def_id.expect_local(); - assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id); + assert_eq!(self.tcx.hir_body_owner_def_id(body.id()), closure_def_id); let mut delegate = InferBorrowKind { closure_def_id, capture_information: Default::default(), diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index dbcf99157905..8c50cc59c1d5 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, body: &'tcx hir::Body<'tcx>, ) -> &'tcx ty::TypeckResults<'tcx> { - let item_def_id = self.tcx.hir().body_owner_def_id(body.id()); + let item_def_id = self.tcx.hir_body_owner_def_id(body.id()); // This attribute causes us to dump some writeback information // in the form of errors, which is used for unit tests. @@ -49,7 +49,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_node_id(param.pat.span, param.hir_id); } // Type only exists for constants and statics, not functions. - match self.tcx.hir().body_owner_kind(item_def_id) { + match self.tcx.hir_body_owner_kind(item_def_id) { hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => { let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id); wbcx.visit_node_id(body.value.span, item_hir_id); @@ -790,7 +790,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { self.fcx .err_ctxt() .emit_inference_failure_err( - self.fcx.tcx.hir().body_owner_def_id(self.body.id()), + self.fcx.tcx.hir_body_owner_def_id(self.body.id()), self.span.to_span(self.fcx.tcx), p.into(), TypeAnnotationNeeded::E0282, @@ -814,7 +814,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { // expect that types that show up in the typeck are fully // normalized. let mut value = if self.should_normalize { - let body_id = tcx.hir().body_owner_def_id(self.body.id()); + let body_id = tcx.hir_body_owner_def_id(self.body.id()); let cause = ObligationCause::misc(self.span.to_span(tcx), body_id); let at = self.fcx.at(&cause, self.fcx.param_env); let universes = vec![None; outer_exclusive_binder(value).as_usize()]; diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index c2f9ebc5262a..d4407559202f 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -76,7 +76,7 @@ pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; visitor.process_attrs(CRATE_DEF_ID); - tcx.hir().visit_all_item_likes_in_crate(&mut visitor); + tcx.hir_visit_all_item_likes_in_crate(&mut visitor); (visitor.if_this_changed, visitor.then_this_would_need) }; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index a95599e7a860..118a6fed036e 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -166,7 +166,7 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; - tcx.hir().walk_attributes(&mut all_attrs); + tcx.hir_walk_attributes(&mut all_attrs); // Note that we cannot use the existing "unused attribute"-infrastructure // here, since that is running before codegen. This is also the reason why diff --git a/compiler/rustc_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs index 3de513797e3e..8f01edec09f3 100644 --- a/compiler/rustc_interface/src/limits.rs +++ b/compiler/rustc_interface/src/limits.rs @@ -20,21 +20,21 @@ use crate::errors::LimitInvalid; pub(crate) fn provide(providers: &mut Providers) { providers.limits = |tcx, ()| Limits { - recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess), + recursion_limit: get_recursion_limit(tcx.hir_krate_attrs(), tcx.sess), move_size_limit: get_limit( - tcx.hir().krate_attrs(), + tcx.hir_krate_attrs(), tcx.sess, sym::move_size_limit, Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0)), ), type_length_limit: get_limit( - tcx.hir().krate_attrs(), + tcx.hir_krate_attrs(), tcx.sess, sym::type_length_limit, Limit::new(2usize.pow(24)), ), pattern_complexity_limit: get_limit( - tcx.hir().krate_attrs(), + tcx.hir_krate_attrs(), tcx.sess, sym::pattern_complexity_limit, Limit::unlimited(), diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d7d183e17edb..d70d9d344b94 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -846,7 +846,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { CStore::from_tcx(tcx).report_unused_deps(tcx); }, { - tcx.hir().par_for_each_module(|module| { + tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_loops(module); tcx.ensure_ok().check_mod_attrs(module); tcx.ensure_ok().check_mod_naked_functions(module); @@ -871,7 +871,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { rustc_hir_analysis::check_crate(tcx); sess.time("MIR_coroutine_by_move_body", || { - tcx.hir().par_body_owners(|def_id| { + tcx.par_hir_body_owners(|def_id| { if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { tcx.ensure_done().coroutine_by_move_body_def_id(def_id); } @@ -885,7 +885,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.untracked().definitions.freeze(); sess.time("MIR_borrow_checking", || { - tcx.hir().par_body_owners(|def_id| { + tcx.par_hir_body_owners(|def_id| { // Run unsafety check because it's responsible for stealing and // deallocating THIR. tcx.ensure_ok().check_unsafety(def_id); @@ -893,21 +893,21 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { }); }); sess.time("MIR_effect_checking", || { - tcx.hir().par_body_owners(|def_id| { + tcx.par_hir_body_owners(|def_id| { tcx.ensure_ok().has_ffi_unwind_calls(def_id); // If we need to codegen, ensure that we emit all errors from // `mir_drops_elaborated_and_const_checked` now, to avoid discovering // them later during codegen. if tcx.sess.opts.output_types.should_codegen() - || tcx.hir().body_const_context(def_id).is_some() + || tcx.hir_body_const_context(def_id).is_some() { tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } }); }); sess.time("coroutine_obligations", || { - tcx.hir().par_body_owners(|def_id| { + tcx.par_hir_body_owners(|def_id| { if tcx.is_coroutine(def_id.to_def_id()) { tcx.ensure_ok().mir_coroutine_witnesses(def_id); tcx.ensure_ok().check_coroutine_obligations( @@ -931,7 +931,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts. if tcx.sess.opts.unstable_opts.validate_mir { sess.time("ensuring_final_MIR_is_computable", || { - tcx.hir().par_body_owners(|def_id| { + tcx.par_hir_body_owners(|def_id| { tcx.instance_mir(ty::InstanceKind::Item(def_id.into())); }); }); @@ -967,7 +967,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { tcx.ensure_ok().check_private_in_public(()); }, { - tcx.hir().par_for_each_module(|module| { + tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_deathness(module) }); }, @@ -983,7 +983,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { }, { sess.time("privacy_checking_modules", || { - tcx.hir().par_for_each_module(|module| { + tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_privacy(module); }); }); diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 59390b7e4206..757fc1f58bd5 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>( let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env()); let ocx = ObligationCtxt::new(&infcx); - let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); + let body_def_id = cx.tcx.hir_body_owner_def_id(body_id); let cause = ObligationCause::new(span, body_def_id, rustc_infer::traits::ObligationCauseCode::Misc); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index f17570e4a81f..d22515d62d60 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -379,7 +379,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( ) { let mut cx = LateContextAndPass { context, pass }; - let (module, _span, hir_id) = tcx.hir().get_module(module_def_id); + let (module, _span, hir_id) = tcx.hir_get_module(module_def_id); cx.with_lint_attrs(hir_id, |cx| { // There is no module lint that will have the crate itself as an item, so check it here. @@ -445,7 +445,7 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>( // Since the root module isn't visited as an item (because it isn't an // item), warn for it here. lint_callback!(cx, check_crate,); - tcx.hir().walk_toplevel_module(cx); + tcx.hir_walk_toplevel_module(cx); lint_callback!(cx, check_crate_post,); }) } @@ -462,7 +462,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) { || { tcx.sess.time("module_lints", || { // Run per-module lints - tcx.hir().par_for_each_module(|module| tcx.ensure_ok().lint_mod(module)); + tcx.par_hir_for_each_module(|module| tcx.ensure_ok().lint_mod(module)); }); }, ); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 7e13205bbf1e..4ede9b440879 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -144,7 +144,7 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { let mut visitor = LintLevelMaximum { tcx, dont_need_to_run }; visitor.process_opts(); - tcx.hir().walk_attributes(&mut visitor); + tcx.hir_walk_attributes(&mut visitor); visitor.dont_need_to_run } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1ac2f6e81e58..88a88847e6b8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -696,7 +696,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers()); let root = stat!("final", || { - let attrs = tcx.hir().krate_attrs(); + let attrs = tcx.hir_krate_attrs(); self.lazy(CrateRoot { header: CrateHeader { name: tcx.crate_name(LOCAL_CRATE), @@ -1763,7 +1763,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_const(tcx.def_kind(def_id)) { let qualifs = tcx.mir_const_qualif(def_id); record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs); - let body = tcx.hir().maybe_body_owned_by(def_id); + let body = tcx.hir_maybe_body_owned_by(def_id); if let Some(body) = body { let const_data = rendered_const(self.tcx, &body, def_id); record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data); diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index b44f14315d75..3436c2f372f4 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -229,64 +229,62 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir_body(self, id: BodyId) -> &'tcx Body<'tcx> { self.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id] } -} -impl<'hir> Map<'hir> { #[track_caller] - pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - self.tcx.hir_node(hir_id).fn_decl() + pub fn hir_fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'tcx FnDecl<'tcx>> { + self.hir_node(hir_id).fn_decl() } #[track_caller] - pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - self.tcx.hir_node(hir_id).fn_sig() + pub fn hir_fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'tcx FnSig<'tcx>> { + self.hir_node(hir_id).fn_sig() } #[track_caller] - pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId { - for (_, node) in self.parent_iter(hir_id) { + pub fn hir_enclosing_body_owner(self, hir_id: HirId) -> LocalDefId { + for (_, node) in self.hir().parent_iter(hir_id) { if let Some((def_id, _)) = node.associated_body() { return def_id; } } - bug!("no `enclosing_body_owner` for hir_id `{}`", hir_id); + bug!("no `hir_enclosing_body_owner` for hir_id `{}`", hir_id); } /// Returns the `HirId` that corresponds to the definition of /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. - pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId { - let parent = self.tcx.parent_hir_id(hir_id); - assert_eq!(self.tcx.hir_node(parent).body_id().unwrap().hir_id, hir_id, "{hir_id:?}"); + pub fn hir_body_owner(self, BodyId { hir_id }: BodyId) -> HirId { + let parent = self.parent_hir_id(hir_id); + assert_eq!(self.hir_node(parent).body_id().unwrap().hir_id, hir_id, "{hir_id:?}"); parent } - pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId { - self.tcx.parent_hir_node(hir_id).associated_body().unwrap().0 + pub fn hir_body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId { + self.parent_hir_node(hir_id).associated_body().unwrap().0 } /// Given a `LocalDefId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. - pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<&'hir Body<'hir>> { - Some(self.tcx.hir_body(self.tcx.hir_node_by_def_id(id).body_id()?)) + pub fn hir_maybe_body_owned_by(self, id: LocalDefId) -> Option<&'tcx Body<'tcx>> { + Some(self.hir_body(self.hir_node_by_def_id(id).body_id()?)) } /// Given a body owner's id, returns the `BodyId` associated with it. #[track_caller] - pub fn body_owned_by(self, id: LocalDefId) -> &'hir Body<'hir> { - self.maybe_body_owned_by(id).unwrap_or_else(|| { - let hir_id = self.tcx.local_def_id_to_hir_id(id); + pub fn hir_body_owned_by(self, id: LocalDefId) -> &'tcx Body<'tcx> { + self.hir_maybe_body_owned_by(id).unwrap_or_else(|| { + let hir_id = self.local_def_id_to_hir_id(id); span_bug!( - self.span(hir_id), + self.hir().span(hir_id), "body_owned_by: {} has no associated body", - self.node_to_string(hir_id) + self.hir().node_to_string(hir_id) ); }) } - pub fn body_param_names(self, id: BodyId) -> impl Iterator + 'hir { - self.tcx.hir_body(id).params.iter().map(|arg| match arg.pat.kind { + pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator + 'tcx { + self.hir_body(id).params.iter().map(|arg| match arg.pat.kind { PatKind::Binding(_, _, ident, _) => ident, _ => Ident::empty(), }) @@ -295,9 +293,9 @@ impl<'hir> Map<'hir> { /// Returns the `BodyOwnerKind` of this `LocalDefId`. /// /// Panics if `LocalDefId` does not have an associated body. - pub fn body_owner_kind(self, def_id: impl Into) -> BodyOwnerKind { + pub fn hir_body_owner_kind(self, def_id: impl Into) -> BodyOwnerKind { let def_id = def_id.into(); - match self.tcx.def_kind(def_id) { + match self.def_kind(def_id) { DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { BodyOwnerKind::Const { inline: false } } @@ -318,17 +316,17 @@ impl<'hir> Map<'hir> { /// This should only be used for determining the context of a body, a return /// value of `Some` does not always suggest that the owner of the body is `const`, /// just that it has to be checked as if it were. - pub fn body_const_context(self, def_id: impl Into) -> Option { + pub fn hir_body_const_context(self, def_id: impl Into) -> Option { let def_id = def_id.into(); - let ccx = match self.body_owner_kind(def_id) { + let ccx = match self.hir_body_owner_kind(def_id) { BodyOwnerKind::Const { inline } => ConstContext::Const { inline }, BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability), - BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None, - BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn(def_id) => { + BodyOwnerKind::Fn if self.is_constructor(def_id) => return None, + BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.is_const_fn(def_id) => { ConstContext::ConstFn } - BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn, + BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn, BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None, }; @@ -339,55 +337,55 @@ impl<'hir> Map<'hir> { /// crate. If you would prefer to iterate over the bodies /// themselves, you can do `self.hir().krate().body_ids.iter()`. #[inline] - pub fn body_owners(self) -> impl Iterator + 'hir { - self.tcx.hir_crate_items(()).body_owners.iter().copied() + pub fn hir_body_owners(self) -> impl Iterator + 'tcx { + self.hir_crate_items(()).body_owners.iter().copied() } #[inline] - pub fn par_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) { - par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); + pub fn par_hir_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) { + par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); } - pub fn ty_param_owner(self, def_id: LocalDefId) -> LocalDefId { - let def_kind = self.tcx.def_kind(def_id); + pub fn hir_ty_param_owner(self, def_id: LocalDefId) -> LocalDefId { + let def_kind = self.def_kind(def_id); match def_kind { DefKind::Trait | DefKind::TraitAlias => def_id, DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => { - self.tcx.local_parent(def_id) + self.local_parent(def_id) } _ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind), } } - pub fn ty_param_name(self, def_id: LocalDefId) -> Symbol { - let def_kind = self.tcx.def_kind(def_id); + pub fn hir_ty_param_name(self, def_id: LocalDefId) -> Symbol { + let def_kind = self.def_kind(def_id); match def_kind { DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper, DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => { - self.tcx.item_name(def_id.to_def_id()) + self.item_name(def_id.to_def_id()) } _ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind), } } - pub fn trait_impls(self, trait_did: DefId) -> &'hir [LocalDefId] { - self.tcx.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) + pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] { + self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) } /// Gets the attributes on the crate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. - pub fn krate_attrs(self) -> &'hir [Attribute] { - self.attrs(CRATE_HIR_ID) + pub fn hir_krate_attrs(self) -> &'tcx [Attribute] { + self.hir().attrs(CRATE_HIR_ID) } - pub fn rustc_coherence_is_core(self) -> bool { - self.krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core)) + pub fn hir_rustc_coherence_is_core(self) -> bool { + self.hir_krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core)) } - pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { + pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); - match self.tcx.hir_owner_node(hir_id.owner) { + match self.hir_owner_node(hir_id.owner) { OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. }) => (m, span, hir_id), OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), @@ -395,20 +393,20 @@ impl<'hir> Map<'hir> { } /// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`. - pub fn walk_toplevel_module(self, visitor: &mut V) -> V::Result + pub fn hir_walk_toplevel_module(self, visitor: &mut V) -> V::Result where - V: Visitor<'hir>, + V: Visitor<'tcx>, { - let (top_mod, span, hir_id) = self.get_module(LocalModDefId::CRATE_DEF_ID); + let (top_mod, span, hir_id) = self.hir_get_module(LocalModDefId::CRATE_DEF_ID); visitor.visit_mod(top_mod, span, hir_id) } /// Walks the attributes in a crate. - pub fn walk_attributes(self, visitor: &mut V) -> V::Result + pub fn hir_walk_attributes(self, visitor: &mut V) -> V::Result where - V: Visitor<'hir>, + V: Visitor<'tcx>, { - let krate = self.tcx.hir_crate(()); + let krate = self.hir_crate(()); for info in krate.owners.iter() { if let MaybeOwner::Owner(info) = info { for attrs in info.attrs.map.values() { @@ -422,89 +420,87 @@ impl<'hir> Map<'hir> { /// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you /// need to process every item-like, and don't care about visiting nested items in a particular /// order then this method is the best choice. If you do care about this nesting, you should - /// use the `tcx.hir().walk_toplevel_module`. + /// use the `tcx.hir_walk_toplevel_module`. /// /// Note that this function will access HIR for all the item-likes in the crate. If you only /// need to access some of them, it is usually better to manually loop on the iterators /// provided by `tcx.hir_crate_items(())`. /// /// Please see the notes in `intravisit.rs` for more information. - pub fn visit_all_item_likes_in_crate(self, visitor: &mut V) -> V::Result + pub fn hir_visit_all_item_likes_in_crate(self, visitor: &mut V) -> V::Result where - V: Visitor<'hir>, + V: Visitor<'tcx>, { - let krate = self.tcx.hir_crate_items(()); - walk_list!(visitor, visit_item, krate.free_items().map(|id| self.tcx.hir_item(id))); + let krate = self.hir_crate_items(()); + walk_list!(visitor, visit_item, krate.free_items().map(|id| self.hir_item(id))); walk_list!( visitor, visit_trait_item, - krate.trait_items().map(|id| self.tcx.hir_trait_item(id)) - ); - walk_list!( - visitor, - visit_impl_item, - krate.impl_items().map(|id| self.tcx.hir_impl_item(id)) + krate.trait_items().map(|id| self.hir_trait_item(id)) ); + walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.hir_impl_item(id))); walk_list!( visitor, visit_foreign_item, - krate.foreign_items().map(|id| self.tcx.hir_foreign_item(id)) + krate.foreign_items().map(|id| self.hir_foreign_item(id)) ); V::Result::output() } /// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to /// item-likes in a single module. - pub fn visit_item_likes_in_module(self, module: LocalModDefId, visitor: &mut V) -> V::Result + pub fn hir_visit_item_likes_in_module( + self, + module: LocalModDefId, + visitor: &mut V, + ) -> V::Result where - V: Visitor<'hir>, + V: Visitor<'tcx>, { - let module = self.tcx.hir_module_items(module); - walk_list!(visitor, visit_item, module.free_items().map(|id| self.tcx.hir_item(id))); + let module = self.hir_module_items(module); + walk_list!(visitor, visit_item, module.free_items().map(|id| self.hir_item(id))); walk_list!( visitor, visit_trait_item, - module.trait_items().map(|id| self.tcx.hir_trait_item(id)) - ); - walk_list!( - visitor, - visit_impl_item, - module.impl_items().map(|id| self.tcx.hir_impl_item(id)) + module.trait_items().map(|id| self.hir_trait_item(id)) ); + walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.hir_impl_item(id))); walk_list!( visitor, visit_foreign_item, - module.foreign_items().map(|id| self.tcx.hir_foreign_item(id)) + module.foreign_items().map(|id| self.hir_foreign_item(id)) ); V::Result::output() } - pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) { - let crate_items = self.tcx.hir_crate_items(()); + pub fn hir_for_each_module(self, mut f: impl FnMut(LocalModDefId)) { + let crate_items = self.hir_crate_items(()); for module in crate_items.submodules.iter() { f(LocalModDefId::new_unchecked(module.def_id)) } } #[inline] - pub fn par_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) { - let crate_items = self.tcx.hir_crate_items(()); + pub fn par_hir_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) { + let crate_items = self.hir_crate_items(()); par_for_each_in(&crate_items.submodules[..], |module| { f(LocalModDefId::new_unchecked(module.def_id)) }) } #[inline] - pub fn try_par_for_each_module( + pub fn try_par_hir_for_each_module( self, f: impl Fn(LocalModDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - let crate_items = self.tcx.hir_crate_items(()); + let crate_items = self.hir_crate_items(()); try_par_for_each_in(&crate_items.submodules[..], |module| { f(LocalModDefId::new_unchecked(module.def_id)) }) } +} +impl<'hir> Map<'hir> { /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] @@ -540,7 +536,7 @@ impl<'hir> Map<'hir> { /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. /// Used exclusively for diagnostics, to avoid suggestion function calls. pub fn is_inside_const_context(self, hir_id: HirId) -> bool { - self.body_const_context(self.enclosing_body_owner(hir_id)).is_some() + self.tcx.hir_body_const_context(self.tcx.hir_enclosing_body_owner(hir_id)).is_some() } /// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is @@ -566,7 +562,8 @@ impl<'hir> Map<'hir> { /// } /// ``` pub fn get_fn_id_for_return_block(self, id: HirId) -> Option { - let enclosing_body_owner = self.tcx.local_def_id_to_hir_id(self.enclosing_body_owner(id)); + let enclosing_body_owner = + self.tcx.local_def_id_to_hir_id(self.tcx.hir_enclosing_body_owner(id)); // Return `None` if the `id` expression is not the returned value of the enclosing body let mut iter = [id].into_iter().chain(self.parent_id_iter(id)).peekable(); @@ -1249,7 +1246,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems { let mut collector = ItemCollector::new(tcx, false); - let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); + let (hir_mod, span, hir_id) = tcx.hir_get_module(module_id); collector.visit_mod(hir_mod, span, hir_id); let ItemCollector { @@ -1282,7 +1279,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { // module item (the former starts at the crate root) but only // the former needs to collect it. ItemCollector does not do this for us. collector.submodules.push(CRATE_OWNER_ID); - tcx.hir().walk_toplevel_module(&mut collector); + tcx.hir_walk_toplevel_module(&mut collector); let ItemCollector { submodules, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 0d2acf96d08f..2a201e230155 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -213,7 +213,7 @@ pub fn provide(providers: &mut Providers) { providers.fn_arg_names = |tcx, def_id| { let hir = tcx.hir(); if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() { - tcx.arena.alloc_from_iter(hir.body_param_names(body_id)) + tcx.arena.alloc_from_iter(tcx.hir_body_param_names(body_id)) } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), .. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index b0df6c71014a..1e3b8d029e1b 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1588,7 +1588,7 @@ pub fn write_allocations<'tcx>( Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => { write!(w, " (static: {}", tcx.def_path_str(did))?; if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup) - && tcx.hir().body_const_context(body.source.def_id()).is_some() + && tcx.hir_body_const_context(body.source.def_id()).is_some() { // Statics may be cyclic and evaluating them too early // in the MIR pipeline may cause cycle errors even though diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cd81890598e7..693823b4af4d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -163,7 +163,7 @@ rustc_queries! { /// The items in a module. /// - /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. + /// This can be conveniently accessed by `tcx.hir_visit_item_likes_in_module`. /// Avoid calling this query directly. query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { arena_cache @@ -771,7 +771,7 @@ rustc_queries! { query type_param_predicates( key: (LocalDefId, LocalDefId, rustc_span::Ident) ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir().ty_param_name(key.1) } + desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir_ty_param_name(key.1) } } query trait_def(key: DefId) -> &'tcx ty::TraitDef { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ea2b610a727b..35893ad953d1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2079,7 +2079,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.local_def_id_to_hir_id(scope_def_id); let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = - self.hir().fn_decl_by_hir_id(hir_id) + self.hir_fn_decl_by_hir_id(hir_id) else { return vec![]; }; @@ -2099,7 +2099,7 @@ impl<'tcx> TyCtxt<'tcx> { let hir_id = self.local_def_id_to_hir_id(scope_def_id); let mut v = TraitObjectVisitor(vec![], self.hir()); // when the return type is a type alias - if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) + if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id) && let hir::TyKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind @@ -3297,9 +3297,9 @@ pub fn provide(providers: &mut Providers) { providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); providers.is_panic_runtime = - |tcx, LocalCrate| contains_name(tcx.hir().krate_attrs(), sym::panic_runtime); + |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime); providers.is_compiler_builtins = - |tcx, LocalCrate| contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins); + |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::compiler_builtins); providers.has_panic_handler = |tcx, LocalCrate| { // We want to check if the panic handler was defined in this crate tcx.lang_items().panic_impl().is_some_and(|did| did.is_local()) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7beb6d84044f..c52e774c8b7e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1470,7 +1470,7 @@ pub enum ImplTraitInTraitData { impl<'tcx> TyCtxt<'tcx> { pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> { - self.typeck(self.hir().body_owner_def_id(body)) + self.typeck(self.hir_body_owner_def_id(body)) } pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator { diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index b84cc57234f4..17e90c15d413 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -235,7 +235,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait } } - for &impl_def_id in tcx.hir().trait_impls(trait_id) { + for &impl_def_id in tcx.hir_trait_impls(trait_id) { let impl_def_id = impl_def_id.to_def_id(); let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index e04c70b58837..fb0aa354913f 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -465,11 +465,10 @@ fn construct_fn<'tcx>( assert_eq!(expr.as_usize(), thir.exprs.len() - 1); // Figure out what primary body this item has. - let body = tcx.hir().body_owned_by(fn_def); + let body = tcx.hir_body_owned_by(fn_def); let span_with_body = tcx.hir().span_with_body(fn_id); let return_ty_span = tcx - .hir() - .fn_decl_by_hir_id(fn_id) + .hir_fn_decl_by_hir_id(fn_id) .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def)) .output .span(); @@ -758,7 +757,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { check_overflow |= tcx.sess.overflow_checks(); // Constants always need overflow checks. check_overflow |= matches!( - tcx.hir().body_owner_kind(def), + tcx.hir_body_owner_kind(def), hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) ); diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 8b6fcec3837c..84f58f1968db 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -927,7 +927,7 @@ impl UnsafeOpKind { && let hir::BlockCheckMode::UnsafeBlock(_) = block.rules { true - } else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) + } else if let Some(sig) = tcx.hir_fn_sig_by_hir_id(*id) && matches!(sig.header.safety, hir::HeaderSafety::Normal(hir::Safety::Unsafe)) { true @@ -1145,7 +1145,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { let thir = &thir.steal(); let hir_id = tcx.local_def_id_to_hir_id(def); - let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { + let safety_context = tcx.hir_fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { match fn_sig.header.safety { // We typeck the body as safe, but otherwise treat it as unsafe everywhere else. // Call sites to other SafeTargetFeatures functions are checked explicitly and don't need diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index a01609012b8f..7a9f6e463045 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -22,8 +22,7 @@ pub(crate) fn thir_body( tcx: TyCtxt<'_>, owner_def: LocalDefId, ) -> Result<(&Steal>, ExprId), ErrorGuaranteed> { - let hir = tcx.hir(); - let body = hir.body_owned_by(owner_def); + let body = tcx.hir_body_owned_by(owner_def); let mut cx = ThirBuildCx::new(tcx, owner_def); if let Some(reported) = cx.typeck_results.tainted_by_errors { return Err(reported); @@ -31,7 +30,7 @@ pub(crate) fn thir_body( let expr = cx.mirror_expr(body.value); let owner_id = tcx.local_def_id_to_hir_id(owner_def); - if let Some(fn_decl) = hir.fn_decl_by_hir_id(owner_id) { + if let Some(fn_decl) = tcx.hir_fn_decl_by_hir_id(owner_id) { let closure_env_param = cx.closure_env_param(owner_def, owner_id); let explicit_params = cx.explicit_params(owner_id, fn_decl, &body); cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect(); @@ -77,7 +76,7 @@ impl<'tcx> ThirBuildCx<'tcx> { let hir = tcx.hir(); let hir_id = tcx.local_def_id_to_hir_id(def); - let body_type = if hir.body_owner_kind(def).is_fn_or_closure() { + let body_type = if tcx.hir_body_owner_kind(def).is_fn_or_closure() { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id]) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 551ec5cf4e9c..667d59d858e3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -148,7 +148,7 @@ impl<'tcx> ConstToPat<'tcx> { if let ty::GenericArgKind::Type(ty) = arg.unpack() && let ty::Param(param_ty) = ty.kind() { - let def_id = self.tcx.hir().enclosing_body_owner(self.id); + let def_id = self.tcx.hir_enclosing_body_owner(self.id); let generics = self.tcx.generics_of(def_id); let param = generics.type_param(*param_ty, self.tcx); let span = self.tcx.def_span(param.def_id); diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs index 497f4a660eaa..83c3cda5a505 100644 --- a/compiler/rustc_mir_transform/src/check_inline.rs +++ b/compiler/rustc_mir_transform/src/check_inline.rs @@ -16,7 +16,7 @@ pub(super) struct CheckForceInline; impl<'tcx> MirLint<'tcx> for CheckForceInline { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id(); - if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() { + if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() { return; } let InlineAttr::Force { attr_span, .. } = tcx.codegen_fn_attrs(def_id).inline else { diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 9a6a153c7ba9..5d21d687a35a 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -113,7 +113,7 @@ fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> b let def_id = body.source.def_id(); // Only do inlining into fn bodies. - if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() { + if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() { return false; } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 3dc4edaaa5ae..da346dfc48c1 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -36,7 +36,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { typing_env: body.typing_env(tcx), }; let preserve_ub_checks = - attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); + attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { match statement.kind { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 46abdcb2a870..04c9375b8317 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -314,11 +314,11 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// MIR associated with them. fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { // All body-owners have MIR associated with them. - let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect(); + let mut set: FxIndexSet<_> = tcx.hir_body_owners().collect(); // Coroutine-closures (e.g. async closures) have an additional by-move MIR // body that isn't in the HIR. - for body_owner in tcx.hir().body_owners() { + for body_owner in tcx.hir_body_owners() { if let DefKind::Closure = tcx.def_kind(body_owner) && tcx.needs_coroutine_by_move_body_def_id(body_owner.to_def_id()) { @@ -470,7 +470,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { } let body = tcx.mir_drops_elaborated_and_const_checked(def); - let body = match tcx.hir().body_const_context(def) { + let body = match tcx.hir_body_const_context(def) { // consts and statics do not have `optimized_mir`, so we can steal the body instead of // cloning it. Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => body.steal(), @@ -729,7 +729,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { return shim::build_adt_ctor(tcx, did.to_def_id()); } - match tcx.hir().body_const_context(did) { + match tcx.hir_body_const_context(did) { // Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked` // which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it // computes and caches its result. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 396a0cbc8895..5111a025f94e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2461,7 +2461,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) { let mut diag = tcx.dcx().create_err(errors::ProcMacroBadSig { span, kind }); - let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id); + let hir_sig = tcx.hir_fn_sig_by_hir_id(hir_id); if let Some(hir_sig) = hir_sig { #[allow(rustc::diagnostic_outside_of_impl)] // FIXME match terr { @@ -2791,10 +2791,10 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) }; - tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor); + tcx.hir_visit_item_likes_in_module(module_def_id, check_attr_visitor); if module_def_id.to_local_def_id().is_top_level_module() { check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None); - check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs()); + check_invalid_crate_level_attr(tcx, tcx.hir_krate_attrs()); } if check_attr_visitor.abort.get() { tcx.dcx().abort_if_errors() diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 696cc79bfeb6..7b4fecf2ed19 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -358,7 +358,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let Some(local_impl_of) = impl_of.as_local() && let Some(local_def_id) = def_id.as_local() && let Some(fn_sig) = - self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) + self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) && let TyKind::Path(hir::QPath::Resolved(_, path)) = self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind @@ -779,7 +779,7 @@ fn check_item<'tcx>( // check the function may construct Self let mut may_construct_self = false; if let Some(fn_sig) = - tcx.hir().fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id)) + tcx.hir_fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id)) { may_construct_self = matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None); diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 43f2f892e77d..509c2f547752 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -9,11 +9,11 @@ use rustc_middle::ty::TyCtxt; pub fn check_crate(tcx: TyCtxt<'_>) { let errors = Lock::new(Vec::new()); - tcx.hir().par_for_each_module(|module_id| { + tcx.par_hir_for_each_module(|module_id| { let mut v = HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors }; - tcx.hir().visit_item_likes_in_module(module_id, &mut v); + tcx.hir_visit_item_likes_in_module(module_id, &mut v); }); let errors = errors.into_inner(); diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index e60dcc807c96..92ea49f18e5d 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -63,8 +63,8 @@ struct StatCollector<'k> { pub fn print_hir_stats(tcx: TyCtxt<'_>) { let mut collector = StatCollector { tcx: Some(tcx), nodes: FxHashMap::default(), seen: FxHashSet::default() }; - tcx.hir().walk_toplevel_module(&mut collector); - tcx.hir().walk_attributes(&mut collector); + tcx.hir_walk_toplevel_module(&mut collector); + tcx.hir_walk_attributes(&mut collector); collector.print("HIR STATS", "hir-stats"); } diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 09d59e1f7172..e123fbac1bee 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -148,7 +148,7 @@ fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures { } let mut collector = LibFeatureCollector::new(tcx); - tcx.hir().walk_attributes(&mut collector); + tcx.hir_walk_attributes(&mut collector); collector.lib_features } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 60f7616a5fba..a7bca67e4e4a 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -152,8 +152,8 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { } let mut maps = IrMaps::new(tcx); - let body = tcx.hir().body_owned_by(def_id); - let hir_id = tcx.hir().body_owner(body.id()); + let body = tcx.hir_body_owned_by(def_id); + let hir_id = tcx.hir_body_owner(body.id()); if let Some(upvars) = tcx.upvars_mentioned(def_id) { for &var_hir_id in upvars.keys() { @@ -1522,8 +1522,7 @@ impl<'tcx> Liveness<'_, 'tcx> { } fn warn_about_unused_args(&self, body: &hir::Body<'_>, entry_ln: LiveNode) { - if let Some(intrinsic) = - self.ir.tcx.intrinsic(self.ir.tcx.hir().body_owner_def_id(body.id())) + if let Some(intrinsic) = self.ir.tcx.intrinsic(self.ir.tcx.hir_body_owner_def_id(body.id())) { if intrinsic.must_be_overridden { return; diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0fd980af0b54..8e59c0b3251c 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -76,7 +76,7 @@ struct CheckLoopVisitor<'tcx> { fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let mut check = CheckLoopVisitor { tcx, cx_stack: vec![Normal], block_breaks: Default::default() }; - tcx.hir().visit_item_likes_in_module(module_def_id, &mut check); + tcx.hir_visit_item_likes_in_module(module_def_id, &mut check); check.report_outside_loop_error(); } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index d045e61d1d4c..a65859466561 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -721,7 +721,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { InheritDeprecation::Yes, InheritConstStability::No, InheritStability::No, - |v| tcx.hir().walk_toplevel_module(v), + |v| tcx.hir_walk_toplevel_module(v), ); } index @@ -730,7 +730,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { /// Cross-references the feature names of unstable APIs with enabled /// features and possibly prints errors. fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }); + tcx.hir_visit_item_likes_in_module(module_def_id, &mut Checker { tcx }); } pub(crate) fn provide(providers: &mut Providers) { @@ -1059,8 +1059,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let effective_visibilities = &tcx.effective_visibilities(()); let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities }; missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID)); - tcx.hir().walk_toplevel_module(&mut missing); - tcx.hir().visit_all_item_likes_in_crate(&mut missing); + tcx.hir_walk_toplevel_module(&mut missing); + tcx.hir_visit_all_item_likes_in_crate(&mut missing); } let enabled_lang_features = tcx.features().enabled_lang_features(); diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 0544d08f5b19..fae88fbba360 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -16,7 +16,7 @@ pub(crate) fn provide(providers: &mut Providers) { } let local_def_id = def_id.expect_local(); - let body = tcx.hir().maybe_body_owned_by(local_def_id)?; + let body = tcx.hir_maybe_body_owned_by(local_def_id)?; let mut local_collector = LocalCollector::default(); local_collector.visit_body(&body); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index b8490da26f4e..6faa2c1a00d2 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1771,7 +1771,7 @@ pub fn provide(providers: &mut Providers) { fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // Check privacy of names not checked in previous compilation stages. let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None }; - tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); + tcx.hir_visit_item_likes_in_module(module_def_id, &mut visitor); // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. @@ -1782,7 +1782,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { for def_id in module.definitions() { rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); - if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id) { + if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) { visitor.visit_nested_body(body_id.id()); } } @@ -1863,7 +1863,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { } loop { - tcx.hir().visit_all_item_likes_in_crate(&mut visitor); + tcx.hir_visit_all_item_likes_in_crate(&mut visitor); if visitor.changed { visitor.changed = false; } else { @@ -1875,7 +1875,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { let mut check_visitor = TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities }; check_visitor.effective_visibility_diagnostic(CRATE_DEF_ID); - tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor); + tcx.hir_visit_all_item_likes_in_crate(&mut check_visitor); tcx.arena.alloc(visitor.effective_visibilities) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 55eb3f777d6b..2bb38f3ed14a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -489,7 +489,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg); - if let Some(body) = self.tcx.hir().maybe_body_owned_by( + if let Some(body) = self.tcx.hir_maybe_body_owned_by( self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(), ) { let expr = body.value; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 35fd4e588ef9..5b8d48e3ca9e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { | ObligationCauseCode::BlockTailExpression(hir_id, ..) = cause.code() { let parent_id = tcx.hir().get_parent_item(*hir_id); - if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { + if let Some(fn_decl) = tcx.hir_fn_decl_by_hir_id(parent_id.into()) { let mut span: MultiSpan = fn_decl.output.span().into(); let mut spans = Vec::new(); let mut add_label = true; @@ -490,7 +490,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // obligation comes from the `impl`. Find that `impl` so that we can point // at it in the suggestion. let trait_did = trait_id.to_def_id(); - tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { + tcx.hir_trait_impls(trait_did).iter().find_map(|&impl_did| { if let Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. }) = tcx.hir_node_by_def_id(impl_did) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 0695cc579787..cc2ab1c34328 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -99,11 +99,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] }; match assoc_item.kind { ty::AssocKind::Fn => { - let hir = self.tcx().hir(); if let Some(hir_id) = assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id)) { - if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) { + if let Some(decl) = self.tcx().hir_fn_decl_by_hir_id(hir_id) { visitor.visit_fn_decl(decl); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 445937ad1692..245764c94abf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -64,10 +64,10 @@ pub fn find_param_with_region<'tcx>( _ => {} } - let body = hir.maybe_body_owned_by(def_id)?; + let body = tcx.hir_maybe_body_owned_by(def_id)?; - let owner_id = hir.body_owner(body.id()); - let fn_decl = hir.fn_decl_by_hir_id(owner_id)?; + let owner_id = tcx.hir_body_owner(body.id()); + let fn_decl = tcx.hir_fn_decl_by_hir_id(owner_id)?; let poly_fn_sig = tcx.fn_sig(id).instantiate_identity(); let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index bb25c5e8bd1b..628888c8d45c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -624,7 +624,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body| { + self.tcx.hir_maybe_body_owned_by(cause.body_id).and_then(|body| { IfVisitor { err_span: span, found_if: false } .visit_body(&body) .is_break() diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 6beb108bc3ae..f15f1b78b528 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -316,7 +316,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack()) - && let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) + && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) { let mut expr_finder = FindExprBySpan::new(span, self.tcx); expr_finder.visit_expr(&body.value); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index ecfffb65fbc1..a8ee4d61e65e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -367,7 +367,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (span.shrink_to_lo(), format!("(")), (span.shrink_to_hi(), format!(" as {})", cand.self_ty())), ] - } else if let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) { + } else if let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) { let mut expr_finder = FindExprBySpan::new(span, self.tcx); expr_finder.visit_expr(body.value); if let Some(expr) = expr_finder.result && diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ac1ced2ed3c3..3d89b6ed2f07 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -876,7 +876,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span.remove_mark(); } let mut expr_finder = FindExprBySpan::new(span, self.tcx); - let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { + let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else { return; }; expr_finder.visit_expr(body.value); @@ -1347,8 +1347,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Issue #104961, we need to add parentheses properly for compound expressions // for example, `x.starts_with("hi".to_string() + "you")` // should be `x.starts_with(&("hi".to_string() + "you"))` - let Some(body) = - self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) + let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else { return false; }; @@ -1447,7 +1446,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span.remove_mark(); } let mut expr_finder = super::FindExprBySpan::new(span, self.tcx); - let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { + let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else { return false; }; expr_finder.visit_expr(body.value); @@ -1766,7 +1765,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.children.clear(); let span = obligation.cause.span; - let body = self.tcx.hir().body_owned_by(obligation.cause.body_id); + let body = self.tcx.hir_body_owned_by(obligation.cause.body_id); let mut visitor = ReturnsVisitor::default(); visitor.visit_body(&body); @@ -2300,7 +2299,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); let coroutine_body = - coroutine_did.as_local().and_then(|def_id| hir.maybe_body_owned_by(def_id)); + coroutine_did.as_local().and_then(|def_id| self.tcx.hir_maybe_body_owned_by(def_id)); let mut visitor = AwaitsVisitor::default(); if let Some(body) = coroutine_body { visitor.visit_body(&body); @@ -4130,7 +4129,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; suggest_restriction( tcx, - hir.body_owner_def_id(body_id), + tcx.hir_body_owner_def_id(body_id), generics, &format!("type parameter `{ty}`"), err, @@ -4352,7 +4351,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { term: ty.into(), }), )); - let body_def_id = self.tcx.hir().enclosing_body_owner(body_id); + let body_def_id = self.tcx.hir_enclosing_body_owner(body_id); // Add `::Item = _` obligation. ocx.register_obligation(Obligation::misc( self.tcx, diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 32d9469c296c..7ce72c76e5c0 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -109,7 +109,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[instrument(level = "trace", skip(self))] fn collect_taits_declared_in_body(&mut self) { - let body = self.tcx.hir().body_owned_by(self.item).value; + let body = self.tcx.hir_body_owned_by(self.item).value; struct TaitInBodyFinder<'a, 'tcx> { collector: &'a mut OpaqueTypeCollector<'tcx>, } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 8b424499724b..fc7c4b42047d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2121,7 +2121,7 @@ impl Discriminant { /// simplified pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option { self.expr - .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir().body_owner_def_id(body))) + .map(|body| rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body))) } pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String { print_evaluated_const(tcx, self.value, with_underscores, false).unwrap() @@ -2417,7 +2417,7 @@ impl ConstantKind { ConstantKind::Path { ref path } => path.to_string(), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { - rendered_const(tcx, tcx.hir_body(body), tcx.hir().body_owner_def_id(body)) + rendered_const(tcx, tcx.hir_body(body), tcx.hir_body_owner_def_id(body)) } ConstantKind::Infer { .. } => "_".to_string(), } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 8a7d140bb1a6..6b1d1a2fcdd8 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -336,7 +336,7 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => { let s = if let Some(def) = def.as_local() { - rendered_const(cx.tcx, cx.tcx.hir().body_owned_by(def), def) + rendered_const(cx.tcx, cx.tcx.hir_body_owned_by(def), def) } else { inline::print_inlined_const(cx.tcx, def) }; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1ead87fd69da..757a2a6e0dd0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -304,8 +304,7 @@ pub(crate) fn create_config( return tcx.typeck(typeck_root_def_id); } - let hir = tcx.hir(); - let body = hir.body_owned_by(def_id); + let body = tcx.hir_body_owned_by(def_id); debug!("visiting body for {def_id:?}"); EmitIgnoredResolutionErrors::new(tcx).visit_body(body); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) @@ -335,14 +334,14 @@ pub(crate) fn run_global_ctxt( // NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes. let _ = tcx.sess.time("wf_checking", || { - tcx.hir().try_par_for_each_module(|module| tcx.ensure_ok().check_mod_type_wf(module)) + tcx.try_par_hir_for_each_module(|module| tcx.ensure_ok().check_mod_type_wf(module)) }); tcx.dcx().abort_if_errors(); tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx)); tcx.sess.time("check_mod_attrs", || { - tcx.hir().for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module)) + tcx.hir_for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module)) }); rustc_passes::stability::check_unused_or_stable_features(tcx); diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 0d52e21419fc..1ac3c040b591 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -81,7 +81,7 @@ impl<'tcx> HirCollector<'tcx> { pub fn collect_crate(mut self) -> Vec { let tcx = self.tcx; self.visit_testable("".to_string(), CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| { - tcx.hir().walk_toplevel_module(this) + tcx.hir_walk_toplevel_module(this) }); self.collector.tests } diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index fa2465c1926e..658d5965b3d2 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -51,7 +51,7 @@ pub(crate) fn collect_spans_and_sources( let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() }; if generate_link_to_definition { - tcx.hir().walk_toplevel_module(&mut visitor); + tcx.hir_walk_toplevel_module(&mut visitor); } let sources = sources::collect_local_sources(tcx, src_root, krate); (sources, visitor.matches) @@ -173,18 +173,18 @@ impl SpanMapVisitor<'_> { } fn infer_id(&mut self, hir_id: HirId, expr_hir_id: Option, span: Span) { - let hir = self.tcx.hir(); - let body_id = hir.enclosing_body_owner(hir_id); + let tcx = self.tcx; + let body_id = tcx.hir_enclosing_body_owner(hir_id); // FIXME: this is showing error messages for parts of the code that are not // compiled (because of cfg)! // // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352 - let typeck_results = self.tcx.typeck_body(hir.body_owned_by(body_id).id()); + let typeck_results = tcx.typeck_body(tcx.hir_body_owned_by(body_id).id()); // Interestingly enough, for method calls, we need the whole expression whereas for static // method/function calls, we need the call expression specifically. if let Some(def_id) = typeck_results.type_dependent_def_id(expr_hir_id.unwrap_or(hir_id)) { let link = if def_id.as_local().is_some() { - LinkFromSrc::Local(rustc_span(def_id, self.tcx)) + LinkFromSrc::Local(rustc_span(def_id, tcx)) } else { LinkFromSrc::External(def_id) }; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bef59469179c..9606ba76991a 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -846,7 +846,7 @@ fn convert_static( is_unsafe: safety.is_unsafe(), expr: stat .expr - .map(|e| rendered_const(tcx, tcx.hir_body(e), tcx.hir().body_owner_def_id(e))) + .map(|e| rendered_const(tcx, tcx.hir_body(e), tcx.hir_body_owner_def_id(e))) .unwrap_or_default(), } } diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index dd9dbd7170e5..a36dcb0d30e5 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -135,8 +135,7 @@ where // If we visit an item that contains an expression outside a function body, // then we need to exit before calling typeck (which will panic). See // test/run-make/rustdoc-scrape-examples-invalid-expr for an example. - let hir = tcx.hir(); - if hir.maybe_body_owned_by(ex.hir_id.owner.def_id).is_none() { + if tcx.hir_maybe_body_owned_by(ex.hir_id.owner.def_id).is_none() { return; } @@ -302,7 +301,7 @@ pub(crate) fn run( // Run call-finder on all items let mut calls = FxIndexMap::default(); let mut finder = FindCalls { calls: &mut calls, cx, target_crates, bin_crate }; - tcx.hir().visit_all_item_likes_in_crate(&mut finder); + tcx.hir_visit_all_item_likes_in_crate(&mut finder); // The visitor might have found a type error, which we need to // promote to a fatal error diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 772268e7899e..784214c29af9 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -52,11 +52,10 @@ declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]); impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback { fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { - let hir = cx.tcx.hir(); // NOTE: this is different from `clippy_utils::is_inside_always_const_context`. // Inline const supports type inference. let is_parent_const = matches!( - hir.body_const_context(hir.body_owner_def_id(body.id())), + cx.tcx.hir_body_const_context(cx.tcx.hir_body_owner_def_id(body.id())), Some(ConstContext::Const { inline: false } | ConstContext::Static(_)) ); let mut visitor = NumericFallbackVisitor::new(cx, is_parent_const); diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index a090a987d4fc..2e1f8ac615a2 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -41,7 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { if let ItemKind::Enum(def, _) = &item.kind { for var in def.variants { if let Some(anon_const) = &var.disr_expr { - let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body); + let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body); let mut ty = cx.tcx.type_of(def_id.to_def_id()).instantiate_identity(); let constant = cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs index 6d1c55d06938..cb83b1395d26 100644 --- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs @@ -39,7 +39,7 @@ fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_ pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) { if let FnKind::ItemFn(_, generics, _) = kind - && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() + && cx.tcx.visibility(cx.tcx.hir_body_owner_def_id(body.id())).is_public() && !is_in_test(cx.tcx, hir_id) { for param in generics.params { @@ -57,7 +57,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { && let hir::Impl { of_trait, .. } = *impl_ && of_trait.is_none() && let body = cx.tcx.hir_body(body_id) - && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() + && cx.tcx.visibility(cx.tcx.hir_body_owner_def_id(body.id())).is_public() && !is_in_test(cx.tcx, impl_item.hir_id()) { for param in impl_item.generics.params { diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs index ac2e866e4ff7..5ad83f886e2e 100644 --- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs @@ -22,7 +22,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored && let Some(did) = trait_item_def_id_of_impl(items, item.owner_id) && !is_from_ignored_trait(trait_ref, ignored_traits) { - let mut param_idents_iter = cx.tcx.hir().body_param_names(body_id); + let mut param_idents_iter = cx.tcx.hir_body_param_names(body_id); let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied(); let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter); diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index 052e6502da92..2a5aa12d126c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { && exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2 && !expr.span.in_external_macro(cx.sess().source_map()) && ( - is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into()) + is_not_const(cx.tcx, cx.tcx.hir_enclosing_body_owner(expr.hir_id).into()) || self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY) ) && let [first, second, const_1, const_2] = exprs diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 4a8a221e8c36..b1107d8cc72f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -58,8 +58,7 @@ pub(super) fn check<'tcx>( unwrap_or_span: unwrap_arg.span, }; - let map = cx.tcx.hir(); - let body = map.body_owned_by(map.enclosing_body_owner(expr.hir_id)); + let body = cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)); // Visit the body, and return if we've found a reference if reference_visitor.visit_body(body).is_break() { diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index 7f91e555054d..ea1d7e5d4382 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { if self .possible_borrowers .last() - .is_some_and(|&(local_def_id, _)| local_def_id == cx.tcx.hir().body_owner_def_id(body.id())) + .is_some_and(|&(local_def_id, _)| local_def_id == cx.tcx.hir_body_owner_def_id(body.id())) { self.possible_borrowers.pop(); } @@ -359,7 +359,7 @@ fn referent_used_exactly_once<'tcx>( && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind && !place.is_indirect_first_projection() { - let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id); + let body_owner_local_def_id = cx.tcx.hir_enclosing_body_owner(reference.hir_id); if possible_borrowers .last() .is_none_or(|&(local_def_id, _)| local_def_id != body_owner_local_def_id) diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index 6a1dc5e41a07..5e85d23718a9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -352,7 +352,7 @@ impl MutablyUsedVariablesCtxt<'_> { fn is_in_unsafe_block(&self, item: HirId) -> bool { let hir = self.tcx.hir(); for (parent, node) in hir.parent_iter(item) { - if let Some(fn_sig) = hir.fn_sig_by_hir_id(parent) { + if let Some(fn_sig) = self.tcx.hir_fn_sig_by_hir_id(parent) { return fn_sig.header.is_unsafe(); } else if let Node::Block(block) = node { if matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) { diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 9d07a14718da..594101427f5a 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -349,10 +349,10 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { } fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { - let body_owner = cx.tcx.hir().body_owner(body.id()); - let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id()); + let body_owner = cx.tcx.hir_body_owner(body.id()); + let body_owner_def_id = cx.tcx.hir_body_owner_def_id(body.id()); - let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id); + let body_owner_kind = cx.tcx.hir_body_owner_kind(body_owner_def_id); if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind { let body_span = cx.tcx.hir().span_with_body(body_owner); if let Some(span) = self.const_span @@ -365,7 +365,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { } fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { - let body_owner = cx.tcx.hir().body_owner(body.id()); + let body_owner = cx.tcx.hir_body_owner(body.id()); let body_span = cx.tcx.hir().span(body_owner); if let Some(span) = self.const_span && span.contains(body_span) diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs index 2083f2bf628d..cda99a362dca 100644 --- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs @@ -68,10 +68,10 @@ impl Context { } pub fn enter_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { - let body_owner = cx.tcx.hir().body_owner(body.id()); - let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id()); + let body_owner = cx.tcx.hir_body_owner(body.id()); + let body_owner_def_id = cx.tcx.hir_body_owner_def_id(body.id()); - match cx.tcx.hir().body_owner_kind(body_owner_def_id) { + match cx.tcx.hir_body_owner_kind(body_owner_def_id) { hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => { let body_span = cx.tcx.hir().span_with_body(body_owner); @@ -87,7 +87,7 @@ impl Context { } pub fn body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) { - let body_owner = cx.tcx.hir().body_owner(body.id()); + let body_owner = cx.tcx.hir_body_owner(body.id()); let body_span = cx.tcx.hir().span_with_body(body_owner); if let Some(span) = self.const_span { diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index ebe3e7c20196..e15e12629209 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { /// assert_static(closure); /// ``` fn is_by_value_closure_capture(cx: &LateContext<'_>, redefinition: HirId, root_variable: HirId) -> bool { - let closure_def_id = cx.tcx.hir().enclosing_body_owner(redefinition); + let closure_def_id = cx.tcx.hir_enclosing_body_owner(redefinition); cx.tcx.is_closure_like(closure_def_id.to_def_id()) && cx.tcx.closure_captures(closure_def_id).iter().any(|c| { diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 83199ba0f707..a931e39bac9c 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -149,17 +149,15 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { } fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { - let hir = cx.tcx.hir(); - let owner_id = hir.body_owner_def_id(body.id()); - if !matches!(hir.body_owner_kind(owner_id), BodyOwnerKind::Closure) { + let owner_id = cx.tcx.hir_body_owner_def_id(body.id()); + if !matches!(cx.tcx.hir_body_owner_kind(owner_id), BodyOwnerKind::Closure) { self.bindings.push((FxHashMap::default(), owner_id)); } } fn check_body_post(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { - let hir = cx.tcx.hir(); if !matches!( - hir.body_owner_kind(hir.body_owner_def_id(body.id())), + cx.tcx.hir_body_owner_kind(cx.tcx.hir_body_owner_def_id(body.id())), BodyOwnerKind::Closure ) { self.bindings.pop(); diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs index fdbccbaa8a59..1a2fb77acc15 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -90,8 +90,7 @@ impl SingleCallFn { || fn_span.in_external_macro(cx.sess().source_map()) || cx .tcx - .hir() - .maybe_body_owned_by(fn_def_id) + .hir_maybe_body_owned_by(fn_def_id) .is_none_or(|body| is_in_test_function(cx.tcx, body.value.hir_id)) || match cx.tcx.hir_node(fn_hir_id) { Node::Item(item) => is_from_proc_macro(cx, item), diff --git a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs index 4961dd6b280a..0b5d83ef58ca 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -28,8 +28,8 @@ fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) } fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool { - let def_id = cx.tcx.hir().enclosing_body_owner(expr_hir_id); - if let Some(body) = cx.tcx.hir().maybe_body_owned_by(def_id) { + let def_id = cx.tcx.hir_enclosing_body_owner(expr_hir_id); + if let Some(body) = cx.tcx.hir_maybe_body_owned_by(def_id) { return body.value.peel_blocks().hir_id == expr_hir_id; } false diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index 529f85be3720..76a0b927df42 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -331,8 +331,8 @@ impl UnconditionalRecursion { && let [return_expr] = get_return_calls_in_body(body).as_slice() && let ExprKind::Call(call_expr, _) = return_expr.kind // We need to use typeck here to infer the actual function being called. - && let body_def_id = cx.tcx.hir().enclosing_body_owner(call_expr.hir_id) - && let Some(body_owner) = cx.tcx.hir().maybe_body_owned_by(body_def_id) + && let body_def_id = cx.tcx.hir_enclosing_body_owner(call_expr.hir_id) + && let Some(body_owner) = cx.tcx.hir_maybe_body_owned_by(body_def_id) && let typeck = cx.tcx.typeck_body(body_owner.id()) && let Some(call_def_id) = typeck.type_dependent_def_id(call_expr.hir_id) { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index ce489054e16e..5fc166438e84 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -132,8 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for Author { } fn check_item(cx: &LateContext<'_>, hir_id: HirId) { - let hir = cx.tcx.hir(); - if let Some(body) = hir.maybe_body_owned_by(hir_id.expect_owner().def_id) { + if let Some(body) = cx.tcx.hir_maybe_body_owned_by(hir_id.expect_owner().def_id) { check_node(cx, hir_id, |v| { v.expr(&v.bind("expr", body.value)); }); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index e31da9e9f611..d6f10f1e4b80 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { output: &mut self.registered_lints, cx, }; - let body = cx.tcx.hir().body_owned_by( + let body = cx.tcx.hir_body_owned_by( impl_item_refs .iter() .find(|iiref| iiref.ident.as_str() == "lint_vec") diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index ccf32f42a47b..15e395731ade 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -237,8 +237,7 @@ pub fn is_in_const_context(cx: &LateContext<'_>) -> bool { debug_assert!(cx.enclosing_body.is_some(), "`LateContext` has no enclosing body"); cx.enclosing_body.is_some_and(|id| { cx.tcx - .hir() - .body_const_context(cx.tcx.hir().body_owner_def_id(id)) + .hir_body_const_context(cx.tcx.hir_body_owner_def_id(id)) .is_some() }) } @@ -251,8 +250,7 @@ pub fn is_in_const_context(cx: &LateContext<'_>) -> bool { /// * associated constants pub fn is_inside_always_const_context(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { use ConstContext::{Const, ConstFn, Static}; - let hir = tcx.hir(); - let Some(ctx) = hir.body_const_context(hir.enclosing_body_owner(hir_id)) else { + let Some(ctx) = tcx.hir_body_const_context(tcx.hir_enclosing_body_owner(hir_id)) else { return false; }; match ctx { @@ -1648,7 +1646,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool if is_integer_literal(e, value) { return true; } - let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); + let enclosing_body = cx.tcx.hir_enclosing_body_owner(e.hir_id); if let Some(Constant::Int(v)) = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e) { @@ -2762,7 +2760,7 @@ impl<'tcx> ExprUseCtxt<'tcx> { Node::Expr(use_expr) => match use_expr.kind { ExprKind::Ret(_) => ExprUseNode::Return(OwnerId { - def_id: cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()), + def_id: cx.tcx.hir_body_owner_def_id(cx.enclosing_body.unwrap()), }), ExprKind::Closure(closure) => ExprUseNode::Return(OwnerId { def_id: closure.def_id }), diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 85250f81dc47..637c0bafd964 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -136,8 +136,8 @@ pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option { /// Returns the `mir::Body` containing the node associated with `hir_id`. #[allow(clippy::module_name_repetitions)] pub fn enclosing_mir(tcx: TyCtxt<'_>, hir_id: HirId) -> Option<&Body<'_>> { - let body_owner_local_def_id = tcx.hir().enclosing_body_owner(hir_id); - if tcx.hir().body_owner_kind(body_owner_local_def_id).is_fn_or_closure() { + let body_owner_local_def_id = tcx.hir_enclosing_body_owner(hir_id); + if tcx.hir_body_owner_kind(body_owner_local_def_id).is_fn_or_closure() { Some(tcx.optimized_mir(body_owner_local_def_id.to_def_id())) } else { None diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index a5374f6904e3..8eef6a7f57ed 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -267,7 +267,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( // through calling `body_owner_kind`, which would panic if the callee // does not have a body. if let Some(callee_id) = callee_id { - let _ = tcx.hir().body_owner_kind(callee_id); + let _ = tcx.hir_body_owner_kind(callee_id); } let ty = tcx.erase_regions(ty); @@ -705,7 +705,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option { let decl = id .as_local() - .and_then(|id| cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.local_def_id_to_hir_id(id))); + .and_then(|id| cx.tcx.hir_fn_decl_by_hir_id(cx.tcx.local_def_id_to_hir_id(id))); Some(ExprFnSig::Closure(decl, subs.as_closure().sig())) }, ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).instantiate(cx.tcx, subs), Some(id))), From a1daa34ad005d0b34d30c878cb4e2e995346d300 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 11:24:57 +1100 Subject: [PATCH 128/158] Use `MirPatch` in `EnumSizeOpt`. Instead of `expand_statements`. This makes the code shorter and consistent with other MIR transform passes. The tests require updating because there is a slight change in MIR output: - the old code replaced the original statement with twelve new statements. - the new code inserts converts the original statement to a `nop` and then insert twelve new statements in front of it. I.e. we now end up with an extra `nop`, which doesn't matter at all. --- .../rustc_mir_transform/src/large_enums.rs | 176 +++++++----------- .../enum_opt.cand.EnumSizeOpt.32bit.diff | 2 + .../enum_opt.cand.EnumSizeOpt.64bit.diff | 2 + .../enum_opt.unin.EnumSizeOpt.32bit.diff | 2 + .../enum_opt.unin.EnumSizeOpt.64bit.diff | 2 + 5 files changed, 77 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 1e546bfbeb30..47cb478fe33e 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -6,6 +6,8 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::Session; +use crate::patch::MirPatch; + /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large /// enough discrepancy between them. /// @@ -41,31 +43,34 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { let mut alloc_cache = FxHashMap::default(); let typing_env = body.typing_env(tcx); - let blocks = body.basic_blocks.as_mut(); - let local_decls = &mut body.local_decls; + let mut patch = MirPatch::new(body); - for bb in blocks { - bb.expand_statements(|st| { + for (block, data) in body.basic_blocks.as_mut().iter_enumerated_mut() { + for (statement_index, st) in data.statements.iter_mut().enumerate() { let StatementKind::Assign(box ( lhs, Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), )) = &st.kind else { - return None; + continue; }; - let ty = lhs.ty(local_decls, tcx).ty; + let location = Location { block, statement_index }; - let (adt_def, num_variants, alloc_id) = - self.candidate(tcx, typing_env, ty, &mut alloc_cache)?; + let ty = lhs.ty(&body.local_decls, tcx).ty; - let source_info = st.source_info; - let span = source_info.span; + let Some((adt_def, num_variants, alloc_id)) = + self.candidate(tcx, typing_env, ty, &mut alloc_cache) + else { + continue; + }; + + let span = st.source_info.span; let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); - let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); - let store_live = - Statement { source_info, kind: StatementKind::StorageLive(size_array_local) }; + let size_array_local = patch.new_temp(tmp_ty, span); + + let store_live = StatementKind::StorageLive(size_array_local); let place = Place::from(size_array_local); let constant_vals = ConstOperand { @@ -77,108 +82,63 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { ), }; let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); - let const_assign = - Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) }; + let const_assign = StatementKind::Assign(Box::new((place, rval))); - let discr_place = Place::from( - local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), - ); - let store_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_place, - Rvalue::Discriminant(*rhs), - ))), - }; + let discr_place = + Place::from(patch.new_temp(adt_def.repr().discr_type().to_ty(tcx), span)); + let store_discr = + StatementKind::Assign(Box::new((discr_place, Rvalue::Discriminant(*rhs)))); - let discr_cast_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - let cast_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_cast_place, - Rvalue::Cast( - CastKind::IntToInt, - Operand::Copy(discr_place), - tcx.types.usize, - ), - ))), - }; + let discr_cast_place = Place::from(patch.new_temp(tcx.types.usize, span)); + let cast_discr = StatementKind::Assign(Box::new(( + discr_cast_place, + Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr_place), tcx.types.usize), + ))); - let size_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - let store_size = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - size_place, - Rvalue::Use(Operand::Copy(Place { - local: size_array_local, - projection: tcx - .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), - })), - ))), - }; + let size_place = Place::from(patch.new_temp(tcx.types.usize, span)); + let store_size = StatementKind::Assign(Box::new(( + size_place, + Rvalue::Use(Operand::Copy(Place { + local: size_array_local, + projection: tcx.mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), + })), + ))); - let dst = - Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span))); - let dst_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst, - Rvalue::RawPtr(RawPtrKind::Mut, *lhs), - ))), - }; + let dst = Place::from(patch.new_temp(Ty::new_mut_ptr(tcx, ty), span)); + let dst_ptr = + StatementKind::Assign(Box::new((dst, Rvalue::RawPtr(RawPtrKind::Mut, *lhs)))); let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); - let dst_cast_place = - Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); - let dst_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), - ))), - }; + let dst_cast_place = Place::from(patch.new_temp(dst_cast_ty, span)); + let dst_cast = StatementKind::Assign(Box::new(( + dst_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), + ))); - let src = - Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span))); - let src_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src, - Rvalue::RawPtr(RawPtrKind::Const, *rhs), - ))), - }; + let src = Place::from(patch.new_temp(Ty::new_imm_ptr(tcx, ty), span)); + let src_ptr = + StatementKind::Assign(Box::new((src, Rvalue::RawPtr(RawPtrKind::Const, *rhs)))); let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); - let src_cast_place = - Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); - let src_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), - ))), - }; + let src_cast_place = Place::from(patch.new_temp(src_cast_ty, span)); + let src_cast = StatementKind::Assign(Box::new(( + src_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), + ))); - let deinit_old = - Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) }; + let deinit_old = StatementKind::Deinit(Box::new(dst)); - let copy_bytes = Statement { - source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src: Operand::Copy(src_cast_place), - dst: Operand::Copy(dst_cast_place), - count: Operand::Copy(size_place), - }), - )), - }; + let copy_bytes = StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + src: Operand::Copy(src_cast_place), + dst: Operand::Copy(dst_cast_place), + count: Operand::Copy(size_place), + }), + )); - let store_dead = - Statement { source_info, kind: StatementKind::StorageDead(size_array_local) }; + let store_dead = StatementKind::StorageDead(size_array_local); - let iter = [ + let stmts = [ store_live, const_assign, store_discr, @@ -191,14 +151,16 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { deinit_old, copy_bytes, store_dead, - ] - .into_iter(); + ]; + for stmt in stmts { + patch.add_statement(location, stmt); + } st.make_nop(); - - Some(iter) - }); + } } + + patch.apply(body); } fn is_required(&self) -> bool { diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff index 727efe4b0d95..267a4c1cf6be 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -47,6 +47,7 @@ + Deinit(_8); + copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); ++ nop; StorageDead(_2); - _0 = move _1; + StorageLive(_12); @@ -61,6 +62,7 @@ + Deinit(_16); + copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); ++ nop; StorageDead(_1); return; } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff index 8d0cd97f7866..8e5c403cd7e6 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -47,6 +47,7 @@ + Deinit(_8); + copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); ++ nop; StorageDead(_2); - _0 = move _1; + StorageLive(_12); @@ -61,6 +62,7 @@ + Deinit(_16); + copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); ++ nop; StorageDead(_1); return; } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff index 6d1e2a72fdb7..96c5aadd85fd 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -47,6 +47,7 @@ + Deinit(_8); + copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); ++ nop; StorageDead(_2); - _0 = move _1; + StorageLive(_12); @@ -61,6 +62,7 @@ + Deinit(_16); + copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); ++ nop; StorageDead(_1); return; } diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff index 4b1406d0d623..d20e2e08eaaf 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -47,6 +47,7 @@ + Deinit(_8); + copy_nonoverlapping(dst = copy _9, src = copy _11, count = copy _7); + StorageDead(_4); ++ nop; StorageDead(_2); - _0 = move _1; + StorageLive(_12); @@ -61,6 +62,7 @@ + Deinit(_16); + copy_nonoverlapping(dst = copy _17, src = copy _19, count = copy _15); + StorageDead(_12); ++ nop; StorageDead(_1); return; } From e3316ae453a86eed28840a85b12df2ea1917aac7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 12:48:27 +1100 Subject: [PATCH 129/158] Improve `MirPatch` documentation and naming. It's currently lacking comments. This commit adds some, which is useful because there are some methods with non-obvious behaviour. The commit also renames two things: - `patch_map` becomes `term_patch_map`, because it's only about terminators. - `is_patched` becomes `is_term_patched`, for the same reason. (I would guess that originally `MirPatch` only handled terminators, and then over time it expanded to allow other modifications, but these names weren't updated.) --- .../src/elaborate_drops.rs | 6 +-- compiler/rustc_mir_transform/src/patch.rs | 51 ++++++++++++++----- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index ab6aafab446b..530c72ca549a 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -417,7 +417,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { .. } = data.terminator().kind { - assert!(!self.patch.is_patched(bb)); + assert!(!self.patch.is_term_patched(bb)); let loc = Location { block: tgt, statement_index: 0 }; let path = self.move_data().rev_lookup.find(destination.as_ref()); @@ -462,7 +462,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { // a Goto; see `MirPatch::new`). } _ => { - assert!(!self.patch.is_patched(bb)); + assert!(!self.patch.is_term_patched(bb)); } } } @@ -486,7 +486,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { .. } = data.terminator().kind { - assert!(!self.patch.is_patched(bb)); + assert!(!self.patch.is_term_patched(bb)); let loc = Location { block: bb, statement_index: data.statements.len() }; let path = self.move_data().rev_lookup.find(destination.as_ref()); diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index b4f6fa514a48..d3d181f6cb2b 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -4,11 +4,12 @@ use rustc_middle::ty::Ty; use rustc_span::Span; use tracing::debug; -/// This struct represents a patch to MIR, which can add -/// new statements and basic blocks and patch over block -/// terminators. +/// This struct lets you "patch" a MIR body, i.e. modify it. You can queue up +/// various changes, such as the addition of new statements and basic blocks +/// and replacement of terminators, and then apply the queued changes all at +/// once with `apply`. This is useful for MIR transformation passes. pub(crate) struct MirPatch<'tcx> { - patch_map: IndexVec>>, + term_patch_map: IndexVec>>, new_blocks: Vec>, new_statements: Vec<(Location, StatementKind<'tcx>)>, new_locals: Vec>, @@ -24,9 +25,10 @@ pub(crate) struct MirPatch<'tcx> { } impl<'tcx> MirPatch<'tcx> { + /// Creates a new, empty patch. pub(crate) fn new(body: &Body<'tcx>) -> Self { let mut result = MirPatch { - patch_map: IndexVec::from_elem(None, &body.basic_blocks), + term_patch_map: IndexVec::from_elem(None, &body.basic_blocks), new_blocks: vec![], new_statements: vec![], new_locals: vec![], @@ -141,10 +143,12 @@ impl<'tcx> MirPatch<'tcx> { bb } - pub(crate) fn is_patched(&self, bb: BasicBlock) -> bool { - self.patch_map[bb].is_some() + /// Has a replacement of this block's terminator been queued in this patch? + pub(crate) fn is_term_patched(&self, bb: BasicBlock) -> bool { + self.term_patch_map[bb].is_some() } + /// Queues the addition of a new temporary with additional local info. pub(crate) fn new_local_with_info( &mut self, ty: Ty<'tcx>, @@ -159,6 +163,7 @@ impl<'tcx> MirPatch<'tcx> { Local::new(index) } + /// Queues the addition of a new temporary. pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; @@ -174,29 +179,46 @@ impl<'tcx> MirPatch<'tcx> { self.new_locals[new_local_idx].ty } + /// Queues the addition of a new basic block. pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock { - let block = BasicBlock::new(self.patch_map.len()); + let block = BasicBlock::new(self.term_patch_map.len()); debug!("MirPatch: new_block: {:?}: {:?}", block, data); self.new_blocks.push(data); - self.patch_map.push(None); + self.term_patch_map.push(None); block } + /// Queues the replacement of a block's terminator. pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) { - assert!(self.patch_map[block].is_none()); + assert!(self.term_patch_map[block].is_none()); debug!("MirPatch: patch_terminator({:?}, {:?})", block, new); - self.patch_map[block] = Some(new); + self.term_patch_map[block] = Some(new); } + /// Queues the insertion of a statement at a given location. The statement + /// currently at that location, and all statements that follow, are shifted + /// down. If multiple statements are queued for addition at the same + /// location, the final statement order after calling `apply` will match + /// the queue insertion order. + /// + /// E.g. if we have `s0` at location `loc` and do these calls: + /// + /// p.add_statement(loc, s1); + /// p.add_statement(loc, s2); + /// p.apply(body); + /// + /// then the final order will be `s1, s2, s0`, with `s1` at `loc`. pub(crate) fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) { debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt); self.new_statements.push((loc, stmt)); } + /// Like `add_statement`, but specialized for assignments. pub(crate) fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) { self.add_statement(loc, StatementKind::Assign(Box::new((place, rv)))); } + /// Applies the queued changes. pub(crate) fn apply(self, body: &mut Body<'tcx>) { debug!( "MirPatch: {:?} new temps, starting from index {}: {:?}", @@ -209,14 +231,14 @@ impl<'tcx> MirPatch<'tcx> { self.new_blocks.len(), body.basic_blocks.len() ); - let bbs = if self.patch_map.is_empty() && self.new_blocks.is_empty() { + let bbs = if self.term_patch_map.is_empty() && self.new_blocks.is_empty() { body.basic_blocks.as_mut_preserves_cfg() } else { body.basic_blocks.as_mut() }; bbs.extend(self.new_blocks); body.local_decls.extend(self.new_locals); - for (src, patch) in self.patch_map.into_iter_enumerated() { + for (src, patch) in self.term_patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); bbs[src].terminator_mut().kind = patch; @@ -224,6 +246,9 @@ impl<'tcx> MirPatch<'tcx> { } let mut new_statements = self.new_statements; + + // This must be a stable sort to provide the ordering described in the + // comment for `add_statement`. new_statements.sort_by_key(|s| s.0); let mut delta = 0; From 627e08c909168aa451c613570a7f624e05f72766 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 13:05:41 +1100 Subject: [PATCH 130/158] Remove `BasicBlockData::expand_statements`. The previous commit removed its single use. `MirPatch` is a more flexible alternative. --- compiler/rustc_middle/src/mir/mod.rs | 49 ---------------------------- 1 file changed, 49 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 795cfcef2d36..c78cde82e15d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1376,55 +1376,6 @@ impl<'tcx> BasicBlockData<'tcx> { } } - pub fn expand_statements(&mut self, mut f: F) - where - F: FnMut(&mut Statement<'tcx>) -> Option, - I: iter::TrustedLen>, - { - // Gather all the iterators we'll need to splice in, and their positions. - let mut splices: Vec<(usize, I)> = vec![]; - let mut extra_stmts = 0; - for (i, s) in self.statements.iter_mut().enumerate() { - if let Some(mut new_stmts) = f(s) { - if let Some(first) = new_stmts.next() { - // We can already store the first new statement. - *s = first; - - // Save the other statements for optimized splicing. - let remaining = new_stmts.size_hint().0; - if remaining > 0 { - splices.push((i + 1 + extra_stmts, new_stmts)); - extra_stmts += remaining; - } - } else { - s.make_nop(); - } - } - } - - // Splice in the new statements, from the end of the block. - // FIXME(eddyb) This could be more efficient with a "gap buffer" - // where a range of elements ("gap") is left uninitialized, with - // splicing adding new elements to the end of that gap and moving - // existing elements from before the gap to the end of the gap. - // For now, this is safe code, emulating a gap but initializing it. - let mut gap = self.statements.len()..self.statements.len() + extra_stmts; - self.statements.resize( - gap.end, - Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop }, - ); - for (splice_start, new_stmts) in splices.into_iter().rev() { - let splice_end = splice_start + new_stmts.size_hint().0; - while gap.end > splice_end { - gap.start -= 1; - gap.end -= 1; - self.statements.swap(gap.start, gap.end); - } - self.statements.splice(splice_start..splice_end, new_stmts); - gap.end = splice_start; - } - } - pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> { if index < self.statements.len() { &self.statements[index] } else { &self.terminator } } From 69f5e342bf179c991e325587fb9b16a75851b372 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 13:31:08 +1100 Subject: [PATCH 131/158] Inline and remove `BasicBlockData::retain_statements`. It has a single call site, and the code is clearer this way. --- compiler/rustc_middle/src/mir/mod.rs | 11 ----------- compiler/rustc_mir_transform/src/coroutine.rs | 11 ++++++----- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index c78cde82e15d..582941e7e049 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1365,17 +1365,6 @@ impl<'tcx> BasicBlockData<'tcx> { self.terminator.as_mut().expect("invalid terminator state") } - pub fn retain_statements(&mut self, mut f: F) - where - F: FnMut(&mut Statement<'_>) -> bool, - { - for s in &mut self.statements { - if !f(s) { - s.make_nop(); - } - } - } - pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> { if index < self.statements.len() { &self.statements[index] } else { &self.terminator } } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index afc49c5cc54a..f3f3a65cd805 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -393,12 +393,13 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { // Remove StorageLive and StorageDead statements for remapped locals - data.retain_statements(|s| match s.kind { - StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => { - !self.remap.contains(l) + for s in &mut data.statements { + if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = s.kind + && self.remap.contains(l) + { + s.make_nop(); } - _ => true, - }); + } let ret_val = match data.terminator().kind { TerminatorKind::Return => { From 9fc759099b20993e17a911e2fc7ffec83042b6f1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 17 Feb 2025 21:16:08 -0500 Subject: [PATCH 132/158] Enforce T: Hash for Interned<...> This adds panicking Hash impls for several resolver types that don't actually satisfy this condition. It's not obvious to me that rustc_resolve actually upholds the Interned guarantees but fixing that seems pretty hard (the structures have at minimum some interior mutability, so it's not really recursively hashable in place...). --- compiler/rustc_data_structures/src/intern.rs | 5 +++- compiler/rustc_resolve/src/imports.rs | 13 ++++++++++ compiler/rustc_resolve/src/lib.rs | 26 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 850b052f564b..8079212fac55 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -92,7 +92,10 @@ impl<'a, T: Ord> Ord for Interned<'a, T> { } } -impl<'a, T> Hash for Interned<'a, T> { +impl<'a, T> Hash for Interned<'a, T> +where + T: Hash, +{ #[inline] fn hash(&self, s: &mut H) { // Pointer hashing is sufficient, due to the uniqueness constraint. diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b1b234eb7573..46e52e1f131b 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -182,6 +182,19 @@ pub(crate) struct ImportData<'ra> { /// so we can use referential equality to compare them. pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>; +// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the +// contained data. +// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees +// are upheld. +impl std::hash::Hash for ImportData<'_> { + fn hash(&self, _: &mut H) + where + H: std::hash::Hasher, + { + unreachable!() + } +} + impl<'ra> ImportData<'ra> { pub(crate) fn is_glob(&self) -> bool { matches!(self.kind, ImportKind::Glob { .. }) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 90191b7776f3..5bc37e09f089 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -589,6 +589,19 @@ struct ModuleData<'ra> { #[rustc_pass_by_value] struct Module<'ra>(Interned<'ra, ModuleData<'ra>>); +// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the +// contained data. +// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees +// are upheld. +impl std::hash::Hash for ModuleData<'_> { + fn hash(&self, _: &mut H) + where + H: std::hash::Hasher, + { + unreachable!() + } +} + impl<'ra> ModuleData<'ra> { fn new( parent: Option>, @@ -739,6 +752,19 @@ struct NameBindingData<'ra> { /// so we can use referential equality to compare them. type NameBinding<'ra> = Interned<'ra, NameBindingData<'ra>>; +// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the +// contained data. +// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees +// are upheld. +impl std::hash::Hash for NameBindingData<'_> { + fn hash(&self, _: &mut H) + where + H: std::hash::Hasher, + { + unreachable!() + } +} + trait ToNameBinding<'ra> { fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra>; } From 04eeda47abd07a5ba6f3f93e586ecf75d5574545 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 13:40:58 +1100 Subject: [PATCH 133/158] Inline and replace `Statement::replace_nop`. It has a single call site, and doesn't seem worth having as an API function. --- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/mir/statement.rs | 9 --------- compiler/rustc_mir_transform/src/single_use_consts.rs | 8 +++++--- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 582941e7e049..74ecff720824 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -4,8 +4,8 @@ use std::borrow::Cow; use std::fmt::{self, Debug, Formatter}; +use std::iter; use std::ops::{Index, IndexMut}; -use std::{iter, mem}; pub use basic_blocks::BasicBlocks; use either::Either; diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index d345c99f902f..690a907f9a33 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -19,15 +19,6 @@ impl Statement<'_> { pub fn make_nop(&mut self) { self.kind = StatementKind::Nop } - - /// Changes a statement to a nop and returns the original statement. - #[must_use = "If you don't need the statement, use `make_nop` instead"] - pub fn replace_nop(&mut self) -> Self { - Statement { - source_info: self.source_info, - kind: mem::replace(&mut self.kind, StatementKind::Nop), - } - } } impl<'tcx> StatementKind<'tcx> { diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index c5e951eb8b2c..02caa92ad3fc 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -48,9 +48,11 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { // We're only changing an operand, not the terminator kinds or successors let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); - let init_statement = - basic_blocks[init_loc.block].statements[init_loc.statement_index].replace_nop(); - let StatementKind::Assign(place_and_rvalue) = init_statement.kind else { + let init_statement_kind = std::mem::replace( + &mut basic_blocks[init_loc.block].statements[init_loc.statement_index].kind, + StatementKind::Nop, + ); + let StatementKind::Assign(place_and_rvalue) = init_statement_kind else { bug!("No longer an assign?"); }; let (place, rvalue) = *place_and_rvalue; From d2f15971de97eb4a18c2e54890c78c629858d51b Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Mon, 17 Feb 2025 20:21:05 -0800 Subject: [PATCH 134/158] Remove std::os::wasi::fs::FileExt::tell Following #137165 (Use `tell` for `::stream_position`), `tell` is now directly exposed via `stream_position`, making `::tell` redundant. Remove it. --- library/std/src/os/wasi/fs.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index 42aada131dad..34f0e89f2f1e 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -162,13 +162,6 @@ pub trait FileExt { Ok(()) } - /// Returns the current position within the file. - /// - /// This corresponds to the `fd_tell` syscall and is similar to - /// `seek` where you offset 0 bytes from the current position. - #[doc(alias = "fd_tell")] - fn tell(&self) -> io::Result; - /// Adjusts the flags associated with this file. /// /// This corresponds to the `fd_fdstat_set_flags` syscall. @@ -240,10 +233,6 @@ impl FileExt for fs::File { self.as_inner().as_inner().pwrite(bufs, offset) } - fn tell(&self) -> io::Result { - self.as_inner().as_inner().tell() - } - fn fdstat_set_flags(&self, flags: u16) -> io::Result<()> { self.as_inner().as_inner().set_flags(flags) } From 693f7035f1a98cc9a640b045c9e996c8bb1606cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 04:50:11 +0000 Subject: [PATCH 135/158] Make E0599 a structured error --- compiler/rustc_hir_analysis/messages.ftl | 2 ++ compiler/rustc_hir_analysis/src/errors.rs | 9 +++++++++ .../src/hir_ty_lowering/mod.rs | 17 ++++++++--------- compiler/rustc_hir_analysis/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 14 +++++--------- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 5560d087e96f..47d5976be09e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -387,6 +387,8 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}` + hir_analysis_not_supported_delegation = {$descr} .label = callee defined here diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 14ea10461cbe..1a0b0edb2570 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1417,6 +1417,15 @@ pub(crate) struct CrossCrateTraitsDefined { pub traits: String, } +#[derive(Diagnostic)] +#[diag(hir_analysis_no_variant_named, code = E0599)] +pub struct NoVariantNamed<'tcx> { + #[primary_span] + pub span: Span, + pub ident: Ident, + pub ty: Ty<'tcx>, +} + // FIXME(fmease): Deduplicate: #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 88323db6dda6..3b17d7fe6ffc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,7 +53,9 @@ use tracing::{debug, instrument}; use crate::bounds::Bounds; use crate::check::check_abi_fn_ptr; -use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType}; +use crate::errors::{ + AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed, +}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -1188,14 +1190,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let msg = format!("expected type, found variant `{assoc_ident}`"); self.dcx().span_err(span, msg) } else if qself_ty.is_enum() { - let mut err = struct_span_code_err!( - self.dcx(), - assoc_ident.span, - E0599, - "no variant named `{}` found for enum `{}`", - assoc_ident, - qself_ty, - ); + let mut err = self.dcx().create_err(NoVariantNamed { + span: assoc_ident.span, + ident: assoc_ident, + ty: qself_ty, + }); let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT"); if let Some(variant_name) = find_best_match_for_name( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 8a529e9c686e..2068b9f2dea6 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -93,6 +93,7 @@ mod impl_wf_check; mod outlives; mod variance; +pub use errors::NoVariantNamed; use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9ccd67460874..9000868ec276 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -19,6 +19,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; +use rustc_hir_analysis::NoVariantNamed; use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; @@ -3837,15 +3838,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_enumerated() .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else { - type_error_struct!( - self.dcx(), - ident.span, - container, - E0599, - "no variant named `{ident}` found for enum `{container}`", - ) - .with_span_label(field.span, "variant not found") - .emit(); + self.dcx() + .create_err(NoVariantNamed { span: ident.span, ident, ty: container }) + .with_span_label(field.span, "variant not found") + .emit_unless(container.references_error()); break; }; let Some(&subfield) = fields.next() else { From 2d2de181668bbfc50b3396f470da64cd46443c39 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 00:12:26 -0800 Subject: [PATCH 136/158] compiler: Stop reexporting stuff in cg_llvm::abi The reexports confuse tooling like rustdoc into thinking cg_llvm is the source of key types that originate in rustc_target. --- compiler/rustc_codegen_llvm/src/abi.rs | 19 ++++++++----------- .../src/debuginfo/metadata.rs | 18 ++++++++++-------- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/declare.rs | 3 ++- compiler/rustc_codegen_llvm/src/intrinsic.rs | 12 ++++++------ 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 28f423efc214..8c75125e009b 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -2,19 +2,18 @@ use std::borrow::Borrow; use std::cmp; use libc::c_uint; -use rustc_abi as abi; -pub(crate) use rustc_abi::ExternAbi; -use rustc_abi::{HasDataLayout, Primitive, Reg, RegKind, Size}; +use rustc_abi::{BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::*; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; -pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA}; use rustc_middle::{bug, ty}; use rustc_session::config; -pub(crate) use rustc_target::callconv::*; +use rustc_target::callconv::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, Conv, FnAbi, PassMode, +}; use rustc_target::spec::SanitizerSet; use smallvec::SmallVec; @@ -458,7 +457,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { match &self.ret.mode { PassMode::Direct(attrs) => { attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); - if let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr { + if let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr { apply_range_attr(llvm::AttributePlace::ReturnValue, scalar); } } @@ -499,7 +498,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } PassMode::Direct(attrs) => { let i = apply(attrs); - if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr { + if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr { apply_range_attr(llvm::AttributePlace::Argument(i), scalar); } } @@ -514,9 +513,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Pair(a, b) => { let i = apply(a); let ii = apply(b); - if let abi::BackendRepr::ScalarPair(scalar_a, scalar_b) = - arg.layout.backend_repr - { + if let BackendRepr::ScalarPair(scalar_a, scalar_b) = arg.layout.backend_repr { apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a); apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b); } @@ -576,7 +573,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } if bx.cx.sess().opts.optimize != config::OptLevel::No && llvm_util::get_version() < (19, 0, 0) - && let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr + && let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr && matches!(scalar.primitive(), Primitive::Int(..)) // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 59c3fe635d07..98d59f5a8ae0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -11,7 +11,9 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{ + HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA, +}; use rustc_middle::ty::{ self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, }; @@ -34,12 +36,12 @@ use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::dwarf_const; use crate::debuginfo::metadata::type_map::build_type_with_children; use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind}; +use crate::llvm; use crate::llvm::debuginfo::{ DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind, DebugNameTableKind, }; use crate::value::Value; -use crate::{abi, llvm}; impl PartialEq for llvm::Metadata { fn eq(&self, other: &Self) -> bool { @@ -211,16 +213,16 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( }; let layout = cx.layout_of(layout_type); - let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR); - let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA); + let addr_field = layout.field(cx, WIDE_PTR_ADDR); + let extra_field = layout.field(cx, WIDE_PTR_EXTRA); let (addr_field_name, extra_field_name) = match wide_pointer_kind { WidePtrKind::Dyn => ("pointer", "vtable"), WidePtrKind::Slice => ("data_ptr", "length"), }; - assert_eq!(abi::WIDE_PTR_ADDR, 0); - assert_eq!(abi::WIDE_PTR_EXTRA, 1); + assert_eq!(WIDE_PTR_ADDR, 0); + assert_eq!(WIDE_PTR_EXTRA, 1); // The data pointer type is a regular, thin pointer, regardless of whether this // is a slice or a trait object. @@ -242,7 +244,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( owner, addr_field_name, (addr_field.size, addr_field.align.abi), - layout.fields.offset(abi::WIDE_PTR_ADDR), + layout.fields.offset(WIDE_PTR_ADDR), DIFlags::FlagZero, data_ptr_type_di_node, None, @@ -252,7 +254,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( owner, extra_field_name, (extra_field.size, extra_field.align.abi), - layout.fields.offset(abi::WIDE_PTR_EXTRA), + layout.fields.offset(WIDE_PTR_EXTRA), DIFlags::FlagZero, type_di_node(cx, extra_field.ty), None, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 17f2d5f4e731..10819a53b1df 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -22,6 +22,7 @@ use rustc_session::config::{self, DebugInfo}; use rustc_span::{ BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId, Symbol, }; +use rustc_target::callconv::FnAbi; use rustc_target::spec::DebuginfoKind; use smallvec::SmallVec; use tracing::debug; @@ -29,7 +30,6 @@ use tracing::debug; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node}; use self::namespace::mangled_name_of_instance; use self::utils::{DIB, create_DIArray, is_node_local_to_unit}; -use crate::abi::FnAbi; use crate::builder::Builder; use crate::common::{AsCCharPtr, CodegenCx}; use crate::llvm; diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index cebceef1b93f..e79662ebc647 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -16,10 +16,11 @@ use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods; use rustc_data_structures::fx::FxIndexSet; use rustc_middle::ty::{Instance, Ty}; use rustc_sanitizers::{cfi, kcfi}; +use rustc_target::callconv::FnAbi; use smallvec::SmallVec; use tracing::debug; -use crate::abi::{FnAbi, FnAbiLlvmExt}; +use crate::abi::FnAbiLlvmExt; use crate::common::AsCCharPtr; use crate::context::{CodegenCx, SimpleCx}; use crate::llvm::AttributePlace::Function; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 8b9768859045..7e1a9d361e6f 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1,7 +1,7 @@ use std::assert_matches::assert_matches; use std::cmp::Ordering; -use rustc_abi::{self as abi, Align, Float, HasDataLayout, Primitive, Size}; +use rustc_abi::{Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size}; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization}; @@ -14,10 +14,11 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; +use rustc_target::callconv::{FnAbi, PassMode}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use tracing::debug; -use crate::abi::{ExternAbi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode}; +use crate::abi::{FnAbiLlvmExt, LlvmType}; use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, Metadata}; @@ -257,7 +258,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::va_arg => { match fn_abi.ret.layout.backend_repr { - abi::BackendRepr::Scalar(scalar) => { + BackendRepr::Scalar(scalar) => { match scalar.primitive() { Primitive::Int(..) => { if self.cx().size_of(ret_ty).bytes() < 4 { @@ -470,7 +471,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::raw_eq => { - use abi::BackendRepr::*; + use BackendRepr::*; let tp_ty = fn_args.type_at(0); let layout = self.layout_of(tp_ty).layout; let use_integer_compare = match layout.backend_repr() { @@ -582,8 +583,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } let llret_ty = if ret_ty.is_simd() - && let abi::BackendRepr::Memory { .. } = - self.layout_of(ret_ty).layout.backend_repr + && let BackendRepr::Memory { .. } = self.layout_of(ret_ty).layout.backend_repr { let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx()); let elem_ll_ty = match elem_ty.kind() { From fa53181f424f167b8aafc78bcb6b75356d3c5748 Mon Sep 17 00:00:00 2001 From: Jubilee Date: Tue, 18 Feb 2025 01:29:23 -0800 Subject: [PATCH 137/158] cg_clif: Tweak formatting of global comments Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- compiler/rustc_codegen_cranelift/src/abi/comments.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs index e2c9f40d1479..c74efeb59f3f 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs @@ -84,13 +84,13 @@ pub(super) fn add_local_place_comments<'tcx>( let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( - "{:<5} {:5} {:30} {:4}b {}, {}{}", + "{:<5} {:5} {:30} {:4}b {}{}{}", kind, format!("{:?}", local), format!("{:?}", ty), size.bytes(), align.abi.bytes(), - if extra.is_empty() { "" } else { " " }, + if extra.is_empty() { "" } else { " " }, extra, )); } From f910684616f357a8084151a162ed3c3fe0e512e6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 18 Feb 2025 10:29:16 +0100 Subject: [PATCH 138/158] don't ICE for alias-relate goals with error term --- .../src/solve/alias_relate.rs | 12 +++++++++++- compiler/rustc_type_ir/src/inherent.rs | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index d8c1dc8b4e9f..0fc313e33b32 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -34,7 +34,17 @@ where ) -> QueryResult { let cx = self.cx(); let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; - debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); + + // Check that the alias-relate goal is reasonable. Writeback for + // `coroutine_stalled_predicates` can replace alias terms with + // `{type error}` if the alias still contains infer vars, so we also + // accept alias-relate goals where one of the terms is an error. + debug_assert!( + lhs.to_alias_term().is_some() + || rhs.to_alias_term().is_some() + || lhs.is_error() + || rhs.is_error() + ); // Structurally normalize the lhs. let lhs = if let Some(alias) = lhs.to_alias_term() { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 6924216bd26e..9277226b718b 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -126,6 +126,10 @@ pub trait Ty>: matches!(self.kind(), ty::Infer(ty::TyVar(_))) } + fn is_ty_error(self) -> bool { + matches!(self.kind(), ty::Error(_)) + } + fn is_floating_point(self) -> bool { matches!(self.kind(), ty::Float(_) | ty::Infer(ty::FloatVar(_))) } @@ -284,6 +288,10 @@ pub trait Const>: fn is_ct_var(self) -> bool { matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_))) } + + fn is_ct_error(self) -> bool { + matches!(self.kind(), ty::ConstKind::Error(_)) + } } pub trait ValueConst>: Copy + Debug + Hash + Eq { @@ -370,6 +378,13 @@ pub trait Term>: } } + fn is_error(self) -> bool { + match self.kind() { + ty::TermKind::Ty(ty) => ty.is_ty_error(), + ty::TermKind::Const(ct) => ct.is_ct_error(), + } + } + fn to_alias_term(self) -> Option> { match self.kind() { ty::TermKind::Ty(ty) => match ty.kind() { From a72402a0f950e92758600aa7996899b5241bb6a5 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 18 Feb 2025 10:54:37 +0100 Subject: [PATCH 139/158] add last std diagnostic items for clippy --- compiler/rustc_span/src/symbol.rs | 7 +++++++ library/core/src/char/methods.rs | 1 + library/std/src/io/stdio.rs | 1 + library/std/src/panic.rs | 1 + library/std/src/process.rs | 4 ++++ 5 files changed, 14 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 940390894808..d155e95078be 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -192,6 +192,7 @@ symbols! { Capture, Cell, Center, + Child, Cleanup, Clone, CoercePointee, @@ -336,6 +337,7 @@ symbols! { SliceIter, Some, SpanCtxt, + Stdin, String, StructuralPartialEq, SubdiagMessage, @@ -599,6 +601,9 @@ symbols! { cfi, cfi_encoding, char, + char_is_ascii, + child_id, + child_kill, client, clippy, clobber_abi, @@ -1468,6 +1473,7 @@ symbols! { panic_2015, panic_2021, panic_abort, + panic_any, panic_bounds_check, panic_cannot_unwind, panic_const_add_overflow, @@ -1573,6 +1579,7 @@ symbols! { proc_macro_mod, proc_macro_non_items, proc_macro_path_invoc, + process_abort, process_exit, profiler_builtins, profiler_runtime, diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index ccfdbf0eb704..34f5c3e94bcd 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1168,6 +1168,7 @@ impl char { #[must_use] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "char_is_ascii")] #[inline] pub const fn is_ascii(&self) -> bool { *self as u32 <= 0x7F diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 318c35082216..661c422811ab 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -239,6 +239,7 @@ fn handle_ebadf_lazy(r: io::Result, default: impl FnOnce() -> T) -> io::Re /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Stdin")] pub struct Stdin { inner: &'static Mutex>, } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 61801db072a0..22776ae2bc4a 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -255,6 +255,7 @@ pub use crate::panicking::{set_hook, take_hook}; #[stable(feature = "panic_any", since = "1.51.0")] #[inline] #[track_caller] +#[cfg_attr(not(test), rustc_diagnostic_item = "panic_any")] pub fn panic_any(msg: M) -> ! { crate::panicking::begin_panic(msg); } diff --git a/library/std/src/process.rs b/library/std/src/process.rs index fd0fd1cb755e..bdd4844b6511 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -217,6 +217,7 @@ use crate::{fmt, fs, str}; /// /// [`wait`]: Child::wait #[stable(feature = "process", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Child")] pub struct Child { pub(crate) handle: imp::Process, @@ -2115,6 +2116,7 @@ impl Child { /// [`ErrorKind`]: io::ErrorKind /// [`InvalidInput`]: io::ErrorKind::InvalidInput #[stable(feature = "process", since = "1.0.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "child_kill")] pub fn kill(&mut self) -> io::Result<()> { self.handle.kill() } @@ -2135,6 +2137,7 @@ impl Child { /// ``` #[must_use] #[stable(feature = "process_id", since = "1.3.0")] + #[cfg_attr(not(test), rustc_diagnostic_item = "child_id")] pub fn id(&self) -> u32 { self.handle.id() } @@ -2375,6 +2378,7 @@ pub fn exit(code: i32) -> ! { /// [panic hook]: crate::panic::set_hook #[stable(feature = "process_abort", since = "1.17.0")] #[cold] +#[cfg_attr(not(test), rustc_diagnostic_item = "process_abort")] pub fn abort() -> ! { crate::sys::abort_internal(); } From 53effa4566dc1493e1dc5be206105dd99e3192b5 Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Tue, 18 Feb 2025 13:01:01 +0100 Subject: [PATCH 140/158] eval_outlives: bail out early if both regions are in the same SCC --- compiler/rustc_borrowck/src/region_infer/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d2268c4779d6..e0e3e028c612 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1267,6 +1267,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { let sub_region_scc = self.constraint_sccs.scc(sub_region); let sup_region_scc = self.constraint_sccs.scc(sup_region); + if sub_region_scc == sup_region_scc { + debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC"); + return true; + } + // If we are checking that `'sup: 'sub`, and `'sub` contains // some placeholder that `'sup` cannot name, then this is only // true if `'sup` outlives static. From d0a5bbbb8e394095848e078a3fff72beaad14209 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 00:03:10 +0100 Subject: [PATCH 141/158] document and test all `LayoutError` variants --- compiler/rustc_middle/src/ty/layout.rs | 21 ++++++++ tests/ui/layout/debug.rs | 5 ++ tests/ui/layout/debug.stderr | 8 ++- tests/ui/layout/normalization-failure.rs | 57 ++++++++++++++++++++ tests/ui/layout/normalization-failure.stderr | 12 +++++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests/ui/layout/normalization-failure.rs create mode 100644 tests/ui/layout/normalization-failure.stderr diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index bbb8a9fa6714..2a058addf159 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -229,11 +229,32 @@ impl fmt::Display for ValidityRequirement { #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)] pub enum LayoutError<'tcx> { + /// A type doesn't have a sensible layout. + /// + /// This variant is used for layout errors that don't necessarily cause + /// compile errors. + /// + /// For example, this can happen if a struct contains an unsized type in a + /// non-tail field, but has an unsatisfiable bound like `str: Sized`. Unknown(Ty<'tcx>), + /// The size of a type exceeds [`TargetDataLayout::obj_size_bound`]. SizeOverflow(Ty<'tcx>), + /// The layout can vary due to a generic parameter. + /// + /// Unlike `Unknown`, this variant is a "soft" error and indicates that the layout + /// may become computable after further instantiating the generic parameter(s). TooGeneric(Ty<'tcx>), + /// An alias failed to normalize. + /// + /// This variant is necessary, because, due to trait solver incompleteness, it is + /// possible than an alias that was rigid during analysis fails to normalize after + /// revealing opaque types. + /// + /// See `tests/ui/layout/normalization-failure.rs` for an example. NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), + /// A non-layout error is reported elsewhere. ReferencesError(ErrorGuaranteed), + /// A type has cyclic layout, i.e. the type contains itself without indirection. Cycle(ErrorGuaranteed), } diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index 81dc72852543..c0adf9ec6776 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -82,3 +82,8 @@ type Impossible = (str, str); //~ ERROR: cannot be known at compilation time #[rustc_layout(debug)] union EmptyUnion {} //~ ERROR: has an unknown layout //~^ ERROR: unions cannot have zero fields + +// Test the error message of `LayoutError::TooGeneric` +// (this error is never emitted to users). +#[rustc_layout(debug)] +type TooGeneric = T; //~ ERROR: does not have a fixed size diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 319c0de26a90..d64dee4e27fc 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -596,12 +596,18 @@ error: the type has an unknown layout LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^ +error: `T` does not have a fixed size + --> $DIR/debug.rs:89:1 + | +LL | type TooGeneric = T; + | ^^^^^^^^^^^^^^^^^^ + error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases --> $DIR/debug.rs:75:5 | LL | const C: () = (); | ^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/normalization-failure.rs b/tests/ui/layout/normalization-failure.rs new file mode 100644 index 000000000000..c0f8710c03cb --- /dev/null +++ b/tests/ui/layout/normalization-failure.rs @@ -0,0 +1,57 @@ +//! This test demonstrates how `LayoutError::NormalizationFailure` can happen and why +//! it is necessary. +//! +//! This code does not cause an immediate normalization error in typeck, because we +//! don't reveal the hidden type returned by `opaque` in the analysis typing mode. +//! Instead, `<{opaque} as Project2>::Assoc2` is a *rigid projection*, because we know +//! that `{opaque}: Project2` holds, due to the opaque type's `impl Project2` bound, +//! but cannot normalize `<{opaque} as Project2>::Assoc2` any further. +//! +//! However, in the post-analysis typing mode, which is used for the layout computation, +//! the opaque's hidden type is revealed to be `PhantomData`, and now we fail to +//! normalize ` as Project2>::Assoc2` if there is a `T: Project1` bound +//! in the param env! This happens, because `PhantomData: Project2` only holds if +//! `::Assoc1 == ()` holds. This would usually be satisfied by the +//! blanket `impl Project1 for T`, but due to the `T: Project1` bound we do not +//! normalize `::Assoc1` via the impl and treat it as rigid instead. +//! Therefore, `PhantomData: Project2` does NOT hold and normalizing +//! ` as Project2>::Assoc2` fails. +//! +//! Note that this layout error can only happen when computing the layout in a generic +//! context, which is not required for codegen, but may happen for lints, MIR optimizations, +//! and the transmute check. + +use std::marker::PhantomData; + +trait Project1 { + type Assoc1; +} + +impl Project1 for T { + type Assoc1 = (); +} + +trait Project2 { + type Assoc2; + fn get(self) -> Self::Assoc2; +} + +impl> Project2 for PhantomData { + type Assoc2 = (); + fn get(self) -> Self::Assoc2 {} +} + +fn opaque() -> impl Project2 { + PhantomData:: +} + +fn check() { + unsafe { + std::mem::transmute::<_, ()>(opaque::().get()); + //~^ ERROR: cannot transmute + //~| NOTE: (unable to determine layout for `::Assoc2` because `::Assoc2` cannot be normalized) + //~| NOTE: (0 bits) + } +} + +fn main() {} diff --git a/tests/ui/layout/normalization-failure.stderr b/tests/ui/layout/normalization-failure.stderr new file mode 100644 index 000000000000..5fe38d4403a2 --- /dev/null +++ b/tests/ui/layout/normalization-failure.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/normalization-failure.rs:50:9 + | +LL | std::mem::transmute::<_, ()>(opaque::().get()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `::Assoc2` (unable to determine layout for `::Assoc2` because `::Assoc2` cannot be normalized) + = note: target type: `()` (0 bits) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0512`. From 802b7abab736166fcb12c2567c743e1da6d6806c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 20:26:07 +0100 Subject: [PATCH 142/158] clean up layout error diagnostics - group the fluent slugs together - reword (internal-only) "too generic" error to be more in line with the other errors --- compiler/rustc_middle/messages.ftl | 28 +++++++++++++------------- compiler/rustc_middle/src/error.rs | 10 ++++----- compiler/rustc_middle/src/ty/layout.rs | 12 +++++------ tests/ui/layout/debug.rs | 2 +- tests/ui/layout/debug.stderr | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index dcfa81dab252..0b3c0be1a4e1 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -37,9 +37,6 @@ middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} middle_bounds_check = index out of bounds: the length is {$len} but the index is {$index} -middle_cannot_be_normalized = - unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized - middle_conflict_types = this expression supplies two conflicting concrete types for the same opaque type @@ -52,9 +49,6 @@ middle_const_eval_non_int = middle_const_not_used_in_type_alias = const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias -middle_cycle = - a cycle occurred during layout computation - middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note -> [true] : {$note} *[other] {""} @@ -78,9 +72,23 @@ middle_erroneous_constant = erroneous constant encountered middle_failed_writing_file = failed to write file {$path}: {$error}" +middle_layout_cycle = + a cycle occurred during layout computation + +middle_layout_normalization_failure = + unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized + middle_layout_references_error = the type has an unknown layout +middle_layout_size_overflow = + values of the type `{$ty}` are too big for the target architecture + +middle_layout_too_generic = the type `{$ty}` does not have a fixed layout + +middle_layout_unknown = + the type `{$ty}` has an unknown layout + middle_opaque_hidden_type_mismatch = concrete type differs from previous defining opaque type use .label = expected `{$self_ty}`, got `{$other_ty}` @@ -98,16 +106,8 @@ middle_strict_coherence_needs_negative_coherence = to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled .label = due to this attribute -middle_too_generic = `{$ty}` does not have a fixed size - middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` -middle_unknown_layout = - the type `{$ty}` has an unknown layout - middle_unsupported_union = we don't support unions yet: '{$ty_name}' -middle_values_too_big = - values of the type `{$ty}` are too big for the target architecture - middle_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index c53e3d54cc49..be8a3403ba95 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -132,19 +132,19 @@ impl fmt::Debug for CustomSubdiagnostic<'_> { #[derive(Diagnostic)] pub enum LayoutError<'tcx> { - #[diag(middle_unknown_layout)] + #[diag(middle_layout_unknown)] Unknown { ty: Ty<'tcx> }, - #[diag(middle_too_generic)] + #[diag(middle_layout_too_generic)] TooGeneric { ty: Ty<'tcx> }, - #[diag(middle_values_too_big)] + #[diag(middle_layout_size_overflow)] Overflow { ty: Ty<'tcx> }, - #[diag(middle_cannot_be_normalized)] + #[diag(middle_layout_normalization_failure)] NormalizationFailure { ty: Ty<'tcx>, failure_ty: String }, - #[diag(middle_cycle)] + #[diag(middle_layout_cycle)] Cycle, #[diag(middle_layout_references_error)] diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2a058addf159..19fa83235749 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -264,11 +264,11 @@ impl<'tcx> LayoutError<'tcx> { use crate::fluent_generated::*; match self { - Unknown(_) => middle_unknown_layout, - SizeOverflow(_) => middle_values_too_big, - TooGeneric(_) => middle_too_generic, - NormalizationFailure(_, _) => middle_cannot_be_normalized, - Cycle(_) => middle_cycle, + Unknown(_) => middle_layout_unknown, + SizeOverflow(_) => middle_layout_size_overflow, + TooGeneric(_) => middle_layout_too_generic, + NormalizationFailure(_, _) => middle_layout_normalization_failure, + Cycle(_) => middle_layout_cycle, ReferencesError(_) => middle_layout_references_error, } } @@ -297,7 +297,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { match *self { LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"), LayoutError::TooGeneric(ty) => { - write!(f, "`{ty}` does not have a fixed size") + write!(f, "the type `{ty}` does not have a fixed layout") } LayoutError::SizeOverflow(ty) => { write!(f, "values of the type `{ty}` are too big for the target architecture") diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index c0adf9ec6776..b87a1d2031df 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -86,4 +86,4 @@ union EmptyUnion {} //~ ERROR: has an unknown layout // Test the error message of `LayoutError::TooGeneric` // (this error is never emitted to users). #[rustc_layout(debug)] -type TooGeneric = T; //~ ERROR: does not have a fixed size +type TooGeneric = T; //~ ERROR: does not have a fixed layout diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index d64dee4e27fc..0daf2d3b9e7f 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -596,7 +596,7 @@ error: the type has an unknown layout LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^ -error: `T` does not have a fixed size +error: the type `T` does not have a fixed layout --> $DIR/debug.rs:89:1 | LL | type TooGeneric = T; From 7a667d206c45b96676c260030a4e3d9be1cc8495 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 00:19:56 +0100 Subject: [PATCH 143/158] remove unreachable cases `ty::Placeholder` is used by the trait solver and computing its layout was necessary, because the `PointerLike` trait used to be automatically implemented for all types with pointer-like layout. Nowadays, `PointerLike` requires user-written impls and the trait solver no longer computes any layouts, so this can be removed. Unevaluated constants that aren't generic should have caused a const eval error earlier during normalization. --- compiler/rustc_ty_utils/src/layout.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 8429e68b600d..f9ce709d07cb 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -155,19 +155,12 @@ fn extract_const_value<'tcx>( ty::ConstKind::Error(guar) => { return Err(error(cx, LayoutError::ReferencesError(guar))); } - ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => { + ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => { if !const_.has_param() { - bug!("no generic type found in the type: {ty:?}"); + bug!("failed to normalize const, but it is not generic: {const_:?}"); } return Err(error(cx, LayoutError::TooGeneric(ty))); } - ty::ConstKind::Unevaluated(_) => { - if !const_.has_param() { - return Err(error(cx, LayoutError::Unknown(ty))); - } else { - return Err(error(cx, LayoutError::TooGeneric(ty))); - } - } ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { bug!("unexpected type: {ty:?}"); } @@ -728,17 +721,17 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::Unknown(ty))); } - ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { - bug!("Layout::compute: unexpected type `{}`", ty) + ty::Placeholder(..) + | ty::Bound(..) + | ty::CoroutineWitness(..) + | ty::Infer(_) + | ty::Error(_) => { + bug!("layout_of: unexpected type `{ty}`") } ty::Param(_) => { return Err(error(cx, LayoutError::TooGeneric(ty))); } - - ty::Placeholder(..) => { - return Err(error(cx, LayoutError::Unknown(ty))); - } }) } From 1d1ac3d310dfe90e1ec91c731f2cc306ddbd1eb4 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:02:18 +0100 Subject: [PATCH 144/158] remove redundant code - we normalize before calling `layout_of_uncached`, so we don't need to normalize again later - we check for type/const errors at the top of `layout_of_uncached`, so we don't need to check again later --- compiler/rustc_ty_utils/src/layout.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f9ce709d07cb..5c5558053cc4 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -152,17 +152,19 @@ fn extract_const_value<'tcx>( ) -> Result, &'tcx LayoutError<'tcx>> { match const_.kind() { ty::ConstKind::Value(cv) => Ok(cv), - ty::ConstKind::Error(guar) => { - return Err(error(cx, LayoutError::ReferencesError(guar))); - } ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => { if !const_.has_param() { bug!("failed to normalize const, but it is not generic: {const_:?}"); } return Err(error(cx, LayoutError::TooGeneric(ty))); } - ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { - bug!("unexpected type: {ty:?}"); + ty::ConstKind::Infer(_) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Error(_) => { + // `ty::ConstKind::Error` is handled at the top of `layout_of_uncached` + // (via `ty.error_reported()`). + bug!("layout_of: unexpected const: {const_:?}"); } } } @@ -267,16 +269,11 @@ fn layout_of_uncached<'tcx>( data_ptr.valid_range_mut().start = 1; } - let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); if pointee.is_sized(tcx, cx.typing_env) { return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); } - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() - // Projection eagerly bails out when the pointee references errors, - // fall back to structurally deducing metadata. - && !pointee.references_error() - { + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]); let metadata_ty = match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) { @@ -726,6 +723,7 @@ fn layout_of_uncached<'tcx>( | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { + // `ty::Error` is handled at the top of this function. bug!("layout_of: unexpected type `{ty}`") } From 67345f9203b451f21aa603329ab657f6e782267c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:17:08 +0100 Subject: [PATCH 145/158] remove useless parameter Remove the `repr` parameter from the wrappers around `calc.univariant`, because it's always defaulted. Only ADTs can have a repr and those call `calc.layout_of_struct_or_enum` and not `calc.univariant`. --- compiler/rustc_ty_utils/src/layout.rs | 46 ++++++--------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 5c5558053cc4..36dbddbb9d78 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -134,15 +134,10 @@ fn univariant_uninterned<'tcx>( cx: &LayoutCx<'tcx>, ty: Ty<'tcx>, fields: &IndexSlice>, - repr: &ReprOptions, kind: StructKind, ) -> Result, &'tcx LayoutError<'tcx>> { - let pack = repr.pack; - if pack.is_some() && repr.align.is_some() { - cx.tcx().dcx().bug("struct cannot be packed and aligned"); - } - - cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err)) + let repr = ReprOptions::default(); + cx.calc.univariant(fields, &repr, kind).map_err(|err| map_error(cx, ty, err)) } fn extract_const_value<'tcx>( @@ -189,10 +184,9 @@ fn layout_of_uncached<'tcx>( }; let scalar = |value: Primitive| tcx.mk_layout(LayoutData::scalar(cx, scalar_unit(value))); - let univariant = - |fields: &IndexSlice>, repr: &ReprOptions, kind| { - Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?)) - }; + let univariant = |fields: &IndexSlice>, kind| { + Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, kind)?)) + }; debug_assert!(!ty.has_non_region_infer()); Ok(match *ty.kind() { @@ -405,17 +399,10 @@ fn layout_of_uncached<'tcx>( }), // Odd unit types. - ty::FnDef(..) => { - univariant(IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized)? - } + ty::FnDef(..) => univariant(IndexSlice::empty(), StructKind::AlwaysSized)?, ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => { - let mut unit = univariant_uninterned( - cx, - ty, - IndexSlice::empty(), - &ReprOptions::default(), - StructKind::AlwaysSized, - )?; + let mut unit = + univariant_uninterned(cx, ty, IndexSlice::empty(), StructKind::AlwaysSized)?; match unit.backend_repr { BackendRepr::Memory { ref mut sized } => *sized = false, _ => bug!(), @@ -429,7 +416,6 @@ fn layout_of_uncached<'tcx>( let tys = args.as_closure().upvar_tys(); univariant( &tys.iter().map(|ty| cx.layout_of(ty)).try_collect::>()?, - &ReprOptions::default(), StructKind::AlwaysSized, )? } @@ -438,7 +424,6 @@ fn layout_of_uncached<'tcx>( let tys = args.as_coroutine_closure().upvar_tys(); univariant( &tys.iter().map(|ty| cx.layout_of(ty)).try_collect::>()?, - &ReprOptions::default(), StructKind::AlwaysSized, )? } @@ -447,11 +432,7 @@ fn layout_of_uncached<'tcx>( let kind = if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; - univariant( - &tys.iter().map(|k| cx.layout_of(k)).try_collect::>()?, - &ReprOptions::default(), - kind, - )? + univariant(&tys.iter().map(|k| cx.layout_of(k)).try_collect::>()?, kind)? } // SIMD vector types. @@ -902,13 +883,7 @@ fn coroutine_layout<'tcx>( .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) .try_collect::>()?; - let prefix = univariant_uninterned( - cx, - ty, - &prefix_layouts, - &ReprOptions::default(), - StructKind::AlwaysSized, - )?; + let prefix = univariant_uninterned(cx, ty, &prefix_layouts, StructKind::AlwaysSized)?; let (prefix_size, prefix_align) = (prefix.size, prefix.align); @@ -973,7 +948,6 @@ fn coroutine_layout<'tcx>( cx, ty, &variant_only_tys.map(|ty| cx.layout_of(ty)).try_collect::>()?, - &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), )?; variant.variants = Variants::Single { index }; From 2fbc413d832486106221253a2db7f4670473ee67 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:32:38 +0100 Subject: [PATCH 146/158] cosmetic changes - change function parameter order to `cx, ty, ...` to match the other functions in this file - use `ct` identifier for `ty::Const` to match the majority of the compiler codebase - remove useless return - bring match arms in a more natural order --- compiler/rustc_ty_utils/src/layout.rs | 40 +++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 36dbddbb9d78..556512e0236e 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -141,17 +141,17 @@ fn univariant_uninterned<'tcx>( } fn extract_const_value<'tcx>( - const_: ty::Const<'tcx>, - ty: Ty<'tcx>, cx: &LayoutCx<'tcx>, + ty: Ty<'tcx>, + ct: ty::Const<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { - match const_.kind() { + match ct.kind() { ty::ConstKind::Value(cv) => Ok(cv), ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => { - if !const_.has_param() { - bug!("failed to normalize const, but it is not generic: {const_:?}"); + if !ct.has_param() { + bug!("failed to normalize const, but it is not generic: {ct:?}"); } - return Err(error(cx, LayoutError::TooGeneric(ty))); + Err(error(cx, LayoutError::TooGeneric(ty))) } ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) @@ -159,7 +159,7 @@ fn extract_const_value<'tcx>( | ty::ConstKind::Error(_) => { // `ty::ConstKind::Error` is handled at the top of `layout_of_uncached` // (via `ty.error_reported()`). - bug!("layout_of: unexpected const: {const_:?}"); + bug!("layout_of: unexpected const: {ct:?}"); } } } @@ -199,12 +199,12 @@ fn layout_of_uncached<'tcx>( &mut layout.backend_repr { if let Some(start) = start { - scalar.valid_range_mut().start = extract_const_value(start, ty, cx)? + scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { - let mut end = extract_const_value(end, ty, cx)? + let mut end = extract_const_value(cx, ty, end)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { @@ -338,7 +338,7 @@ fn layout_of_uncached<'tcx>( // Arrays and slices. ty::Array(element, count) => { - let count = extract_const_value(count, ty, cx)? + let count = extract_const_value(cx, ty, count)? .try_to_target_usize(tcx) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; @@ -690,13 +690,21 @@ fn layout_of_uncached<'tcx>( } // Types with no meaningful known layout. + ty::Param(_) => { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + ty::Alias(..) => { - if ty.has_param() { - return Err(error(cx, LayoutError::TooGeneric(ty))); - } // NOTE(eddyb) `layout_of` query should've normalized these away, // if that was possible, so there's no reason to try again here. - return Err(error(cx, LayoutError::Unknown(ty))); + let err = if ty.has_param() { + LayoutError::TooGeneric(ty) + } else { + // This is only reachable with unsatisfiable predicates. For example, if we have + // `u8: Iterator`, then we can't compute the layout of `::Item`. + LayoutError::Unknown(ty) + }; + return Err(error(cx, err)); } ty::Placeholder(..) @@ -707,10 +715,6 @@ fn layout_of_uncached<'tcx>( // `ty::Error` is handled at the top of this function. bug!("layout_of: unexpected type `{ty}`") } - - ty::Param(_) => { - return Err(error(cx, LayoutError::TooGeneric(ty))); - } }) } From 768a5bd470e37feb3559967844544ee814c6c411 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:51:32 +0100 Subject: [PATCH 147/158] Remove scrutinee_hir_id from ExprKind::Match It is unused --- compiler/rustc_middle/src/thir.rs | 1 - compiler/rustc_mir_build/src/thir/cx/expr.rs | 1 - compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 2ab8750f727c..98cc00c367cf 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -376,7 +376,6 @@ pub enum ExprKind<'tcx> { /// A `match` expression. Match { scrutinee: ExprId, - scrutinee_hir_id: HirId, arms: Box<[ArmId]>, match_source: MatchSource, }, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 54da6924db44..d0fca76fcf05 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -828,7 +828,6 @@ impl<'tcx> ThirBuildCx<'tcx> { }, hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match { scrutinee: self.mirror_expr(discr), - scrutinee_hir_id: discr.hir_id, arms: arms.iter().map(|a| self.convert_arm(a)).collect(), match_source, }, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 1e7388010115..6dbb460d8b15 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -151,7 +151,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { } return; } - ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => { + ExprKind::Match { scrutinee, box ref arms, match_source } => { self.check_match(scrutinee, arms, match_source, ex.span); } ExprKind::Let { box ref pat, expr } => { From 803feb5dc679556ba2d93fe616d1883d7ebc7775 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Jan 2025 12:23:15 +0100 Subject: [PATCH 148/158] x86-sse2 ABI: use SSE registers for floats and SIMD --- compiler/rustc_target/src/callconv/mod.rs | 114 +++++++++++------- compiler/rustc_target/src/callconv/x86.rs | 14 ++- .../closure-inherit-target-feature.rs | 7 +- tests/assembly/x86-return-float.rs | 42 +++---- tests/codegen/abi-x86-sse.rs | 36 ++++++ tests/codegen/float/f128.rs | 82 ++++++++----- tests/codegen/float/f16.rs | 43 ++++--- tests/codegen/intrinsics/transmute-x64.rs | 9 -- tests/codegen/issues/issue-32031.rs | 6 +- .../simd-intrinsic-transmute-array.rs | 17 ++- tests/codegen/simd/packed-simd.rs | 25 ++-- tests/codegen/union-abi.rs | 16 ++- ...e-abi-checks.rs => sse-simd-abi-checks.rs} | 5 +- ...ecks.stderr => sse-simd-abi-checks.stderr} | 4 +- 14 files changed, 271 insertions(+), 149 deletions(-) create mode 100644 tests/codegen/abi-x86-sse.rs rename tests/ui/{sse-abi-checks.rs => sse-simd-abi-checks.rs} (82%) rename tests/ui/{sse-abi-checks.stderr => sse-simd-abi-checks.stderr} (94%) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 2bde10556221..c2a176facdfa 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -7,7 +7,7 @@ use rustc_abi::{ }; use rustc_macros::HashStable_Generic; -use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi}; +use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi}; mod aarch64; mod amdgpu; @@ -386,6 +386,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { /// Pass this argument directly instead. Should NOT be used! /// Only exists because of past ABI mistakes that will take time to fix /// (see ). + #[track_caller] pub fn make_direct_deprecated(&mut self) { match self.mode { PassMode::Indirect { .. } => { @@ -398,6 +399,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { /// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead. /// This is valid for both sized and unsized arguments. + #[track_caller] pub fn make_indirect(&mut self) { match self.mode { PassMode::Direct(_) | PassMode::Pair(_, _) => { @@ -412,6 +414,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { /// Same as `make_indirect`, but for arguments that are ignored. Only needed for ABIs that pass /// ZSTs indirectly. + #[track_caller] pub fn make_indirect_from_ignore(&mut self) { match self.mode { PassMode::Ignore => { @@ -716,7 +719,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { C: HasDataLayout + HasTargetSpec, { let spec = cx.target_spec(); - match &spec.arch[..] { + match &*spec.arch { "x86" => x86::compute_rust_abi_info(cx, self, abi), "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi), "loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi), @@ -724,6 +727,22 @@ impl<'a, Ty> FnAbi<'a, Ty> { _ => {} }; + // Decides whether we can pass the given SIMD argument via `PassMode::Direct`. + // May only return `true` if the target will always pass those arguments the same way, + // no matter what the user does with `-Ctarget-feature`! In other words, whatever + // target features are required to pass a SIMD value in registers must be listed in + // the `abi_required_features` for the current target and ABI. + let can_pass_simd_directly = |arg: &ArgAbi<'_, Ty>| match &*spec.arch { + // On x86, if we have SSE2 (which we have by default for x86_64), we can always pass up + // to 128-bit-sized vectors. + "x86" if spec.rustc_abi == Some(RustcAbi::X86Sse2) => arg.layout.size.bits() <= 128, + "x86_64" if spec.rustc_abi != Some(RustcAbi::X86Softfloat) => { + arg.layout.size.bits() <= 128 + } + // So far, we haven't implemented this logic for any other target. + _ => false, + }; + for (arg_idx, arg) in self .args .iter_mut() @@ -731,12 +750,15 @@ impl<'a, Ty> FnAbi<'a, Ty> { .map(|(idx, arg)| (Some(idx), arg)) .chain(iter::once((None, &mut self.ret))) { - if arg.is_ignore() { + // If the logic above already picked a specific type to cast the argument to, leave that + // in place. + if matches!(arg.mode, PassMode::Ignore | PassMode::Cast { .. }) { continue; } if arg_idx.is_none() && arg.layout.size > Primitive::Pointer(AddressSpace::DATA).size(cx) * 2 + && !matches!(arg.layout.backend_repr, BackendRepr::Vector { .. }) { // Return values larger than 2 registers using a return area // pointer. LLVM and Cranelift disagree about how to return @@ -746,7 +768,8 @@ impl<'a, Ty> FnAbi<'a, Ty> { // return value independently and decide to pass it in a // register or not, which would result in the return value // being passed partially in registers and partially through a - // return area pointer. + // return area pointer. For large IR-level values such as `i128`, + // cranelift will even split up the value into smaller chunks. // // While Cranelift may need to be fixed as the LLVM behavior is // generally more correct with respect to the surface language, @@ -776,53 +799,60 @@ impl<'a, Ty> FnAbi<'a, Ty> { // rustc_target already ensure any return value which doesn't // fit in the available amount of return registers is passed in // the right way for the current target. + // + // The adjustment is not necessary nor desired for types with a vector + // representation; those are handled below. arg.make_indirect(); continue; } match arg.layout.backend_repr { - BackendRepr::Memory { .. } => {} + BackendRepr::Memory { .. } => { + // Compute `Aggregate` ABI. - // This is a fun case! The gist of what this is doing is - // that we want callers and callees to always agree on the - // ABI of how they pass SIMD arguments. If we were to *not* - // make these arguments indirect then they'd be immediates - // in LLVM, which means that they'd used whatever the - // appropriate ABI is for the callee and the caller. That - // means, for example, if the caller doesn't have AVX - // enabled but the callee does, then passing an AVX argument - // across this boundary would cause corrupt data to show up. - // - // This problem is fixed by unconditionally passing SIMD - // arguments through memory between callers and callees - // which should get them all to agree on ABI regardless of - // target feature sets. Some more information about this - // issue can be found in #44367. - // - // Note that the intrinsic ABI is exempt here as - // that's how we connect up to LLVM and it's unstable - // anyway, we control all calls to it in libstd. - BackendRepr::Vector { .. } - if abi != ExternAbi::RustIntrinsic && spec.simd_types_indirect => - { - arg.make_indirect(); - continue; + let is_indirect_not_on_stack = + matches!(arg.mode, PassMode::Indirect { on_stack: false, .. }); + assert!(is_indirect_not_on_stack); + + let size = arg.layout.size; + if arg.layout.is_sized() + && size <= Primitive::Pointer(AddressSpace::DATA).size(cx) + { + // We want to pass small aggregates as immediates, but using + // an LLVM aggregate type for this leads to bad optimizations, + // so we pick an appropriately sized integer type instead. + arg.cast_to(Reg { kind: RegKind::Integer, size }); + } } - _ => continue, - } - // Compute `Aggregate` ABI. + BackendRepr::Vector { .. } => { + // This is a fun case! The gist of what this is doing is + // that we want callers and callees to always agree on the + // ABI of how they pass SIMD arguments. If we were to *not* + // make these arguments indirect then they'd be immediates + // in LLVM, which means that they'd used whatever the + // appropriate ABI is for the callee and the caller. That + // means, for example, if the caller doesn't have AVX + // enabled but the callee does, then passing an AVX argument + // across this boundary would cause corrupt data to show up. + // + // This problem is fixed by unconditionally passing SIMD + // arguments through memory between callers and callees + // which should get them all to agree on ABI regardless of + // target feature sets. Some more information about this + // issue can be found in #44367. + // + // Note that the intrinsic ABI is exempt here as those are not + // real functions anyway, and the backend expects very specific types. + if abi != ExternAbi::RustIntrinsic + && spec.simd_types_indirect + && !can_pass_simd_directly(arg) + { + arg.make_indirect(); + } + } - let is_indirect_not_on_stack = - matches!(arg.mode, PassMode::Indirect { on_stack: false, .. }); - assert!(is_indirect_not_on_stack); - - let size = arg.layout.size; - if !arg.layout.is_unsized() && size <= Primitive::Pointer(AddressSpace::DATA).size(cx) { - // We want to pass small aggregates as immediates, but using - // an LLVM aggregate type for this leads to bad optimizations, - // so we pick an appropriately sized integer type instead. - arg.cast_to(Reg { kind: RegKind::Integer, size }); + _ => {} } } } diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 5b9414536d8c..5f4f4cd57f65 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -4,7 +4,7 @@ use rustc_abi::{ }; use crate::callconv::{ArgAttribute, FnAbi, PassMode}; -use crate::spec::HasTargetSpec; +use crate::spec::{HasTargetSpec, RustcAbi}; #[derive(PartialEq)] pub(crate) enum Flavor { @@ -236,8 +236,16 @@ where _ => false, // anyway not passed via registers on x86 }; if has_float { - if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) { - // Same size or smaller than pointer, return in a register. + if cx.target_spec().rustc_abi == Some(RustcAbi::X86Sse2) + && fn_abi.ret.layout.backend_repr.is_scalar() + && fn_abi.ret.layout.size.bits() <= 128 + { + // This is a single scalar that fits into an SSE register, and the target uses the + // SSE ABI. We prefer this over integer registers as float scalars need to be in SSE + // registers for float operations, so that's the best place to pass them around. + fn_abi.ret.cast_to(Reg { kind: RegKind::Vector, size: fn_abi.ret.layout.size }); + } else if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) { + // Same size or smaller than pointer, return in an integer register. fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size }); } else { // Larger than a pointer, return indirectly. diff --git a/tests/assembly/closure-inherit-target-feature.rs b/tests/assembly/closure-inherit-target-feature.rs index b629d8769edf..069204bbd345 100644 --- a/tests/assembly/closure-inherit-target-feature.rs +++ b/tests/assembly/closure-inherit-target-feature.rs @@ -8,8 +8,9 @@ use std::arch::x86_64::{__m128, _mm_blend_ps}; +// Use an explicit return pointer to prevent tail call optimization. #[no_mangle] -pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 { +pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128, ret: *mut __m128) { let f = { // check that _mm_blend_ps is not being inlined into the closure // CHECK-LABEL: {{sse41_blend_nofeature.*closure.*:}} @@ -18,9 +19,9 @@ pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 { // CHECK-NOT: blendps // CHECK: ret #[inline(never)] - |x, y| _mm_blend_ps(x, y, 0b0101) + |x, y, ret: *mut __m128| unsafe { *ret = _mm_blend_ps(x, y, 0b0101) } }; - f(x, y) + f(x, y, ret); } #[no_mangle] diff --git a/tests/assembly/x86-return-float.rs b/tests/assembly/x86-return-float.rs index ad760627b3a3..2c39c830684e 100644 --- a/tests/assembly/x86-return-float.rs +++ b/tests/assembly/x86-return-float.rs @@ -33,19 +33,18 @@ use minicore::*; // CHECK-LABEL: return_f32: #[no_mangle] pub fn return_f32(x: f32) -> f32 { - // CHECK: movl {{.*}}(%ebp), %eax - // CHECK-NOT: ax - // CHECK: retl + // CHECK: movss {{.*}}(%ebp), %xmm0 + // CHECK-NEXT: popl %ebp + // CHECK-NEXT: retl x } // CHECK-LABEL: return_f64: #[no_mangle] pub fn return_f64(x: f64) -> f64 { - // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]] - // CHECK-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL:.*]] - // CHECK-NEXT: movsd %[[VAL]], (%[[PTR]]) - // CHECK: retl + // CHECK: movsd {{.*}}(%ebp), %xmm0 + // CHECK-NEXT: popl %ebp + // CHECK-NEXT: retl x } @@ -157,7 +156,7 @@ pub unsafe fn call_f32(x: &mut f32) { } // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]] // CHECK: calll {{()|_}}get_f32 - // CHECK-NEXT: movl %eax, (%[[PTR]]) + // CHECK-NEXT: movss %xmm0, (%[[PTR]]) *x = get_f32(); } @@ -169,8 +168,7 @@ pub unsafe fn call_f64(x: &mut f64) { } // CHECK: movl {{.*}}(%ebp), %[[PTR:.*]] // CHECK: calll {{()|_}}get_f64 - // CHECK: movsd {{.*}}(%{{ebp|esp}}), %[[VAL:.*]] - // CHECK-NEXT: movsd %[[VAL:.*]], (%[[PTR]]) + // CHECK-NEXT: movlps %xmm0, (%[[PTR]]) *x = get_f64(); } @@ -315,25 +313,21 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) { #[no_mangle] pub fn return_f16(x: f16) -> f16 { // CHECK: pushl %ebp - // CHECK: movl %esp, %ebp - // CHECK: movzwl 8(%ebp), %eax - // CHECK: popl %ebp - // CHECK: retl + // CHECK-NEXT: movl %esp, %ebp + // CHECK-NEXT: pinsrw $0, 8(%ebp), %xmm0 + // CHECK-NEXT: popl %ebp + // CHECK-NEXT: retl x } // CHECK-LABEL: return_f128: #[no_mangle] pub fn return_f128(x: f128) -> f128 { - // CHECK: movl [[#%d,OFFSET:]](%ebp), %[[PTR:.*]] - // CHECK-NEXT: movl [[#%d,OFFSET+4]](%ebp), %[[VAL1:.*]] - // CHECK-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]] - // CHECK-NEXT: movl [[#%d,OFFSET+12]](%ebp), %[[VAL3:.*]] - // CHECK-NEXT: movl [[#%d,OFFSET+16]](%ebp), %[[VAL4:.*]] - // CHECK-NEXT: movl %[[VAL4:.*]] 12(%[[PTR]]) - // CHECK-NEXT: movl %[[VAL3:.*]] 8(%[[PTR]]) - // CHECK-NEXT: movl %[[VAL2:.*]] 4(%[[PTR]]) - // CHECK-NEXT: movl %[[VAL1:.*]] (%[[PTR]]) - // CHECK: retl + // CHECK: pushl %ebp + // CHECK-NEXT: movl %esp, %ebp + // linux-NEXT: movaps 8(%ebp), %xmm0 + // win-NEXT: movups 8(%ebp), %xmm0 + // CHECK-NEXT: popl %ebp + // CHECK-NEXT: retl x } diff --git a/tests/codegen/abi-x86-sse.rs b/tests/codegen/abi-x86-sse.rs new file mode 100644 index 000000000000..837bf6134b01 --- /dev/null +++ b/tests/codegen/abi-x86-sse.rs @@ -0,0 +1,36 @@ +//@ compile-flags: -Z merge-functions=disabled + +//@ revisions: x86-64 +//@[x86-64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86-64] needs-llvm-components: x86 + +//@ revisions: x86-32 +//@[x86-32] compile-flags: --target i686-unknown-linux-gnu +//@[x86-32] needs-llvm-components: x86 + +//@ revisions: x86-32-nosse +//@[x86-32-nosse] compile-flags: --target i586-unknown-linux-gnu +//@[x86-32-nosse] needs-llvm-components: x86 + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +// Ensure this type is passed without ptr indirection on targets that +// require SSE2. +#[repr(simd)] +pub struct Sse([f32; 4]); + +// x86-64: <4 x float> @sse_id(<4 x float> {{[^,]*}}) +// x86-32: <4 x float> @sse_id(<4 x float> {{[^,]*}}) +// x86-32-nosse: void @sse_id(ptr{{( [^,]*)?}} sret([16 x i8]){{( .*)?}}, ptr{{( [^,]*)?}}) +#[no_mangle] +pub fn sse_id(x: Sse) -> Sse { + x +} diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs index 562a8e6c9e9b..d87bab1172a2 100644 --- a/tests/codegen/float/f128.rs +++ b/tests/codegen/float/f128.rs @@ -1,8 +1,11 @@ // 32-bit x86 returns float types differently to avoid the x87 stack. // 32-bit systems will return 128bit values using a return area pointer. // Emscripten aligns f128 to 8 bytes, not 16. -//@ revisions: x86 bit32 bit64 emscripten -//@[x86] only-x86 +//@ revisions: x86-sse x86-nosse bit32 bit64 emscripten +//@[x86-sse] only-x86 +//@[x86-sse] only-rustc_abi-x86-sse2 +//@[x86-nosse] only-x86 +//@[x86-nosse] ignore-rustc_abi-x86-sse2 //@[bit32] ignore-x86 //@[bit32] ignore-emscripten //@[bit32] only-32bit @@ -60,7 +63,8 @@ pub fn f128_le(a: f128, b: f128) -> bool { a <= b } -// x86-LABEL: void @f128_neg({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_neg({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_neg(fp128 // bit32-LABEL: void @f128_neg({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_neg( // emscripten-LABEL: void @f128_neg({{.*}}sret([16 x i8]) @@ -70,7 +74,8 @@ pub fn f128_neg(a: f128) -> f128 { -a } -// x86-LABEL: void @f128_add({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_add({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_add(fp128 // bit32-LABEL: void @f128_add({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_add( // emscripten-LABEL: void @f128_add({{.*}}sret([16 x i8]) @@ -80,7 +85,8 @@ pub fn f128_add(a: f128, b: f128) -> f128 { a + b } -// x86-LABEL: void @f128_sub({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_sub({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_sub(fp128 // bit32-LABEL: void @f128_sub({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_sub( // emscripten-LABEL: void @f128_sub({{.*}}sret([16 x i8]) @@ -90,7 +96,8 @@ pub fn f128_sub(a: f128, b: f128) -> f128 { a - b } -// x86-LABEL: void @f128_mul({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_mul({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_mul(fp128 // bit32-LABEL: void @f128_mul({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_mul( // emscripten-LABEL: void @f128_mul({{.*}}sret([16 x i8]) @@ -100,7 +107,8 @@ pub fn f128_mul(a: f128, b: f128) -> f128 { a * b } -// x86-LABEL: void @f128_div({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_div({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_div(fp128 // bit32-LABEL: void @f128_div({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_div( // emscripten-LABEL: void @f128_div({{.*}}sret([16 x i8]) @@ -110,7 +118,8 @@ pub fn f128_div(a: f128, b: f128) -> f128 { a / b } -// x86-LABEL: void @f128_rem({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_rem({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_rem(fp128 // bit32-LABEL: void @f128_rem({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_rem( // emscripten-LABEL: void @f128_rem({{.*}}sret([16 x i8]) @@ -162,7 +171,8 @@ pub fn f128_rem_assign(a: &mut f128, b: f128) { /* float to float conversions */ -// x86-LABEL: i16 @f128_as_f16( +// x86-sse-LABEL: <2 x i8> @f128_as_f16( +// x86-nosse-LABEL: i16 @f128_as_f16( // bits32-LABEL: half @f128_as_f16( // bits64-LABEL: half @f128_as_f16( #[no_mangle] @@ -171,7 +181,8 @@ pub fn f128_as_f16(a: f128) -> f16 { a as f16 } -// x86-LABEL: i32 @f128_as_f32( +// x86-sse-LABEL: <4 x i8> @f128_as_f32( +// x86-nosse-LABEL: i32 @f128_as_f32( // bit32-LABEL: float @f128_as_f32( // bit64-LABEL: float @f128_as_f32( // emscripten-LABEL: float @f128_as_f32( @@ -181,7 +192,8 @@ pub fn f128_as_f32(a: f128) -> f32 { a as f32 } -// x86-LABEL: void @f128_as_f64( +// x86-sse-LABEL: <8 x i8> @f128_as_f64( +// x86-nosse-LABEL: void @f128_as_f64({{.*}}sret([8 x i8]) // bit32-LABEL: double @f128_as_f64( // bit64-LABEL: double @f128_as_f64( // emscripten-LABEL: double @f128_as_f64( @@ -191,7 +203,8 @@ pub fn f128_as_f64(a: f128) -> f64 { a as f64 } -// x86-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f128_as_self( +// x86-nosse-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_as_self( // emscripten-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) @@ -204,7 +217,8 @@ pub fn f128_as_self(a: f128) -> f128 { a as f128 } -// x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f16_as_f128( +// x86-nosse-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f16_as_f128( // emscripten-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) @@ -214,7 +228,8 @@ pub fn f16_as_f128(a: f16) -> f128 { a as f128 } -// x86-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f32_as_f128( +// x86-nosse-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f32_as_f128( // emscripten-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) @@ -224,7 +239,8 @@ pub fn f32_as_f128(a: f32) -> f128 { a as f128 } -// x86-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f64_as_f128( +// x86-nosse-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f64_as_f128( // emscripten-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) @@ -263,7 +279,8 @@ pub fn f128_as_u64(a: f128) -> u64 { a as u64 } -// x86-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f128_as_u128( // emscripten-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) @@ -300,7 +317,8 @@ pub fn f128_as_i64(a: f128) -> i64 { a as i64 } -// x86-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f128_as_i128( // emscripten-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) @@ -312,7 +330,8 @@ pub fn f128_as_i128(a: f128) -> i128 { /* int to float conversions */ -// x86-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @u8_as_f128( +// x86-nosse-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u8_as_f128( // emscripten-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) @@ -322,7 +341,8 @@ pub fn u8_as_f128(a: u8) -> f128 { a as f128 } -// x86-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @u16_as_f128( +// x86-nosse-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u16_as_f128( // emscripten-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) @@ -332,7 +352,8 @@ pub fn u16_as_f128(a: u16) -> f128 { a as f128 } -// x86-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @u32_as_f128( +// x86-nosse-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u32_as_f128( // emscripten-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) @@ -342,7 +363,8 @@ pub fn u32_as_f128(a: u32) -> f128 { a as f128 } -// x86-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @u64_as_f128( +// x86-nosse-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u64_as_f128( // emscripten-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) @@ -352,7 +374,8 @@ pub fn u64_as_f128(a: u64) -> f128 { a as f128 } -// x86-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @u128_as_f128( +// x86-nosse-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u128_as_f128( // emscripten-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) @@ -362,7 +385,8 @@ pub fn u128_as_f128(a: u128) -> f128 { a as f128 } -// x86-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @i8_as_f128( +// x86-nosse-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i8_as_f128( // emscripten-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) @@ -372,7 +396,8 @@ pub fn i8_as_f128(a: i8) -> f128 { a as f128 } -// x86-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @i16_as_f128( +// x86-nosse-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i16_as_f128( // emscripten-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) @@ -382,7 +407,8 @@ pub fn i16_as_f128(a: i16) -> f128 { a as f128 } -// x86-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @i32_as_f128( +// x86-nosse-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i32_as_f128( // emscripten-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) @@ -392,7 +418,8 @@ pub fn i32_as_f128(a: i32) -> f128 { a as f128 } -// x86-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @i64_as_f128( +// x86-nosse-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i64_as_f128( // emscripten-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) @@ -402,7 +429,8 @@ pub fn i64_as_f128(a: i64) -> f128 { a as f128 } -// x86-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @i128_as_f128( +// x86-nosse-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i128_as_f128( // emscripten-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs index 5c3a5893b9d2..0c40606ad8a4 100644 --- a/tests/codegen/float/f16.rs +++ b/tests/codegen/float/f16.rs @@ -1,7 +1,10 @@ // 32-bit x86 returns float types differently to avoid the x87 stack. // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: x86 bit32 bit64 -//@[x86] only-x86 +//@ revisions: x86-sse x86-nosse bit32 bit64 +//@[x86-sse] only-x86 +//@[x86-sse] only-rustc_abi-x86-sse2 +//@[x86-nosse] only-x86 +//@[x86-nosse] ignore-rustc_abi-x86-sse2 //@[bit32] ignore-x86 //@[bit32] only-32bit //@[bit64] ignore-x86 @@ -59,8 +62,10 @@ pub fn f16_le(a: f16, b: f16) -> bool { } // This is where we check the argument and return ABI for f16. -// other-LABEL: half @f16_neg(half -// x86-LABEL: i16 @f16_neg(half +// bit32-LABEL: half @f16_neg(half +// bit64-LABEL: half @f16_neg(half +// x86-sse-LABEL: <2 x i8> @f16_neg(half +// x86-nosse-LABEL: i16 @f16_neg(half #[no_mangle] pub fn f16_neg(a: f16) -> f16 { // CHECK: fneg half %{{.+}} @@ -144,17 +149,23 @@ pub fn f16_rem_assign(a: &mut f16, b: f16) { /* float to float conversions */ -// other-LABEL: half @f16_as_self( -// x86-LABEL: i16 @f16_as_self( +// bit32-LABEL: half @f16_as_self( +// bit64-LABEL: half @f16_as_self( +// x86-sse-LABEL: <2 x i8> @f16_as_self( +// x86-nosse-LABEL: i16 @f16_as_self( #[no_mangle] pub fn f16_as_self(a: f16) -> f16 { - // other-CHECK: ret half %{{.+}} - // x86-CHECK: bitcast half - // x86-CHECK: ret i16 + // bit32-CHECK: ret half %{{.+}} + // bit64-CHECK: ret half %{{.+}} + // x86-sse-CHECK: bitcast half + // x86-nosse-CHECK: bitcast half + // x86-sse-CHECK: ret i16 + // x86-nosse-CHECK: ret i16 a as f16 } -// x86-LABEL: i32 @f16_as_f32( +// x86-sse-LABEL: <4 x i8> @f16_as_f32( +// x86-nosse-LABEL: i32 @f16_as_f32( // bit32-LABEL: float @f16_as_f32( // bit64-LABEL: float @f16_as_f32( #[no_mangle] @@ -163,7 +174,8 @@ pub fn f16_as_f32(a: f16) -> f32 { a as f32 } -// x86-LABEL: void @f16_as_f64( +// x86-sse-LABEL: <8 x i8> @f16_as_f64( +// x86-nosse-LABEL: void @f16_as_f64({{.*}}sret([8 x i8]) // bit32-LABEL: double @f16_as_f64( // bit64-LABEL: double @f16_as_f64( #[no_mangle] @@ -172,7 +184,8 @@ pub fn f16_as_f64(a: f16) -> f64 { a as f64 } -// x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: <16 x i8> @f16_as_f128( +// x86-nosse-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f16_as_f128( #[no_mangle] @@ -231,7 +244,8 @@ pub fn f16_as_u64(a: f16) -> u64 { a as u64 } -// x86-LABEL: void @f16_as_u128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: void @f16_as_u128({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f16_as_u128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f16_as_u128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f16_as_u128( #[no_mangle] @@ -267,7 +281,8 @@ pub fn f16_as_i64(a: f16) -> i64 { a as i64 } -// x86-LABEL: void @f16_as_i128({{.*}}sret([16 x i8]) +// x86-sse-LABEL: void @f16_as_i128({{.*}}sret([16 x i8]) +// x86-nosse-LABEL: void @f16_as_i128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f16_as_i128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f16_as_i128( #[no_mangle] diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs index fe68f1836670..be45e4db90fd 100644 --- a/tests/codegen/intrinsics/transmute-x64.rs +++ b/tests/codegen/intrinsics/transmute-x64.rs @@ -6,15 +6,6 @@ use std::arch::x86_64::{__m128, __m128i, __m256i}; use std::mem::transmute; -// CHECK-LABEL: @check_sse_float_to_int( -#[no_mangle] -pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i { - // CHECK-NOT: alloca - // CHECK: %0 = load <4 x float>, ptr %x, align 16 - // CHECK: store <4 x float> %0, ptr %_0, align 16 - transmute(x) -} - // CHECK-LABEL: @check_sse_pair_to_avx( #[no_mangle] pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i { diff --git a/tests/codegen/issues/issue-32031.rs b/tests/codegen/issues/issue-32031.rs index 4d6895166f1c..559e8d947fba 100644 --- a/tests/codegen/issues/issue-32031.rs +++ b/tests/codegen/issues/issue-32031.rs @@ -1,7 +1,7 @@ //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 // 32-bit x86 returns `f32` and `f64` differently to avoid the x87 stack. //@ revisions: x86 other -//@[x86] only-x86 +//@[x86] only-rustc_abi-x86-sse2 //@[other] ignore-x86 #![crate_type = "lib"] @@ -10,7 +10,7 @@ pub struct F32(f32); // other: define{{.*}}float @add_newtype_f32(float %a, float %b) -// x86: define{{.*}}i32 @add_newtype_f32(float %a, float %b) +// x86: define{{.*}}<4 x i8> @add_newtype_f32(float %a, float %b) #[inline(never)] #[no_mangle] pub fn add_newtype_f32(a: F32, b: F32) -> F32 { @@ -21,7 +21,7 @@ pub fn add_newtype_f32(a: F32, b: F32) -> F32 { pub struct F64(f64); // other: define{{.*}}double @add_newtype_f64(double %a, double %b) -// x86: define{{.*}}void @add_newtype_f64(ptr{{.*}}sret([8 x i8]){{.*}}%_0, double %a, double %b) +// x86: define{{.*}}<8 x i8> @add_newtype_f64(double %a, double %b) #[inline(never)] #[no_mangle] pub fn add_newtype_f64(a: F64, b: F64) -> F64 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 75f989d6e12c..0d21d5105576 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -1,5 +1,14 @@ // //@ compile-flags: -C no-prepopulate-passes +// LLVM IR isn't very portable and the one tested here depends on the ABI +// which is different between x86 (where we use SSE registers) and others. +// `x86-64` and `x86-32-sse2` are identical, but compiletest does not support +// taking the union of multiple `only` annotations. +//@ revisions: x86-64 x86-32-sse2 other +//@[x86-64] only-x86_64 +//@[x86-32-sse2] only-rustc_abi-x86-sse2 +//@[other] ignore-rustc_abi-x86-sse2 +//@[other] ignore-x86_64 #![crate_type = "lib"] #![allow(non_camel_case_types)] @@ -38,7 +47,9 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> { #[no_mangle] pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> { // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] + // x86-32: ret <4 x float> %[[VAL:.+]] + // x86-64: ret <4 x float> %[[VAL:.+]] + // other: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } @@ -53,6 +64,8 @@ pub fn build_array_t(x: [f32; 4]) -> T { #[no_mangle] pub fn build_array_transmute_t(x: [f32; 4]) -> T { // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] + // x86-32: ret <4 x float> %[[VAL:.+]] + // x86-64: ret <4 x float> %[[VAL:.+]] + // other: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } diff --git a/tests/codegen/simd/packed-simd.rs b/tests/codegen/simd/packed-simd.rs index 1df09c96e6cc..a27d5e3af452 100644 --- a/tests/codegen/simd/packed-simd.rs +++ b/tests/codegen/simd/packed-simd.rs @@ -1,4 +1,5 @@ //@ revisions:opt3 noopt +//@ only-x86_64 //@[opt3] compile-flags: -Copt-level=3 //@[noopt] compile-flags: -Cno-prepopulate-passes @@ -14,14 +15,14 @@ use core::{mem, ptr}; #[repr(simd, packed)] #[derive(Copy, Clone)] -pub struct Simd([T; N]); +pub struct PackedSimd([T; N]); #[repr(simd)] #[derive(Copy, Clone)] pub struct FullSimd([T; N]); // non-powers-of-two have padding and need to be expanded to full vectors -fn load(v: Simd) -> FullSimd { +fn load(v: PackedSimd) -> FullSimd { unsafe { let mut tmp = mem::MaybeUninit::>::uninit(); ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1); @@ -29,18 +30,16 @@ fn load(v: Simd) -> FullSimd { } } -// CHECK-LABEL: square_packed_full -// CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align (8|16)]]{{[^%]*}} [[RET_VREG:%[_0-9]*]] -// CHECK-SAME: ptr{{[a-z_ ]*}} align 4 +// CHECK-LABEL: define <3 x float> @square_packed_full(ptr{{[a-z_ ]*}} align 4 {{[^,]*}}) #[no_mangle] -pub fn square_packed_full(x: Simd) -> FullSimd { - // CHECK-NEXT: start - // noopt: alloca [[RET_TYPE]], [[RET_ALIGN]] - // CHECK: load <3 x float> +pub fn square_packed_full(x: PackedSimd) -> FullSimd { + // The unoptimized version of this is not very interesting to check + // since `load` does not get inlined. + // opt3-NEXT: start: + // opt3-NEXT: load <3 x float> let x = load(x); - // CHECK: [[VREG:%[a-z0-9_]+]] = fmul <3 x float> - // CHECK-NEXT: store <3 x float> [[VREG]], ptr [[RET_VREG]], [[RET_ALIGN]] - // CHECK-NEXT: ret void + // opt3-NEXT: [[VREG:%[a-z0-9_]+]] = fmul <3 x float> + // opt3-NEXT: ret <3 x float> [[VREG:%[a-z0-9_]+]] unsafe { intrinsics::simd_mul(x, x) } } @@ -48,7 +47,7 @@ pub fn square_packed_full(x: Simd) -> FullSimd { // CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align 4]]{{[^%]*}} [[RET_VREG:%[_0-9]*]] // CHECK-SAME: ptr{{[a-z_ ]*}} align 4 #[no_mangle] -pub fn square_packed(x: Simd) -> Simd { +pub fn square_packed(x: PackedSimd) -> PackedSimd { // CHECK-NEXT: start // CHECK-NEXT: load <3 x float> // noopt-NEXT: load <3 x float> diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs index 92d40d8ac14c..16022fad8af7 100644 --- a/tests/codegen/union-abi.rs +++ b/tests/codegen/union-abi.rs @@ -2,8 +2,11 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes // 32-bit x86 returns `f32` differently to avoid the x87 stack. // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: x86 bit32 bit64 -//@[x86] only-x86 +//@ revisions: x86-sse x86-nosse bit32 bit64 +//@[x86-sse] only-x86 +//@[x86-sse] only-rustc_abi-x86-sse2 +//@[x86-nosse] only-x86 +//@[x86-nosse] ignore-rustc_abi-x86-sse2 //@[bit32] ignore-x86 //@[bit32] only-32bit //@[bit64] ignore-x86 @@ -75,7 +78,8 @@ pub union UnionF32 { a: f32, } -// x86: define {{(dso_local )?}}i32 @test_UnionF32(float %_1) +// x86-sse: define {{(dso_local )?}}<4 x i8> @test_UnionF32(float %_1) +// x86-nosse: define {{(dso_local )?}}i32 @test_UnionF32(float %_1) // bit32: define {{(dso_local )?}}float @test_UnionF32(float %_1) // bit64: define {{(dso_local )?}}float @test_UnionF32(float %_1) #[no_mangle] @@ -88,7 +92,8 @@ pub union UnionF32F32 { b: f32, } -// x86: define {{(dso_local )?}}i32 @test_UnionF32F32(float %_1) +// x86-sse: define {{(dso_local )?}}<4 x i8> @test_UnionF32F32(float %_1) +// x86-nosse: define {{(dso_local )?}}i32 @test_UnionF32F32(float %_1) // bit32: define {{(dso_local )?}}float @test_UnionF32F32(float %_1) // bit64: define {{(dso_local )?}}float @test_UnionF32F32(float %_1) #[no_mangle] @@ -110,7 +115,8 @@ pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { pub union UnionU128 { a: u128, } -// x86: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1) +// x86-sse: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1) +// x86-nosse: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1) // bit32: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1) // bit64: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1) #[no_mangle] diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-simd-abi-checks.rs similarity index 82% rename from tests/ui/sse-abi-checks.rs rename to tests/ui/sse-simd-abi-checks.rs index cb3128a890f7..396e9bf13188 100644 --- a/tests/ui/sse-abi-checks.rs +++ b/tests/ui/sse-simd-abi-checks.rs @@ -1,7 +1,8 @@ //! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled -//! on a target, but disabled in this file via a `-C` flag. +//! on a target via the base CPU, but disabled in this file via a `-C` flag. +//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu +//@ compile-flags: -Ctarget-cpu=pentium4 -C target-feature=-sse,-sse2 //@ add-core-stubs -//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu -C target-feature=-sse,-sse2 //@ build-pass //@ ignore-pass (test emits codegen-time warnings) //@ needs-llvm-components: x86 diff --git a/tests/ui/sse-abi-checks.stderr b/tests/ui/sse-simd-abi-checks.stderr similarity index 94% rename from tests/ui/sse-abi-checks.stderr rename to tests/ui/sse-simd-abi-checks.stderr index 9944aa093b4e..95486f480d25 100644 --- a/tests/ui/sse-abi-checks.stderr +++ b/tests/ui/sse-simd-abi-checks.stderr @@ -1,5 +1,5 @@ warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled - --> $DIR/sse-abi-checks.rs:19:1 + --> $DIR/sse-simd-abi-checks.rs:20:1 | LL | pub unsafe extern "C" fn f(_: SseVector) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -13,7 +13,7 @@ warning: 1 warning emitted Future incompatibility report: Future breakage diagnostic: warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled - --> $DIR/sse-abi-checks.rs:19:1 + --> $DIR/sse-simd-abi-checks.rs:20:1 | LL | pub unsafe extern "C" fn f(_: SseVector) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here From 0ffb771607ed2401bbe3d1d840f68d79aaea8c97 Mon Sep 17 00:00:00 2001 From: Xing Xue Date: Wed, 12 Feb 2025 13:04:43 -0500 Subject: [PATCH 149/158] Use `yes` except target_os = "nto". --- tests/ui/process/process-sigpipe.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs index 453e53379fc4..3ecf271599d2 100644 --- a/tests/ui/process/process-sigpipe.rs +++ b/tests/ui/process/process-sigpipe.rs @@ -9,9 +9,9 @@ // Make sure that these behaviors don't get inherited to children // spawned via std::process, since they're needed for traditional UNIX // filter behavior. -// This test checks that `while echo y ; do : ; done | head` terminates -// (instead of running forever), and that it does not print an error -// message about a broken pipe. +// This test checks that `yes` or `while echo y ; do : ; done | head` +// terminates (instead of running forever), and that it does not print an +// error message about a broken pipe. //@ ignore-vxworks no 'sh' //@ ignore-fuchsia no 'sh' @@ -22,14 +22,21 @@ use std::process; use std::thread; fn main() { - // Just in case `yes` doesn't check for EPIPE... + // Just in case `yes` or `while-echo` doesn't check for EPIPE... thread::spawn(|| { thread::sleep_ms(5000); process::exit(1); }); + // QNX Neutrino does not have `yes`. Therefore, use `while-echo` for `nto` + // and `yes` for other platforms. + let command = if cfg!(target_os = "nto") { + "while echo y ; do : ; done | head" + } else { + "yes | head" + }; let output = process::Command::new("sh") .arg("-c") - .arg("while echo y ; do : ; done | head") + .arg(command) .output() .unwrap(); assert!(output.status.success()); From 35674eff6f69b04d55d22e31d879c8177abb3653 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 18 Feb 2025 17:26:33 +0100 Subject: [PATCH 150/158] Clarify that locking on Windows also works for files opened with `.read(true)` --- library/std/src/fs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 0707115cbdd9..df877a035a93 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -649,7 +649,7 @@ impl File { /// this [may change in the future][changes]. /// /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, - /// open it with either `.read(true).append(true)` or `.write(true)`. + /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. /// /// [changes]: io#platform-specific-behavior /// @@ -702,7 +702,7 @@ impl File { /// [may change in the future][changes]. /// /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, - /// open it with either `.read(true).append(true)` or `.write(true)`. + /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. /// /// [changes]: io#platform-specific-behavior /// @@ -760,7 +760,7 @@ impl File { /// [may change in the future][changes]. /// /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, - /// open it with either `.read(true).append(true)` or `.write(true)`. + /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. /// /// [changes]: io#platform-specific-behavior /// @@ -817,7 +817,7 @@ impl File { /// [may change in the future][changes]. /// /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, - /// open it with either `.read(true).append(true)` or `.write(true)`. + /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. /// /// [changes]: io#platform-specific-behavior /// @@ -862,7 +862,7 @@ impl File { /// [may change in the future][changes]. /// /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, - /// open it with either `.read(true).append(true)` or `.write(true)`. + /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. /// /// [changes]: io#platform-specific-behavior /// From ec2034d53d83379abaaa57e395d4d8827ff7c432 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 18 Feb 2025 17:31:10 +0100 Subject: [PATCH 151/158] Reorder "This lock may be advisory or mandatory." earlier in the lock docs --- library/std/src/fs.rs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index df877a035a93..36432b11f204 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -628,17 +628,17 @@ impl File { /// /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. /// + /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], + /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with + /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not + /// cause non-lockholders to block. + /// /// If this file handle/descriptor, or a clone of it, already holds an lock the exact behavior /// is unspecified and platform dependent, including the possibility that it will deadlock. /// However, if this method returns, then an exclusive lock is held. /// /// If the file not open for writing, it is unspecified whether this function returns an error. /// - /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], - /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with - /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not - /// cause non-lockholders to block. - /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. /// @@ -683,15 +683,15 @@ impl File { /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may /// hold an exclusive lock at the same time. /// - /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior - /// is unspecified and platform dependent, including the possibility that it will deadlock. - /// However, if this method returns, then a shared lock is held. - /// /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not /// cause non-lockholders to block. /// + /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior + /// is unspecified and platform dependent, including the possibility that it will deadlock. + /// However, if this method returns, then a shared lock is held. + /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. /// @@ -738,17 +738,17 @@ impl File { /// /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. /// + /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], + /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with + /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not + /// cause non-lockholders to block. + /// /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior /// is unspecified and platform dependent, including the possibility that it will deadlock. /// However, if this method returns `Ok(true)`, then it has acquired an exclusive lock. /// /// If the file not open for writing, it is unspecified whether this function returns an error. /// - /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], - /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with - /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not - /// cause non-lockholders to block. - /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. /// @@ -797,15 +797,15 @@ impl File { /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may /// hold an exclusive lock at the same time. /// - /// If this file handle, or a clone of it, already holds an lock, the exact behavior is - /// unspecified and platform dependent, including the possibility that it will deadlock. - /// However, if this method returns `Ok(true)`, then it has acquired a shared lock. - /// /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not /// cause non-lockholders to block. /// + /// If this file handle, or a clone of it, already holds an lock, the exact behavior is + /// unspecified and platform dependent, including the possibility that it will deadlock. + /// However, if this method returns `Ok(true)`, then it has acquired a shared lock. + /// /// The lock will be released when this file (along with any other file descriptors/handles /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. /// From d93926cb5d1cb2da36757b137cfdbe9961d05625 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Tue, 18 Feb 2025 17:52:11 +0100 Subject: [PATCH 152/158] Fix typo in hidden internal docs of `TrustedRandomAccess` I typoed the coercion direction here 4 years ago; fixing it now --- library/core/src/iter/adapters/zip.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 0c3881159087..8090c98e7edb 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -556,13 +556,13 @@ impl Date: Tue, 18 Feb 2025 10:36:53 -0800 Subject: [PATCH 153/158] Add reference annotations for the `do_not_recommend` attribute --- .../as_expression.current.stderr | 2 +- .../do_not_recommend/as_expression.next.stderr | 6 +++--- .../do_not_recommend/as_expression.rs | 1 + .../does_not_acccept_args.current.stderr | 6 +++--- .../does_not_acccept_args.next.stderr | 6 +++--- .../do_not_recommend/does_not_acccept_args.rs | 1 + .../incorrect-locations.current.stderr | 18 +++++++++--------- .../incorrect-locations.next.stderr | 18 +++++++++--------- .../do_not_recommend/incorrect-locations.rs | 1 + .../do_not_recommend/nested.current.stderr | 4 ++-- .../do_not_recommend/nested.next.stderr | 4 ++-- .../do_not_recommend/nested.rs | 1 + .../do_not_recommend/simple.current.stderr | 4 ++-- .../do_not_recommend/simple.next.stderr | 4 ++-- .../do_not_recommend/simple.rs | 1 + .../do_not_recommend/stacked.current.stderr | 4 ++-- .../do_not_recommend/stacked.next.stderr | 4 ++-- .../do_not_recommend/stacked.rs | 1 + .../supress_suggestions_in_help.current.stderr | 4 ++-- .../supress_suggestions_in_help.next.stderr | 4 ++-- .../supress_suggestions_in_help.rs | 1 + .../type_mismatch.current.stderr | 4 ++-- .../do_not_recommend/type_mismatch.next.stderr | 4 ++-- .../do_not_recommend/type_mismatch.rs | 1 + .../with_lifetime.current.stderr | 2 +- .../do_not_recommend/with_lifetime.next.stderr | 2 +- .../do_not_recommend/with_lifetime.rs | 1 + 27 files changed, 59 insertions(+), 50 deletions(-) diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr index 28e7975c7a23..305fbbd275f1 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&str: AsExpression` is not satisfied - --> $DIR/as_expression.rs:55:15 + --> $DIR/as_expression.rs:56:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression` is not implemented for `&str` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 4f685c508c72..90bb715a0522 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&str: AsExpression<::SqlType>` is not satisfied - --> $DIR/as_expression.rs:55:21 + --> $DIR/as_expression.rs:56:21 | LL | SelectInt.check("bar"); | ----- ^^^^^ the trait `AsExpression<::SqlType>` is not implemented for `&str` @@ -8,7 +8,7 @@ LL | SelectInt.check("bar"); | = help: the trait `AsExpression` is implemented for `&str` note: required by a bound in `Foo::check` - --> $DIR/as_expression.rs:46:12 + --> $DIR/as_expression.rs:47:12 | LL | fn check(&self, _: T) -> ::SqlType>>::Expression | ----- required by a bound in this associated function @@ -17,7 +17,7 @@ LL | T: AsExpression, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` error[E0271]: type mismatch resolving `::SqlType == Text` - --> $DIR/as_expression.rs:55:5 + --> $DIR/as_expression.rs:56:5 | LL | SelectInt.check("bar"); | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 48c1ed2b02d7..73a238ddf50d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro pub trait Expression { type SqlType; diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr index 47597a5d405e..8a478a5c7336 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:10:1 + --> $DIR/does_not_acccept_args.rs:11:1 | LL | #[diagnostic::do_not_recommend(not_accepted)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:14:1 + --> $DIR/does_not_acccept_args.rs:15:1 | LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:18:1 + --> $DIR/does_not_acccept_args.rs:19:1 | LL | #[diagnostic::do_not_recommend(not_accepted(42))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr index 47597a5d405e..8a478a5c7336 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:10:1 + --> $DIR/does_not_acccept_args.rs:11:1 | LL | #[diagnostic::do_not_recommend(not_accepted)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:14:1 + --> $DIR/does_not_acccept_args.rs:15:1 | LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:18:1 + --> $DIR/does_not_acccept_args.rs:19:1 | LL | #[diagnostic::do_not_recommend(not_accepted(42))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs index eeff5e2e6e8f..5c21c045e10a 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs @@ -2,6 +2,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.syntax trait Foo {} trait Bar {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr index ee6ebabadd97..e348f0c89028 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:6:1 + --> $DIR/incorrect-locations.rs:7:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,49 +7,49 @@ LL | #[diagnostic::do_not_recommend] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:10:1 + --> $DIR/incorrect-locations.rs:11:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:14:1 + --> $DIR/incorrect-locations.rs:15:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:18:1 + --> $DIR/incorrect-locations.rs:19:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:22:1 + --> $DIR/incorrect-locations.rs:23:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:26:1 + --> $DIR/incorrect-locations.rs:27:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:30:1 + --> $DIR/incorrect-locations.rs:31:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:34:1 + --> $DIR/incorrect-locations.rs:35:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:38:1 + --> $DIR/incorrect-locations.rs:39:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr index ee6ebabadd97..e348f0c89028 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:6:1 + --> $DIR/incorrect-locations.rs:7:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,49 +7,49 @@ LL | #[diagnostic::do_not_recommend] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:10:1 + --> $DIR/incorrect-locations.rs:11:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:14:1 + --> $DIR/incorrect-locations.rs:15:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:18:1 + --> $DIR/incorrect-locations.rs:19:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:22:1 + --> $DIR/incorrect-locations.rs:23:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:26:1 + --> $DIR/incorrect-locations.rs:27:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:30:1 + --> $DIR/incorrect-locations.rs:31:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:34:1 + --> $DIR/incorrect-locations.rs:35:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - --> $DIR/incorrect-locations.rs:38:1 + --> $DIR/incorrect-locations.rs:39:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs index 1cf436aa2af3..e716457eaedf 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs @@ -2,6 +2,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.allowed-positions #[diagnostic::do_not_recommend] //~^WARN `#[diagnostic::do_not_recommend]` can only be placed diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr index b14c68d68976..cb1da8ff8be3 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/nested.rs:21:18 + --> $DIR/nested.rs:22:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/nested.rs:18:18 + --> $DIR/nested.rs:19:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr index b14c68d68976..cb1da8ff8be3 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/nested.rs:21:18 + --> $DIR/nested.rs:22:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/nested.rs:18:18 + --> $DIR/nested.rs:19:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs index 6534157d1fb2..3c96c760dfb2 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/nested.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro trait Root {} trait DontRecommend {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr index 884b13c17b80..dd425f1e6ee6 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:15:17 + --> $DIR/simple.rs:16:17 | LL | needs_foo::<*mut ()>(); | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | note: required by a bound in `needs_foo` - --> $DIR/simple.rs:10:17 + --> $DIR/simple.rs:11:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr index 884b13c17b80..dd425f1e6ee6 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:15:17 + --> $DIR/simple.rs:16:17 | LL | needs_foo::<*mut ()>(); | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | note: required by a bound in `needs_foo` - --> $DIR/simple.rs:10:17 + --> $DIR/simple.rs:11:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs index 6bca2b724d24..a6fa7ac7949e 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro trait Foo {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr index d86058063955..d940c3fd4779 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/stacked.rs:17:18 + --> $DIR/stacked.rs:18:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/stacked.rs:14:18 + --> $DIR/stacked.rs:15:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr index d86058063955..d940c3fd4779 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): Root` is not satisfied - --> $DIR/stacked.rs:17:18 + --> $DIR/stacked.rs:18:18 | LL | needs_root::<()>(); | ^^ the trait `Root` is not implemented for `()` | note: required by a bound in `needs_root` - --> $DIR/stacked.rs:14:18 + --> $DIR/stacked.rs:15:18 | LL | fn needs_root() {} | ^^^^ required by this bound in `needs_root` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs index 842e04b9d901..fd7be35ff841 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro trait Root {} trait DontRecommend {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr index 95ccbb92a89b..0b07b0731725 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/supress_suggestions_in_help.rs:21:11 + --> $DIR/supress_suggestions_in_help.rs:22:11 | LL | check(()); | ----- ^^ the trait `Foo` is not implemented for `()` @@ -8,7 +8,7 @@ LL | check(()); | = help: the trait `Foo` is implemented for `i32` note: required by a bound in `check` - --> $DIR/supress_suggestions_in_help.rs:18:18 + --> $DIR/supress_suggestions_in_help.rs:19:18 | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr index 95ccbb92a89b..0b07b0731725 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/supress_suggestions_in_help.rs:21:11 + --> $DIR/supress_suggestions_in_help.rs:22:11 | LL | check(()); | ----- ^^ the trait `Foo` is not implemented for `()` @@ -8,7 +8,7 @@ LL | check(()); | = help: the trait `Foo` is implemented for `i32` note: required by a bound in `check` - --> $DIR/supress_suggestions_in_help.rs:18:18 + --> $DIR/supress_suggestions_in_help.rs:19:18 | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs index 2c7c15161230..04cf8243a673 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro trait Foo {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr index b53febbb71ab..31a1ae991ec4 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr @@ -1,11 +1,11 @@ error[E0277]: Very important message! - --> $DIR/type_mismatch.rs:23:14 + --> $DIR/type_mismatch.rs:24:14 | LL | verify::(); | ^^ the trait `TheImportantOne` is not implemented for `u8` | note: required by a bound in `verify` - --> $DIR/type_mismatch.rs:20:14 + --> $DIR/type_mismatch.rs:21:14 | LL | fn verify() {} | ^^^^^^^^^^^^^^^ required by this bound in `verify` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr index b53febbb71ab..31a1ae991ec4 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr @@ -1,11 +1,11 @@ error[E0277]: Very important message! - --> $DIR/type_mismatch.rs:23:14 + --> $DIR/type_mismatch.rs:24:14 | LL | verify::(); | ^^ the trait `TheImportantOne` is not implemented for `u8` | note: required by a bound in `verify` - --> $DIR/type_mismatch.rs:20:14 + --> $DIR/type_mismatch.rs:21:14 | LL | fn verify() {} | ^^^^^^^^^^^^^^^ required by this bound in `verify` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs index 7f30fdb06c75..b5bd14745cda 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro #[diagnostic::on_unimplemented(message = "Very important message!")] trait TheImportantOne {} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr index a8429ff60f83..7e348842e19d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.current.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/with_lifetime.rs:17:5 + --> $DIR/with_lifetime.rs:18:5 | LL | fn foo<'a>(a: &'a ()) { | -- lifetime `'a` defined here diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr index a8429ff60f83..7e348842e19d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.next.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/with_lifetime.rs:17:5 + --> $DIR/with_lifetime.rs:18:5 | LL | fn foo<'a>(a: &'a ()) { | -- lifetime `'a` defined here diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs index 6a67d83d5fe4..98916ed061f1 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/with_lifetime.rs @@ -1,6 +1,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ reference: attributes.diagnostic.do_not_recommend.intro trait Root {} trait DontRecommend {} From 5d1551b9c6ebaded328d2f10deb92f7a87cf928c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 17:48:27 +1100 Subject: [PATCH 154/158] Remove `rustc_middle::mir::tcx` module. This is a really weird module. For example, what does `tcx` in `rustc_middle::mir::tcx::PlaceTy` mean? The answer is "not much". The top-level module comment says: > Methods for the various MIR types. These are intended for use after > building is complete. Awfully broad for a module that has a handful of impl blocks for some MIR types, none of which really relates to `TyCtxt`. `git blame` indicates the comment is ancient, from 2015, and made sense then. This module is now vestigial. This commit removes it and moves all the code within into `rustc_middle::mir::statement`. Some specifics: - `Place`, `PlaceRef`, `Rvalue`, `Operand`, `BorrowKind`: they all have `impl` blocks in both the `tcx` and `statement` modules. The commit merges the former into the latter. - `BinOp`, `UnOp`: they only have `impl` blocks in `tcx`. The commit moves these into `statement`. - `PlaceTy`, `RvalueInitializationState`: they are defined in `tcx`. This commit moves them into `statement` *and* makes them available in `mir::*`, like many other MIR types. --- .../src/diagnostics/conflict_errors.rs | 5 +- .../rustc_borrowck/src/diagnostics/mod.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 1 - compiler/rustc_borrowck/src/type_check/mod.rs | 1 - compiler/rustc_codegen_ssa/src/mir/place.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 1 - compiler/rustc_middle/src/mir/statement.rs | 396 +++++++++++++++++ compiler/rustc_middle/src/mir/syntax.rs | 2 +- compiler/rustc_middle/src/mir/tcx.rs | 416 ------------------ .../src/builder/custom/parse/instruction.rs | 1 - .../src/move_paths/builder.rs | 1 - .../rustc_mir_dataflow/src/value_analysis.rs | 1 - .../rustc_mir_transform/src/elaborate_drop.rs | 2 +- 13 files changed, 402 insertions(+), 430 deletions(-) delete mode 100644 compiler/rustc_middle/src/mir/tcx.rs diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 59c76cb7f2bb..0b27838beee1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -18,12 +18,11 @@ use rustc_hir::intravisit::{Visitor, walk_block, walk_expr}; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField}; use rustc_middle::bug; use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, - Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, VarBindingForm, VarDebugInfoContents, + Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement, StatementKind, + Terminator, TerminatorKind, VarBindingForm, VarDebugInfoContents, }; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 07ea369c5c7f..7da089c5e8c6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -13,10 +13,9 @@ use rustc_infer::infer::{ }; use rustc_infer::traits::SelectionError; use rustc_middle::bug; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo, - LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, + LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, find_self_call, }; use rustc_middle::ty::print::Print; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 53cf4f34ae79..f3a99e0a75d9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -33,7 +33,6 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{ InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, }; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::fold::fold_regions; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 93081919ec79..84759a0ae04a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -19,7 +19,6 @@ use rustc_infer::infer::{ BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, }; use rustc_infer::traits::PredicateObligations; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index eb4270ffe809..e32d298869be 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,7 +1,7 @@ use rustc_abi::Primitive::{Int, Pointer}; use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants}; +use rustc_middle::mir::PlaceTy; use rustc_middle::mir::interpret::Scalar; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir}; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 795cfcef2d36..862661044c37 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -53,7 +53,6 @@ pub mod pretty; mod query; mod statement; mod syntax; -pub mod tcx; mod terminator; pub mod traversal; diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index d345c99f902f..8f5fd31411a3 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -1,7 +1,10 @@ //! Functionality for statements, operands, places, and things that appear in them. +use tracing::{debug, instrument}; + use super::interpret::GlobalAlloc; use super::*; +use crate::ty::CoroutineArgsExt; /////////////////////////////////////////////////////////////////////////// // Statements @@ -49,6 +52,162 @@ impl<'tcx> StatementKind<'tcx> { /////////////////////////////////////////////////////////////////////////// // Places +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] +pub struct PlaceTy<'tcx> { + pub ty: Ty<'tcx>, + /// Downcast to a particular variant of an enum or a coroutine, if included. + pub variant_index: Option, +} + +// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers. +#[cfg(target_pointer_width = "64")] +rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16); + +impl<'tcx> PlaceTy<'tcx> { + #[inline] + pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> { + PlaceTy { ty, variant_index: None } + } + + /// `place_ty.field_ty(tcx, f)` computes the type of a given field. + /// + /// Most clients of `PlaceTy` can instead just extract the relevant type + /// directly from their `PlaceElem`, but some instances of `ProjectionElem` + /// do not carry a `Ty` for `T`. + /// + /// Note that the resulting type has not been normalized. + #[instrument(level = "debug", skip(tcx), ret)] + pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> { + if let Some(variant_index) = self.variant_index { + match *self.ty.kind() { + ty::Adt(adt_def, args) if adt_def.is_enum() => { + adt_def.variant(variant_index).fields[f].ty(tcx, args) + } + ty::Coroutine(def_id, args) => { + let mut variants = args.as_coroutine().state_tys(def_id, tcx); + let Some(mut variant) = variants.nth(variant_index.into()) else { + bug!("variant {variant_index:?} of coroutine out of range: {self:?}"); + }; + + variant + .nth(f.index()) + .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")) + } + _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"), + } + } else { + match self.ty.kind() { + ty::Adt(adt_def, args) if !adt_def.is_enum() => { + adt_def.non_enum_variant().fields[f].ty(tcx, args) + } + ty::Closure(_, args) => args + .as_closure() + .upvar_tys() + .get(f.index()) + .copied() + .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), + ty::CoroutineClosure(_, args) => args + .as_coroutine_closure() + .upvar_tys() + .get(f.index()) + .copied() + .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), + // Only prefix fields (upvars and current state) are + // accessible without a variant index. + ty::Coroutine(_, args) => args + .as_coroutine() + .prefix_tys() + .get(f.index()) + .copied() + .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), + ty::Tuple(tys) => tys + .get(f.index()) + .copied() + .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), + _ => bug!("can't project out of {self:?}"), + } + } + } + + pub fn multi_projection_ty( + self, + tcx: TyCtxt<'tcx>, + elems: &[PlaceElem<'tcx>], + ) -> PlaceTy<'tcx> { + elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem)) + } + + /// Convenience wrapper around `projection_ty_core` for + /// `PlaceElem`, where we can just use the `Ty` that is already + /// stored inline on field projection elems. + pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> { + self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty) + } + + /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` + /// projects `place_ty` onto `elem`, returning the appropriate + /// `Ty` or downcast variant corresponding to that projection. + /// The `handle_field` callback must map a `FieldIdx` to its `Ty`, + /// (which should be trivial when `T` = `Ty`). + pub fn projection_ty_core( + self, + tcx: TyCtxt<'tcx>, + elem: &ProjectionElem, + mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, + mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>, + ) -> PlaceTy<'tcx> + where + V: ::std::fmt::Debug, + T: ::std::fmt::Debug + Copy, + { + if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) { + bug!("cannot use non field projection on downcasted place") + } + let answer = match *elem { + ProjectionElem::Deref => { + let ty = self.ty.builtin_deref(true).unwrap_or_else(|| { + bug!("deref projection of non-dereferenceable ty {:?}", self) + }); + PlaceTy::from_ty(ty) + } + ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => { + PlaceTy::from_ty(self.ty.builtin_index().unwrap()) + } + ProjectionElem::Subslice { from, to, from_end } => { + PlaceTy::from_ty(match self.ty.kind() { + ty::Slice(..) => self.ty, + ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from), + ty::Array(inner, size) if from_end => { + let size = size + .try_to_target_usize(tcx) + .expect("expected subslice projection on fixed-size array"); + let len = size - from - to; + Ty::new_array(tcx, *inner, len) + } + _ => bug!("cannot subslice non-array type: `{:?}`", self), + }) + } + ProjectionElem::Downcast(_name, index) => { + PlaceTy { ty: self.ty, variant_index: Some(index) } + } + ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)), + ProjectionElem::OpaqueCast(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } + ProjectionElem::Subtype(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } + + // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general. + ProjectionElem::UnwrapUnsafeBinder(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } + }; + debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); + answer + } +} + impl ProjectionElem { /// Returns `true` if the target of this projection may refer to a different region of memory /// than the base. @@ -192,6 +351,25 @@ impl<'tcx> Place<'tcx> { self.as_ref().project_deeper(more_projections, tcx) } + + pub fn ty_from( + local: Local, + projection: &[PlaceElem<'tcx>], + local_decls: &D, + tcx: TyCtxt<'tcx>, + ) -> PlaceTy<'tcx> + where + D: HasLocalDecls<'tcx>, + { + PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection) + } + + pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx> + where + D: HasLocalDecls<'tcx>, + { + Place::ty_from(self.local, self.projection, local_decls, tcx) + } } impl From for Place<'_> { @@ -294,6 +472,13 @@ impl<'tcx> PlaceRef<'tcx> { Place { local: self.local, projection: tcx.mk_place_elems(new_projections) } } + + pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx> + where + D: HasLocalDecls<'tcx>, + { + Place::ty_from(self.local, self.projection, local_decls, tcx) + } } impl From for PlaceRef<'_> { @@ -388,6 +573,28 @@ impl<'tcx> Operand<'tcx> { let const_ty = self.constant()?.const_.ty(); if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None } } + + pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx> + where + D: HasLocalDecls<'tcx>, + { + match self { + &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, + Operand::Constant(c) => c.const_.ty(), + } + } + + pub fn span(&self, local_decls: &D) -> Span + where + D: HasLocalDecls<'tcx>, + { + match self { + &Operand::Copy(ref l) | &Operand::Move(ref l) => { + local_decls.local_decls()[l.local].source_info.span + } + Operand::Constant(c) => c.span, + } + } } impl<'tcx> ConstOperand<'tcx> { @@ -413,6 +620,11 @@ impl<'tcx> ConstOperand<'tcx> { /////////////////////////////////////////////////////////////////////////// /// Rvalues +pub enum RvalueInitializationState { + Shallow, + Deep, +} + impl<'tcx> Rvalue<'tcx> { /// Returns true if rvalue can be safely removed when the result is unused. #[inline] @@ -452,6 +664,70 @@ impl<'tcx> Rvalue<'tcx> { | Rvalue::WrapUnsafeBinder(_, _) => true, } } + + pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx> + where + D: HasLocalDecls<'tcx>, + { + match *self { + Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), + Rvalue::Repeat(ref operand, count) => { + Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count) + } + Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did), + Rvalue::Ref(reg, bk, ref place) => { + let place_ty = place.ty(local_decls, tcx).ty; + Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy()) + } + Rvalue::RawPtr(kind, ref place) => { + let place_ty = place.ty(local_decls, tcx).ty; + Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy()) + } + Rvalue::Len(..) => tcx.types.usize, + Rvalue::Cast(.., ty) => ty, + Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => { + let lhs_ty = lhs.ty(local_decls, tcx); + let rhs_ty = rhs.ty(local_decls, tcx); + op.ty(tcx, lhs_ty, rhs_ty) + } + Rvalue::UnaryOp(op, ref operand) => { + let arg_ty = operand.ty(local_decls, tcx); + op.ty(tcx, arg_ty) + } + Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { + tcx.types.usize + } + Rvalue::NullaryOp(NullOp::ContractChecks, _) + | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool, + Rvalue::Aggregate(ref ak, ref ops) => match **ak { + AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), + AggregateKind::Tuple => { + Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx))) + } + AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args), + AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args), + AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args), + AggregateKind::CoroutineClosure(did, args) => { + Ty::new_coroutine_closure(tcx, did, args) + } + AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability), + }, + Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), + Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, + Rvalue::WrapUnsafeBinder(_, ty) => ty, + } + } + + #[inline] + /// Returns `true` if this rvalue is deeply initialized (most rvalues) or + /// whether its only shallowly initialized (`Rvalue::Box`). + pub fn initialization_state(&self) -> RvalueInitializationState { + match *self { + Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow, + _ => RvalueInitializationState::Deep, + } + } } impl BorrowKind { @@ -474,4 +750,124 @@ impl BorrowKind { BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow } => true, } } + + pub fn to_mutbl_lossy(self) -> hir::Mutability { + match self { + BorrowKind::Mut { .. } => hir::Mutability::Mut, + BorrowKind::Shared => hir::Mutability::Not, + + // We have no type corresponding to a shallow borrow, so use + // `&` as an approximation. + BorrowKind::Fake(_) => hir::Mutability::Not, + } + } +} + +impl<'tcx> UnOp { + pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { + match self { + UnOp::Not | UnOp::Neg => arg_ty, + UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx), + } + } +} + +impl<'tcx> BinOp { + pub fn ty(&self, tcx: TyCtxt<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) -> Ty<'tcx> { + // FIXME: handle SIMD correctly + match self { + &BinOp::Add + | &BinOp::AddUnchecked + | &BinOp::Sub + | &BinOp::SubUnchecked + | &BinOp::Mul + | &BinOp::MulUnchecked + | &BinOp::Div + | &BinOp::Rem + | &BinOp::BitXor + | &BinOp::BitAnd + | &BinOp::BitOr => { + // these should be integers or floats of the same size. + assert_eq!(lhs_ty, rhs_ty); + lhs_ty + } + &BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => { + // these should be integers of the same size. + assert_eq!(lhs_ty, rhs_ty); + Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool]) + } + &BinOp::Shl + | &BinOp::ShlUnchecked + | &BinOp::Shr + | &BinOp::ShrUnchecked + | &BinOp::Offset => { + lhs_ty // lhs_ty can be != rhs_ty + } + &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => { + tcx.types.bool + } + &BinOp::Cmp => { + // these should be integer-like types of the same size. + assert_eq!(lhs_ty, rhs_ty); + tcx.ty_ordering_enum(None) + } + } + } + pub(crate) fn to_hir_binop(self) -> hir::BinOpKind { + match self { + // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending + // on whether overflow checks are enabled or not. + BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add, + BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub, + BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul, + BinOp::Div => hir::BinOpKind::Div, + BinOp::Rem => hir::BinOpKind::Rem, + BinOp::BitXor => hir::BinOpKind::BitXor, + BinOp::BitAnd => hir::BinOpKind::BitAnd, + BinOp::BitOr => hir::BinOpKind::BitOr, + BinOp::Shl => hir::BinOpKind::Shl, + BinOp::Shr => hir::BinOpKind::Shr, + BinOp::Eq => hir::BinOpKind::Eq, + BinOp::Ne => hir::BinOpKind::Ne, + BinOp::Lt => hir::BinOpKind::Lt, + BinOp::Gt => hir::BinOpKind::Gt, + BinOp::Le => hir::BinOpKind::Le, + BinOp::Ge => hir::BinOpKind::Ge, + // We don't have HIR syntax for these. + BinOp::Cmp + | BinOp::AddUnchecked + | BinOp::SubUnchecked + | BinOp::MulUnchecked + | BinOp::ShlUnchecked + | BinOp::ShrUnchecked + | BinOp::Offset => { + unreachable!() + } + } + } + + /// If this is a `FooWithOverflow`, return `Some(Foo)`. + pub fn overflowing_to_wrapping(self) -> Option { + Some(match self { + BinOp::AddWithOverflow => BinOp::Add, + BinOp::SubWithOverflow => BinOp::Sub, + BinOp::MulWithOverflow => BinOp::Mul, + _ => return None, + }) + } + + /// Returns whether this is a `FooWithOverflow` + pub fn is_overflowing(self) -> bool { + self.overflowing_to_wrapping().is_some() + } + + /// If this is a `Foo`, return `Some(FooWithOverflow)`. + pub fn wrapping_to_overflowing(self) -> Option { + Some(match self { + BinOp::Add => BinOp::AddWithOverflow, + BinOp::Sub => BinOp::SubWithOverflow, + BinOp::Mul => BinOp::MulWithOverflow, + _ => return None, + }) + } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 9cec8d832dd1..45fcec41fde3 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1125,7 +1125,7 @@ pub type AssertMessage<'tcx> = AssertKind>; /// /// 1. The address in memory that the place refers to. /// 2. The provenance with which the place is being accessed. -/// 3. The type of the place and an optional variant index. See [`PlaceTy`][super::tcx::PlaceTy]. +/// 3. The type of the place and an optional variant index. See [`PlaceTy`][super::PlaceTy]. /// 4. Optionally, some metadata. This exists if and only if the type of the place is not `Sized`. /// /// We'll give a description below of how all pieces of the place except for the provenance are diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs deleted file mode 100644 index 862f78d72598..000000000000 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ /dev/null @@ -1,416 +0,0 @@ -/*! - * Methods for the various MIR types. These are intended for use after - * building is complete. - */ - -use rustc_hir as hir; -use tracing::{debug, instrument}; -use ty::CoroutineArgsExt; - -use crate::mir::*; - -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] -pub struct PlaceTy<'tcx> { - pub ty: Ty<'tcx>, - /// Downcast to a particular variant of an enum or a coroutine, if included. - pub variant_index: Option, -} - -// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers. -#[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16); - -impl<'tcx> PlaceTy<'tcx> { - #[inline] - pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> { - PlaceTy { ty, variant_index: None } - } - - /// `place_ty.field_ty(tcx, f)` computes the type of a given field. - /// - /// Most clients of `PlaceTy` can instead just extract the relevant type - /// directly from their `PlaceElem`, but some instances of `ProjectionElem` - /// do not carry a `Ty` for `T`. - /// - /// Note that the resulting type has not been normalized. - #[instrument(level = "debug", skip(tcx), ret)] - pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> { - if let Some(variant_index) = self.variant_index { - match *self.ty.kind() { - ty::Adt(adt_def, args) if adt_def.is_enum() => { - adt_def.variant(variant_index).fields[f].ty(tcx, args) - } - ty::Coroutine(def_id, args) => { - let mut variants = args.as_coroutine().state_tys(def_id, tcx); - let Some(mut variant) = variants.nth(variant_index.into()) else { - bug!("variant {variant_index:?} of coroutine out of range: {self:?}"); - }; - - variant - .nth(f.index()) - .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")) - } - _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"), - } - } else { - match self.ty.kind() { - ty::Adt(adt_def, args) if !adt_def.is_enum() => { - adt_def.non_enum_variant().fields[f].ty(tcx, args) - } - ty::Closure(_, args) => args - .as_closure() - .upvar_tys() - .get(f.index()) - .copied() - .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), - ty::CoroutineClosure(_, args) => args - .as_coroutine_closure() - .upvar_tys() - .get(f.index()) - .copied() - .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), - // Only prefix fields (upvars and current state) are - // accessible without a variant index. - ty::Coroutine(_, args) => args - .as_coroutine() - .prefix_tys() - .get(f.index()) - .copied() - .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), - ty::Tuple(tys) => tys - .get(f.index()) - .copied() - .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")), - _ => bug!("can't project out of {self:?}"), - } - } - } - - pub fn multi_projection_ty( - self, - tcx: TyCtxt<'tcx>, - elems: &[PlaceElem<'tcx>], - ) -> PlaceTy<'tcx> { - elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem)) - } - - /// Convenience wrapper around `projection_ty_core` for - /// `PlaceElem`, where we can just use the `Ty` that is already - /// stored inline on field projection elems. - pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty) - } - - /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` - /// projects `place_ty` onto `elem`, returning the appropriate - /// `Ty` or downcast variant corresponding to that projection. - /// The `handle_field` callback must map a `FieldIdx` to its `Ty`, - /// (which should be trivial when `T` = `Ty`). - pub fn projection_ty_core( - self, - tcx: TyCtxt<'tcx>, - elem: &ProjectionElem, - mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, - mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>, - ) -> PlaceTy<'tcx> - where - V: ::std::fmt::Debug, - T: ::std::fmt::Debug + Copy, - { - if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) { - bug!("cannot use non field projection on downcasted place") - } - let answer = match *elem { - ProjectionElem::Deref => { - let ty = self.ty.builtin_deref(true).unwrap_or_else(|| { - bug!("deref projection of non-dereferenceable ty {:?}", self) - }); - PlaceTy::from_ty(ty) - } - ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => { - PlaceTy::from_ty(self.ty.builtin_index().unwrap()) - } - ProjectionElem::Subslice { from, to, from_end } => { - PlaceTy::from_ty(match self.ty.kind() { - ty::Slice(..) => self.ty, - ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from), - ty::Array(inner, size) if from_end => { - let size = size - .try_to_target_usize(tcx) - .expect("expected subslice projection on fixed-size array"); - let len = size - from - to; - Ty::new_array(tcx, *inner, len) - } - _ => bug!("cannot subslice non-array type: `{:?}`", self), - }) - } - ProjectionElem::Downcast(_name, index) => { - PlaceTy { ty: self.ty, variant_index: Some(index) } - } - ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)), - ProjectionElem::OpaqueCast(ty) => { - PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) - } - ProjectionElem::Subtype(ty) => { - PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) - } - - // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general. - ProjectionElem::UnwrapUnsafeBinder(ty) => { - PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) - } - }; - debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); - answer - } -} - -impl<'tcx> Place<'tcx> { - pub fn ty_from( - local: Local, - projection: &[PlaceElem<'tcx>], - local_decls: &D, - tcx: TyCtxt<'tcx>, - ) -> PlaceTy<'tcx> - where - D: HasLocalDecls<'tcx>, - { - PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection) - } - - pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx> - where - D: HasLocalDecls<'tcx>, - { - Place::ty_from(self.local, self.projection, local_decls, tcx) - } -} - -impl<'tcx> PlaceRef<'tcx> { - pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx> - where - D: HasLocalDecls<'tcx>, - { - Place::ty_from(self.local, self.projection, local_decls, tcx) - } -} - -pub enum RvalueInitializationState { - Shallow, - Deep, -} - -impl<'tcx> Rvalue<'tcx> { - pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx> - where - D: HasLocalDecls<'tcx>, - { - match *self { - Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), - Rvalue::Repeat(ref operand, count) => { - Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count) - } - Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did), - Rvalue::Ref(reg, bk, ref place) => { - let place_ty = place.ty(local_decls, tcx).ty; - Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy()) - } - Rvalue::RawPtr(kind, ref place) => { - let place_ty = place.ty(local_decls, tcx).ty; - Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy()) - } - Rvalue::Len(..) => tcx.types.usize, - Rvalue::Cast(.., ty) => ty, - Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => { - let lhs_ty = lhs.ty(local_decls, tcx); - let rhs_ty = rhs.ty(local_decls, tcx); - op.ty(tcx, lhs_ty, rhs_ty) - } - Rvalue::UnaryOp(op, ref operand) => { - let arg_ty = operand.ty(local_decls, tcx); - op.ty(tcx, arg_ty) - } - Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { - tcx.types.usize - } - Rvalue::NullaryOp(NullOp::ContractChecks, _) - | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool, - Rvalue::Aggregate(ref ak, ref ops) => match **ak { - AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), - AggregateKind::Tuple => { - Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx))) - } - AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args), - AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args), - AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args), - AggregateKind::CoroutineClosure(did, args) => { - Ty::new_coroutine_closure(tcx, did, args) - } - AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability), - }, - Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), - Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, - Rvalue::WrapUnsafeBinder(_, ty) => ty, - } - } - - #[inline] - /// Returns `true` if this rvalue is deeply initialized (most rvalues) or - /// whether its only shallowly initialized (`Rvalue::Box`). - pub fn initialization_state(&self) -> RvalueInitializationState { - match *self { - Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow, - _ => RvalueInitializationState::Deep, - } - } -} - -impl<'tcx> Operand<'tcx> { - pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx> - where - D: HasLocalDecls<'tcx>, - { - match self { - &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, - Operand::Constant(c) => c.const_.ty(), - } - } - - pub fn span(&self, local_decls: &D) -> Span - where - D: HasLocalDecls<'tcx>, - { - match self { - &Operand::Copy(ref l) | &Operand::Move(ref l) => { - local_decls.local_decls()[l.local].source_info.span - } - Operand::Constant(c) => c.span, - } - } -} - -impl<'tcx> BinOp { - pub fn ty(&self, tcx: TyCtxt<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) -> Ty<'tcx> { - // FIXME: handle SIMD correctly - match self { - &BinOp::Add - | &BinOp::AddUnchecked - | &BinOp::Sub - | &BinOp::SubUnchecked - | &BinOp::Mul - | &BinOp::MulUnchecked - | &BinOp::Div - | &BinOp::Rem - | &BinOp::BitXor - | &BinOp::BitAnd - | &BinOp::BitOr => { - // these should be integers or floats of the same size. - assert_eq!(lhs_ty, rhs_ty); - lhs_ty - } - &BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => { - // these should be integers of the same size. - assert_eq!(lhs_ty, rhs_ty); - Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool]) - } - &BinOp::Shl - | &BinOp::ShlUnchecked - | &BinOp::Shr - | &BinOp::ShrUnchecked - | &BinOp::Offset => { - lhs_ty // lhs_ty can be != rhs_ty - } - &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => { - tcx.types.bool - } - &BinOp::Cmp => { - // these should be integer-like types of the same size. - assert_eq!(lhs_ty, rhs_ty); - tcx.ty_ordering_enum(None) - } - } - } -} - -impl<'tcx> UnOp { - pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { - match self { - UnOp::Not | UnOp::Neg => arg_ty, - UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx), - } - } -} - -impl BorrowKind { - pub fn to_mutbl_lossy(self) -> hir::Mutability { - match self { - BorrowKind::Mut { .. } => hir::Mutability::Mut, - BorrowKind::Shared => hir::Mutability::Not, - - // We have no type corresponding to a shallow borrow, so use - // `&` as an approximation. - BorrowKind::Fake(_) => hir::Mutability::Not, - } - } -} - -impl BinOp { - pub(crate) fn to_hir_binop(self) -> hir::BinOpKind { - match self { - // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending - // on whether overflow checks are enabled or not. - BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add, - BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub, - BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul, - BinOp::Div => hir::BinOpKind::Div, - BinOp::Rem => hir::BinOpKind::Rem, - BinOp::BitXor => hir::BinOpKind::BitXor, - BinOp::BitAnd => hir::BinOpKind::BitAnd, - BinOp::BitOr => hir::BinOpKind::BitOr, - BinOp::Shl => hir::BinOpKind::Shl, - BinOp::Shr => hir::BinOpKind::Shr, - BinOp::Eq => hir::BinOpKind::Eq, - BinOp::Ne => hir::BinOpKind::Ne, - BinOp::Lt => hir::BinOpKind::Lt, - BinOp::Gt => hir::BinOpKind::Gt, - BinOp::Le => hir::BinOpKind::Le, - BinOp::Ge => hir::BinOpKind::Ge, - // We don't have HIR syntax for these. - BinOp::Cmp - | BinOp::AddUnchecked - | BinOp::SubUnchecked - | BinOp::MulUnchecked - | BinOp::ShlUnchecked - | BinOp::ShrUnchecked - | BinOp::Offset => { - unreachable!() - } - } - } - - /// If this is a `FooWithOverflow`, return `Some(Foo)`. - pub fn overflowing_to_wrapping(self) -> Option { - Some(match self { - BinOp::AddWithOverflow => BinOp::Add, - BinOp::SubWithOverflow => BinOp::Sub, - BinOp::MulWithOverflow => BinOp::Mul, - _ => return None, - }) - } - - /// Returns whether this is a `FooWithOverflow` - pub fn is_overflowing(self) -> bool { - self.overflowing_to_wrapping().is_some() - } - - /// If this is a `Foo`, return `Some(FooWithOverflow)`. - pub fn wrapping_to_overflowing(self) -> Option { - Some(match self { - BinOp::Add => BinOp::AddWithOverflow, - BinOp::Sub => BinOp::SubWithOverflow, - BinOp::Mul => BinOp::MulWithOverflow, - _ => return None, - }) - } -} diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index eab414e150fa..19669021eefb 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -1,6 +1,5 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_middle::mir::interpret::Scalar; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index b6c259aa4e0a..8bbc89fdcecb 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -1,7 +1,6 @@ use std::mem; use rustc_index::IndexVec; -use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index a51af8c40fd4..104a2e8c0910 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -7,7 +7,6 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 2de55e38052e..9330a9481f52 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -185,7 +185,7 @@ where place.ty(self.elaborator.body(), self.tcx()).ty } else { // We don't have a slice with all the locals, since some are in the patch. - tcx::PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local)) + PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local)) .multi_projection_ty(self.elaborator.tcx(), place.projection) .ty } From 20eb224a559c3bd74ed97efc7c98c0a25f5b5225 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 19 Feb 2025 05:06:01 +0000 Subject: [PATCH 155/158] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0ea62d4d8502..a2a2f28ea71c 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -d1fb81e8dd5354ddf7cb334d5a234cab7f64b3bb +17c1c329a5512d718b67ef6797538b154016cd34 From c7981d64117a4e1228e94ddc47a16d171a011c0b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 12:17:09 +1000 Subject: [PATCH 156/158] Remove `NtVis`. We now use invisible delimiters for expanded `vis` fragments, instead of `Token::Interpolated`. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 13 ++++-- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 35 +++++++++++++- compiler/rustc_parse/src/parser/mod.rs | 46 ++++++++++++++++++- .../rustc_parse/src/parser/nonterminal.rs | 13 +++--- tests/ui/macros/block-to-expr-metavar.rs | 17 +++++++ 8 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 tests/ui/macros/block-to-expr-metavar.rs diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 60f8c6e10481..a2923d6448ae 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -206,7 +206,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtTy(ty) => ty.tokens(), Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), - Nonterminal::NtVis(vis) => vis.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } } @@ -219,7 +218,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtTy(ty) => ty.tokens_mut(), Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), - Nonterminal::NtVis(vis) => vis.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index de9f049704a4..47cf77cefa7b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -916,7 +916,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { visit_lazy_tts(vis, tokens); } token::NtPath(path) => vis.visit_path(path), - token::NtVis(visib) => vis.visit_vis(visib), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 36a7b7d87892..661f2c3eca24 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -969,6 +969,15 @@ impl Token { } } + /// Is this an invisible open delimiter at the start of a token sequence + /// from an expanded metavar? + pub fn is_metavar_seq(&self) -> Option { + match self.kind { + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => Some(kind), + _ => None, + } + } + pub fn glue(&self, joint: &Token) -> Option { let kind = match self.kind { Eq => match joint.kind { @@ -1072,7 +1081,6 @@ pub enum Nonterminal { /// Stuff inside brackets for attributes NtMeta(P), NtPath(P), - NtVis(P), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] @@ -1169,7 +1177,6 @@ impl Nonterminal { NtTy(ty) => ty.span, NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, - NtVis(vis) => vis.span, } } @@ -1184,7 +1191,6 @@ impl Nonterminal { NtTy(..) => "type", NtMeta(..) => "attribute", NtPath(..) => "path", - NtVis(..) => "visibility", } } } @@ -1211,7 +1217,6 @@ impl fmt::Debug for Nonterminal { NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), - NtVis(..) => f.pad("NtVis(..)"), } } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 50f10d083a04..1b6d825a22c8 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -472,7 +472,6 @@ impl TokenStream { Nonterminal::NtTy(ty) => TokenStream::from_ast(ty), Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), - Nonterminal::NtVis(vis) => TokenStream::from_ast(vis), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 595c8c3279f4..1723b47798b0 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -3,7 +3,10 @@ use std::sync::Arc; use rustc_ast::ExprKind; use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{ + self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, + TokenKind, +}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; @@ -274,6 +277,33 @@ pub(super) fn transcribe<'a>( // some of the unnecessary whitespace. let ident = MacroRulesNormalizedIdent::new(original_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { + // We wrap the tokens in invisible delimiters, unless they are already wrapped + // in invisible delimiters with the same `MetaVarKind`. Because some proc + // macros can't multiple layers of invisible delimiters of the same + // `MetaVarKind`. This loses some span info, though it hopefully won't matter. + let mut mk_delimited = |mv_kind, mut stream: TokenStream| { + if stream.len() == 1 { + let tree = stream.iter().next().unwrap(); + if let TokenTree::Delimited(_, _, delim, inner) = tree + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mvk)) = delim + && mv_kind == *mvk + { + stream = inner.clone(); + } + } + + // Emit as a token stream within `Delimiter::Invisible` to maintain + // parsing priorities. + marker.visit_span(&mut sp); + // Both the open delim and close delim get the same span, which covers the + // `$foo` in the decl macro RHS. + TokenTree::Delimited( + DelimSpan::from_single(sp), + DelimSpacing::new(Spacing::Alone, Spacing::Alone), + Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)), + stream, + ) + }; let tt = match cur_matched { MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", @@ -292,6 +322,9 @@ pub(super) fn transcribe<'a>( let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } + MatchedSingle(ParseNtResult::Vis(vis)) => { + mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) + } MatchedSingle(ParseNtResult::Nt(nt)) => { // Other variables are emitted into the output stream as groups with // `Delimiter::Invisible` to maintain parsing priorities. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1de452dcf396..ecbc4e396cee 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -721,6 +721,43 @@ impl<'a> Parser<'a> { if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) } } + /// Consume a sequence produced by a metavar expansion, if present. + fn eat_metavar_seq( + &mut self, + mv_kind: MetaVarKind, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + self.eat_metavar_seq_with_matcher(|mvk| mvk == mv_kind, f) + } + + /// A slightly more general form of `eat_metavar_seq`, for use with the + /// `MetaVarKind` variants that have parameters, where an exact match isn't + /// desired. + fn eat_metavar_seq_with_matcher( + &mut self, + match_mv_kind: impl Fn(MetaVarKind) -> bool, + mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + if let token::OpenDelim(delim) = self.token.kind + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + let res = f(self).expect("failed to reparse {mv_kind:?}"); + if let token::CloseDelim(delim) = self.token.kind + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + Some(res) + } else { + panic!("no close delim when reparsing {mv_kind:?}"); + } + } else { + None + } + } + /// Is the given keyword `kw` followed by a non-reserved identifier? fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) @@ -1455,7 +1492,11 @@ impl<'a> Parser<'a> { /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { - maybe_whole!(self, NtVis, |vis| vis.into_inner()); + if let Some(vis) = self + .eat_metavar_seq(MetaVarKind::Vis, |this| this.parse_visibility(FollowedByType::Yes)) + { + return Ok(vis); + } if !self.eat_keyword(exp!(Pub)) { // We need a span for our `Spanned`, but there's inherently no @@ -1683,7 +1724,8 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Vis(P), - /// This case will eventually be removed, along with `Token::Interpolate`. + /// This variant will eventually be removed, along with `Token::Interpolate`. Nt(Arc), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index eefdb641da22..f102821adf7c 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -56,9 +56,7 @@ impl<'a> Parser<'a> { | NtMeta(_) | NtPath(_) => true, - NtItem(_) - | NtBlock(_) - | NtVis(_) => false, + NtItem(_) | NtBlock(_) => false, } } @@ -88,7 +86,7 @@ impl<'a> Parser<'a> { NonterminalKind::Ident => get_macro_ident(token).is_some(), NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), NonterminalKind::Vis => match token.kind { - // The follow-set of :vis + "priv" keyword + interpolated + // The follow-set of :vis + "priv" keyword + interpolated/metavar-expansion. token::Comma | token::Ident(..) | token::NtIdent(..) @@ -102,7 +100,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false, + NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -208,8 +206,9 @@ impl<'a> Parser<'a> { } NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)), NonterminalKind::Vis => { - NtVis(P(self - .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)) + return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| { + this.parse_visibility(FollowedByType::Yes) + })?))); } NonterminalKind::Lifetime => { // We want to keep `'keyword` parsing, just like `keyword` is still diff --git a/tests/ui/macros/block-to-expr-metavar.rs b/tests/ui/macros/block-to-expr-metavar.rs new file mode 100644 index 000000000000..04f10ad0f988 --- /dev/null +++ b/tests/ui/macros/block-to-expr-metavar.rs @@ -0,0 +1,17 @@ +//@ check-pass +// +// A test case where a `block` fragment specifier is interpreted as an `expr` +// fragment specifier. It's an interesting case for the handling of invisible +// delimiters. + +macro_rules! m_expr { + ($e:expr) => { const _CURRENT: u32 = $e; }; +} + +macro_rules! m_block { + ($b:block) => ( m_expr!($b); ); +} + +fn main() { + m_block!({ 1 }); +} From 76b04437be91069260c72a6d59d130a4e127a9a8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 13:17:44 +1000 Subject: [PATCH 157/158] Remove `NtTy`. Notes about tests: - tests/ui/parser/macro/trait-object-macro-matcher.rs: the syntax error is duplicated, because it occurs now when parsing the decl macro input, and also when parsing the expanded decl macro. But this won't show up for normal users due to error de-duplication. - tests/ui/associated-consts/issue-93835.rs: similar, plus there are some additional errors about this very broken code. - The changes to metavariable descriptions in #132629 are now visible in error message for several tests. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 1 - compiler/rustc_ast/src/token.rs | 7 +-- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 3 ++ compiler/rustc_parse/src/parser/mod.rs | 33 +++++++++++--- .../rustc_parse/src/parser/nonterminal.rs | 7 +-- compiler/rustc_parse/src/parser/path.rs | 17 ++++---- compiler/rustc_parse/src/parser/ty.rs | 14 ++++-- tests/ui/associated-consts/issue-93835.rs | 4 +- tests/ui/associated-consts/issue-93835.stderr | 43 +++++++++++++++---- tests/ui/macros/macro-interpolation.rs | 2 +- tests/ui/macros/macro-interpolation.stderr | 4 +- tests/ui/macros/syntax-error-recovery.rs | 4 +- tests/ui/macros/syntax-error-recovery.stderr | 4 +- tests/ui/parser/macro/issue-37113.rs | 2 +- tests/ui/parser/macro/issue-37113.stderr | 4 +- .../macro/trait-object-macro-matcher.rs | 1 + .../macro/trait-object-macro-matcher.stderr | 10 ++++- 19 files changed, 112 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index a2923d6448ae..346edc87c86b 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -203,7 +203,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtStmt(stmt) => stmt.tokens(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), Nonterminal::NtPat(pat) => pat.tokens(), - Nonterminal::NtTy(ty) => ty.tokens(), Nonterminal::NtMeta(attr_item) => attr_item.tokens(), Nonterminal::NtPath(path) => path.tokens(), Nonterminal::NtBlock(block) => block.tokens(), @@ -215,7 +214,6 @@ impl HasTokens for Nonterminal { Nonterminal::NtStmt(stmt) => stmt.tokens_mut(), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), Nonterminal::NtPat(pat) => pat.tokens_mut(), - Nonterminal::NtTy(ty) => ty.tokens_mut(), Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(), Nonterminal::NtPath(path) => path.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 47cf77cefa7b..40b29fdba250 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -907,7 +907,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { }), token::NtPat(pat) => vis.visit_pat(pat), token::NtExpr(expr) => vis.visit_expr(expr), - token::NtTy(ty) => vis.visit_ty(ty), token::NtLiteral(expr) => vis.visit_expr(expr), token::NtMeta(item) => { let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut(); diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 661f2c3eca24..8ac6dc3b4d8c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -659,7 +659,6 @@ impl Token { | NtMeta(..) | NtPat(..) | NtPath(..) - | NtTy(..) ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | @@ -688,7 +687,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path PathSep => true, // global path - Interpolated(ref nt) => matches!(&**nt, NtTy(..) | NtPath(..)), + Interpolated(ref nt) => matches!(&**nt, NtPath(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Ty | MetaVarKind::Path @@ -1076,7 +1075,6 @@ pub enum Nonterminal { NtStmt(P), NtPat(P), NtExpr(P), - NtTy(P), NtLiteral(P), /// Stuff inside brackets for attributes NtMeta(P), @@ -1174,7 +1172,6 @@ impl Nonterminal { NtStmt(stmt) => stmt.span, NtPat(pat) => pat.span, NtExpr(expr) | NtLiteral(expr) => expr.span, - NtTy(ty) => ty.span, NtMeta(attr_item) => attr_item.span(), NtPath(path) => path.span, } @@ -1188,7 +1185,6 @@ impl Nonterminal { NtPat(..) => "pattern", NtExpr(..) => "expression", NtLiteral(..) => "literal", - NtTy(..) => "type", NtMeta(..) => "attribute", NtPath(..) => "path", } @@ -1213,7 +1209,6 @@ impl fmt::Debug for Nonterminal { NtStmt(..) => f.pad("NtStmt(..)"), NtPat(..) => f.pad("NtPat(..)"), NtExpr(..) => f.pad("NtExpr(..)"), - NtTy(..) => f.pad("NtTy(..)"), NtLiteral(..) => f.pad("NtLiteral(..)"), NtMeta(..) => f.pad("NtMeta(..)"), NtPath(..) => f.pad("NtPath(..)"), diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 1b6d825a22c8..1123ea3a449b 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -469,7 +469,6 @@ impl TokenStream { } Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt), Nonterminal::NtPat(pat) => TokenStream::from_ast(pat), - Nonterminal::NtTy(ty) => TokenStream::from_ast(ty), Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr), Nonterminal::NtPath(path) => TokenStream::from_ast(path), Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 1723b47798b0..fa0c2c7da781 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -322,6 +322,9 @@ pub(super) fn transcribe<'a>( let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } + MatchedSingle(ParseNtResult::Ty(ty)) => { + mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) + } MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ecbc4e396cee..4b26100c46de 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -117,12 +117,16 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.may_recover() - && $self.look_ahead(1, |t| t == &token::PathSep) - && let token::Interpolated(nt) = &$self.token.kind - && let token::NtTy(ty) = &**nt + && let Some(token::MetaVarKind::Ty) = $self.token.is_metavar_seq() + && $self.check_noexpect_past_close_delim(&token::PathSep) { - let ty = ty.clone(); - $self.bump(); + // Reparse the type, then move to recovery. + let ty = $self + .eat_metavar_seq(token::MetaVarKind::Ty, |this| { + this.parse_ty_no_question_mark_recover() + }) + .expect("metavar seq ty"); + return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty); } }; @@ -614,6 +618,24 @@ impl<'a> Parser<'a> { self.token == *tok } + // Check the first token after the delimiter that closes the current + // delimited sequence. (Panics if used in the outermost token stream, which + // has no delimiters.) It uses a clone of the relevant tree cursor to skip + // past the entire `TokenTree::Delimited` in a single step, avoiding the + // need for unbounded token lookahead. + // + // Primarily used when `self.token` matches + // `OpenDelim(Delimiter::Invisible(_))`, to look ahead through the current + // metavar expansion. + fn check_noexpect_past_close_delim(&self, tok: &TokenKind) -> bool { + let mut tree_cursor = self.token_cursor.stack.last().unwrap().clone(); + tree_cursor.bump(); + matches!( + tree_cursor.curr(), + Some(TokenTree::Token(token::Token { kind, .. }, _)) if kind == tok + ) + } + /// Consumes a token 'tok' if it exists. Returns whether the given token was present. /// /// the main purpose of this function is to reduce the cluttering of the suggestions list @@ -1724,6 +1746,7 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), + Ty(P), Vis(P), /// This variant will eventually be removed, along with `Token::Interpolate`. diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index f102821adf7c..e9cf8f1bbba9 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -51,7 +51,6 @@ impl<'a> Parser<'a> { NtStmt(_) | NtPat(_) | NtExpr(_) - | NtTy(_) | NtLiteral(_) // `true`, `false` | NtMeta(_) | NtPath(_) => true, @@ -100,7 +99,7 @@ impl<'a> Parser<'a> { token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, - NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) => false, + NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -187,7 +186,9 @@ impl<'a> Parser<'a> { NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) } NonterminalKind::Ty => { - NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?) + return Ok(ParseNtResult::Ty( + self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, + )); } // this could be handled like a token, since it is one NonterminalKind::Ident => { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index b241aa892db9..b68eb9c99f52 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -2,7 +2,7 @@ use std::mem; use ast::token::IdentIsRaw; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, MetaVarKind, Token, TokenKind}; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint, AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, @@ -196,13 +196,14 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner())); - if let token::Interpolated(nt) = &self.token.kind { - if let token::NtTy(ty) = &**nt { - if let ast::TyKind::Path(None, path) = &ty.kind { - let path = path.clone(); - self.bump(); - return Ok(reject_generics_if_mod_style(self, path)); - } + if let Some(MetaVarKind::Ty) = self.token.is_metavar_seq() { + let mut snapshot = self.create_snapshot_for_diagnostic(); + let ty = snapshot + .eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) + .expect("metavar seq ty"); + if let ast::TyKind::Path(None, path) = ty.into_inner().kind { + self.restore_snapshot(snapshot); + return Ok(reject_generics_if_mod_style(self, path)); } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index dc5919b3630c..c78c7bff9b57 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,5 +1,5 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind}; +use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, @@ -18,7 +18,7 @@ use crate::errors::{ HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow, }; -use crate::{exp, maybe_recover_from_interpolated_ty_qpath, maybe_whole}; +use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; /// Signals whether parsing a type should allow `+`. /// @@ -183,7 +183,8 @@ impl<'a> Parser<'a> { ) } - /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>` + /// Parse a type without recovering `:` as `->` to avoid breaking code such + /// as `where fn() : for<'a>`. pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P> { self.parse_ty_common( AllowPlus::Yes, @@ -247,7 +248,12 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - maybe_whole!(self, NtTy, |ty| ty); + + if let Some(ty) = + self.eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) + { + return Ok(ty); + } let lo = self.token.span; let mut impl_dyn_multi = false; diff --git a/tests/ui/associated-consts/issue-93835.rs b/tests/ui/associated-consts/issue-93835.rs index 9cc33d53f9cd..048681f04778 100644 --- a/tests/ui/associated-consts/issue-93835.rs +++ b/tests/ui/associated-consts/issue-93835.rs @@ -3,9 +3,11 @@ fn e() { type_ascribe!(p, a>); //~^ ERROR cannot find type `a` in this scope + //~| ERROR path separator must be a double colon //~| ERROR cannot find value //~| ERROR associated const equality - //~| ERROR cannot find trait `p` in this scope + //~| ERROR associated const equality + //~| ERROR failed to resolve: use of unresolved module or unlinked crate `p` } fn main() {} diff --git a/tests/ui/associated-consts/issue-93835.stderr b/tests/ui/associated-consts/issue-93835.stderr index dfe78b3d1f38..e154ae25de26 100644 --- a/tests/ui/associated-consts/issue-93835.stderr +++ b/tests/ui/associated-consts/issue-93835.stderr @@ -1,3 +1,15 @@ +error: path separator must be a double colon + --> $DIR/issue-93835.rs:4:25 + | +LL | type_ascribe!(p, a>); + | ^ + | + = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 +help: use a double colon instead + | +LL | type_ascribe!(p, a>); + | + + error[E0425]: cannot find value `p` in this scope --> $DIR/issue-93835.rs:4:19 | @@ -10,12 +22,6 @@ error[E0412]: cannot find type `a` in this scope LL | type_ascribe!(p, a>); | ^ not found in this scope -error[E0405]: cannot find trait `p` in this scope - --> $DIR/issue-93835.rs:4:26 - | -LL | type_ascribe!(p, a>); - | ^ not found in this scope - error[E0658]: associated const equality is incomplete --> $DIR/issue-93835.rs:4:28 | @@ -26,7 +32,26 @@ LL | type_ascribe!(p, a>); = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 4 previous errors +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 + | +LL | type_ascribe!(p, a>); + | ^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -Some errors have detailed explanations: E0405, E0412, E0425, E0658. -For more information about an error, try `rustc --explain E0405`. +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `p` + --> $DIR/issue-93835.rs:4:24 + | +LL | type_ascribe!(p, a>); + | ^ use of unresolved module or unlinked crate `p` + | + = help: you might be missing a crate named `p` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0412, E0425, E0433, E0658. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs index 48c1f19e777f..b5d2322c8052 100644 --- a/tests/ui/macros/macro-interpolation.rs +++ b/tests/ui/macros/macro-interpolation.rs @@ -19,7 +19,7 @@ macro_rules! qpath { (ty, <$type:ty as $trait:ty>::$name:ident) => { <$type as $trait>::$name - //~^ ERROR expected identifier, found `!` + //~^ ERROR expected identifier, found metavariable }; } diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr index e6b39dfef858..bc24a1586129 100644 --- a/tests/ui/macros/macro-interpolation.stderr +++ b/tests/ui/macros/macro-interpolation.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found `!` +error: expected identifier, found metavariable --> $DIR/macro-interpolation.rs:21:19 | LL | <$type as $trait>::$name - | ^^^^^^ expected identifier + | ^^^^^^ expected identifier, found metavariable ... LL | let _: qpath!(ty, ::Owned); | ----------------------------- diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index 016e4def2849..6cf9d54e8263 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -9,8 +9,8 @@ macro_rules! values { } }; } -//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` -//~| ERROR macro expansion ignores type `(String)` and any tokens following +//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable +//~| ERROR macro expansion ignores `ty` metavariable and any tokens following values!(STRING(1) as (String) => cfg(test),); //~^ ERROR expected one of `!` or `::`, found `` diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index 3cfbd8ce82b5..61758fb9d7dc 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -1,4 +1,4 @@ -error: expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` +error: expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable --> $DIR/syntax-error-recovery.rs:7:26 | LL | $token $($inner)? = $value, @@ -10,7 +10,7 @@ LL | values!(STRING(1) as (String) => cfg(test),); = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) -error: macro expansion ignores type `(String)` and any tokens following +error: macro expansion ignores `ty` metavariable and any tokens following --> $DIR/syntax-error-recovery.rs:7:26 | LL | $token $($inner)? = $value, diff --git a/tests/ui/parser/macro/issue-37113.rs b/tests/ui/parser/macro/issue-37113.rs index 0044aa5610f5..e0957542f8f1 100644 --- a/tests/ui/parser/macro/issue-37113.rs +++ b/tests/ui/parser/macro/issue-37113.rs @@ -1,7 +1,7 @@ macro_rules! test_macro { ( $( $t:ty ),* $(),*) => { enum SomeEnum { - $( $t, )* //~ ERROR expected identifier, found `String` + $( $t, )* //~ ERROR expected identifier, found metavariable }; }; } diff --git a/tests/ui/parser/macro/issue-37113.stderr b/tests/ui/parser/macro/issue-37113.stderr index 1f2fe23106ae..560329df5ccb 100644 --- a/tests/ui/parser/macro/issue-37113.stderr +++ b/tests/ui/parser/macro/issue-37113.stderr @@ -1,10 +1,10 @@ -error: expected identifier, found `String` +error: expected identifier, found metavariable --> $DIR/issue-37113.rs:4:16 | LL | enum SomeEnum { | -------- while parsing this enum LL | $( $t, )* - | ^^ expected identifier + | ^^ expected identifier, found metavariable ... LL | test_macro!(String,); | -------------------- in this macro invocation diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.rs b/tests/ui/parser/macro/trait-object-macro-matcher.rs index 560195977d03..d4ec199070e7 100644 --- a/tests/ui/parser/macro/trait-object-macro-matcher.rs +++ b/tests/ui/parser/macro/trait-object-macro-matcher.rs @@ -10,5 +10,6 @@ macro_rules! m { fn main() { m!('static); //~^ ERROR lifetime in trait object type must be followed by `+` + //~| ERROR lifetime in trait object type must be followed by `+` //~| ERROR at least one trait is required for an object type } diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.stderr index 40082564bad4..81dca6f71c43 100644 --- a/tests/ui/parser/macro/trait-object-macro-matcher.stderr +++ b/tests/ui/parser/macro/trait-object-macro-matcher.stderr @@ -4,12 +4,20 @@ error: lifetime in trait object type must be followed by `+` LL | m!('static); | ^^^^^^^ +error: lifetime in trait object type must be followed by `+` + --> $DIR/trait-object-macro-matcher.rs:11:8 + | +LL | m!('static); + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0224]: at least one trait is required for an object type --> $DIR/trait-object-macro-matcher.rs:11:8 | LL | m!('static); | ^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0224`. From 0f490b040af82820e423a7e71e0e2e1f6ca7ab57 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Feb 2025 16:47:07 +1100 Subject: [PATCH 158/158] Avoid snapshotting the parser in `parse_path_inner`. --- compiler/rustc_ast/src/token.rs | 10 ++++++---- compiler/rustc_expand/src/mbe/transcribe.rs | 5 +++-- compiler/rustc_parse/src/parser/mod.rs | 7 +++---- compiler/rustc_parse/src/parser/nonterminal.rs | 4 ++-- compiler/rustc_parse/src/parser/path.rs | 15 ++++++--------- compiler/rustc_parse/src/parser/ty.rs | 7 ++++--- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 8ac6dc3b4d8c..97d121909f8d 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -84,7 +84,9 @@ pub enum MetaVarKind { // This field is needed for `Token::can_begin_string_literal`. can_begin_string_literal: bool, }, - Ty, + Ty { + is_path: bool, + }, Ident, Lifetime, Literal, @@ -104,7 +106,7 @@ impl fmt::Display for MetaVarKind { MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param, MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr, MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021, - MetaVarKind::Ty => sym::ty, + MetaVarKind::Ty { .. } => sym::ty, MetaVarKind::Ident => sym::ident, MetaVarKind::Lifetime => sym::lifetime, MetaVarKind::Literal => sym::literal, @@ -666,7 +668,7 @@ impl Token { MetaVarKind::Meta | MetaVarKind::Pat(_) | MetaVarKind::Path | - MetaVarKind::Ty + MetaVarKind::Ty { .. } ))) => true, _ => false, } @@ -689,7 +691,7 @@ impl Token { PathSep => true, // global path Interpolated(ref nt) => matches!(&**nt, NtPath(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - MetaVarKind::Ty | + MetaVarKind::Ty { .. } | MetaVarKind::Path ))) => true, // For anonymous structs or unions, which only appear in specific positions diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index fa0c2c7da781..721798b0ce46 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,13 +1,13 @@ use std::mem; use std::sync::Arc; -use rustc_ast::ExprKind; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; +use rustc_ast::{ExprKind, TyKind}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; @@ -323,7 +323,8 @@ pub(super) fn transcribe<'a>( TokenTree::token_alone(kind, sp) } MatchedSingle(ParseNtResult::Ty(ty)) => { - mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) + let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); + mk_delimited(MetaVarKind::Ty { is_path }, TokenStream::from_ast(ty)) } MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4b26100c46de..bbd73dec2e47 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -117,14 +117,13 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.may_recover() - && let Some(token::MetaVarKind::Ty) = $self.token.is_metavar_seq() + && let Some(mv_kind) = $self.token.is_metavar_seq() + && let token::MetaVarKind::Ty { .. } = mv_kind && $self.check_noexpect_past_close_delim(&token::PathSep) { // Reparse the type, then move to recovery. let ty = $self - .eat_metavar_seq(token::MetaVarKind::Ty, |this| { - this.parse_ty_no_question_mark_recover() - }) + .eat_metavar_seq(mv_kind, |this| this.parse_ty_no_question_mark_recover()) .expect("metavar seq ty"); return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty); diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index e9cf8f1bbba9..f202f85752e1 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -30,7 +30,7 @@ impl<'a> Parser<'a> { MetaVarKind::Stmt | MetaVarKind::Pat(_) | MetaVarKind::Expr { .. } - | MetaVarKind::Ty + | MetaVarKind::Ty { .. } | MetaVarKind::Literal // `true`, `false` | MetaVarKind::Meta | MetaVarKind::Path => true, @@ -108,7 +108,7 @@ impl<'a> Parser<'a> { | MetaVarKind::Literal => true, MetaVarKind::Item | MetaVarKind::Pat(_) - | MetaVarKind::Ty + | MetaVarKind::Ty { .. } | MetaVarKind::Meta | MetaVarKind::Path | MetaVarKind::Vis => false, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index b68eb9c99f52..c24305ea9a86 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -196,15 +196,12 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner())); - if let Some(MetaVarKind::Ty) = self.token.is_metavar_seq() { - let mut snapshot = self.create_snapshot_for_diagnostic(); - let ty = snapshot - .eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) - .expect("metavar seq ty"); - if let ast::TyKind::Path(None, path) = ty.into_inner().kind { - self.restore_snapshot(snapshot); - return Ok(reject_generics_if_mod_style(self, path)); - } + // If we have a `ty` metavar in the form of a path, reparse it directly as a path, instead + // of reparsing it as a `ty` and then extracting the path. + if let Some(path) = self.eat_metavar_seq(MetaVarKind::Ty { is_path: true }, |this| { + this.parse_path(PathStyle::Type) + }) { + return Ok(reject_generics_if_mod_style(self, path)); } let lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index c78c7bff9b57..18af0a1c79aa 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -249,9 +249,10 @@ impl<'a> Parser<'a> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - if let Some(ty) = - self.eat_metavar_seq(MetaVarKind::Ty, |this| this.parse_ty_no_question_mark_recover()) - { + if let Some(ty) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }), + |this| this.parse_ty_no_question_mark_recover(), + ) { return Ok(ty); }