From 08ee5f5e63afe3e6a3d852932484c506d0eaee87 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sat, 18 Jan 2025 23:40:27 +0000 Subject: Do not ICE on default_field_value const with lifetimes Fix #135649. --- compiler/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 26af86c0cdd..b25f449079a 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 00000000000..71d90ddd935 --- /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 00000000000..20b9afe80cd --- /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`. -- cgit 1.4.1-3-g733a5 From ee6b5cff4f0e43961be2ad932938200aef7825e4 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 7 Jan 2025 22:57:40 +0100 Subject: Make Pat::Range's start and end Option --- .../rust-analyzer/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 +- src/tools/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 9df6eaade75..5ff6a7ffe56 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 88f770da02a..d2715ac8760 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))) - } - pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { - let subpat = self.collect_pat(pat.clone(), binding_list); - Some(Box::new(LiteralOrConst::Const(subpat))) + 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, } - _ => 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 6a0b1e51979..c28cfb24529 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 0dcddf162b2..a964512beb2 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 0b5f1319243..59aaf85164a 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 2ffea34c85a..d78d15288ad 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) -- cgit 1.4.1-3-g733a5 From 31a56851449d0e8a65991d2e2a0ae637d5779d9c Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 8 Jan 2025 00:26:47 +0100 Subject: Make higher levels adapt Bodys exprs having ExprOrPatId values --- .../rust-analyzer/crates/hir/src/diagnostics.rs | 35 +++++++++++----------- .../rust-analyzer/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 64e982c42d7..9a5e50af079 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 82c90ac3010..a34b4980832 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 56090bc6b60..26b2819913e 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 3c9e7065c41..29d3736bae7 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 ca239826d4f..cf756c67975 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 7126617cdee..0520bb3fe9b 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 4accd181ca4..dfb03eee732 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 4ab649cc162..dd1b593e8f6 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()) -- cgit 1.4.1-3-g733a5 From 8a18dce223a84e32dff217a0ba641576203600be Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 8 Jan 2025 00:48:25 +0100 Subject: 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 d2715ac8760..3f3beb21858 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 9bf1ddb4793..5ce9a67f9b6 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"); + } + } + _ => {} + } + } +} -- cgit 1.4.1-3-g733a5 From d694b2086ce3f60591220ea1ef31b9bdd5738fea Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 22 Jan 2025 19:01:56 +0200 Subject: 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 ++--- .../crates/rust-analyzer/tests/slow-tests/main.rs | 36 +++++++++++++++++++++- .../rust-analyzer/crates/vfs-notify/src/lib.rs | 5 +-- .../docs/book/src/configuration_generated.md | 4 +-- src/tools/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 7656c07c948..daddeae13aa 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 2b3c0a47a22..5ad28d0b909 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 0ae8b7baf46..32003341764 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 49eb7248898..a7f54289b96 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 57f4254b689..5db8ca52a58 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": { -- cgit 1.4.1-3-g733a5 From cee2df27b7a1ae72cecad3d1d4d16911db1e596d Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 23:07:05 +0200 Subject: Refactor `TyLoweringContext::substs_from_args_and_bindings()` to always take a `GenericDefId` --- src/tools/rust-analyzer/crates/hir-ty/src/infer.rs | 3 +- src/tools/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 617ebba8811..cf6905a0b28 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 db13e1fd354..595929a8f41 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)), ); -- cgit 1.4.1-3-g733a5 From 54ad31b5b885bfcec5fd7d470ed03c0718656cac Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 23:07:35 +0200 Subject: 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 86e5afdb509..ab3c039ece3 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(_), -- cgit 1.4.1-3-g733a5 From 66599f1dd5ade8f87cfeca3b2334649820c659d9 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 23:07:48 +0200 Subject: 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 7fe196cdbb5..dac04307b74 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, } -- cgit 1.4.1-3-g733a5 From c7e331bfb8d131d52278785e2fe8338010020eb0 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 4 Feb 2025 17:53:52 +0200 Subject: 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. --- .../rust-analyzer/crates/load-cargo/src/lib.rs | 4 +- .../crates/rust-analyzer/src/config.rs | 6 +- .../crates/rust-analyzer/src/global_state.rs | 25 ++- .../rust-analyzer/src/handlers/notification.rs | 16 +- .../crates/rust-analyzer/src/handlers/request.rs | 170 +++++++++++---------- .../rust-analyzer/src/integrated_benchmarks.rs | 14 +- .../rust-analyzer/crates/rust-analyzer/src/lib.rs | 11 ++ .../crates/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 5654c04a592..67ee9d11199 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 daddeae13aa..758f60dc3e4 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 b52f64aaace..70105cda006 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 48856d19e15..55344a4d6ac 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 ed028f1d37b..a3cb8c9be61 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 5cdc51a1c19..c6aa8ba1707 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 1221f7c7012..27d6225cdb7 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 47e9961cf13..6375a1a054b 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 ebc65373b52..f5d9469f262 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 d18e5770477..e3c003dbf8b 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 a26444e9ea2..3feca512e55 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 { -- cgit 1.4.1-3-g733a5 From 720101002876ad6043735004b9ae20600a989fe8 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 8 Feb 2025 02:38:41 +0900 Subject: fix: Apply adjustments to proper expr when invoking `CoerceMany` --- src/tools/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 617ebba8811..9f20117bf14 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 d40816ba8ce..b490a31f68f 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 f1e86daea23..9625ae5f88e 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 7992f1feeeb..7e7c1f835c7 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 -- cgit 1.4.1-3-g733a5 From 01794a4973c6e9b41af78cebd2f8adf9cdb36f9f Mon Sep 17 00:00:00 2001 From: Julian Eager Date: Sat, 8 Feb 2025 01:39:07 +0800 Subject: simplify panic_context --- .../rust-analyzer/crates/stdx/src/panic_context.rs | 40 ++++++++++------------ 1 file changed, 18 insertions(+), 22 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 4ec74c0742a..a35d50b78df 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs @@ -1,28 +1,25 @@ //! 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 { +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 init() { + fn set_hook() { let default_hook = panic::take_hook(); - #[allow(deprecated)] - let hook = move |panic_info: &panic::PanicInfo<'_>| { + panic::set_hook(Box::new(move |panic_info| { with_ctx(|ctx| { if !ctx.is_empty() { eprintln!("Panic context:"); @@ -30,17 +27,16 @@ impl PanicContext { eprintln!("> {frame}\n"); } } - default_hook(panic_info); }); - }; - panic::set_hook(Box::new(hook)); + default_hook(panic_info); + })); } -} -impl Drop for PanicContext { - fn drop(&mut self) { - with_ctx(|ctx| assert!(ctx.pop().is_some())); - } + 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)) { -- cgit 1.4.1-3-g733a5 From 050c63a054bf29dbfc6161fb1ec12d89a319a87e Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 19 Jan 2025 23:58:49 +0100 Subject: 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 +++++++++++++++++++++- src/tools/rust-analyzer/crates/hir-def/src/hir.rs | 14 ++++ .../rust-analyzer/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 +- src/tools/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 3f3beb21858..e4fcf949d91 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 c28cfb24529..82ad756dc2c 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 5ce9a67f9b6..89364560441 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,7 @@ 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; @@ -470,8 +471,46 @@ mod x { } const fn f(x: i32) -> i32 { match x { - -1..=5 => x * 10, 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; +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, } }"#, @@ -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 a964512beb2..6aca610a938 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 cc6ed122af4..69b3b9c02a0 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 d78d15288ad..289175feefb 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 882a27182f0..90c6e7e7b3b 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 29d3736bae7..227a60bee24 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 bad53608056..c45cb4294f0 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() { -- cgit 1.4.1-3-g733a5 From e402c8cd7e2a0f108f10a9718c28f76afe06d6e6 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 18:53:37 +0100 Subject: 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 89364560441..73eed744715 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 cf756c67975..06fcebad65d 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) = -- cgit 1.4.1-3-g733a5 From 3e9633b4611ec61b81611963dde154508192e8b3 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 19:21:41 +0100 Subject: resolve_bind_pat_to_const does not early return if expr --- .../crates/hir-def/src/expr_store/tests.rs | 112 +++------------------ .../crates/hir/src/source_analyzer.rs | 15 ++- 2 files changed, 28 insertions(+), 99 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 73eed744715..b84043af687 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()]); - } - _ => {} - } -} - -#[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, - } -}"#, - ); + let hir_start = &body.exprs[start.unwrap()]; + let hir_end = &body.exprs[end.unwrap()]; - 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"); - } - } - _ => {} + assert!(matches!(hir_start, Expr::Path { .. })); + assert!(matches!(hir_end, Expr::Path { .. })); } - } -} - -#[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 06fcebad65d..8a1e4fba6b7 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), -- cgit 1.4.1-3-g733a5 From 0d544cf622f8bfcfc7c324a4ff5709e27604726b Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 19:30:41 +0100 Subject: 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 90c6e7e7b3b..882a27182f0 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 c45cb4294f0..bad53608056 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() { -- cgit 1.4.1-3-g733a5 From fcc796829e0cbd189af0e29f283fb433a148ad11 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 21:14:16 +0100 Subject: 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 e4fcf949d91..2be7b9963bb 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 b84043af687..16bf46d3e3f 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#" -- cgit 1.4.1-3-g733a5 From bf2f2c4d71915a9b98d64e75c31264665a0399a7 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 23:22:39 +0100 Subject: Fix clippy errors --- src/tools/rust-analyzer/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 +++--- .../rust-analyzer/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 2be7b9963bb..95dd1e53ae7 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 6aca610a938..494644d8eff 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 69b3b9c02a0..f3f564459de 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 227a60bee24..29d3736bae7 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())?; -- cgit 1.4.1-3-g733a5 From bc5f61c76914aa192c04e8c5ecfff07dd37adf11 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 3 Feb 2025 12:07:52 +0100 Subject: Check if PatPtr resolves to ExprId --- .../crates/hir-def/src/expr_store/lower.rs | 22 ++++------- .../rust-analyzer/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 95dd1e53ae7..6e505a6b112 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 9a5e50af079..5876529df96 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 26b2819913e..8b8203acb14 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 8a1e4fba6b7..9e7f2c19480 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)); } -- cgit 1.4.1-3-g733a5 From 9bd9bcf4964ee3eeed2bbb99567619c8fb3d70d6 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Feb 2025 14:12:00 -0500 Subject: fix off-by-one error --- src/tools/rust-analyzer/.github/workflows/ci.yaml | 6 +- .../crates/rust-analyzer/src/handlers/request.rs | 3 +- .../crates/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 ec33009239c..81b55712d7f 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 ed028f1d37b..37e4a4940ba 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 2b3c0a47a22..7f95641746e 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() { -- cgit 1.4.1-3-g733a5 From d2459e5c1ef0c24582f8b84ae150204d9ab2d1f8 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Feb 2025 14:12:21 -0500 Subject: fix target dir test --- src/tools/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 e915e55722b..2e9bb8c08e2 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 36be9937d3f..e7279fa1f66 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"); -- cgit 1.4.1-3-g733a5 From b5ad702c621ca92a2a24088b6fb2e7fcf30638e9 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 10 Feb 2025 01:28:28 +0200 Subject: 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 +++++++++++++--------- .../rust-analyzer/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 70e3e1ed4e9..a43c0eb9d70 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 01a3103af82..626a82ae08e 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)?; - } - 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 + _ => {} } - // 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 ca596583590..613f27c7958 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()) + } +} -- cgit 1.4.1-3-g733a5 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: 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 23e7518883b..c687e2d8a0c 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 bdafb701ff5..60a904233a9 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(); +} +"#, + ); + } } -- cgit 1.4.1-3-g733a5 From 8f8e1c6f08ec25ea42b74c44b0a5c93fffb84610 Mon Sep 17 00:00:00 2001 From: austaras Date: Sun, 9 Feb 2025 20:40:41 +0800 Subject: pass struct fields to chalk --- .../rust-analyzer/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 c8ff6cba3dd..6d4753ea389 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 7992f1feeeb..a5978d905b1 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 dda7bfb2baf..f0eb41b1ce7 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; -- cgit 1.4.1-3-g733a5 From e1c6eade1619e2b84b39d61811407afc1f82fd12 Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 9 Feb 2025 04:11:23 -0800 Subject: move pattern migration setup/emitting to a separate module --- compiler/rustc_mir_build/src/errors.rs | 3 - .../rustc_mir_build/src/thir/pattern/migration.rs | 87 ++++++++++++++++++++++ compiler/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 07bdc59756a..9f8b52165ab 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 00000000000..be1ebd57d11 --- /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 83fef7b0de6..5535ac9bd63 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 { -- cgit 1.4.1-3-g733a5 From f1c287f45bace992857b0a9c850da6f1a849a6f7 Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 9 Feb 2025 07:11:08 -0800 Subject: move pattern migration internals to the `migration` module --- .../rustc_mir_build/src/thir/pattern/migration.rs | 113 +++++++++++++++++++-- compiler/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 be1ebd57d11..bd7787b643d 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 5535ac9bd63..5734eb1a0d8 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 -- cgit 1.4.1-3-g733a5 From 724b85ef11213e128985a22c073c7373d80fd792 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 10 Feb 2025 15:47:31 +0200 Subject: 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 2c39a8fdfed..28e2853096e 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 })); +} + "#, + ); + } } -- cgit 1.4.1-3-g733a5 From 0dd7aad8c323630a728b7595914f1c09fbac142d Mon Sep 17 00:00:00 2001 From: Josh Rotenberg Date: Mon, 10 Feb 2025 15:14:00 -0800 Subject: 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 a9d10df6643..043524b2341 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`. -- cgit 1.4.1-3-g733a5 From 7c68345e1b4ab3ca838bb8e8548253b029824da8 Mon Sep 17 00:00:00 2001 From: Josh Rotenberg Date: Mon, 10 Feb 2025 15:20:51 -0800 Subject: 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 ba3c1dede5d..a6f6a6ed784 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 -- cgit 1.4.1-3-g733a5 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: 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] --- .../rust-analyzer/editors/code/package-lock.json | 307 +++++++++++++-------- src/tools/rust-analyzer/editors/code/package.json | 2 +- 2 files changed, 193 insertions(+), 116 deletions(-) diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index 6027f813311..86a066454a5 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/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.18.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.12.tgz", - "integrity": "sha512-LIxaNIQfkFZbTLb4+cX7dozHlAbAshhFE5PKdro0l+FnCpx1GDJaQ2WMcqm+ToXKMt8p8Uojk/MFRuGyz3V5Sw==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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.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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "node": ">=18" } }, "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==", + "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": ">=12" + "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-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "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==", + "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": ">=12" + "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": ">=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==", + "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": ">=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==", + "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 0a603767705..ef69e754f2b 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", -- cgit 1.4.1-3-g733a5 From 11c49a659570d4f9a5a05497fcf8808d7881ecbd Mon Sep 17 00:00:00 2001 From: asuto15 Date: Tue, 11 Feb 2025 15:06:56 +0900 Subject: Fix highlighting for extern crate in doc comments --- .../rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs | 1 + .../ide/src/syntax_highlighting/test_data/highlight_doctest.html | 3 +++ src/tools/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 479c0b381a4..c6e11b9cbdf 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 5ff96ae2a74..2f7bc65d14b 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 b9520ae2bba..ad3d4763911 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; /// ``` -- cgit 1.4.1-3-g733a5 From 6e6bdc311add561e3f71a3d49c781e0cac49eb26 Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Tue, 11 Feb 2025 15:24:46 +0800 Subject: don't emit implicit drop inlay hints for macro --- src/tools/rust-analyzer/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 27c7c3d4981..8c91958d8c9 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(), -- cgit 1.4.1-3-g733a5 From 4036a7a77d04e48b0237baac07c7e4d9fc7dd6de Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Tue, 11 Feb 2025 15:27:34 +0800 Subject: add test case for ignoring inlay hint for macro call --- .../crates/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 8c91958d8c9..58dc0fdf62c 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!() + } "#, ); } -- cgit 1.4.1-3-g733a5 From d695e33c8304241a7feb6a81707e4ee7bc371e09 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 11 Feb 2025 12:10:32 -0800 Subject: 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 18f49643dc7..e84c259e979 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) } } -- cgit 1.4.1-3-g733a5 From 16abb39c9dd7e346ffecd5bf03c315bf374ece5f Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 11 Feb 2025 17:48:36 +0100 Subject: 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 83b009c86dc..7c8279f2555 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 -- cgit 1.4.1-3-g733a5 From bc59397f8f320eefc5c2c60d1ad9fa816bbee2e4 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 11 Feb 2025 17:51:30 +0100 Subject: 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 7c8279f2555..0707115cbdd 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 -- cgit 1.4.1-3-g733a5 From 3a7a47b3b676defd22ef3789eefff99ebddc2934 Mon Sep 17 00:00:00 2001 From: Josh Rotenberg Date: Tue, 11 Feb 2025 13:52:01 -0800 Subject: 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 a6f6a6ed784..5ca4badde87 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 -- cgit 1.4.1-3-g733a5 From 3a041fcc2cc514ef87f29d8aa8300a0f6a2fa0da Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 09:24:33 +0100 Subject: Propogate error types in mir type projections --- src/tools/rust-analyzer/crates/hir-ty/src/mir.rs | 11 +++++++++-- .../crates/ide-diagnostics/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 84d8950b1aa..41304bbd8a9 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 67ece566941..d5caf4de336 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 +} "#, ); } -- cgit 1.4.1-3-g733a5 From c12a2e750d3dab2897f7b1c7471f10487d1f0285 Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Wed, 12 Feb 2025 17:18:42 +0800 Subject: 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 58dc0fdf62c..390139d214e 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, }; -- cgit 1.4.1-3-g733a5 From a09ece29254cd06a1ee9529622e47c9a72645cb1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 7 Feb 2025 14:56:36 +0100 Subject: fix: Do not show safety hints for extern items lacking semantics --- .../rust-analyzer/crates/hir-def/src/dyn_map.rs | 7 ++-- .../rust-analyzer/crates/hir-def/src/item_scope.rs | 18 ++++++++-- .../crates/hir-def/src/nameres/collector.rs | 24 +++++++------ src/tools/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 + .../crates/hir/src/semantics/child_by_source.rs | 3 ++ .../crates/hir/src/semantics/source_to_def.rs | 14 +++++--- src/tools/rust-analyzer/crates/ide-db/src/defs.rs | 2 +- .../crates/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 0f73595347b..e9318d146dd 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 65a39c56561..0ca1eb9bcfe 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 06276335b71..254c1379917 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 537401afdc3..72df07ef8c0 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 56090bc6b60..3c17ddb7b7d 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 882a27182f0..c9145f7d212 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 d5dfb985718..d0fdf5cbdf7 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 3c9e7065c41..4e61f5b5a35 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 bad53608056..6f71c3d9bd7 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 2bc91b68ed8..652dff0bc56 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(()) } -- cgit 1.4.1-3-g733a5 From 0d8015cb23a99a014e7bc82c19cd81e8ffa536a3 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 13 Jan 2025 04:31:15 +0800 Subject: fix: handle character boundary in search mode --- .../rust-analyzer/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 6137bd34d64..d43776b8a66 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 00000000000..3617badeef5 --- /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 00000000000..d34c459ad02 --- /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 00000000000..2c5829b1f54 --- /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 -- cgit 1.4.1-3-g733a5 From f26f1dda44552500b9653d4ec81862275cbc0ccd Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 08:30:30 +0100 Subject: 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 | 294 ++++++++++++++------- .../crates/rust-analyzer/src/cli/rustc_tests.rs | 6 +- .../crates/rust-analyzer/src/reload.rs | 1 + .../crates/rust-analyzer/tests/slow-tests/main.rs | 6 +- 6 files changed, 228 insertions(+), 112 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 8f633d24be9..4659d5288b1 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 28560865436..6d9e68f0043 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 dcd62753cb2..e21c373b75f 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(); + + // 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 = 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, + 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 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 toolchain = version::get(query_config, &config.extra_env).ok().flatten(); + 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 199f61e70f0..59dec9a9f36 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 e3c003dbf8b..ba72ea35df6 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 e764bd47703..a33b9e46fed 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(); -- cgit 1.4.1-3-g733a5 From d9256abe72cb6a0e08c34edad64f24cb1bfb89e2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 15:15:47 +0100 Subject: Improve error recovery when method-calling a field --- .../rust-analyzer/crates/hir-ty/src/infer/expr.rs | 204 +++++++++++++-------- src/tools/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 86e5afdb509..41d739a078e 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 69ec35f406d..f5a4d4ff35c 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 def06f2d59d..d0d31bf2a5a 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} +} +"#, + ); +} -- cgit 1.4.1-3-g733a5 From 875f3e2c883fd71eb5210f34790e705b45097442 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 12 Feb 2025 16:32:11 +0100 Subject: Rename sysroot src/lib related things --- .../rust-analyzer/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 ++--- .../crates/rust-analyzer/src/cli/rustc_tests.rs | 6 +- .../crates/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 fc1fd7b877f..0c734474682 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 4659d5288b1..510c18dd147 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 6d9e68f0043..25e4368d95a 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 e21c373b75f..4f8449cb68c 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 59dec9a9f36..b9b7ad1faf8 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 a33b9e46fed..6f26bdc2cf0 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); } -- cgit 1.4.1-3-g733a5 From 7ef1fcf972be411f4e4f6855b963904b90c6eb5e Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 11 Feb 2025 15:16:54 -0800 Subject: manual: Separate out installation and configuration pages Organise the installation content into: * VS Code instructions * Binary installation * Editor configuration --- src/tools/rust-analyzer/docs/book/src/SUMMARY.md | 3 + .../rust-analyzer/docs/book/src/installation.md | 632 +-------------------- .../rust-analyzer/docs/book/src/other_editors.md | 423 ++++++++++++++ .../docs/book/src/rust_analyzer_binary.md | 74 +++ src/tools/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 b3ed1e6df0a..9dc4f1f2d2a 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 5b697e9bc33..3a4c0cf2277 100644 --- a/src/tools/rust-analyzer/docs/book/src/installation.md +++ b/src/tools/rust-analyzer/docs/book/src/installation.md @@ -1,19 +1,19 @@ # 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 - $ rustup component add rust-src +rust-analyzer will attempt to install the standard library source code +automatically. You can also install it manually with `rustup`. -## Toolchain + $ rustup component add rust-src Only the latest stable standard library source is officially supported for use with rust-analyzer. If you are using an older toolchain or have @@ -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 00000000000..0a9a453e013 --- /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 00000000000..c7ac3087ced --- /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 00000000000..233b862d2c6 --- /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. + -- cgit 1.4.1-3-g733a5 From d72b2df1526b9a2c168ffc851cc805db3f4fd8df Mon Sep 17 00:00:00 2001 From: asuto15 Date: Thu, 13 Feb 2025 03:58:20 +0900 Subject: Add modifiers to highlighting for extern crate --- .../crates/ide/src/syntax_highlighting/highlight.rs | 19 ++++++++++++++++++- .../test_data/highlight_doctest.html | 8 +++++++- .../crates/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 c6e11b9cbdf..d580b3001c3 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 2f7bc65d14b..9a55f7d01b9 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 ad3d4763911..364d0909243 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; -- cgit 1.4.1-3-g733a5 From 21b0c22054d0a3e58d496b6b5fb920ca9468efed Mon Sep 17 00:00:00 2001 From: asuto15 Date: Thu, 13 Feb 2025 04:33:08 +0900 Subject: Delete useless comma --- src/tools/rust-analyzer/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 d580b3001c3..8abaccd2536 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()), -- cgit 1.4.1-3-g733a5 From b3ef716d165c70f4f2cfb239813d8fdd5a1193f0 Mon Sep 17 00:00:00 2001 From: David Richey Date: Wed, 12 Feb 2025 13:16:38 -0600 Subject: Apply cfg.setTest to json projects --- .../crates/project-model/src/tests.rs | 5 +- .../crates/project-model/src/workspace.rs | 84 +++++++++++----------- .../test_data/output/rust_project_cfg_groups.txt | 2 + .../rust_project_hello_world_project_model.txt | 1 + .../crates/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 25e4368d95a..54eb0e3478a 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 4f8449cb68c..f5d46daa80f 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 2026ab2b8c2..587d3c17827 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 a0e14b8fcb2..00805c79bcc 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 b9b7ad1faf8..e9ca12deaf6 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, -- cgit 1.4.1-3-g733a5 From 7c61ec72e7b8ae411135d20fc25baf0fdcb62d52 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Fri, 14 Feb 2025 02:36:05 +0900 Subject: 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 -------- .../rust-analyzer/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 5899ec5a005..a9a2875a60c 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 first_new_arm = added_arms.first().cloned(); - let last_new_arm = added_arms.last().cloned(); - - for arm in added_arms { - new_match_arm_list.add_arm(arm); + let arm = make.match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo()); + arms.push(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); - } - } + let new_match_arm_list = make.match_arm_list(arms); - // 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 291fc646e21..aedf810b794 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 ff027ac5848..9dc2d832530 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") -- cgit 1.4.1-3-g733a5 From bad69a3d044f651e1fa652558ef47f247f885bc3 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 13 Feb 2025 18:45:31 -0800 Subject: 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 fda4ac80023..aabe0dd662b 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, }, ``` -- cgit 1.4.1-3-g733a5 From bf3e787891e93cf7c596ec590a362985bd6057a4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 20 Jan 2025 11:07:09 +0100 Subject: Update to LLVM 20 --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f9bd42edab3..97a0c0c54cf 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 7e8c93c87c6..92e80685d0d 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 7e8c93c87c611f21d9bd95100563392f4c18bfe7 +Subproject commit 92e80685d0d5dcea3ccf321995c43b72338639c6 -- cgit 1.4.1-3-g733a5 From 97f6e4d34b7e103150c35d390e33d17041363af3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Feb 2025 14:50:40 +0100 Subject: 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. --- compiler/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 a6b2384f2d7..7eb11f9e608 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'); -- cgit 1.4.1-3-g733a5 From 36c314cfb7999a66a49932822a336aea47f62292 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 14 Feb 2025 11:16:32 +0100 Subject: 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 167b8a5b168..84c94a268a3 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 7a014989e68..677ac76439e 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(), }; -- cgit 1.4.1-3-g733a5 From 08b4f6d2c650d3e6e9010e8a27631962bf31dec7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 14 Feb 2025 11:16:47 +0100 Subject: generate-copyright: pass the list of manifests from bootstrap --- src/bootstrap/src/core/build_steps/run.rs | 15 ++++++++++ src/tools/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 84c94a268a3..3f5e701e7e1 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 51e353e9b22..16c5b5e7104 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 677ac76439e..7b7cf0f4b69 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) { -- cgit 1.4.1-3-g733a5 From 66a45401556b3dbce317c681f3824aabb8a312bb Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 14 Feb 2025 15:31:34 +0300 Subject: 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 96a290ad5a0..296b5ebdfaf 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 21bad6705ab..b59451d7c75 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 29f6791ee6a..74d3ae699f6 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)] -- cgit 1.4.1-3-g733a5 From 84485a8568f864befdf0eacb7eb275068403dd40 Mon Sep 17 00:00:00 2001 From: asuto15 Date: Sat, 15 Feb 2025 12:06:21 +0900 Subject: Delete library modifier to highlighting for extern crate --- .../crates/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 8abaccd2536..92211e9e3a9 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 9a55f7d01b9..eb77c14c2a5 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; -- cgit 1.4.1-3-g733a5 From eaf22bcdce02cca4d71fb6619f89fe048026a8bd Mon Sep 17 00:00:00 2001 From: asuto15 Date: Sat, 15 Feb 2025 13:18:18 +0900 Subject: fix: remove unnecessary conversion --- src/tools/rust-analyzer/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 92211e9e3a9..194fde11601 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()), -- cgit 1.4.1-3-g733a5 From d22554a996a11bb1559ebf9e5bbd7db8f048fcad Mon Sep 17 00:00:00 2001 From: xizheyin Date: Sat, 15 Feb 2025 12:18:30 +0800 Subject: fix: Alloc new errorcode E0803 for E0495 Signed-off-by: xizheyin --- .../rustc_error_codes/src/error_codes/E0803.md | 46 ++++++++++++++++++++++ compiler/rustc_error_codes/src/lib.rs | 1 + .../src/error_reporting/infer/region.rs | 4 +- ...mplied-bounds-compatibility-unnormalized.stderr | 4 +- tests/ui/issues/issue-20831-debruijn.stderr | 4 +- tests/ui/nll/normalization-bounds-error.stderr | 4 +- .../regions-normalize-in-where-clause-list.stderr | 4 +- tests/ui/regions/resolve-re-error-ice.stderr | 4 +- tests/ui/static/static-lifetime.stderr | 4 +- ...supertrait-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 00000000000..4c022688a2d --- /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 e970b16f610..098ca42be2b 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 f35a5349ecb..5f54087eba2 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 f498257e12f..f8ee6fef824 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 fe310998f09..bed75ed6ba2 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 2e76333e26f..ca9ceeeeff3 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 41c5f0fa92e..f463a97c5bc 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 7a956dbfeef..9b5869fd0dc 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 8bf8536c74e..4e324209fe9 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 04288112fa8..ae00d3fc667 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`. -- cgit 1.4.1-3-g733a5 From ea10f8efa1d9515a2ced80a05245c5bd19e55040 Mon Sep 17 00:00:00 2001 From: Niklas Korz Date: Sat, 15 Feb 2025 12:04:48 +0100 Subject: 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 dedcc139ae1..1f0787b9c63 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, -- cgit 1.4.1-3-g733a5 From 6e7838d81d99688575a1cfaa49b40fb6cae7b377 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 15 Feb 2025 13:23:32 +0100 Subject: Factor out business logic of expand_glob_import --- .../ide-assists/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 094fdc46eb7..ea82bdc9026 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( -- cgit 1.4.1-3-g733a5 From 12530066a26262621616db9d53ed5d3b3872b606 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 15 Feb 2025 16:07:33 +0100 Subject: Implement expand_glob_reexport assist --- .../ide-assists/src/handlers/expand_glob_import.rs | 226 +++++++++++++++++++-- .../rust-analyzer/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 ea82bdc9026..0b95d6177f9 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 5c95b25f28d..179742f91b4 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, -- cgit 1.4.1-3-g733a5 From 4c7b6099ca4eaad4f83280570673e79f70429ed4 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Fri, 14 Feb 2025 02:38:11 +0900 Subject: Temporarily ignore tests with comments --- .../crates/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 a9a2875a60c..4a9e2256e9b 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( -- cgit 1.4.1-3-g733a5 From 824b18248c72a8d9fa0fd8ad57b1292cc079fb9f Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Sat, 15 Feb 2025 16:26:28 +0100 Subject: 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 4b0fa704a22..0662527a387 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( -- cgit 1.4.1-3-g733a5 From 1d7cf0ff407beea447334c2784d39658e4be3ca0 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 15 Feb 2025 13:57:21 -0500 Subject: 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 b8773f9ff38..9e33824afe2 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 da1c706d67c..d3847e5f272 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 8f4639fc2e6..b25758048bd 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 e5a4e38c875..2e90e5251e2 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 52cb8f57a88..cb5b5948e6f 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 ee271048fc1..6a67009fe90 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 { -- cgit 1.4.1-3-g733a5 From 84bdc5de6e4f9dc3434b806a74d89b5b676f4a67 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Sat, 15 Feb 2025 22:05:54 +0100 Subject: HIR analysis: Remove unnecessary abstraction over list of clauses --- compiler/rustc_hir_analysis/src/bounds.rs | 100 ----------------- .../rustc_hir_analysis/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 ++- .../rustc_hir_analysis/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 9b02651a8bd..00000000000 --- 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 41c4cfbaa82..1c1a246cc15 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 d94383d6f3d..70e7451a5fb 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 ef6167907b5..75c97001c32 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 a8b37fa5054..830dca0d3cd 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 88323db6dda..288e88f4aeb 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. - } - 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, - ); + // 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::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 8a529e9c686..886360dfb6c 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 fd84d75b53f..56a38a84c9f 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, -- cgit 1.4.1-3-g733a5 From ca288273b43d4218f00c15e31e78f89949d8cbba Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 8 Feb 2025 21:59:35 +0000 Subject: 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 b289f6026ff..9eb71922218 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 782303d5f3f..80dd2f39b42 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. -- cgit 1.4.1-3-g733a5 From 0f220efb1a9c1bab199baadcb01ce2129bce0037 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 15 Feb 2025 19:09:38 -0600 Subject: 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 dbfd2e74abe..17dad3277b9 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 {} -- cgit 1.4.1-3-g733a5 From af804d23e204ffaec33aa7dfcd17cc31f082a559 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 10:51:58 +0100 Subject: Set `RUSTUP_TOOLCHAIN` when loading sysroot workspace --- src/tools/rust-analyzer/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 e4a61134620..b5f4e43a115 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 510c18dd147..544ba43ba66 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, &|_| (), -- cgit 1.4.1-3-g733a5 From 95a5ecc995f031478708c6c654a196197e71ba20 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 16 Feb 2025 10:28:08 +0000 Subject: Enable relative-path-include-bytes on Windows --- .../doctest/relative-path-include-bytes-132203.edition2015.stdout | 2 +- tests/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 ca6e7750264..13e142df837 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 6fddaa49fac..ceacd69a5fd 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 -- cgit 1.4.1-3-g733a5 From b621a485faf006c830996049ed6d601e0f562065 Mon Sep 17 00:00:00 2001 From: "许杰友 Jieyou Xu (Joe)" <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 15 Feb 2025 20:25:30 +0800 Subject: 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 479327d6369..bae18a96d90 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 ae3761a97e5..96d0cf48fbf 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 18da0e8252b..9f62879c36d 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 1291a634a6f..a54db9d7815 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 ecec589fc32..6d77e38b129 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 62625fc3660..d27a8b155df 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 7cd8aacf0d6..34df3ca2320 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. -- cgit 1.4.1-3-g733a5 From 7b118168c7902ae8ec266996a724cfec1c88ea1c Mon Sep 17 00:00:00 2001 From: "许杰友 Jieyou Xu (Joe)" <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 15 Feb 2025 22:58:46 +0800 Subject: 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 bae18a96d90..755ff4cd0f0 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 96d0cf48fbf..509ee9e1acf 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 9f62879c36d..3025f955660 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 26ed0e5deaa..b3f4a7bad99 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 5e3e0ef654f..445b5dfbeab 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 9e4a0816e0d..241b7386d18 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 34df3ca2320..62ddc7d682e 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 } } -- cgit 1.4.1-3-g733a5 From 05ba1a450adb266cdaa7001f73a2e5899405b3b4 Mon Sep 17 00:00:00 2001 From: "许杰友 Jieyou Xu (Joe)" <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 15 Feb 2025 22:59:01 +0800 Subject: 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 04fa5b204dd..04d8e91dcb4 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: -- cgit 1.4.1-3-g733a5 From 930918d827f2598098ec8c6bf9aaa5a1e061fb3b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 10:51:58 +0100 Subject: Improve error recovery when method-calling an assoc function --- src/tools/rust-analyzer/crates/hir-ty/src/infer.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/infer/expr.rs | 91 +++++++++++++--------- .../crates/hir-ty/src/tests/diagnostics.rs | 33 +++++++- .../crates/hir-ty/src/tests/method_resolution.rs | 2 +- .../rust-analyzer/crates/hir/src/diagnostics.rs | 8 +- .../src/handlers/unresolved_method.rs | 47 +++++------ 6 files changed, 112 insertions(+), 71 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 9f20117bf14..a8cd971b057 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 41d739a078e..bff88143475 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 d0d31bf2a5a..855034117c0 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 e5f791ea6ff..3a258ecad10 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 5876529df96..307673f52c7 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 dd1b593e8f6..e4de107249b 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. - - // 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, + 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) }; let mut receiver_type_adt_name = -- cgit 1.4.1-3-g733a5 From 345c313def0a559e7a29bc059c2e242ed398a760 Mon Sep 17 00:00:00 2001 From: may Date: Sun, 16 Feb 2025 12:02:06 +0100 Subject: 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 05c16791ce7..062f7dcc940 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) }; -- cgit 1.4.1-3-g733a5 From 2a8fbb5f5678e3fa61e06430da957662030ad404 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 16 Feb 2025 12:15:55 +0100 Subject: 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 f0def1a0e42..038d7ca639f 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) -- cgit 1.4.1-3-g733a5 From b54269c2b1c858a489ea588b3679bd21f0d06bbb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 12:20:41 +0100 Subject: fix: Stabilize sort order of runnables --- .../rust-analyzer/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 006e6e8246e..a0add4741f3 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 78c9f2309a0..16dd039eabb 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 { -- cgit 1.4.1-3-g733a5 From c5f49cf07194185a02a5dd353d3125775fe5ed82 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 16 Feb 2025 13:11:50 +0100 Subject: fix: Stabilize sort order of `related_tests` --- .../rust-analyzer/crates/ide/src/runnables.rs | 59 ++++++++++++---------- .../crates/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 16dd039eabb..9e3b70fa8ea 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 b9520ae2bba..30b8fa74f81 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( -- cgit 1.4.1-3-g733a5 From f53d0f502dba3b378d8baef159b97e685ba40f33 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 16 Feb 2025 00:40:25 +0300 Subject: 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 480d97e377a..dbe24c9cdf2 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 0081374922e..11eb079ddc0 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 62723e385cf..4c2f7ad6d3c 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 05c16791ce7..fd2cd59f88e 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 2d1822a54ac..8f8000fe34d 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 07616e11801..715ecf56f21 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 -- cgit 1.4.1-3-g733a5 From 77571a5c8bd1a8958865de75b8ec8b1bc2b4b756 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 16 Feb 2025 01:18:29 +0300 Subject: 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 6164a6191db..4a5f143a2d3 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 -- cgit 1.4.1-3-g733a5 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: 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 ea464fc8ebb..1de452dcf39 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 62723e385cf..757450cc068 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 00000000000..93015ee6c49 --- /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); -- cgit 1.4.1-3-g733a5 From 4a4207a65073dcf1148c298d76e2fda11974284c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Feb 2025 17:56:22 +0100 Subject: 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 +-- tests/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 +- tests/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 +++++++++++----------- .../ui/simd-abi-checks-s390x.z13_no_vector.stderr | 62 +++++++++++----------- .../ui/simd-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 439385b14b0..8e4e0850325 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 1c5f9eeba3c..0aa8b6b8f89 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 dd361898144..825a5c1b09c 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 835cc7393e5..46cfb2972df 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 60d49f93081..c33b41a7bbe 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 b057147ab13..75dabd74a79 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 d9742612bcf..c8f7d0a517c 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 0e98b5f806b..1015f7d8898 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 6b299ffadb7..c1dac41f876 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 0e98b5f806b..1015f7d8898 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 0e98b5f806b..1015f7d8898 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 d9742612bcf..c8f7d0a517c 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 0e98b5f806b..1015f7d8898 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 fd4957b5b93..ca0889364fc 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 91c61884fd0..111dda42f33 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 7e408f66561..424ac00edcf 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 ab97299e84a..d2f7abb7c32 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 ab97299e84a..d2f7abb7c32 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 ab97299e84a..d2f7abb7c32 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 3c9fe1f0ddb..cb3128a890f 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 712322a5848..9944aa093b4 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 -- cgit 1.4.1-3-g733a5 From 2e7158b4587a42043c88ab653b305c378b602b76 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 10 Feb 2025 11:33:02 +0200 Subject: 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. --- src/tools/rust-analyzer/crates/hir-def/src/data.rs | 4 + src/tools/rust-analyzer/crates/hir-def/src/path.rs | 10 +- .../rust-analyzer/crates/hir-def/src/resolver.rs | 3 +- .../rust-analyzer/crates/hir-expand/src/name.rs | 4 +- src/tools/rust-analyzer/crates/hir-ty/src/infer.rs | 52 +- .../crates/hir-ty/src/infer/diagnostics.rs | 76 +- .../rust-analyzer/crates/hir-ty/src/infer/pat.rs | 14 +- .../rust-analyzer/crates/hir-ty/src/infer/path.rs | 150 ++-- src/tools/rust-analyzer/crates/hir-ty/src/lower.rs | 975 ++------------------- .../crates/hir-ty/src/lower/diagnostics.rs | 1 + .../rust-analyzer/crates/hir-ty/src/lower/path.rs | 911 +++++++++++++++++++ .../rust-analyzer/crates/hir/src/diagnostics.rs | 16 +- .../parenthesized_generic_args_without_fn_trait.rs | 59 ++ .../crates/ide-diagnostics/src/lib.rs | 8 +- .../test_data/highlight_general.html | 15 +- .../crates/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 c5bbd4edba9..bec66278772 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 e59c37104dd..e6c2504d07a 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 7e13ae2f7a1..9dfb6e3cc4b 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 21e5fb5ef9e..0758bd4515e 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 cf6905a0b28..3ac2d90468f 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 b85378531ad..8c0446953a6 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, - 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, + #[inline] + pub(super) fn at_path<'b>( + &'b mut self, + path: &'b Path, 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 5ff22bea34d..d0fe00ecebd 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 36ec60a7a2f..3794912ee98 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 595929a8f41..af73b5ed9a7 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) - } - } - } - - 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, - }, - ); - } + #[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)) + }, } - - 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 dac04307b74..5c77bcd0736 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 00000000000..22c5bb9923f --- /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 64e982c42d7..f6c0bdc6a62 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 00000000000..ccf51723418 --- /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 50c91a69602..3ea41aa7e85 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 9be7c92fc79..9477d0d1b87 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 b9520ae2bba..75dc5235625 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 a53da69d901..1958e3f7b1d 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 4ed68d18e80..202afebde70 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;
-- 
cgit 1.4.1-3-g733a5


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: 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 dd38f86bced..394e6f9e6bf 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
-- 
cgit 1.4.1-3-g733a5


From 4cf21866e8f18449ea0c41ee1ba031c05419d94c Mon Sep 17 00:00:00 2001
From: Ben Kimock 
Date: Sat, 15 Feb 2025 15:18:19 -0500
Subject: 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 +
 .../rustc_codegen_ssa/src/debuginfo/type_names.rs  |   3 +-
 compiler/rustc_data_structures/Cargo.toml          |   1 +
 compiler/rustc_data_structures/src/fingerprint.rs  |   5 +-
 compiler/rustc_data_structures/src/hashes.rs       | 152 ---------------------
 compiler/rustc_data_structures/src/lib.rs          |   1 -
 .../rustc_data_structures/src/stable_hasher.rs     |   3 +-
 .../rustc_data_structures/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 ++
 compiler/rustc_hashes/src/lib.rs                   | 131 ++++++++++++++++++
 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 +
 .../rust-analyzer/crates/hir-def/src/data/adt.rs   |   3 +-
 src/tools/rust-analyzer/crates/hir-def/src/lib.rs  |   6 +
 .../rust-analyzer/crates/hir-ty/src/layout.rs      |   9 +-
 src/tools/rust-analyzer/crates/hir-ty/src/lib.rs   |   6 +
 tests/run-make/rustc-crates-on-stable/rmake.rs     |   2 +
 .../ui-fulldeps/missing-rustc-driver-error.stderr  |   8 ++
 51 files changed, 272 insertions(+), 187 deletions(-)
 delete mode 100644 compiler/rustc_data_structures/src/hashes.rs
 create mode 100644 compiler/rustc_hashes/Cargo.toml
 create mode 100644 compiler/rustc_hashes/src/lib.rs

diff --git a/Cargo.lock b/Cargo.lock
index d31ef9c4b17..10492c0a4f3 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 1013f1d3958..3d6f4a6a109 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 9e33824afe2..45cd0b517f6 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 d3847e5f272..dbb4bed5cdd 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 94f21ac5f57..a8172270548 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 78b3a7f8541..f17d98fa242 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 2afc1efc1b3..963d9258be6 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 53953b089c6..84703a0a156 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 a8f83ca13e2..1705af1e210 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 16c66824c5b..c7c0d0ab072 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/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs
deleted file mode 100644
index b25758048bd..00000000000
--- a/compiler/rustc_data_structures/src/hashes.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-//! 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.
-//!
-//! 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
-//! hash value as an integer type and accidentally apply varint encoding to it.
-//!
-//! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct
-//! and decompose these types into constituent pieces. The point of these types is only to
-//! connect the fact that they can only be produced by a `StableHasher` to their
-//! `Encode`/`Decode` impls.
-
-use std::fmt;
-use std::ops::BitXorAssign;
-
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
-use crate::stable_hasher::{FromStableHash, StableHasherHash};
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
-pub struct Hash64 {
-    inner: u64,
-}
-
-impl Hash64 {
-    pub const ZERO: Hash64 = Hash64 { inner: 0 };
-
-    #[inline]
-    pub fn new(n: u64) -> Self {
-        Self { inner: n }
-    }
-
-    #[inline]
-    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 {
-    #[inline]
-    fn bitxor_assign(&mut self, rhs: u64) {
-        self.inner ^= rhs;
-    }
-}
-
-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;
-
-    #[inline]
-    fn from(StableHasherHash([_0, __1]): Self::Hash) -> Self {
-        Self { inner: _0 }
-    }
-}
-
-impl fmt::Debug for Hash64 {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.inner.fmt(f)
-    }
-}
-
-impl fmt::LowerHex for Hash64 {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::LowerHex::fmt(&self.inner, f)
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
-pub struct Hash128 {
-    inner: u128,
-}
-
-// We expect Hash128 to be well mixed. So there's no point in hashing both parts.
-//
-// This also allows using Hash128-containing types in UnHash-based hashmaps, which would otherwise
-// debug_assert! that we're hashing more than a single u64.
-impl std::hash::Hash for Hash128 {
-    fn hash(&self, h: &mut H) {
-        h.write_u64(self.truncate().as_u64());
-    }
-}
-
-impl Hash128 {
-    #[inline]
-    pub fn truncate(self) -> Hash64 {
-        Hash64 { inner: self.inner as u64 }
-    }
-
-    #[inline]
-    pub fn wrapping_add(self, other: Self) -> Self {
-        Self { inner: self.inner.wrapping_add(other.inner) }
-    }
-
-    #[inline]
-    pub fn as_u128(self) -> u128 {
-        self.inner
-    }
-}
-
-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;
-
-    #[inline]
-    fn from(StableHasherHash([_0, _1]): Self::Hash) -> Self {
-        Self { inner: u128::from(_0) | (u128::from(_1) << 64) }
-    }
-}
-
-impl fmt::Debug for Hash128 {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.inner.fmt(f)
-    }
-}
-
-impl fmt::LowerHex for Hash128 {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::LowerHex::fmt(&self.inner, f)
-    }
-}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 6ef73debadd..66d3834d857 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 9cd0cc499ca..ffbe54d6206 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 b1bdee18d6d..9c1e4cefa69 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 fbb6a1cc475..434f8c1c767 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 8ff5dc12596..6fce1fade26 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 00000000000..c2bae2fe8cb
--- /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_hashes/src/lib.rs b/compiler/rustc_hashes/src/lib.rs
new file mode 100644
index 00000000000..3755caaaa29
--- /dev/null
+++ b/compiler/rustc_hashes/src/lib.rs
@@ -0,0 +1,131 @@
+//! 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. 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
+//! hash value as an integer type and accidentally apply varint encoding to it.
+//!
+//! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct
+//! and decompose these types into constituent pieces. The point of these types is only to
+//! connect the fact that they can only be produced by a `StableHasher` to their
+//! `Encode`/`Decode` impls.
+
+use std::fmt;
+use std::ops::BitXorAssign;
+
+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,
+}
+
+impl Hash64 {
+    pub const ZERO: Hash64 = Hash64 { inner: 0 };
+
+    #[inline]
+    pub fn new(n: u64) -> Self {
+        Self { inner: n }
+    }
+
+    #[inline]
+    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 {
+    #[inline]
+    fn bitxor_assign(&mut self, rhs: u64) {
+        self.inner ^= rhs;
+    }
+}
+
+impl FromStableHash for Hash64 {
+    type Hash = StableHasherHash;
+
+    #[inline]
+    fn from(StableHasherHash([_0, __1]): Self::Hash) -> Self {
+        Self { inner: _0 }
+    }
+}
+
+impl fmt::Debug for Hash64 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+impl fmt::LowerHex for Hash64 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::LowerHex::fmt(&self.inner, f)
+    }
+}
+
+/// 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,
+}
+
+// We expect Hash128 to be well mixed. So there's no point in hashing both parts.
+//
+// This also allows using Hash128-containing types in UnHash-based hashmaps, which would otherwise
+// debug_assert! that we're hashing more than a single u64.
+impl std::hash::Hash for Hash128 {
+    fn hash(&self, h: &mut H) {
+        h.write_u64(self.truncate().as_u64());
+    }
+}
+
+impl Hash128 {
+    #[inline]
+    pub fn new(n: u128) -> Self {
+        Self { inner: n }
+    }
+
+    #[inline]
+    pub fn truncate(self) -> Hash64 {
+        Hash64 { inner: self.inner as u64 }
+    }
+
+    #[inline]
+    pub fn wrapping_add(self, other: Self) -> Self {
+        Self { inner: self.inner.wrapping_add(other.inner) }
+    }
+
+    #[inline]
+    pub fn as_u128(self) -> u128 {
+        self.inner
+    }
+}
+
+impl FromStableHash for Hash128 {
+    type Hash = StableHasherHash;
+
+    #[inline]
+    fn from(StableHasherHash([_0, _1]): Self::Hash) -> Self {
+        Self { inner: u128::from(_0) | (u128::from(_1) << 64) }
+    }
+}
+
+impl fmt::Debug for Hash128 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+impl fmt::LowerHex for Hash128 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::LowerHex::fmt(&self.inner, f)
+    }
+}
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 5bfc4756ec6..b1516e53173 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 9a6dee1e511..35c6e57b877 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 dc527240f74..08a0a5225e7 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 e0e63d183c6..0837444ffdb 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 de722e62043..1b6a174c093 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 d4a9aac3733..4a21b6ad237 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 2e90e5251e2..bbb8a9fa671 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 94bd359f6eb..88d57498542 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 8b0cc9d726b..fd1d21b6a89 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 e95c186f6b6..f98d6421307 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 a42329b4614..d9560f3eb0f 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 82c51193a19..7490a3f3503 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 8bf98c16361..a6815c7a447 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 db8555edd0f..1eefd76f92b 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 b9c535df4bd..31892c13438 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 7d473b86ff5..85ef69ea2b7 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 35819f896c5..351dad3f3e4 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 781fe6a11fe..991c75cc98d 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 f61ce37131e..641bac88ad0 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 2910bcdf51d..9bf1d305e54 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 0e146baef37..695edc956cd 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 1fb647cab5b..4c51c908f54 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 07c5f544792..e965e6a7d53 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 8ae35572d01..88754f1f15b 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 40356e0c978..f88f8c38d50 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 6a67009fe90..8429e68b600 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 52e4fa19cb0..83631f7fe34 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 8fc19854033..5d1834a8642 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 c8efd904320..9c947df35e9 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 108171586ea..b6f7c44c2ae 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 55d81875a2b..daddcf0b242 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 9fbc675cc9a..cbc1f24b8c1 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 d7bf27d6349..faad6264522 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
 
-- 
cgit 1.4.1-3-g733a5


From b023671ce2019cdc1768d4acfb148c86ab70183a Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 10:57:14 +1100
Subject: 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 ++++
 .../rustc_mir_build/src/thir/pattern/check_match.rs  | 20 ++++++--------------
 compiler/rustc_pattern_analysis/src/rustc.rs         | 10 +++++++---
 compiler/rustc_pattern_analysis/src/usefulness.rs    | 17 +++++++++--------
 compiler/rustc_pattern_analysis/tests/common/mod.rs  |  2 +-
 compiler/rustc_pattern_analysis/tests/complexity.rs  |  2 +-
 .../rustc_pattern_analysis/tests/exhaustiveness.rs   |  3 ++-
 .../rustc_pattern_analysis/tests/intersection.rs     |  3 ++-
 compiler/rustc_session/src/session.rs                |  7 +++++++
 .../src/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 8a367a947d1..7dc1db5a22d 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 cb8dc692148..ea2b610a727 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 697cb7cf37a..7dd2ed7bbdf 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 2694cf472f4..0b1e954d64d 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 cc09cd491af..1dff76141da 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 cd697632d1b..23560ad6419 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 43b585bc533..abd1ec24d93 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 0d80042a850..61ce0fd11e7 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 a852056b6a6..45674338efd 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 f795ad1ee17..c4d45ee02ee 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 2b854310a15..3312da470c0 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)
     }
 
-- 
cgit 1.4.1-3-g733a5


From 30b8c84de693885a9645add17c0e0e6a7c391db3 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 14:16:59 +1100
Subject: 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 7dc1db5a22d..53590eee927 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
 }
-- 
cgit 1.4.1-3-g733a5


From 13280eed6a04b94efa3702733d733f5496f60d27 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 14:28:52 +1100
Subject: 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 53590eee927..bc5d629c9ab 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))
 }
-- 
cgit 1.4.1-3-g733a5


From 223c95fd59f361ff482bf26434900fc8f72fbe04 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 16:19:05 +1100
Subject: 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 +
 compiler/rustc_interface/src/limits.rs     | 85 ++++++++++++++++++++++++++++++
 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/limits.rs | 84 -----------------------------
 compiler/rustc_middle/src/middle/mod.rs    |  5 --
 compiler/rustc_middle/src/ty/mod.rs        |  1 -
 10 files changed, 103 insertions(+), 106 deletions(-)
 create mode 100644 compiler/rustc_interface/src/limits.rs
 delete mode 100644 compiler/rustc_middle/src/middle/limits.rs

diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 43c69c8e571..adc7ed54e14 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 c3b858d4f2e..ca4e556dcdb 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 a2a29612e48..54cd341698f 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_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs
new file mode 100644
index 00000000000..08d155a2c23
--- /dev/null
+++ b/compiler/rustc_interface/src/limits.rs
@@ -0,0 +1,85 @@
+//! Registering limits:
+//! - 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
+//!
+//! 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;
+
+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::errors::LimitInvalid;
+
+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(
+            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.sess,
+            sym::type_length_limit,
+            Limit::new(2usize.pow(24)),
+        ),
+        pattern_complexity_limit: get_limit(
+            tcx.hir().krate_attrs(),
+            tcx.sess,
+            sym::pattern_complexity,
+            Limit::unlimited(),
+        ),
+    }
+}
+
+// This one is separate because it must be read prior to macro expansion.
+pub(crate) fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
+    get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128))
+}
+
+fn get_limit(
+    krate_attrs: &[impl AttributeExt],
+    sess: &Session,
+    name: Symbol,
+    default: Limit,
+) -> Limit {
+    for attr in krate_attrs {
+        if !attr.has_name(name) {
+            continue;
+        }
+
+        if let Some(sym) = attr.value_str() {
+            match sym.as_str().parse() {
+                Ok(n) => return Limit::new(n),
+                Err(e) => {
+                    let error_str = match e.kind() {
+                        IntErrorKind::PosOverflow => "`limit` is too large",
+                        IntErrorKind::Empty => "`limit` must be a non-negative integer",
+                        IntErrorKind::InvalidDigit => "not a valid integer",
+                        IntErrorKind::NegOverflow => {
+                            bug!("`limit` should never negatively overflow")
+                        }
+                        IntErrorKind::Zero => bug!("zero is a valid `limit`"),
+                        kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
+                    };
+                    sess.dcx().emit_err(LimitInvalid {
+                        span: attr.span(),
+                        value_span: attr.value_span().unwrap(),
+                        error_str,
+                    });
+                }
+            }
+        }
+    }
+    default
+}
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index fcebca3ecc9..d7d183e17ed 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 09c16222be1..dcfa81dab25 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 91b18295b43..c53e3d54cc4 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/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
deleted file mode 100644
index bc5d629c9ab..00000000000
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-//! Registering limits:
-//! - 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
-//!
-//! 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;
-
-use rustc_ast::attr::AttributeExt;
-use rustc_session::{Limit, Limits, Session};
-use rustc_span::{Symbol, sym};
-
-use crate::error::LimitInvalid;
-use crate::query::Providers;
-
-pub 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(
-            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.sess,
-            sym::type_length_limit,
-            Limit::new(2usize.pow(24)),
-        ),
-        pattern_complexity_limit: get_limit(
-            tcx.hir().krate_attrs(),
-            tcx.sess,
-            sym::pattern_complexity,
-            Limit::unlimited(),
-        ),
-    }
-}
-
-// 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))
-}
-
-fn get_limit(
-    krate_attrs: &[impl AttributeExt],
-    sess: &Session,
-    name: Symbol,
-    default: Limit,
-) -> Limit {
-    for attr in krate_attrs {
-        if !attr.has_name(name) {
-            continue;
-        }
-
-        if let Some(sym) = attr.value_str() {
-            match sym.as_str().parse() {
-                Ok(n) => return Limit::new(n),
-                Err(e) => {
-                    let error_str = match e.kind() {
-                        IntErrorKind::PosOverflow => "`limit` is too large",
-                        IntErrorKind::Empty => "`limit` must be a non-negative integer",
-                        IntErrorKind::InvalidDigit => "not a valid integer",
-                        IntErrorKind::NegOverflow => {
-                            bug!("`limit` should never negatively overflow")
-                        }
-                        IntErrorKind::Zero => bug!("zero is a valid `limit`"),
-                        kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
-                    };
-                    sess.dcx().emit_err(LimitInvalid {
-                        span: attr.span(),
-                        value_span: attr.value_span().unwrap(),
-                        error_str,
-                    });
-                }
-            }
-        }
-    }
-    default
-}
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 692fe027c49..9f71971ea08 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 52cb8f57a88..04519008711 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,
-- 
cgit 1.4.1-3-g733a5


From 7a8c0fc117a4d866ea0c362cc173f90c7bf14dd6 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 7 Feb 2025 15:58:00 +1100
Subject: 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 +-
 src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs |  4 ++--
 .../feature-gates/feature-gate-pattern-complexity-limit.rs   |  6 ++++++
 .../feature-gate-pattern-complexity-limit.stderr             | 12 ++++++++++++
 tests/ui/feature-gates/feature-gate-pattern-complexity.rs    |  6 ------
 .../ui/feature-gates/feature-gate-pattern-complexity.stderr  | 12 ------------
 tests/ui/pattern/complexity_limit.rs                         |  2 +-
 .../issue-118437-exponential-time-on-diagonal-match.rs       |  2 +-
 11 files changed, 26 insertions(+), 26 deletions(-)
 create mode 100644 tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs
 create mode 100644 tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr
 delete mode 100644 tests/ui/feature-gates/feature-gate-pattern-complexity.rs
 delete mode 100644 tests/ui/feature-gates/feature-gate-pattern-complexity.stderr

diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index eb5fac96af2..8eb9bf15829 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 a638a845c07..e852f239aa2 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 08d155a2c23..3de513797e3 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 62723e385cf..1bd97916d1c 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 14af22c3193..ed9d6c67501 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 00000000000..d1f6f4755f0
--- /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-limit.stderr b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr
new file mode 100644
index 00000000000..e6f17710e09
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr
@@ -0,0 +1,12 @@
+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_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
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
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 43e9a00c9a7..00000000000
--- 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/feature-gates/feature-gate-pattern-complexity.stderr b/tests/ui/feature-gates/feature-gate-pattern-complexity.stderr
deleted file mode 100644
index c05e6abb017..00000000000
--- a/tests/ui/feature-gates/feature-gate-pattern-complexity.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-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
-   |
-LL | #![pattern_complexity = "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
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/pattern/complexity_limit.rs b/tests/ui/pattern/complexity_limit.rs
index c9a3f99bccd..7c127820511 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 783512d5cca..44d1586ce4f 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 {
-- 
cgit 1.4.1-3-g733a5


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

Very minor changes that will make the next few commits easier to follow.
---
 .../rustc_mir_dataflow/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 07517d7edab..528debcaba3 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);
                     }
 
-- 
cgit 1.4.1-3-g733a5


From 23dbff88f6ecf7b92129ec3cfc41971b5cd9579c Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Thu, 13 Feb 2025 10:46:34 +1100
Subject: 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 c32cf5f8253..5c670830376 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(|| {
-- 
cgit 1.4.1-3-g733a5


From 8403d39dce2b6875381974a3f413c0c610f2ca1a Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 14 Feb 2025 09:54:01 +1100
Subject: 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 +-
 .../rustc_mir_dataflow/src/framework/direction.rs    |  9 ++++++---
 compiler/rustc_mir_dataflow/src/framework/mod.rs     |  6 ++++--
 compiler/rustc_mir_dataflow/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 5c670830376..107c3198525 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 795cfcef2d3..cc22cabcb3e 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 528debcaba3..02b2bbb3507 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 60c5cb0cae8..14630991cd6 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 3be450a0b3f..f2fbadaac09 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(
-- 
cgit 1.4.1-3-g733a5


From db1ca60470d3d9bcb533ad1130e669dcd8c7ffd2 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 14 Feb 2025 10:57:06 +1100
Subject: 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 9cec8d832dd..dfd40a9535b 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]>,
 }
 
-- 
cgit 1.4.1-3-g733a5


From 3b81d9d42d07d3e2c4f9f0c714fb16d2527758fe Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Fri, 14 Feb 2025 13:23:00 +1100
Subject: 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.
---
 compiler/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 02b2bbb3507..3d7f9e2d8e7 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 14630991cd6..09f6cdb5c4a 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 f2fbadaac09..f5ffc42d52a 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(
-- 
cgit 1.4.1-3-g733a5


From 7ff67901acd7dd0669a2f41a618d5e539b6d3663 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 16:08:48 +1100
Subject: 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 6269728e67f..8fa409f4e38 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)
-- 
cgit 1.4.1-3-g733a5


From b51ab7d9be51ad70addf7ddb62dfa85e2bac1e2e Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 15:29:12 +1100
Subject: 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 f632041dba9..01e6fb89053 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;
 
     ///////////////////////////////////////////////////////////////////////////
-- 
cgit 1.4.1-3-g733a5


From 6021ba0668a00fde339936f32a4f58fa4dace876 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 10:24:10 +1100
Subject: 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.rs     | 1405 ++++++++++++++++++++++++++++++
 compiler/rustc_middle/src/hir/map/mod.rs | 1405 ------------------------------
 2 files changed, 1405 insertions(+), 1405 deletions(-)
 create mode 100644 compiler/rustc_middle/src/hir/map.rs
 delete mode 100644 compiler/rustc_middle/src/hir/map/mod.rs

diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
new file mode 100644
index 00000000000..83c7bb0f52f
--- /dev/null
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -0,0 +1,1405 @@
+use rustc_abi::ExternAbi;
+use rustc_ast::visit::{VisitorResult, walk_list};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::svh::Svh;
+use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::*;
+use rustc_hir_pretty as pprust_hir;
+use rustc_span::def_id::StableCrateId;
+use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans};
+
+use crate::hir::{ModuleItems, nested_filter};
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
+use crate::query::LocalCrate;
+use crate::ty::TyCtxt;
+
+// FIXME: the structure was necessary in the past but now it
+// only serves as "namespace" for HIR-related methods, and can be
+// removed if all the methods are reasonably renamed and moved to tcx
+// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
+#[derive(Copy, Clone)]
+pub struct Map<'hir> {
+    pub(super) tcx: TyCtxt<'hir>,
+}
+
+/// An iterator that walks up the ancestor tree of a given `HirId`.
+/// Constructed using `tcx.hir().parent_iter(hir_id)`.
+struct ParentHirIterator<'hir> {
+    current_id: HirId,
+    map: Map<'hir>,
+    // Cache the current value of `hir_owner_nodes` to avoid repeatedly calling the same query for
+    // the same owner, which will uselessly record many times the same query dependency.
+    current_owner_nodes: Option<&'hir OwnerNodes<'hir>>,
+}
+
+impl<'hir> ParentHirIterator<'hir> {
+    fn new(map: Map<'hir>, current_id: HirId) -> ParentHirIterator<'hir> {
+        ParentHirIterator { current_id, map, current_owner_nodes: None }
+    }
+}
+
+impl<'hir> Iterator for ParentHirIterator<'hir> {
+    type Item = HirId;
+
+    fn next(&mut self) -> Option {
+        if self.current_id == CRATE_HIR_ID {
+            return None;
+        }
+
+        let HirId { owner, local_id } = self.current_id;
+
+        let parent_id = if local_id == ItemLocalId::ZERO {
+            // We go from an owner to its parent, so clear the cache.
+            self.current_owner_nodes = None;
+            self.map.tcx.hir_owner_parent(owner)
+        } else {
+            let owner_nodes =
+                self.current_owner_nodes.get_or_insert_with(|| self.map.tcx.hir_owner_nodes(owner));
+            let parent_local_id = owner_nodes.nodes[local_id].parent;
+            // HIR indexing should have checked that.
+            debug_assert_ne!(parent_local_id, local_id);
+            HirId { owner, local_id: parent_local_id }
+        };
+
+        debug_assert_ne!(parent_id, self.current_id);
+
+        self.current_id = parent_id;
+        Some(parent_id)
+    }
+}
+
+/// An iterator that walks up the ancestor tree of a given `HirId`.
+/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
+pub struct ParentOwnerIterator<'hir> {
+    current_id: HirId,
+    map: Map<'hir>,
+}
+
+impl<'hir> Iterator for ParentOwnerIterator<'hir> {
+    type Item = (OwnerId, OwnerNode<'hir>);
+
+    fn next(&mut self) -> Option {
+        if self.current_id.local_id.index() != 0 {
+            self.current_id.local_id = ItemLocalId::ZERO;
+            let node = self.map.tcx.hir_owner_node(self.current_id.owner);
+            return Some((self.current_id.owner, node));
+        }
+        if self.current_id == CRATE_HIR_ID {
+            return None;
+        }
+
+        let parent_id = self.map.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
+        });
+        self.current_id = HirId::make_owner(parent_id.def_id);
+
+        let node = self.map.tcx.hir_owner_node(self.current_id.owner);
+        Some((self.current_id.owner, node))
+    }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+    #[inline]
+    fn expect_hir_owner_nodes(self, def_id: LocalDefId) -> &'tcx OwnerNodes<'tcx> {
+        self.opt_hir_owner_nodes(def_id)
+            .unwrap_or_else(|| span_bug!(self.def_span(def_id), "{def_id:?} is not an owner"))
+    }
+
+    #[inline]
+    pub fn hir_owner_nodes(self, owner_id: OwnerId) -> &'tcx OwnerNodes<'tcx> {
+        self.expect_hir_owner_nodes(owner_id.def_id)
+    }
+
+    #[inline]
+    fn opt_hir_owner_node(self, def_id: LocalDefId) -> Option> {
+        self.opt_hir_owner_nodes(def_id).map(|nodes| nodes.node())
+    }
+
+    #[inline]
+    pub fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> {
+        self.expect_hir_owner_nodes(def_id).node()
+    }
+
+    #[inline]
+    pub fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> {
+        self.hir_owner_nodes(owner_id).node()
+    }
+
+    /// Retrieves the `hir::Node` corresponding to `id`.
+    pub fn hir_node(self, id: HirId) -> Node<'tcx> {
+        self.hir_owner_nodes(id.owner).nodes[id.local_id].node
+    }
+
+    /// Retrieves the `hir::Node` corresponding to `id`.
+    #[inline]
+    pub fn hir_node_by_def_id(self, id: LocalDefId) -> Node<'tcx> {
+        self.hir_node(self.local_def_id_to_hir_id(id))
+    }
+
+    /// Returns `HirId` of the parent HIR node of node with this `hir_id`.
+    /// Returns the same `hir_id` if and only if `hir_id == CRATE_HIR_ID`.
+    ///
+    /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
+    pub fn parent_hir_id(self, hir_id: HirId) -> HirId {
+        let HirId { owner, local_id } = hir_id;
+        if local_id == ItemLocalId::ZERO {
+            self.hir_owner_parent(owner)
+        } else {
+            let parent_local_id = self.hir_owner_nodes(owner).nodes[local_id].parent;
+            // HIR indexing should have checked that.
+            debug_assert_ne!(parent_local_id, local_id);
+            HirId { owner, local_id: parent_local_id }
+        }
+    }
+
+    /// Returns parent HIR node of node with this `hir_id`.
+    /// Returns HIR node of the same `hir_id` if and only if `hir_id == CRATE_HIR_ID`.
+    pub fn parent_hir_node(self, hir_id: HirId) -> Node<'tcx> {
+        self.hir_node(self.parent_hir_id(hir_id))
+    }
+}
+
+impl<'hir> Map<'hir> {
+    #[inline]
+    pub fn krate(self) -> &'hir Crate<'hir> {
+        self.tcx.hir_crate(())
+    }
+
+    #[inline]
+    pub fn root_module(self) -> &'hir Mod<'hir> {
+        match self.tcx.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()
+    }
+
+    #[inline]
+    pub fn module_items(self, module: LocalModDefId) -> impl Iterator + 'hir {
+        self.tcx.hir_module_items(module).free_items()
+    }
+
+    pub fn 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)
+    }
+
+    pub fn 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)
+    }
+
+    #[inline]
+    pub fn 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)
+    }
+
+    pub fn get_if_local(self, id: DefId) -> Option> {
+        id.as_local().map(|id| self.tcx.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 item(self, id: ItemId) -> &'hir Item<'hir> {
+        self.tcx.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 impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.tcx.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 body(self, id: BodyId) -> &'hir Body<'hir> {
+        self.tcx.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
+    }
+
+    #[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()
+    }
+
+    #[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()
+    }
+
+    #[track_caller]
+    pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
+        for (_, node) in self.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);
+    }
+
+    /// 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:?}");
+        parent
+    }
+
+    pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
+        self.tcx.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.body(self.tcx.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);
+            span_bug!(
+                self.span(hir_id),
+                "body_owned_by: {} has no associated body",
+                self.node_to_string(hir_id)
+            );
+        })
+    }
+
+    pub fn body_param_names(self, id: BodyId) -> impl Iterator + 'hir {
+        self.body(id).params.iter().map(|arg| match arg.pat.kind {
+            PatKind::Binding(_, _, ident, _) => ident,
+            _ => Ident::empty(),
+        })
+    }
+
+    /// 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 {
+        let def_id = def_id.into();
+        match self.tcx.def_kind(def_id) {
+            DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
+                BodyOwnerKind::Const { inline: false }
+            }
+            DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
+            DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
+            DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure,
+            DefKind::Static { safety: _, mutability, nested: false } => {
+                BodyOwnerKind::Static(mutability)
+            }
+            dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
+        }
+    }
+
+    /// Returns the `ConstContext` of the body associated with this `LocalDefId`.
+    ///
+    /// Panics if `LocalDefId` does not have an associated body.
+    ///
+    /// 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 {
+        let def_id = def_id.into();
+        let ccx = match self.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) => {
+                ConstContext::ConstFn
+            }
+            BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
+        };
+
+        Some(ccx)
+    }
+
+    /// Returns an iterator of the `DefId`s for all body-owners in this
+    /// 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()
+    }
+
+    #[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 ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
+        let def_kind = self.tcx.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)
+            }
+            _ => 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);
+        match def_kind {
+            DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
+            DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
+                self.tcx.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[..])
+    }
+
+    /// 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 rustc_coherence_is_core(self) -> bool {
+        self.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) {
+        let hir_id = HirId::make_owner(module.to_local_def_id());
+        match self.tcx.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:?}"),
+        }
+    }
+
+    /// 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
+    where
+        V: Visitor<'hir>,
+    {
+        let (top_mod, span, hir_id) = self.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
+    where
+        V: Visitor<'hir>,
+    {
+        let krate = self.krate();
+        for info in krate.owners.iter() {
+            if let MaybeOwner::Owner(info) = info {
+                for attrs in info.attrs.map.values() {
+                    walk_list!(visitor, visit_attribute, *attrs);
+                }
+            }
+        }
+        V::Result::output()
+    }
+
+    /// 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`.
+    ///
+    /// 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
+    where
+        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_foreign_item,
+            krate.foreign_items().map(|id| self.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
+    where
+        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_foreign_item,
+            module.foreign_items().map(|id| self.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(());
+        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(());
+        par_for_each_in(&crate_items.submodules[..], |module| {
+            f(LocalModDefId::new_unchecked(module.def_id))
+        })
+    }
+
+    #[inline]
+    pub fn try_par_for_each_module(
+        self,
+        f: impl Fn(LocalModDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
+    ) -> Result<(), ErrorGuaranteed> {
+        let crate_items = self.tcx.hir_crate_items(());
+        try_par_for_each_in(&crate_items.submodules[..], |module| {
+            f(LocalModDefId::new_unchecked(module.def_id))
+        })
+    }
+
+    /// 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]
+    pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator + 'hir {
+        ParentHirIterator::new(self, current_id)
+    }
+
+    /// 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]
+    pub fn parent_iter(self, current_id: HirId) -> impl Iterator)> {
+        self.parent_id_iter(current_id).map(move |id| (id, self.tcx.hir_node(id)))
+    }
+
+    /// 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]
+    pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
+        ParentOwnerIterator { current_id, map: self }
+    }
+
+    /// Checks if the node is left-hand side of an assignment.
+    pub fn is_lhs(self, id: HirId) -> bool {
+        match self.tcx.parent_hir_node(id) {
+            Node::Expr(expr) => match expr.kind {
+                ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
+                _ => false,
+            },
+            _ => false,
+        }
+    }
+
+    /// 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()
+    }
+
+    /// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
+    /// in the "tail" position of the function, in other words if it's likely to correspond
+    /// to the return type of the function.
+    ///
+    /// ```
+    /// fn foo(x: usize) -> bool {
+    ///     if x == 1 {
+    ///         true  // If `get_fn_id_for_return_block` gets passed the `id` corresponding
+    ///     } else {  // to this, it will return `foo`'s `HirId`.
+    ///         false
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// ```compile_fail,E0308
+    /// fn foo(x: usize) -> bool {
+    ///     loop {
+    ///         true  // If `get_fn_id_for_return_block` gets passed the `id` corresponding
+    ///     }         // to this, it will return `None`.
+    ///     false
+    /// }
+    /// ```
+    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));
+
+        // 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();
+        while let Some(cur_id) = iter.next() {
+            if enclosing_body_owner == cur_id {
+                break;
+            }
+
+            // A return statement is always the value returned from the enclosing body regardless of
+            // what the parent expressions are.
+            if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(cur_id) {
+                break;
+            }
+
+            // If the current expression's value doesnt get used as the parent expressions value then return `None`
+            if let Some(&parent_id) = iter.peek() {
+                match self.tcx.hir_node(parent_id) {
+                    // The current node is not the tail expression of the block expression parent expr.
+                    Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None,
+                    Node::Block(Block { expr: Some(e), .. })
+                        if matches!(e.kind, ExprKind::If(_, _, None)) =>
+                    {
+                        return None;
+                    }
+
+                    // The current expression's value does not pass up through these parent expressions
+                    Node::Block(Block { expr: None, .. })
+                    | Node::Expr(Expr { kind: ExprKind::Loop(..), .. })
+                    | Node::LetStmt(..) => return None,
+
+                    _ => {}
+                }
+            }
+        }
+
+        Some(enclosing_body_owner)
+    }
+
+    /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no
+    /// parent item is in this map. The "parent item" is the closest parent node
+    /// in the HIR which is recorded by the map and is an item, either an item
+    /// in a module, trait, or impl.
+    pub fn get_parent_item(self, hir_id: HirId) -> OwnerId {
+        if hir_id.local_id != ItemLocalId::ZERO {
+            // If this is a child of a HIR owner, return the owner.
+            hir_id.owner
+        } else if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() {
+            def_id
+        } else {
+            CRATE_OWNER_ID
+        }
+    }
+
+    /// When on an if expression, a match arm tail expression or a match arm, give back
+    /// the enclosing `if` or `match` expression.
+    ///
+    /// Used by error reporting when there's a type error in an if or match arm caused by the
+    /// expression needing to be unit.
+    pub fn get_if_cause(self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
+        for (_, node) in self.parent_iter(hir_id) {
+            match node {
+                Node::Item(_)
+                | Node::ForeignItem(_)
+                | Node::TraitItem(_)
+                | Node::ImplItem(_)
+                | Node::Stmt(Stmt { kind: StmtKind::Let(_), .. }) => break,
+                Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => {
+                    return Some(expr);
+                }
+                _ => {}
+            }
+        }
+        None
+    }
+
+    /// Returns the nearest enclosing scope. A scope is roughly an item or block.
+    pub fn get_enclosing_scope(self, hir_id: HirId) -> Option {
+        for (hir_id, node) in self.parent_iter(hir_id) {
+            if let Node::Item(Item {
+                kind:
+                    ItemKind::Fn { .. }
+                    | ItemKind::Const(..)
+                    | ItemKind::Static(..)
+                    | ItemKind::Mod(..)
+                    | ItemKind::Enum(..)
+                    | ItemKind::Struct(..)
+                    | ItemKind::Union(..)
+                    | ItemKind::Trait(..)
+                    | ItemKind::Impl { .. },
+                ..
+            })
+            | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(..), .. })
+            | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(..), .. })
+            | Node::Block(_) = node
+            {
+                return Some(hir_id);
+            }
+        }
+        None
+    }
+
+    /// Returns the defining scope for an opaque type definition.
+    pub fn get_defining_scope(self, id: HirId) -> HirId {
+        let mut scope = id;
+        loop {
+            scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
+            if scope == CRATE_HIR_ID || !matches!(self.tcx.hir_node(scope), Node::Block(_)) {
+                return scope;
+            }
+        }
+    }
+
+    pub fn get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
+        let parent = self.get_parent_item(hir_id);
+        if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) =
+            self.tcx.hir_owner_node(parent)
+        {
+            return *abi;
+        }
+        bug!(
+            "expected foreign mod or inlined parent, found {}",
+            self.node_to_string(HirId::make_owner(parent.def_id))
+        )
+    }
+
+    pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
+        match self.tcx.expect_hir_owner_node(id) {
+            OwnerNode::Item(item) => item,
+            _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
+        }
+    }
+
+    pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> {
+        match self.tcx.expect_hir_owner_node(id) {
+            OwnerNode::ImplItem(item) => item,
+            _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
+        }
+    }
+
+    pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> {
+        match self.tcx.expect_hir_owner_node(id) {
+            OwnerNode::TraitItem(item) => item,
+            _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
+        }
+    }
+
+    pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
+        Some(&self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.output)
+    }
+
+    pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
+        match self.tcx.hir_node(id) {
+            Node::Variant(variant) => variant,
+            _ => bug!("expected variant, found {}", self.node_to_string(id)),
+        }
+    }
+
+    pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
+        match self.tcx.hir_node(id) {
+            Node::Field(field) => field,
+            _ => bug!("expected field, found {}", self.node_to_string(id)),
+        }
+    }
+
+    pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
+        match self.tcx.hir_owner_node(id) {
+            OwnerNode::ForeignItem(item) => item,
+            _ => {
+                bug!(
+                    "expected foreign item, found {}",
+                    self.node_to_string(HirId::make_owner(id.def_id))
+                )
+            }
+        }
+    }
+
+    #[track_caller]
+    pub fn expect_opaque_ty(self, id: LocalDefId) -> &'hir OpaqueTy<'hir> {
+        match self.tcx.hir_node_by_def_id(id) {
+            Node::OpaqueTy(opaq) => opaq,
+            _ => {
+                bug!(
+                    "expected opaque type definition, found {}",
+                    self.node_to_string(self.tcx.local_def_id_to_hir_id(id))
+                )
+            }
+        }
+    }
+
+    pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
+        match self.tcx.hir_node(id) {
+            Node::Expr(expr) => expr,
+            _ => bug!("expected expr, found {}", self.node_to_string(id)),
+        }
+    }
+
+    pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option {
+        self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
+    }
+
+    #[inline]
+    fn opt_ident(self, id: HirId) -> Option {
+        match self.tcx.hir_node(id) {
+            Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
+            // A `Ctor` doesn't have an identifier itself, but its parent
+            // struct/variant does. Compare with `hir::Map::span`.
+            Node::Ctor(..) => match self.tcx.parent_hir_node(id) {
+                Node::Item(item) => Some(item.ident),
+                Node::Variant(variant) => Some(variant.ident),
+                _ => unreachable!(),
+            },
+            node => node.ident(),
+        }
+    }
+
+    #[inline]
+    pub(super) fn opt_ident_span(self, id: HirId) -> Option {
+        self.opt_ident(id).map(|ident| ident.span)
+    }
+
+    #[inline]
+    pub fn ident(self, id: HirId) -> Ident {
+        self.opt_ident(id).unwrap()
+    }
+
+    #[inline]
+    pub fn opt_name(self, id: HirId) -> Option {
+        self.opt_ident(id).map(|ident| ident.name)
+    }
+
+    pub fn name(self, id: HirId) -> Symbol {
+        self.opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.node_to_string(id)))
+    }
+
+    /// Given a node ID, gets a list of attributes associated with the AST
+    /// corresponding to the node-ID.
+    pub fn attrs(self, id: HirId) -> &'hir [Attribute] {
+        self.tcx.hir_attrs(id.owner).get(id.local_id)
+    }
+
+    /// Gets the span of the definition of the specified HIR node.
+    /// This is used by `tcx.def_span`.
+    pub fn span(self, hir_id: HirId) -> Span {
+        fn until_within(outer: Span, end: Span) -> Span {
+            if let Some(end) = end.find_ancestor_inside(outer) {
+                outer.with_hi(end.hi())
+            } else {
+                outer
+            }
+        }
+
+        fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) -> Span {
+            if ident.name != kw::Empty {
+                let mut span = until_within(item_span, ident.span);
+                if let Some(g) = generics
+                    && !g.span.is_dummy()
+                    && let Some(g_span) = g.span.find_ancestor_inside(item_span)
+                {
+                    span = span.to(g_span);
+                }
+                span
+            } else {
+                item_span
+            }
+        }
+
+        let span = match self.tcx.hir_node(hir_id) {
+            // Function-like.
+            Node::Item(Item { kind: ItemKind::Fn { sig, .. }, span: outer_span, .. })
+            | Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Fn(sig, ..),
+                span: outer_span,
+                ..
+            })
+            | Node::ImplItem(ImplItem {
+                kind: ImplItemKind::Fn(sig, ..), span: outer_span, ..
+            })
+            | Node::ForeignItem(ForeignItem {
+                kind: ForeignItemKind::Fn(sig, ..),
+                span: outer_span,
+                ..
+            }) => {
+                // Ensure that the returned span has the item's SyntaxContext, and not the
+                // SyntaxContext of the visibility.
+                sig.span.find_ancestor_in_same_ctxt(*outer_span).unwrap_or(*outer_span)
+            }
+            // Impls, including their where clauses.
+            Node::Item(Item {
+                kind: ItemKind::Impl(Impl { generics, .. }),
+                span: outer_span,
+                ..
+            }) => until_within(*outer_span, generics.where_clause_span),
+            // Constants and Statics.
+            Node::Item(Item {
+                kind: ItemKind::Const(ty, ..) | ItemKind::Static(ty, ..),
+                span: outer_span,
+                ..
+            })
+            | Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Const(ty, ..),
+                span: outer_span,
+                ..
+            })
+            | Node::ImplItem(ImplItem {
+                kind: ImplItemKind::Const(ty, ..),
+                span: outer_span,
+                ..
+            })
+            | Node::ForeignItem(ForeignItem {
+                kind: ForeignItemKind::Static(ty, ..),
+                span: outer_span,
+                ..
+            }) => until_within(*outer_span, ty.span),
+            // With generics and bounds.
+            Node::Item(Item {
+                kind: ItemKind::Trait(_, _, generics, bounds, _),
+                span: outer_span,
+                ..
+            })
+            | Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Type(bounds, _),
+                generics,
+                span: outer_span,
+                ..
+            }) => {
+                let end = if let Some(b) = bounds.last() { b.span() } else { generics.span };
+                until_within(*outer_span, end)
+            }
+            // Other cases.
+            Node::Item(item) => match &item.kind {
+                ItemKind::Use(path, _) => {
+                    // Ensure that the returned span has the item's SyntaxContext, and not the
+                    // SyntaxContext of the path.
+                    path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span)
+                }
+                _ => named_span(item.span, item.ident, item.kind.generics()),
+            },
+            Node::Variant(variant) => named_span(variant.span, variant.ident, None),
+            Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
+            Node::ForeignItem(item) => named_span(item.span, item.ident, None),
+            Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
+            Node::Expr(Expr {
+                kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
+                span,
+                ..
+            }) => {
+                // Ensure that the returned span has the item's SyntaxContext.
+                fn_decl_span.find_ancestor_inside(*span).unwrap_or(*span)
+            }
+            _ => self.span_with_body(hir_id),
+        };
+        debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt());
+        span
+    }
+
+    /// Like `hir.span()`, but includes the body of items
+    /// (instead of just the item header)
+    pub fn span_with_body(self, hir_id: HirId) -> Span {
+        match self.tcx.hir_node(hir_id) {
+            Node::Param(param) => param.span,
+            Node::Item(item) => item.span,
+            Node::ForeignItem(foreign_item) => foreign_item.span,
+            Node::TraitItem(trait_item) => trait_item.span,
+            Node::ImplItem(impl_item) => impl_item.span,
+            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::ConstArg(const_arg) => const_arg.span(),
+            Node::Expr(expr) => expr.span,
+            Node::ExprField(field) => field.span,
+            Node::Stmt(stmt) => stmt.span,
+            Node::PathSegment(seg) => {
+                let ident_span = seg.ident.span;
+                ident_span
+                    .with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi()))
+            }
+            Node::Ty(ty) => ty.span,
+            Node::AssocItemConstraint(constraint) => constraint.span,
+            Node::TraitRef(tr) => tr.path.span,
+            Node::OpaqueTy(op) => op.span,
+            Node::Pat(pat) => pat.span,
+            Node::TyPat(pat) => pat.span,
+            Node::PatField(field) => field.span,
+            Node::PatExpr(lit) => lit.span,
+            Node::Arm(arm) => arm.span,
+            Node::Block(block) => block.span,
+            Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
+            Node::Lifetime(lifetime) => lifetime.ident.span,
+            Node::GenericParam(param) => param.span,
+            Node::Infer(i) => i.span,
+            Node::LetStmt(local) => local.span,
+            Node::Crate(item) => item.spans.inner_span,
+            Node::WherePredicate(pred) => pred.span,
+            Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
+            Node::Synthetic => unreachable!(),
+            Node::Err(span) => span,
+        }
+    }
+
+    pub fn span_if_local(self, id: DefId) -> Option {
+        id.is_local().then(|| self.tcx.def_span(id))
+    }
+
+    pub fn res_span(self, res: Res) -> Option {
+        match res {
+            Res::Err => None,
+            Res::Local(id) => Some(self.span(id)),
+            res => self.span_if_local(res.opt_def_id()?),
+        }
+    }
+
+    /// Get a representation of this `id` for debugging purposes.
+    /// NOTE: Do NOT use this in diagnostics!
+    pub fn node_to_string(self, id: HirId) -> String {
+        hir_id_to_string(self, id)
+    }
+
+    /// Returns the HirId of `N` in `struct Foo` when
+    /// called with the HirId for the `{ ... }` anon const
+    pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option {
+        let const_arg = self.tcx.parent_hir_id(anon_const);
+        match self.tcx.parent_hir_node(const_arg) {
+            Node::GenericParam(GenericParam {
+                def_id: param_id,
+                kind: GenericParamKind::Const { .. },
+                ..
+            }) => Some(*param_id),
+            _ => None,
+        }
+    }
+
+    pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option {
+        let local = match expr {
+            Expr {
+                kind:
+                    ExprKind::Path(QPath::Resolved(
+                        None,
+                        Path {
+                            res: def::Res::Local(_), segments: [PathSegment { ident, .. }], ..
+                        },
+                    )),
+                ..
+            } => Some(ident),
+            _ => None,
+        }?;
+
+        match self.tcx.parent_hir_node(expr.hir_id) {
+            Node::ExprField(field) => {
+                if field.ident.name == local.name && field.is_shorthand {
+                    return Some(local.name);
+                }
+            }
+            _ => {}
+        }
+
+        None
+    }
+}
+
+impl<'hir> intravisit::Map<'hir> for Map<'hir> {
+    fn hir_node(&self, hir_id: HirId) -> Node<'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)
+    }
+
+    fn item(&self, id: ItemId) -> &'hir Item<'hir> {
+        (*self).item(id)
+    }
+
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        (*self).trait_item(id)
+    }
+
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        (*self).impl_item(id)
+    }
+
+    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
+        (*self).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)
+    }
+}
+
+pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
+    let krate = tcx.hir_crate(());
+    let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
+
+    let upstream_crates = upstream_crates(tcx);
+
+    let resolutions = tcx.resolutions(());
+
+    // We hash the final, remapped names of all local source files so we
+    // don't have to include the path prefix remapping commandline args.
+    // If we included the full mapping in the SVH, we could only have
+    // reproducible builds by compiling from the same directory. So we just
+    // hash the result of the mapping instead of the mapping itself.
+    let mut source_file_names: Vec<_> = tcx
+        .sess
+        .source_map()
+        .files()
+        .iter()
+        .filter(|source_file| source_file.cnum == LOCAL_CRATE)
+        .map(|source_file| source_file.stable_id)
+        .collect();
+
+    source_file_names.sort_unstable();
+
+    // We have to take care of debugger visualizers explicitly. The HIR (and
+    // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
+    // these attributes only store the file path to the visualizer file, not
+    // their content. Yet that content is exported into crate metadata, so any
+    // changes to it need to be reflected in the crate hash.
+    let debugger_visualizers: Vec<_> = tcx
+        .debugger_visualizers(LOCAL_CRATE)
+        .iter()
+        // We ignore the path to the visualizer file since it's not going to be
+        // encoded in crate metadata and we already hash the full contents of
+        // the file.
+        .map(DebuggerVisualizerFile::path_erased)
+        .collect();
+
+    let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
+        let mut stable_hasher = StableHasher::new();
+        hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
+        upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
+        source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
+        debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
+        if tcx.sess.opts.incremental.is_some() {
+            let definitions = tcx.untracked().definitions.freeze();
+            let mut owner_spans: Vec<_> = krate
+                .owners
+                .iter_enumerated()
+                .filter_map(|(def_id, info)| {
+                    let _ = info.as_owner()?;
+                    let def_path_hash = definitions.def_path_hash(def_id);
+                    let span = tcx.source_span(def_id);
+                    debug_assert_eq!(span.parent(), None);
+                    Some((def_path_hash, span))
+                })
+                .collect();
+            owner_spans.sort_unstable_by_key(|bn| bn.0);
+            owner_spans.hash_stable(&mut hcx, &mut stable_hasher);
+        }
+        tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
+        tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher);
+        // Hash visibility information since it does not appear in HIR.
+        // FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on
+        // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`,
+        // and combining it with other hashes here.
+        resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher);
+        with_metavar_spans(|mspans| {
+            mspans.freeze_and_get_read_spans().hash_stable(&mut hcx, &mut stable_hasher);
+        });
+        stable_hasher.finish()
+    });
+
+    Svh::new(crate_hash)
+}
+
+fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
+    let mut upstream_crates: Vec<_> = tcx
+        .crates(())
+        .iter()
+        .map(|&cnum| {
+            let stable_crate_id = tcx.stable_crate_id(cnum);
+            let hash = tcx.crate_hash(cnum);
+            (stable_crate_id, hash)
+        })
+        .collect();
+    upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
+    upstream_crates
+}
+
+fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
+    let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id);
+
+    let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
+    let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
+
+    match map.tcx.hir_node(id) {
+        Node::Item(item) => {
+            let item_str = match item.kind {
+                ItemKind::ExternCrate(..) => "extern crate",
+                ItemKind::Use(..) => "use",
+                ItemKind::Static(..) => "static",
+                ItemKind::Const(..) => "const",
+                ItemKind::Fn { .. } => "fn",
+                ItemKind::Macro(..) => "macro",
+                ItemKind::Mod(..) => "mod",
+                ItemKind::ForeignMod { .. } => "foreign mod",
+                ItemKind::GlobalAsm(..) => "global asm",
+                ItemKind::TyAlias(..) => "ty",
+                ItemKind::Enum(..) => "enum",
+                ItemKind::Struct(..) => "struct",
+                ItemKind::Union(..) => "union",
+                ItemKind::Trait(..) => "trait",
+                ItemKind::TraitAlias(..) => "trait alias",
+                ItemKind::Impl { .. } => "impl",
+            };
+            format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
+        }
+        Node::ForeignItem(item) => {
+            format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
+        }
+        Node::ImplItem(ii) => {
+            let kind = match ii.kind {
+                ImplItemKind::Const(..) => "associated constant",
+                ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+                    ImplicitSelfKind::None => "associated function",
+                    _ => "method",
+                },
+                ImplItemKind::Type(_) => "associated type",
+            };
+            format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
+        }
+        Node::TraitItem(ti) => {
+            let kind = match ti.kind {
+                TraitItemKind::Const(..) => "associated constant",
+                TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+                    ImplicitSelfKind::None => "associated function",
+                    _ => "trait method",
+                },
+                TraitItemKind::Type(..) => "associated type",
+            };
+
+            format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
+        }
+        Node::Variant(variant) => {
+            format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
+        }
+        Node::Field(field) => {
+            format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
+        }
+        Node::AnonConst(_) => node_str("const"),
+        Node::ConstBlock(_) => node_str("const"),
+        Node::ConstArg(_) => node_str("const"),
+        Node::Expr(_) => node_str("expr"),
+        Node::ExprField(_) => node_str("expr field"),
+        Node::Stmt(_) => node_str("stmt"),
+        Node::PathSegment(_) => node_str("path segment"),
+        Node::Ty(_) => node_str("type"),
+        Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
+        Node::TraitRef(_) => node_str("trait ref"),
+        Node::OpaqueTy(_) => node_str("opaque type"),
+        Node::Pat(_) => node_str("pat"),
+        Node::TyPat(_) => node_str("pat ty"),
+        Node::PatField(_) => node_str("pattern field"),
+        Node::PatExpr(_) => node_str("pattern literal"),
+        Node::Param(_) => node_str("param"),
+        Node::Arm(_) => node_str("arm"),
+        Node::Block(_) => node_str("block"),
+        Node::Infer(_) => node_str("infer"),
+        Node::LetStmt(_) => node_str("local"),
+        Node::Ctor(ctor) => format!(
+            "{id} (ctor {})",
+            ctor.ctor_def_id().map_or("".into(), |def_id| path_str(def_id)),
+        ),
+        Node::Lifetime(_) => node_str("lifetime"),
+        Node::GenericParam(param) => {
+            format!("{id} (generic_param {})", path_str(param.def_id))
+        }
+        Node::Crate(..) => String::from("(root_crate)"),
+        Node::WherePredicate(_) => node_str("where predicate"),
+        Node::Synthetic => unreachable!(),
+        Node::Err(_) => node_str("error"),
+        Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
+    }
+}
+
+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);
+    collector.visit_mod(hir_mod, span, hir_id);
+
+    let ItemCollector {
+        submodules,
+        items,
+        trait_items,
+        impl_items,
+        foreign_items,
+        body_owners,
+        opaques,
+        nested_bodies,
+        ..
+    } = collector;
+    ModuleItems {
+        submodules: submodules.into_boxed_slice(),
+        free_items: items.into_boxed_slice(),
+        trait_items: trait_items.into_boxed_slice(),
+        impl_items: impl_items.into_boxed_slice(),
+        foreign_items: foreign_items.into_boxed_slice(),
+        body_owners: body_owners.into_boxed_slice(),
+        opaques: opaques.into_boxed_slice(),
+        nested_bodies: nested_bodies.into_boxed_slice(),
+    }
+}
+
+pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
+    let mut collector = ItemCollector::new(tcx, true);
+
+    // A "crate collector" and "module collector" start at a
+    // 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);
+
+    let ItemCollector {
+        submodules,
+        items,
+        trait_items,
+        impl_items,
+        foreign_items,
+        body_owners,
+        opaques,
+        nested_bodies,
+        ..
+    } = collector;
+
+    ModuleItems {
+        submodules: submodules.into_boxed_slice(),
+        free_items: items.into_boxed_slice(),
+        trait_items: trait_items.into_boxed_slice(),
+        impl_items: impl_items.into_boxed_slice(),
+        foreign_items: foreign_items.into_boxed_slice(),
+        body_owners: body_owners.into_boxed_slice(),
+        opaques: opaques.into_boxed_slice(),
+        nested_bodies: nested_bodies.into_boxed_slice(),
+    }
+}
+
+struct ItemCollector<'tcx> {
+    // When true, it collects all items in the create,
+    // otherwise it collects items in some module.
+    crate_collector: bool,
+    tcx: TyCtxt<'tcx>,
+    submodules: Vec,
+    items: Vec,
+    trait_items: Vec,
+    impl_items: Vec,
+    foreign_items: Vec,
+    body_owners: Vec,
+    opaques: Vec,
+    nested_bodies: Vec,
+}
+
+impl<'tcx> ItemCollector<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, crate_collector: bool) -> ItemCollector<'tcx> {
+        ItemCollector {
+            crate_collector,
+            tcx,
+            submodules: Vec::default(),
+            items: Vec::default(),
+            trait_items: Vec::default(),
+            impl_items: Vec::default(),
+            foreign_items: Vec::default(),
+            body_owners: Vec::default(),
+            opaques: Vec::default(),
+            nested_bodies: Vec::default(),
+        }
+    }
+}
+
+impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
+    type NestedFilter = nested_filter::All;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+
+    fn visit_item(&mut self, item: &'hir Item<'hir>) {
+        if Node::Item(item).associated_body().is_some() {
+            self.body_owners.push(item.owner_id.def_id);
+        }
+
+        self.items.push(item.item_id());
+
+        // Items that are modules are handled here instead of in visit_mod.
+        if let ItemKind::Mod(module) = &item.kind {
+            self.submodules.push(item.owner_id);
+            // A module collector does not recurse inside nested modules.
+            if self.crate_collector {
+                intravisit::walk_mod(self, module, item.hir_id());
+            }
+        } else {
+            intravisit::walk_item(self, item)
+        }
+    }
+
+    fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
+        self.foreign_items.push(item.foreign_item_id());
+        intravisit::walk_foreign_item(self, item)
+    }
+
+    fn visit_anon_const(&mut self, c: &'hir AnonConst) {
+        self.body_owners.push(c.def_id);
+        intravisit::walk_anon_const(self, c)
+    }
+
+    fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
+        self.body_owners.push(c.def_id);
+        self.nested_bodies.push(c.def_id);
+        intravisit::walk_inline_const(self, c)
+    }
+
+    fn visit_opaque_ty(&mut self, o: &'hir OpaqueTy<'hir>) {
+        self.opaques.push(o.def_id);
+        intravisit::walk_opaque_ty(self, o)
+    }
+
+    fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
+        if let ExprKind::Closure(closure) = ex.kind {
+            self.body_owners.push(closure.def_id);
+            self.nested_bodies.push(closure.def_id);
+        }
+        intravisit::walk_expr(self, ex)
+    }
+
+    fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
+        if Node::TraitItem(item).associated_body().is_some() {
+            self.body_owners.push(item.owner_id.def_id);
+        }
+
+        self.trait_items.push(item.trait_item_id());
+        intravisit::walk_trait_item(self, item)
+    }
+
+    fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
+        if Node::ImplItem(item).associated_body().is_some() {
+            self.body_owners.push(item.owner_id.def_id);
+        }
+
+        self.impl_items.push(item.impl_item_id());
+        intravisit::walk_impl_item(self, item)
+    }
+}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
deleted file mode 100644
index 83c7bb0f52f..00000000000
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ /dev/null
@@ -1,1405 +0,0 @@
-use rustc_abi::ExternAbi;
-use rustc_ast::visit::{VisitorResult, walk_list};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in};
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::*;
-use rustc_hir_pretty as pprust_hir;
-use rustc_span::def_id::StableCrateId;
-use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans};
-
-use crate::hir::{ModuleItems, nested_filter};
-use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
-use crate::query::LocalCrate;
-use crate::ty::TyCtxt;
-
-// FIXME: the structure was necessary in the past but now it
-// only serves as "namespace" for HIR-related methods, and can be
-// removed if all the methods are reasonably renamed and moved to tcx
-// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
-#[derive(Copy, Clone)]
-pub struct Map<'hir> {
-    pub(super) tcx: TyCtxt<'hir>,
-}
-
-/// An iterator that walks up the ancestor tree of a given `HirId`.
-/// Constructed using `tcx.hir().parent_iter(hir_id)`.
-struct ParentHirIterator<'hir> {
-    current_id: HirId,
-    map: Map<'hir>,
-    // Cache the current value of `hir_owner_nodes` to avoid repeatedly calling the same query for
-    // the same owner, which will uselessly record many times the same query dependency.
-    current_owner_nodes: Option<&'hir OwnerNodes<'hir>>,
-}
-
-impl<'hir> ParentHirIterator<'hir> {
-    fn new(map: Map<'hir>, current_id: HirId) -> ParentHirIterator<'hir> {
-        ParentHirIterator { current_id, map, current_owner_nodes: None }
-    }
-}
-
-impl<'hir> Iterator for ParentHirIterator<'hir> {
-    type Item = HirId;
-
-    fn next(&mut self) -> Option {
-        if self.current_id == CRATE_HIR_ID {
-            return None;
-        }
-
-        let HirId { owner, local_id } = self.current_id;
-
-        let parent_id = if local_id == ItemLocalId::ZERO {
-            // We go from an owner to its parent, so clear the cache.
-            self.current_owner_nodes = None;
-            self.map.tcx.hir_owner_parent(owner)
-        } else {
-            let owner_nodes =
-                self.current_owner_nodes.get_or_insert_with(|| self.map.tcx.hir_owner_nodes(owner));
-            let parent_local_id = owner_nodes.nodes[local_id].parent;
-            // HIR indexing should have checked that.
-            debug_assert_ne!(parent_local_id, local_id);
-            HirId { owner, local_id: parent_local_id }
-        };
-
-        debug_assert_ne!(parent_id, self.current_id);
-
-        self.current_id = parent_id;
-        Some(parent_id)
-    }
-}
-
-/// An iterator that walks up the ancestor tree of a given `HirId`.
-/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
-pub struct ParentOwnerIterator<'hir> {
-    current_id: HirId,
-    map: Map<'hir>,
-}
-
-impl<'hir> Iterator for ParentOwnerIterator<'hir> {
-    type Item = (OwnerId, OwnerNode<'hir>);
-
-    fn next(&mut self) -> Option {
-        if self.current_id.local_id.index() != 0 {
-            self.current_id.local_id = ItemLocalId::ZERO;
-            let node = self.map.tcx.hir_owner_node(self.current_id.owner);
-            return Some((self.current_id.owner, node));
-        }
-        if self.current_id == CRATE_HIR_ID {
-            return None;
-        }
-
-        let parent_id = self.map.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
-        });
-        self.current_id = HirId::make_owner(parent_id.def_id);
-
-        let node = self.map.tcx.hir_owner_node(self.current_id.owner);
-        Some((self.current_id.owner, node))
-    }
-}
-
-impl<'tcx> TyCtxt<'tcx> {
-    #[inline]
-    fn expect_hir_owner_nodes(self, def_id: LocalDefId) -> &'tcx OwnerNodes<'tcx> {
-        self.opt_hir_owner_nodes(def_id)
-            .unwrap_or_else(|| span_bug!(self.def_span(def_id), "{def_id:?} is not an owner"))
-    }
-
-    #[inline]
-    pub fn hir_owner_nodes(self, owner_id: OwnerId) -> &'tcx OwnerNodes<'tcx> {
-        self.expect_hir_owner_nodes(owner_id.def_id)
-    }
-
-    #[inline]
-    fn opt_hir_owner_node(self, def_id: LocalDefId) -> Option> {
-        self.opt_hir_owner_nodes(def_id).map(|nodes| nodes.node())
-    }
-
-    #[inline]
-    pub fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> {
-        self.expect_hir_owner_nodes(def_id).node()
-    }
-
-    #[inline]
-    pub fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> {
-        self.hir_owner_nodes(owner_id).node()
-    }
-
-    /// Retrieves the `hir::Node` corresponding to `id`.
-    pub fn hir_node(self, id: HirId) -> Node<'tcx> {
-        self.hir_owner_nodes(id.owner).nodes[id.local_id].node
-    }
-
-    /// Retrieves the `hir::Node` corresponding to `id`.
-    #[inline]
-    pub fn hir_node_by_def_id(self, id: LocalDefId) -> Node<'tcx> {
-        self.hir_node(self.local_def_id_to_hir_id(id))
-    }
-
-    /// Returns `HirId` of the parent HIR node of node with this `hir_id`.
-    /// Returns the same `hir_id` if and only if `hir_id == CRATE_HIR_ID`.
-    ///
-    /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
-    pub fn parent_hir_id(self, hir_id: HirId) -> HirId {
-        let HirId { owner, local_id } = hir_id;
-        if local_id == ItemLocalId::ZERO {
-            self.hir_owner_parent(owner)
-        } else {
-            let parent_local_id = self.hir_owner_nodes(owner).nodes[local_id].parent;
-            // HIR indexing should have checked that.
-            debug_assert_ne!(parent_local_id, local_id);
-            HirId { owner, local_id: parent_local_id }
-        }
-    }
-
-    /// Returns parent HIR node of node with this `hir_id`.
-    /// Returns HIR node of the same `hir_id` if and only if `hir_id == CRATE_HIR_ID`.
-    pub fn parent_hir_node(self, hir_id: HirId) -> Node<'tcx> {
-        self.hir_node(self.parent_hir_id(hir_id))
-    }
-}
-
-impl<'hir> Map<'hir> {
-    #[inline]
-    pub fn krate(self) -> &'hir Crate<'hir> {
-        self.tcx.hir_crate(())
-    }
-
-    #[inline]
-    pub fn root_module(self) -> &'hir Mod<'hir> {
-        match self.tcx.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()
-    }
-
-    #[inline]
-    pub fn module_items(self, module: LocalModDefId) -> impl Iterator + 'hir {
-        self.tcx.hir_module_items(module).free_items()
-    }
-
-    pub fn 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)
-    }
-
-    pub fn 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)
-    }
-
-    #[inline]
-    pub fn 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)
-    }
-
-    pub fn get_if_local(self, id: DefId) -> Option> {
-        id.as_local().map(|id| self.tcx.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 item(self, id: ItemId) -> &'hir Item<'hir> {
-        self.tcx.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 impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        self.tcx.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 body(self, id: BodyId) -> &'hir Body<'hir> {
-        self.tcx.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
-    }
-
-    #[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()
-    }
-
-    #[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()
-    }
-
-    #[track_caller]
-    pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
-        for (_, node) in self.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);
-    }
-
-    /// 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:?}");
-        parent
-    }
-
-    pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
-        self.tcx.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.body(self.tcx.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);
-            span_bug!(
-                self.span(hir_id),
-                "body_owned_by: {} has no associated body",
-                self.node_to_string(hir_id)
-            );
-        })
-    }
-
-    pub fn body_param_names(self, id: BodyId) -> impl Iterator + 'hir {
-        self.body(id).params.iter().map(|arg| match arg.pat.kind {
-            PatKind::Binding(_, _, ident, _) => ident,
-            _ => Ident::empty(),
-        })
-    }
-
-    /// 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 {
-        let def_id = def_id.into();
-        match self.tcx.def_kind(def_id) {
-            DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
-                BodyOwnerKind::Const { inline: false }
-            }
-            DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
-            DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
-            DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure,
-            DefKind::Static { safety: _, mutability, nested: false } => {
-                BodyOwnerKind::Static(mutability)
-            }
-            dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
-        }
-    }
-
-    /// Returns the `ConstContext` of the body associated with this `LocalDefId`.
-    ///
-    /// Panics if `LocalDefId` does not have an associated body.
-    ///
-    /// 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 {
-        let def_id = def_id.into();
-        let ccx = match self.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) => {
-                ConstContext::ConstFn
-            }
-            BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
-            BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
-        };
-
-        Some(ccx)
-    }
-
-    /// Returns an iterator of the `DefId`s for all body-owners in this
-    /// 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()
-    }
-
-    #[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 ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
-        let def_kind = self.tcx.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)
-            }
-            _ => 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);
-        match def_kind {
-            DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
-            DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
-                self.tcx.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[..])
-    }
-
-    /// 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 rustc_coherence_is_core(self) -> bool {
-        self.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) {
-        let hir_id = HirId::make_owner(module.to_local_def_id());
-        match self.tcx.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:?}"),
-        }
-    }
-
-    /// 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
-    where
-        V: Visitor<'hir>,
-    {
-        let (top_mod, span, hir_id) = self.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
-    where
-        V: Visitor<'hir>,
-    {
-        let krate = self.krate();
-        for info in krate.owners.iter() {
-            if let MaybeOwner::Owner(info) = info {
-                for attrs in info.attrs.map.values() {
-                    walk_list!(visitor, visit_attribute, *attrs);
-                }
-            }
-        }
-        V::Result::output()
-    }
-
-    /// 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`.
-    ///
-    /// 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
-    where
-        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_foreign_item,
-            krate.foreign_items().map(|id| self.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
-    where
-        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_foreign_item,
-            module.foreign_items().map(|id| self.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(());
-        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(());
-        par_for_each_in(&crate_items.submodules[..], |module| {
-            f(LocalModDefId::new_unchecked(module.def_id))
-        })
-    }
-
-    #[inline]
-    pub fn try_par_for_each_module(
-        self,
-        f: impl Fn(LocalModDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
-    ) -> Result<(), ErrorGuaranteed> {
-        let crate_items = self.tcx.hir_crate_items(());
-        try_par_for_each_in(&crate_items.submodules[..], |module| {
-            f(LocalModDefId::new_unchecked(module.def_id))
-        })
-    }
-
-    /// 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]
-    pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator + 'hir {
-        ParentHirIterator::new(self, current_id)
-    }
-
-    /// 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]
-    pub fn parent_iter(self, current_id: HirId) -> impl Iterator)> {
-        self.parent_id_iter(current_id).map(move |id| (id, self.tcx.hir_node(id)))
-    }
-
-    /// 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]
-    pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
-        ParentOwnerIterator { current_id, map: self }
-    }
-
-    /// Checks if the node is left-hand side of an assignment.
-    pub fn is_lhs(self, id: HirId) -> bool {
-        match self.tcx.parent_hir_node(id) {
-            Node::Expr(expr) => match expr.kind {
-                ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
-                _ => false,
-            },
-            _ => false,
-        }
-    }
-
-    /// 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()
-    }
-
-    /// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
-    /// in the "tail" position of the function, in other words if it's likely to correspond
-    /// to the return type of the function.
-    ///
-    /// ```
-    /// fn foo(x: usize) -> bool {
-    ///     if x == 1 {
-    ///         true  // If `get_fn_id_for_return_block` gets passed the `id` corresponding
-    ///     } else {  // to this, it will return `foo`'s `HirId`.
-    ///         false
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// ```compile_fail,E0308
-    /// fn foo(x: usize) -> bool {
-    ///     loop {
-    ///         true  // If `get_fn_id_for_return_block` gets passed the `id` corresponding
-    ///     }         // to this, it will return `None`.
-    ///     false
-    /// }
-    /// ```
-    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));
-
-        // 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();
-        while let Some(cur_id) = iter.next() {
-            if enclosing_body_owner == cur_id {
-                break;
-            }
-
-            // A return statement is always the value returned from the enclosing body regardless of
-            // what the parent expressions are.
-            if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(cur_id) {
-                break;
-            }
-
-            // If the current expression's value doesnt get used as the parent expressions value then return `None`
-            if let Some(&parent_id) = iter.peek() {
-                match self.tcx.hir_node(parent_id) {
-                    // The current node is not the tail expression of the block expression parent expr.
-                    Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None,
-                    Node::Block(Block { expr: Some(e), .. })
-                        if matches!(e.kind, ExprKind::If(_, _, None)) =>
-                    {
-                        return None;
-                    }
-
-                    // The current expression's value does not pass up through these parent expressions
-                    Node::Block(Block { expr: None, .. })
-                    | Node::Expr(Expr { kind: ExprKind::Loop(..), .. })
-                    | Node::LetStmt(..) => return None,
-
-                    _ => {}
-                }
-            }
-        }
-
-        Some(enclosing_body_owner)
-    }
-
-    /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no
-    /// parent item is in this map. The "parent item" is the closest parent node
-    /// in the HIR which is recorded by the map and is an item, either an item
-    /// in a module, trait, or impl.
-    pub fn get_parent_item(self, hir_id: HirId) -> OwnerId {
-        if hir_id.local_id != ItemLocalId::ZERO {
-            // If this is a child of a HIR owner, return the owner.
-            hir_id.owner
-        } else if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() {
-            def_id
-        } else {
-            CRATE_OWNER_ID
-        }
-    }
-
-    /// When on an if expression, a match arm tail expression or a match arm, give back
-    /// the enclosing `if` or `match` expression.
-    ///
-    /// Used by error reporting when there's a type error in an if or match arm caused by the
-    /// expression needing to be unit.
-    pub fn get_if_cause(self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
-        for (_, node) in self.parent_iter(hir_id) {
-            match node {
-                Node::Item(_)
-                | Node::ForeignItem(_)
-                | Node::TraitItem(_)
-                | Node::ImplItem(_)
-                | Node::Stmt(Stmt { kind: StmtKind::Let(_), .. }) => break,
-                Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => {
-                    return Some(expr);
-                }
-                _ => {}
-            }
-        }
-        None
-    }
-
-    /// Returns the nearest enclosing scope. A scope is roughly an item or block.
-    pub fn get_enclosing_scope(self, hir_id: HirId) -> Option {
-        for (hir_id, node) in self.parent_iter(hir_id) {
-            if let Node::Item(Item {
-                kind:
-                    ItemKind::Fn { .. }
-                    | ItemKind::Const(..)
-                    | ItemKind::Static(..)
-                    | ItemKind::Mod(..)
-                    | ItemKind::Enum(..)
-                    | ItemKind::Struct(..)
-                    | ItemKind::Union(..)
-                    | ItemKind::Trait(..)
-                    | ItemKind::Impl { .. },
-                ..
-            })
-            | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(..), .. })
-            | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. })
-            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(..), .. })
-            | Node::Block(_) = node
-            {
-                return Some(hir_id);
-            }
-        }
-        None
-    }
-
-    /// Returns the defining scope for an opaque type definition.
-    pub fn get_defining_scope(self, id: HirId) -> HirId {
-        let mut scope = id;
-        loop {
-            scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
-            if scope == CRATE_HIR_ID || !matches!(self.tcx.hir_node(scope), Node::Block(_)) {
-                return scope;
-            }
-        }
-    }
-
-    pub fn get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
-        let parent = self.get_parent_item(hir_id);
-        if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) =
-            self.tcx.hir_owner_node(parent)
-        {
-            return *abi;
-        }
-        bug!(
-            "expected foreign mod or inlined parent, found {}",
-            self.node_to_string(HirId::make_owner(parent.def_id))
-        )
-    }
-
-    pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
-            OwnerNode::Item(item) => item,
-            _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
-        }
-    }
-
-    pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
-            OwnerNode::ImplItem(item) => item,
-            _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
-        }
-    }
-
-    pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
-            OwnerNode::TraitItem(item) => item,
-            _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
-        }
-    }
-
-    pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
-        Some(&self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.output)
-    }
-
-    pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Variant(variant) => variant,
-            _ => bug!("expected variant, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Field(field) => field,
-            _ => bug!("expected field, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
-        match self.tcx.hir_owner_node(id) {
-            OwnerNode::ForeignItem(item) => item,
-            _ => {
-                bug!(
-                    "expected foreign item, found {}",
-                    self.node_to_string(HirId::make_owner(id.def_id))
-                )
-            }
-        }
-    }
-
-    #[track_caller]
-    pub fn expect_opaque_ty(self, id: LocalDefId) -> &'hir OpaqueTy<'hir> {
-        match self.tcx.hir_node_by_def_id(id) {
-            Node::OpaqueTy(opaq) => opaq,
-            _ => {
-                bug!(
-                    "expected opaque type definition, found {}",
-                    self.node_to_string(self.tcx.local_def_id_to_hir_id(id))
-                )
-            }
-        }
-    }
-
-    pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Expr(expr) => expr,
-            _ => bug!("expected expr, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option {
-        self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
-    }
-
-    #[inline]
-    fn opt_ident(self, id: HirId) -> Option {
-        match self.tcx.hir_node(id) {
-            Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
-            // A `Ctor` doesn't have an identifier itself, but its parent
-            // struct/variant does. Compare with `hir::Map::span`.
-            Node::Ctor(..) => match self.tcx.parent_hir_node(id) {
-                Node::Item(item) => Some(item.ident),
-                Node::Variant(variant) => Some(variant.ident),
-                _ => unreachable!(),
-            },
-            node => node.ident(),
-        }
-    }
-
-    #[inline]
-    pub(super) fn opt_ident_span(self, id: HirId) -> Option {
-        self.opt_ident(id).map(|ident| ident.span)
-    }
-
-    #[inline]
-    pub fn ident(self, id: HirId) -> Ident {
-        self.opt_ident(id).unwrap()
-    }
-
-    #[inline]
-    pub fn opt_name(self, id: HirId) -> Option {
-        self.opt_ident(id).map(|ident| ident.name)
-    }
-
-    pub fn name(self, id: HirId) -> Symbol {
-        self.opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.node_to_string(id)))
-    }
-
-    /// Given a node ID, gets a list of attributes associated with the AST
-    /// corresponding to the node-ID.
-    pub fn attrs(self, id: HirId) -> &'hir [Attribute] {
-        self.tcx.hir_attrs(id.owner).get(id.local_id)
-    }
-
-    /// Gets the span of the definition of the specified HIR node.
-    /// This is used by `tcx.def_span`.
-    pub fn span(self, hir_id: HirId) -> Span {
-        fn until_within(outer: Span, end: Span) -> Span {
-            if let Some(end) = end.find_ancestor_inside(outer) {
-                outer.with_hi(end.hi())
-            } else {
-                outer
-            }
-        }
-
-        fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) -> Span {
-            if ident.name != kw::Empty {
-                let mut span = until_within(item_span, ident.span);
-                if let Some(g) = generics
-                    && !g.span.is_dummy()
-                    && let Some(g_span) = g.span.find_ancestor_inside(item_span)
-                {
-                    span = span.to(g_span);
-                }
-                span
-            } else {
-                item_span
-            }
-        }
-
-        let span = match self.tcx.hir_node(hir_id) {
-            // Function-like.
-            Node::Item(Item { kind: ItemKind::Fn { sig, .. }, span: outer_span, .. })
-            | Node::TraitItem(TraitItem {
-                kind: TraitItemKind::Fn(sig, ..),
-                span: outer_span,
-                ..
-            })
-            | Node::ImplItem(ImplItem {
-                kind: ImplItemKind::Fn(sig, ..), span: outer_span, ..
-            })
-            | Node::ForeignItem(ForeignItem {
-                kind: ForeignItemKind::Fn(sig, ..),
-                span: outer_span,
-                ..
-            }) => {
-                // Ensure that the returned span has the item's SyntaxContext, and not the
-                // SyntaxContext of the visibility.
-                sig.span.find_ancestor_in_same_ctxt(*outer_span).unwrap_or(*outer_span)
-            }
-            // Impls, including their where clauses.
-            Node::Item(Item {
-                kind: ItemKind::Impl(Impl { generics, .. }),
-                span: outer_span,
-                ..
-            }) => until_within(*outer_span, generics.where_clause_span),
-            // Constants and Statics.
-            Node::Item(Item {
-                kind: ItemKind::Const(ty, ..) | ItemKind::Static(ty, ..),
-                span: outer_span,
-                ..
-            })
-            | Node::TraitItem(TraitItem {
-                kind: TraitItemKind::Const(ty, ..),
-                span: outer_span,
-                ..
-            })
-            | Node::ImplItem(ImplItem {
-                kind: ImplItemKind::Const(ty, ..),
-                span: outer_span,
-                ..
-            })
-            | Node::ForeignItem(ForeignItem {
-                kind: ForeignItemKind::Static(ty, ..),
-                span: outer_span,
-                ..
-            }) => until_within(*outer_span, ty.span),
-            // With generics and bounds.
-            Node::Item(Item {
-                kind: ItemKind::Trait(_, _, generics, bounds, _),
-                span: outer_span,
-                ..
-            })
-            | Node::TraitItem(TraitItem {
-                kind: TraitItemKind::Type(bounds, _),
-                generics,
-                span: outer_span,
-                ..
-            }) => {
-                let end = if let Some(b) = bounds.last() { b.span() } else { generics.span };
-                until_within(*outer_span, end)
-            }
-            // Other cases.
-            Node::Item(item) => match &item.kind {
-                ItemKind::Use(path, _) => {
-                    // Ensure that the returned span has the item's SyntaxContext, and not the
-                    // SyntaxContext of the path.
-                    path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span)
-                }
-                _ => named_span(item.span, item.ident, item.kind.generics()),
-            },
-            Node::Variant(variant) => named_span(variant.span, variant.ident, None),
-            Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
-            Node::ForeignItem(item) => named_span(item.span, item.ident, None),
-            Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
-            Node::Expr(Expr {
-                kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
-                span,
-                ..
-            }) => {
-                // Ensure that the returned span has the item's SyntaxContext.
-                fn_decl_span.find_ancestor_inside(*span).unwrap_or(*span)
-            }
-            _ => self.span_with_body(hir_id),
-        };
-        debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt());
-        span
-    }
-
-    /// Like `hir.span()`, but includes the body of items
-    /// (instead of just the item header)
-    pub fn span_with_body(self, hir_id: HirId) -> Span {
-        match self.tcx.hir_node(hir_id) {
-            Node::Param(param) => param.span,
-            Node::Item(item) => item.span,
-            Node::ForeignItem(foreign_item) => foreign_item.span,
-            Node::TraitItem(trait_item) => trait_item.span,
-            Node::ImplItem(impl_item) => impl_item.span,
-            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::ConstArg(const_arg) => const_arg.span(),
-            Node::Expr(expr) => expr.span,
-            Node::ExprField(field) => field.span,
-            Node::Stmt(stmt) => stmt.span,
-            Node::PathSegment(seg) => {
-                let ident_span = seg.ident.span;
-                ident_span
-                    .with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi()))
-            }
-            Node::Ty(ty) => ty.span,
-            Node::AssocItemConstraint(constraint) => constraint.span,
-            Node::TraitRef(tr) => tr.path.span,
-            Node::OpaqueTy(op) => op.span,
-            Node::Pat(pat) => pat.span,
-            Node::TyPat(pat) => pat.span,
-            Node::PatField(field) => field.span,
-            Node::PatExpr(lit) => lit.span,
-            Node::Arm(arm) => arm.span,
-            Node::Block(block) => block.span,
-            Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
-            Node::Lifetime(lifetime) => lifetime.ident.span,
-            Node::GenericParam(param) => param.span,
-            Node::Infer(i) => i.span,
-            Node::LetStmt(local) => local.span,
-            Node::Crate(item) => item.spans.inner_span,
-            Node::WherePredicate(pred) => pred.span,
-            Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
-            Node::Synthetic => unreachable!(),
-            Node::Err(span) => span,
-        }
-    }
-
-    pub fn span_if_local(self, id: DefId) -> Option {
-        id.is_local().then(|| self.tcx.def_span(id))
-    }
-
-    pub fn res_span(self, res: Res) -> Option {
-        match res {
-            Res::Err => None,
-            Res::Local(id) => Some(self.span(id)),
-            res => self.span_if_local(res.opt_def_id()?),
-        }
-    }
-
-    /// Get a representation of this `id` for debugging purposes.
-    /// NOTE: Do NOT use this in diagnostics!
-    pub fn node_to_string(self, id: HirId) -> String {
-        hir_id_to_string(self, id)
-    }
-
-    /// Returns the HirId of `N` in `struct Foo` when
-    /// called with the HirId for the `{ ... }` anon const
-    pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option {
-        let const_arg = self.tcx.parent_hir_id(anon_const);
-        match self.tcx.parent_hir_node(const_arg) {
-            Node::GenericParam(GenericParam {
-                def_id: param_id,
-                kind: GenericParamKind::Const { .. },
-                ..
-            }) => Some(*param_id),
-            _ => None,
-        }
-    }
-
-    pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option {
-        let local = match expr {
-            Expr {
-                kind:
-                    ExprKind::Path(QPath::Resolved(
-                        None,
-                        Path {
-                            res: def::Res::Local(_), segments: [PathSegment { ident, .. }], ..
-                        },
-                    )),
-                ..
-            } => Some(ident),
-            _ => None,
-        }?;
-
-        match self.tcx.parent_hir_node(expr.hir_id) {
-            Node::ExprField(field) => {
-                if field.ident.name == local.name && field.is_shorthand {
-                    return Some(local.name);
-                }
-            }
-            _ => {}
-        }
-
-        None
-    }
-}
-
-impl<'hir> intravisit::Map<'hir> for Map<'hir> {
-    fn hir_node(&self, hir_id: HirId) -> Node<'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)
-    }
-
-    fn item(&self, id: ItemId) -> &'hir Item<'hir> {
-        (*self).item(id)
-    }
-
-    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        (*self).trait_item(id)
-    }
-
-    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        (*self).impl_item(id)
-    }
-
-    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        (*self).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)
-    }
-}
-
-pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
-    let krate = tcx.hir_crate(());
-    let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
-
-    let upstream_crates = upstream_crates(tcx);
-
-    let resolutions = tcx.resolutions(());
-
-    // We hash the final, remapped names of all local source files so we
-    // don't have to include the path prefix remapping commandline args.
-    // If we included the full mapping in the SVH, we could only have
-    // reproducible builds by compiling from the same directory. So we just
-    // hash the result of the mapping instead of the mapping itself.
-    let mut source_file_names: Vec<_> = tcx
-        .sess
-        .source_map()
-        .files()
-        .iter()
-        .filter(|source_file| source_file.cnum == LOCAL_CRATE)
-        .map(|source_file| source_file.stable_id)
-        .collect();
-
-    source_file_names.sort_unstable();
-
-    // We have to take care of debugger visualizers explicitly. The HIR (and
-    // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
-    // these attributes only store the file path to the visualizer file, not
-    // their content. Yet that content is exported into crate metadata, so any
-    // changes to it need to be reflected in the crate hash.
-    let debugger_visualizers: Vec<_> = tcx
-        .debugger_visualizers(LOCAL_CRATE)
-        .iter()
-        // We ignore the path to the visualizer file since it's not going to be
-        // encoded in crate metadata and we already hash the full contents of
-        // the file.
-        .map(DebuggerVisualizerFile::path_erased)
-        .collect();
-
-    let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
-        let mut stable_hasher = StableHasher::new();
-        hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
-        upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
-        source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
-        debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
-        if tcx.sess.opts.incremental.is_some() {
-            let definitions = tcx.untracked().definitions.freeze();
-            let mut owner_spans: Vec<_> = krate
-                .owners
-                .iter_enumerated()
-                .filter_map(|(def_id, info)| {
-                    let _ = info.as_owner()?;
-                    let def_path_hash = definitions.def_path_hash(def_id);
-                    let span = tcx.source_span(def_id);
-                    debug_assert_eq!(span.parent(), None);
-                    Some((def_path_hash, span))
-                })
-                .collect();
-            owner_spans.sort_unstable_by_key(|bn| bn.0);
-            owner_spans.hash_stable(&mut hcx, &mut stable_hasher);
-        }
-        tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
-        tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher);
-        // Hash visibility information since it does not appear in HIR.
-        // FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on
-        // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`,
-        // and combining it with other hashes here.
-        resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher);
-        with_metavar_spans(|mspans| {
-            mspans.freeze_and_get_read_spans().hash_stable(&mut hcx, &mut stable_hasher);
-        });
-        stable_hasher.finish()
-    });
-
-    Svh::new(crate_hash)
-}
-
-fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
-    let mut upstream_crates: Vec<_> = tcx
-        .crates(())
-        .iter()
-        .map(|&cnum| {
-            let stable_crate_id = tcx.stable_crate_id(cnum);
-            let hash = tcx.crate_hash(cnum);
-            (stable_crate_id, hash)
-        })
-        .collect();
-    upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
-    upstream_crates
-}
-
-fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
-    let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id);
-
-    let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
-    let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
-
-    match map.tcx.hir_node(id) {
-        Node::Item(item) => {
-            let item_str = match item.kind {
-                ItemKind::ExternCrate(..) => "extern crate",
-                ItemKind::Use(..) => "use",
-                ItemKind::Static(..) => "static",
-                ItemKind::Const(..) => "const",
-                ItemKind::Fn { .. } => "fn",
-                ItemKind::Macro(..) => "macro",
-                ItemKind::Mod(..) => "mod",
-                ItemKind::ForeignMod { .. } => "foreign mod",
-                ItemKind::GlobalAsm(..) => "global asm",
-                ItemKind::TyAlias(..) => "ty",
-                ItemKind::Enum(..) => "enum",
-                ItemKind::Struct(..) => "struct",
-                ItemKind::Union(..) => "union",
-                ItemKind::Trait(..) => "trait",
-                ItemKind::TraitAlias(..) => "trait alias",
-                ItemKind::Impl { .. } => "impl",
-            };
-            format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
-        }
-        Node::ForeignItem(item) => {
-            format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
-        }
-        Node::ImplItem(ii) => {
-            let kind = match ii.kind {
-                ImplItemKind::Const(..) => "associated constant",
-                ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
-                    ImplicitSelfKind::None => "associated function",
-                    _ => "method",
-                },
-                ImplItemKind::Type(_) => "associated type",
-            };
-            format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
-        }
-        Node::TraitItem(ti) => {
-            let kind = match ti.kind {
-                TraitItemKind::Const(..) => "associated constant",
-                TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
-                    ImplicitSelfKind::None => "associated function",
-                    _ => "trait method",
-                },
-                TraitItemKind::Type(..) => "associated type",
-            };
-
-            format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
-        }
-        Node::Variant(variant) => {
-            format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
-        }
-        Node::Field(field) => {
-            format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
-        }
-        Node::AnonConst(_) => node_str("const"),
-        Node::ConstBlock(_) => node_str("const"),
-        Node::ConstArg(_) => node_str("const"),
-        Node::Expr(_) => node_str("expr"),
-        Node::ExprField(_) => node_str("expr field"),
-        Node::Stmt(_) => node_str("stmt"),
-        Node::PathSegment(_) => node_str("path segment"),
-        Node::Ty(_) => node_str("type"),
-        Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
-        Node::TraitRef(_) => node_str("trait ref"),
-        Node::OpaqueTy(_) => node_str("opaque type"),
-        Node::Pat(_) => node_str("pat"),
-        Node::TyPat(_) => node_str("pat ty"),
-        Node::PatField(_) => node_str("pattern field"),
-        Node::PatExpr(_) => node_str("pattern literal"),
-        Node::Param(_) => node_str("param"),
-        Node::Arm(_) => node_str("arm"),
-        Node::Block(_) => node_str("block"),
-        Node::Infer(_) => node_str("infer"),
-        Node::LetStmt(_) => node_str("local"),
-        Node::Ctor(ctor) => format!(
-            "{id} (ctor {})",
-            ctor.ctor_def_id().map_or("".into(), |def_id| path_str(def_id)),
-        ),
-        Node::Lifetime(_) => node_str("lifetime"),
-        Node::GenericParam(param) => {
-            format!("{id} (generic_param {})", path_str(param.def_id))
-        }
-        Node::Crate(..) => String::from("(root_crate)"),
-        Node::WherePredicate(_) => node_str("where predicate"),
-        Node::Synthetic => unreachable!(),
-        Node::Err(_) => node_str("error"),
-        Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
-    }
-}
-
-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);
-    collector.visit_mod(hir_mod, span, hir_id);
-
-    let ItemCollector {
-        submodules,
-        items,
-        trait_items,
-        impl_items,
-        foreign_items,
-        body_owners,
-        opaques,
-        nested_bodies,
-        ..
-    } = collector;
-    ModuleItems {
-        submodules: submodules.into_boxed_slice(),
-        free_items: items.into_boxed_slice(),
-        trait_items: trait_items.into_boxed_slice(),
-        impl_items: impl_items.into_boxed_slice(),
-        foreign_items: foreign_items.into_boxed_slice(),
-        body_owners: body_owners.into_boxed_slice(),
-        opaques: opaques.into_boxed_slice(),
-        nested_bodies: nested_bodies.into_boxed_slice(),
-    }
-}
-
-pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
-    let mut collector = ItemCollector::new(tcx, true);
-
-    // A "crate collector" and "module collector" start at a
-    // 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);
-
-    let ItemCollector {
-        submodules,
-        items,
-        trait_items,
-        impl_items,
-        foreign_items,
-        body_owners,
-        opaques,
-        nested_bodies,
-        ..
-    } = collector;
-
-    ModuleItems {
-        submodules: submodules.into_boxed_slice(),
-        free_items: items.into_boxed_slice(),
-        trait_items: trait_items.into_boxed_slice(),
-        impl_items: impl_items.into_boxed_slice(),
-        foreign_items: foreign_items.into_boxed_slice(),
-        body_owners: body_owners.into_boxed_slice(),
-        opaques: opaques.into_boxed_slice(),
-        nested_bodies: nested_bodies.into_boxed_slice(),
-    }
-}
-
-struct ItemCollector<'tcx> {
-    // When true, it collects all items in the create,
-    // otherwise it collects items in some module.
-    crate_collector: bool,
-    tcx: TyCtxt<'tcx>,
-    submodules: Vec,
-    items: Vec,
-    trait_items: Vec,
-    impl_items: Vec,
-    foreign_items: Vec,
-    body_owners: Vec,
-    opaques: Vec,
-    nested_bodies: Vec,
-}
-
-impl<'tcx> ItemCollector<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, crate_collector: bool) -> ItemCollector<'tcx> {
-        ItemCollector {
-            crate_collector,
-            tcx,
-            submodules: Vec::default(),
-            items: Vec::default(),
-            trait_items: Vec::default(),
-            impl_items: Vec::default(),
-            foreign_items: Vec::default(),
-            body_owners: Vec::default(),
-            opaques: Vec::default(),
-            nested_bodies: Vec::default(),
-        }
-    }
-}
-
-impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_item(&mut self, item: &'hir Item<'hir>) {
-        if Node::Item(item).associated_body().is_some() {
-            self.body_owners.push(item.owner_id.def_id);
-        }
-
-        self.items.push(item.item_id());
-
-        // Items that are modules are handled here instead of in visit_mod.
-        if let ItemKind::Mod(module) = &item.kind {
-            self.submodules.push(item.owner_id);
-            // A module collector does not recurse inside nested modules.
-            if self.crate_collector {
-                intravisit::walk_mod(self, module, item.hir_id());
-            }
-        } else {
-            intravisit::walk_item(self, item)
-        }
-    }
-
-    fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
-        self.foreign_items.push(item.foreign_item_id());
-        intravisit::walk_foreign_item(self, item)
-    }
-
-    fn visit_anon_const(&mut self, c: &'hir AnonConst) {
-        self.body_owners.push(c.def_id);
-        intravisit::walk_anon_const(self, c)
-    }
-
-    fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
-        self.body_owners.push(c.def_id);
-        self.nested_bodies.push(c.def_id);
-        intravisit::walk_inline_const(self, c)
-    }
-
-    fn visit_opaque_ty(&mut self, o: &'hir OpaqueTy<'hir>) {
-        self.opaques.push(o.def_id);
-        intravisit::walk_opaque_ty(self, o)
-    }
-
-    fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
-        if let ExprKind::Closure(closure) = ex.kind {
-            self.body_owners.push(closure.def_id);
-            self.nested_bodies.push(closure.def_id);
-        }
-        intravisit::walk_expr(self, ex)
-    }
-
-    fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
-        if Node::TraitItem(item).associated_body().is_some() {
-            self.body_owners.push(item.owner_id.def_id);
-        }
-
-        self.trait_items.push(item.trait_item_id());
-        intravisit::walk_trait_item(self, item)
-    }
-
-    fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
-        if Node::ImplItem(item).associated_body().is_some() {
-            self.body_owners.push(item.owner_id.def_id);
-        }
-
-        self.impl_items.push(item.impl_item_id());
-        intravisit::walk_impl_item(self, item)
-    }
-}
-- 
cgit 1.4.1-3-g733a5


From cd1d84cdf76e86f2647eb7fd157047b73e76bdf5 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 10:54:00 +1100
Subject: 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 01e6fb89053..f57d1a5cc2c 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 83c7bb0f52f..2c5deecd746 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)
     }
-- 
cgit 1.4.1-3-g733a5


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: rustc_target: import TargetMetadata

---
 compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs      | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs  | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs   | 4 ++--
 .../src/spec/targets/aarch64_be_unknown_linux_gnu.rs             | 4 ++--
 .../src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs       | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs  | 4 ++--
 .../src/spec/targets/aarch64_nintendo_switch_freestanding.rs     | 5 +++--
 .../rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs  | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs     | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs     | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_illumos.rs     | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs   | 4 ++--
 .../src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs          | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs  | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs   | 4 ++--
 .../src/spec/targets/aarch64_unknown_none_softfloat.rs           | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs  | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs | 6 ++++--
 compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs   | 4 ++--
 .../rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs      | 4 ++--
 compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs       | 4 ++--
 compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs      | 4 ++--
 .../rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs  | 4 ++--
 .../rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs   | 4 ++--
 .../rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs | 4 ++--
 .../rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs  | 4 ++--
 .../src/spec/targets/arm_unknown_linux_musleabihf.rs             | 4 ++--
 .../rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs     | 5 +++--
 compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs   | 5 +++--
 compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs       | 5 +++--
 .../src/spec/targets/armv4t_unknown_linux_gnueabi.rs             | 4 ++--
 compiler/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 ++--
 compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs  | 4 ++--
 .../rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs    | 6 ++++--
 .../rustc_target/src/spec/targets/armv7_linux_androideabi.rs     | 6 ++++--
 compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs     | 5 +++--
 .../src/spec/targets/armv7_sony_vita_newlibeabihf.rs             | 6 ++++--
 compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs  | 4 ++--
 .../rustc_target/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 ++--
 .../rustc_target/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 ++--
 .../rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs   | 5 +++--
 .../rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs    | 4 ++--
 .../rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs  | 4 ++--
 .../src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs             | 4 ++--
 compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs       | 5 +++--
 compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs     | 5 +++--
 compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs      | 5 +++--
 compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs    | 5 +++--
 compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs       | 5 +++--
 compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs     | 5 +++--
 compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs       | 4 ++--
 compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs     | 5 +++--
 compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs     | 4 ++--
 .../rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs | 4 ++--
 .../src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs            | 4 ++--
 .../rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs  | 4 ++--
 .../rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/i386_apple_ios.rs         | 4 ++--
 compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs     | 9 ++-------
 compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs      | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_linux_android.rs     | 6 ++++--
 compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs    | 4 ++--
 .../rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs | 6 ++++--
 .../rustc_target/src/spec/targets/i686_unknown_linux_musl.rs     | 6 ++++--
 compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs    | 6 ++++--
 compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs      | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs | 4 ++--
 compiler/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 ++--
 .../rustc_target/src/spec/targets/loongarch64_unknown_none.rs    | 5 +++--
 .../src/spec/targets/loongarch64_unknown_none_softfloat.rs       | 5 +++--
 compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/m68k_unknown_none_elf.rs  | 4 ++--
 .../rustc_target/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 ++--
 compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs      | 6 ++++--
 compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs | 4 ++--
 .../rustc_target/src/spec/targets/mips_unknown_linux_musl.rs     | 4 ++--
 .../rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs    | 6 ++++--
 compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs        | 4 ++--
 compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs        | 6 ++++--
 .../rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs    | 4 ++--
 .../rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs   | 4 ++--
 .../rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs  | 4 ++--
 compiler/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 ++--
 .../src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs       | 4 ++--
 .../src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/msp430_none_elf.rs        | 6 ++++--
 compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs    | 5 +++--
 compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs      | 4 ++--
 .../rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs   | 6 ++++--
 .../rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs | 6 ++++--
 .../src/spec/targets/powerpc64_unknown_linux_musl.rs             | 6 ++++--
 .../rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs   | 6 ++++--
 compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs  | 6 ++++--
 .../rustc_target/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 ++++--
 .../rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs     | 6 ++++--
 .../rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs   | 6 ++++--
 .../src/spec/targets/powerpc_unknown_linux_gnuspe.rs             | 6 ++++--
 .../rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs  | 6 ++++--
 .../src/spec/targets/powerpc_unknown_linux_muslspe.rs            | 6 ++++--
 compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs | 6 ++++--
 .../rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs    | 6 ++++--
 .../rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs     | 6 ++++--
 compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs    | 4 ++--
 .../rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs   | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs  | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs | 4 ++--
 .../src/spec/targets/riscv32gc_unknown_linux_musl.rs             | 4 ++--
 .../rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs   | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs    | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs  | 6 ++++--
 .../rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs | 6 ++++--
 compiler/rustc_target/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 ++++--
 .../rustc_target/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 ++++--
 compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs  | 4 ++--
 .../rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs | 6 ++++--
 .../src/spec/targets/riscv32imc_unknown_nuttx_elf.rs             | 6 ++++--
 compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs  | 6 ++++--
 compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs    | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs   | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs   | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs    | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs | 4 ++--
 .../src/spec/targets/riscv64gc_unknown_linux_musl.rs             | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs    | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs  | 4 ++--
 .../rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs | 4 ++--
 .../rustc_target/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 ++--
 .../rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs     | 4 ++--
 .../rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs    | 4 ++--
 .../rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs | 4 ++--
 .../rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs     | 4 ++--
 .../rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs | 6 ++++--
 compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs     | 5 +++--
 compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs  | 4 ++--
 .../rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs    | 6 ++++--
 .../rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs    | 4 ++--
 .../src/spec/targets/thumbv7neon_linux_androideabi.rs            | 4 ++--
 .../src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs      | 4 ++--
 .../src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs     | 4 ++--
 .../rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs     | 4 ++--
 .../rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs    | 4 ++--
 .../rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs     | 4 ++--
 .../rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs   | 4 ++--
 .../rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs    | 4 ++--
 .../rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs  | 4 ++--
 .../rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs   | 5 +++--
 compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs          | 6 ++++--
 compiler/rustc_target/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 ++--
 compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs       | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs      | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs    | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs   | 5 +++--
 compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs      | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs  | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs  | 6 ++++--
 .../rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs | 6 ++++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs  | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs  | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs    | 6 ++++--
 .../rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs   | 6 ++++--
 .../rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs   | 6 ++++--
 .../rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs   | 6 ++++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs  | 5 +++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs  | 5 +++--
 compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs     | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs     | 4 ++--
 .../rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs    | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs   | 4 ++--
 compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs    | 9 ++-------
 compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs  | 4 ++--
 compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs  | 9 ++-------
 .../rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs     | 4 ++--
 compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs  | 9 ++-------
 .../rustc_target/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 adee6f5fe99..d3e0a32c8b8 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 efc42b909e4..183a6c6f2d7 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 be503d18bf1..ce9ae03e699 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 04bbee45cd3..4405e3fec02 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 fa0bc130e1c..037685db1b3 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 428045da493..a386220e6fc 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 9817c5a8eb0..2c1dfdd55ed 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 d411f710540..c0b8b409797 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 abd924b5934..23596271107 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 ba85647fddc..62968f5b555 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 de6fe991460..87c07cd3109 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 8fdaff822fe..e785069c78a 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 4e1e95ab751..97742403c78 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 58fc703946e..f58aa1ac043 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 a021d317cc8..41c25393e12 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 6ac69e0f57f..9b81362b27d 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 8b96f589c74..a8b133d19bb 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 14ce5edd2f3..98d78520c98 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 dd90161f440..7306a75aa22 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 df13d52a223..23ed92e62b8 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 459e888eb94..580a36cb2e9 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 699376a7928..1ed4fdb465d 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 18711cb399d..c6be2c20ea2 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 7b0df7d1130..166bb1ed215 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 4fefdfa5c5e..58ba06e124c 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 14a22988a09..f2994b1232e 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 0ec76e4b42f..461730457aa 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 27dd713cc53..6c14f5df466 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 3b719ebaf07..35a4dd72b86 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 f7f8dc1e1ef..243d84a12ec 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 0fcf5c34bb0..c23006adad6 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 7ff99c574ad..39fe71528d3 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 fb8b59f7729..799ff1a806e 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 cebd8ff2f68..126f0251239 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 9656024ddaa..327b52389b9 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 3d7c0269808..a40c8c3a3f2 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 ac53cbaecce..b6826760183 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 bb488c350c2..f20782cabb8 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 a5a6f772ac8..4c3a2f43743 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 744d95445b8..79b95dbde52 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 dace11dae24..848dbeec199 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 2ccdc76c52e..3dbe169e826 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 5026c52429e..bb3e3e544cb 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 73fb02c6731..d74468899f5 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 87e790a1f39..3b6c97167cf 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 6470bf6b611..a3f5389f0aa 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 26241dd0bd4..3919a5e0771 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 4bbde7667b9..ca52e5b3ca6 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 60ec4edbb0d..afb17fd8203 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 18b93f6cbc4..d227d63c4a3 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 6c22cd34fc3..c373afb914e 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 dc8cb4fb187..9571821656c 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 081132b0e68..beaec71093c 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 e0a4f26f0a6..75ab941c5cf 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 ce7060b3847..52e786de3ed 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 62619546891..e675739629b 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 73013bf00b1..dbe1540364a 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 4bbc514f2b3..1625a6b84bb 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 6b9d3ccd215..af9a4359565 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 5438811803b..4c32a5e6216 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 e1cead9e0b7..706fb12a524 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 4e8a9d55f9a..c17db36ee61 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 4b2ab8b8f20..5d292bbf8ad 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 34f118d4f5d..56f2e090e07 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 bb28427c99b..603afe2c48b 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 6bffc0da87b..3b5a337b4f1 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 0436e0d8df4..42fbf6f4861 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 22e49f2f1b0..a3ac0223c84 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 d1261202124..f31dedb04e6 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 ffcd8876eb4..a9e9f4651bb 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 586bd8d3d88..a95f12d0230 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 28d3d572bf3..d155dc58e51 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 b86c788df15..31d492e83cd 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 212c45424db..05be389b57c 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 2ed10045412..26c25139989 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 c9c15b402ae..7032444bea4 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 d59849ec2c4..fb1d7d6c39d 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 06481e6f882..df3a76599a7 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 08cbfc74396..052285b98dc 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 f68c11a9c68..85543e95616 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 e232f54f9b3..8103d132cea 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 1eda0545169..334be483daa 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 d4e85bc9b0a..2bb3e70483a 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 1c3040de06e..ba9edd71461 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 3df42a1482c..8cf1ff95751 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 b95f93c3553..3d39cd26c65 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 711bbb04b19..51f45b01244 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 c90d3bcc6ae..6142c1541f0 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 d0583b7866b..c233ec3ada7 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 003600c26cc..f7416a7e0fd 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 730b19abd2b..e5a927d0953 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 41c5fafe341..29865fcd4c4 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 6aa34f157ab..39a71cf1781 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 29ef8b883a1..08281eda42e 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 6adf690e0dd..161db9a08bb 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 7d61d5ca257..f2d7ec66443 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 06dbf1e3a16..2a26323e514 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 05d848e0393..2e2ea8f81be 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 e0e47113087..6a95afa1d0d 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 71c26041a50..1dfea64ebed 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 464ac46b07c..ab329170a4f 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 2f93e97d9fc..b01f93f7404 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 fe699dbcb51..c70c026f9f7 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 3d25c951e81..47a7eb3d597 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 4bc6eee1ac2..cbd61cadb36 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 a3bdf66a14d..48f7be7dc2b 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 736b9131022..1a7923ca89b 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 0e1b65ef598..d95f779774f 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 44cf9b1adda..fa7a103df79 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 e9100da14cb..f364c2cb032 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 94284a2fe72..233a1c4fd7a 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 4e801955d0c..63ede7b4ab8 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 603c0f99314..9e743a35529 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 d7044dde0f1..d9010b1e4ee 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 11d05db6b0a..c1c859ef25c 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 db527c8b636..91e3064aaed 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 221ca02fe3e..24983900683 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 d3584a1be74..9bd02e842c2 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 8b8693b55c5..6b66052692a 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 4880e993722..1300280e35b 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 daf6d5de4c0..b130ca29c7f 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 03c8fa92450..4ea7c7bff44 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 c7d24871225..a9afea27ef3 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 5e7c37fd46c..7bdd9edda70 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 2815d995c31..def12122416 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 19cf62d19f6..29a451b31a6 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 dbca90ba569..82f2fda7fff 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 c26c7867ec7..0955b3debea 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 f532643b56a..cc9c19e4a0b 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 2c63b0f2f38..37ebb3d174b 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 1b8f9b71e93..8475a43ea63 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 08226449358..6c7ea5c5688 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 339b32b6339..d008bb55189 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 88474e71848..08c4347fe01 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 400e05f1478..502d7382b3c 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 bb8eb24908c..6a201c56475 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 c7b0a05d889..0716f2e483b 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 c75023385c2..81f2424e4de 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 49bec90022c..3eefa27ea04 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 60bda7a5996..0887180791c 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 80cb740450a..b067ac1e54a 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 80bfa358243..598f0f19f0d 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 2125c95e266..a1405188999 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 201ab0d534f..dba45776c94 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 1a2f2125942..1f67bc7f3c2 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 417c8b63c86..49413d27a45 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 15947fdb0ac..f5ca54291c6 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 d48c2f5e744..3e4a58f568a 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 13885c7326a..4640d537e8e 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 06ae54063ce..dd3f660d81e 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 f763c37f535..9e2bfe2c56f 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 d6a84f55f5e..5e1161e2f7d 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 6f3a2baf405..6cde4bd98ac 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 c4d894823e6..03bae9b5977 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 5b5fea666bb..316b62d941b 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 dfd99635ddd..df4fd75b0bd 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 7492077bb88..47a61a1aff2 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 dd82a6a71cd..bc5a50a0539 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 c4f93c60d3e..ca78be2b2b2 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 0284c50bd65..e6345629f03 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 4d3df78a563..55dc6a70627 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 771ffac7d80..00e8532d238 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 3b81c278d3a..f814201601f 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 c18b51ad46e..33df429db72 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 e9c57b99b92..6dda346aaaf 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 a07429bb0c5..ba10e3c6881 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 0e0e13fd1d8..f9a3b217220 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 669c1702fda..162f21c42ba 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 477a6c0e9eb..47b408a12d1 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 68146788d20..a173fb00b32 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 e12c3af6f8f..48db9f44eac 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 adc76f3cdb5..1608f051ea8 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 3eb3d18faf4..4ee02c6b295 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 88d112a012d..0893bd5ad6d 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 0d5eda708d1..0929af7bb75 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 7395e1a6aad..44a84d9082c 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 7864f7f8f9a..8908c0c53d9 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 cec97f86538..82a4d58a398 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 0e00fc69b41..755ffc6154a 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 60d8ec576af..8da0b0e3e6b 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 f694a1cb60d..c8ef737b9e7 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 720549e6a01..58ded24b9c5 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 905bed76db4..ecf65677531 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 7a887b604c5..d673936f5f8 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 a24e24edc59..88b5dca284a 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 da2c272005d..8ffb622511d 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 0a4cc3b8be6..33b08fdcb05 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 9edec38f652..2b647e36f18 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 c32c57d92f7..d6f0a5499b9 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 2cbb8c19b84..bc6829897a4 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 6aacb04418e..75f508d8e93 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 d62ecc07a5d..5c5d4aa32a2 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 306b23d2787..0928250dba6 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 41aa400f3e0..e0d16a7bfa5 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 61c01eba70d..47050c1f769 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 3317fe51c33..a52dadba5a5 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 4c2b971c0f1..21eedc5b6bc 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 81d7bf9a628..b573bdf80a9 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 6abef79be96..ffef6967912 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 00cd7438f7e..c2f64998ddd 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 5b7d560a8e0..1c53e15837c 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 b0eefcab209..7221bd8d4ae 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 1439e4a939f..155e25211c1 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 4333a9c631c..3b4b94da057 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 dcf98acc41f..3c6133dc7ce 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 b5cb393f4b0..5660f97c8b5 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 1aa44a8cc93..d79970b0a0d 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 a62d03ba0d3..33da885cc1a 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 c9df66253b3..b4cc960939e 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 b5cf8ce74f4..c747d721b67 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 c7b54b94efa..309d32042a0 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 a3bc4013e53..57ef4e75e64 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 14bbe38257d..0518872dd62 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 50f7bc1f810..f261009d854 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 2a77f48a9cd..611795e58f1 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 de3ac26a2bd..d3a25163c53 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 120f13ae56d..cce49f274ac 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 1149b6d16eb..81c502bfead 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 823fb828e4d..b35f7bac93b 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 25a100e9c7e..4e5f6898651 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 47304e3027d..38143904efd 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 ddb5132ba60..55b7561da84 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 0bfe2b32ad4..56aca0a8829 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 9f75f23aa93..47525e704da 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 bdb1fc55711..4624c0fd5cb 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 bcf7b69fe74..b5792731a90 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 0862958d05d..26add451ed2 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 2411d386f52..44d906a507d 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 3f4618fad5a..7ad675dc3cf 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 ab1dc21d125..e554e2ac076 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 596e26d1e9d..e8ac93a87ca 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 52ef3fc88fd..2f868e38f1a 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 f421e6b8984..df45f430ecb 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 3687446b939..ee0c2bf31cd 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 07338a364e8..80ca80013f0 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 4a03c250e6f..c503baedb8b 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 60d078371bb..bbaee6c1f6d 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 d8f74f66f70..3a0acaa028c 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 843568a4792..662bbc4a31c 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 b10d4478d5e..16bdd3ee668 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 46c233f1863..1a03390c2b8 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 baf0d8b0c8b..d88aabaa6d3 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 8aa0128aaa3..a5723341fe6 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 6492d3d7d2f..715c0db632b 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 62cafd502e4..4a074539aab 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 a45f8159de0..d41c696ac23 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 b70b38dbbfe..ecb9fc80351 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 2e239cafe95..7abde771798 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 34835a20956..57ce67af36d 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 69715fc257f..17f90db0c90 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 db7e402cc80..a034a9fb244 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 59ec6c7f9d5..0c8353fad18 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 8a613477940..c5d556e5cc6 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 8dcdc5be8a9..cc5f8886240 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 2e63ff21572..896e8a78f86 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 522943c91a5..de9027ba962 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 e4972941957..0403c220982 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 e14a3673589..1a6343595f5 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 3135ecf45dc..2eb09b8cbad 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 43a28fca09a..65b8e2543a4 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 a6af06b03db..c7b002bc9bb 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 bce6aa0ebc6..07f853dacaf 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 0ef41d315af..bf6179cb6c3 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 31861c16099..50b0578da35 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 8f903934a90..df1fe8e7853 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 2eceb688108..876ac011879 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 f003f939ad1..9ab62b3530f 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 0f73a860821..11010b7d92f 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 b2a7c8551e4..c5b4d472fad 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 254ae54db21..d8638e8ac80 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 4fab2bac8e2..dd98f34d323 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 ae7bfbd0394..29bcf12cbaf 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 45d409a509f..dd6e7b6c3e8 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 023a67f2871..ddc909f387e 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),
-- 
cgit 1.4.1-3-g733a5


From 04ab8373c89d143feca797dfd5d501a98f59a43f Mon Sep 17 00:00:00 2001
From: Chayim Refael Friedman 
Date: Mon, 17 Feb 2025 02:26:02 +0200
Subject: 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 a0add4741f3..e47891bbdfe 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 9e3b70fa8ea..509ae3204c3 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)",
                 ]
             "#]],
         );
-- 
cgit 1.4.1-3-g733a5


From f86f7ad5f2d3eb6631e5fab57630a4fee9a50d01 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 10:45:49 +1100
Subject: 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 +-
 compiler/rustc_borrowck/src/diagnostics/mod.rs     |   2 +-
 .../rustc_borrowck/src/diagnostics/move_errors.rs  |   4 +-
 .../src/diagnostics/mutability_errors.rs           |  19 ++--
 .../src/diagnostics/region_errors.rs               |  17 ++-
 compiler/rustc_codegen_cranelift/src/driver/jit.rs |   2 +-
 compiler/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 +-
 compiler/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 +-
 compiler/rustc_hir_analysis/src/check/region.rs    |   4 +-
 compiler/rustc_hir_analysis/src/check/wfcheck.rs   |   2 +-
 .../rustc_hir_analysis/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 +-
 compiler/rustc_hir_analysis/src/collect/dump.rs    |   8 +-
 .../src/collect/resolve_bound_vars.rs              |  10 +-
 compiler/rustc_hir_analysis/src/collect/type_of.rs |   4 +-
 .../src/errors/wrong_number_of_generic_args.rs     |   2 +-
 .../src/hir_ty_lowering/errors.rs                  |   2 +-
 .../src/hir_ty_lowering/generics.rs                |   2 +-
 .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs  |   4 +-
 compiler/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 +-
 compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs     |   2 +-
 compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs    |  10 +-
 .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs    |   4 +-
 compiler/rustc_hir_typeck/src/lib.rs               |   2 +-
 compiler/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 +-
 compiler/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 +-
 .../rustc_lint/src/default_could_be_derived.rs     |   8 +-
 .../rustc_lint/src/for_loops_over_fallibles.rs     |   2 +-
 compiler/rustc_lint/src/late.rs                    |   4 +-
 compiler/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 +-
 compiler/rustc_mir_build/src/check_unsafety.rs     |   2 +-
 compiler/rustc_mir_build/src/errors.rs             |   3 +-
 .../src/thir/pattern/check_match.rs                |   2 +-
 compiler/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 +-
 .../src/error_reporting/infer/need_type_info.rs    |   2 +-
 .../mismatched_static_lifetime.rs                  |   2 +-
 .../infer/nice_region_error/static_impl_trait.rs   |   6 +-
 .../src/error_reporting/infer/note_and_explain.rs  |   4 +-
 .../src/error_reporting/infer/region.rs            |  12 +--
 .../src/error_reporting/infer/suggest.rs           |   5 +-
 .../error_reporting/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 +-
 compiler/rustc_trait_selection/src/traits/misc.rs  |   2 +-
 compiler/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 +-
 src/librustdoc/passes/calculate_doc_coverage.rs    |   2 +-
 src/librustdoc/visit_ast.rs                        |  12 +--
 .../src/arbitrary_source_item_ordering.rs          |   2 +-
 .../clippy/clippy_lints/src/async_yields_async.rs  |   4 +-
 src/tools/clippy/clippy_lints/src/attrs/utils.rs   |   6 +-
 src/tools/clippy/clippy_lints/src/booleans.rs      |   2 +-
 .../clippy_lints/src/collection_is_never_read.rs   |   2 +-
 .../clippy/clippy_lints/src/derivable_impls.rs     |   2 +-
 .../clippy/clippy_lints/src/doc/missing_headers.rs |   2 +-
 src/tools/clippy/clippy_lints/src/doc/mod.rs       |   4 +-
 src/tools/clippy/clippy_lints/src/empty_drop.rs    |   2 +-
 src/tools/clippy/clippy_lints/src/eta_reduction.rs |   2 +-
 .../src/extra_unused_type_parameters.rs            |   2 +-
 .../clippy/clippy_lints/src/fallible_impl_from.rs  |   4 +-
 src/tools/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/clippy_lints/src/functions/must_use.rs  |   6 +-
 .../src/functions/not_unsafe_ptr_arg_deref.rs      |   2 +-
 .../clippy/clippy_lints/src/implicit_hasher.rs     |   4 +-
 src/tools/clippy/clippy_lints/src/infinite_iter.rs |   2 +-
 .../clippy_lints/src/items_after_statements.rs     |   2 +-
 .../clippy_lints/src/items_after_test_module.rs    |   4 +-
 .../clippy_lints/src/iter_without_into_iter.rs     |   2 +-
 src/tools/clippy/clippy_lints/src/len_zero.rs      |   2 +-
 src/tools/clippy/clippy_lints/src/lifetimes.rs     |   2 +-
 .../clippy/clippy_lints/src/lines_filter_map_ok.rs |   2 +-
 .../clippy_lints/src/loops/needless_range_loop.rs  |   2 +-
 .../src/loops/while_let_on_iterator.rs             |   2 +-
 .../clippy/clippy_lints/src/manual_async_fn.rs     |   2 +-
 .../clippy_lints/src/manual_option_as_slice.rs     |   2 +-
 src/tools/clippy/clippy_lints/src/manual_retain.rs |   6 +-
 src/tools/clippy/clippy_lints/src/map_unit_fn.rs   |   2 +-
 .../src/methods/bind_instead_of_map.rs             |   2 +-
 .../clippy/clippy_lints/src/methods/bytecount.rs   |   2 +-
 .../clippy/clippy_lints/src/methods/filter_map.rs  |   6 +-
 .../src/methods/filter_map_bool_then.rs            |   4 +-
 .../clippy_lints/src/methods/format_collect.rs     |   2 +-
 .../clippy/clippy_lints/src/methods/iter_filter.rs |   2 +-
 .../clippy/clippy_lints/src/methods/iter_kv_map.rs |   2 +-
 .../src/methods/iter_overeager_cloned.rs           |   2 +-
 .../clippy_lints/src/methods/manual_inspect.rs     |   4 +-
 .../clippy_lints/src/methods/manual_ok_or.rs       |   2 +-
 .../clippy/clippy_lints/src/methods/map_clone.rs   |   2 +-
 .../clippy_lints/src/methods/map_err_ignore.rs     |   2 +-
 .../map_with_unused_argument_over_ranges.rs        |   2 +-
 src/tools/clippy/clippy_lints/src/methods/mod.rs   |   4 +-
 .../src/methods/needless_character_iteration.rs    |   2 +-
 .../clippy_lints/src/methods/needless_collect.rs   |   2 +-
 .../clippy_lints/src/methods/obfuscated_if_else.rs |   2 +-
 .../src/methods/option_as_ref_deref.rs             |   2 +-
 .../clippy_lints/src/methods/option_map_or_none.rs |   2 +-
 .../clippy/clippy_lints/src/methods/or_fun_call.rs |   2 +-
 .../src/methods/result_map_or_else_none.rs         |   2 +-
 .../clippy_lints/src/methods/return_and_then.rs    |   2 +-
 .../clippy_lints/src/methods/search_is_some.rs     |   2 +-
 .../clippy_lints/src/methods/suspicious_map.rs     |   2 +-
 .../src/methods/unnecessary_filter_map.rs          |   2 +-
 .../clippy_lints/src/methods/unnecessary_fold.rs   |   2 +-
 .../src/methods/unnecessary_lazy_eval.rs           |   2 +-
 .../src/methods/unnecessary_literal_unwrap.rs      |   2 +-
 .../clippy_lints/src/methods/unnecessary_map_or.rs |   2 +-
 .../src/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 +-
 .../clippy_lints/src/missing_fields_in_debug.rs    |   4 +-
 .../clippy/clippy_lints/src/missing_inline.rs      |   4 +-
 .../clippy/clippy_lints/src/needless_for_each.rs   |   2 +-
 .../clippy_lints/src/needless_pass_by_ref_mut.rs   |   3 +-
 .../clippy/clippy_lints/src/new_without_default.rs |   2 +-
 .../clippy/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 +-
 .../clippy_lints/src/redundant_closure_call.rs     |   4 +-
 src/tools/clippy/clippy_lints/src/returns.rs       |   2 +-
 .../clippy/clippy_lints/src/same_name_method.rs    |   4 +-
 .../clippy/clippy_lints/src/string_patterns.rs     |   2 +-
 .../clippy_lints/src/suspicious_trait_impl.rs      |   2 +-
 src/tools/clippy/clippy_lints/src/trait_bounds.rs  |   2 +-
 .../clippy/clippy_lints/src/types/borrowed_box.rs  |   4 +-
 .../clippy_lints/src/unconditional_recursion.rs    |   4 +-
 .../clippy_lints/src/undocumented_unsafe_blocks.rs |   6 +-
 .../clippy_lints/src/unit_return_expecting_ord.rs  |   2 +-
 .../clippy_lints/src/unit_types/let_unit_value.rs  |   2 +-
 src/tools/clippy/clippy_lints/src/unused_self.rs   |   2 +-
 .../clippy/clippy_lints/src/unwrap_in_result.rs    |   2 +-
 src/tools/clippy/clippy_lints/src/utils/author.rs  |   4 +-
 .../src/utils/internal_lints/collapsible_calls.rs  |   2 +-
 .../src/utils/internal_lints/invalid_paths.rs      |   2 +-
 .../utils/internal_lints/lint_without_lint_pass.rs |   2 +-
 .../clippy_lints/src/zero_repeat_side_effects.rs   |   3 +-
 .../clippy/clippy_utils/src/check_proc_macro.rs    |   2 +-
 src/tools/clippy/clippy_utils/src/consts.rs        |   8 +-
 src/tools/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 +-
 src/tools/clippy/tests/ui/author/blocks.stdout     |   4 +-
 .../clippy/tests/ui/author/macro_in_closure.stdout |   2 +-
 src/tools/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 facc9414b20..1c777111896 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 8fa409f4e38..4428d2246a1 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 3e474225afd..976d14bb245 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 df83ac985c6..07ea369c5c7 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 58c5c2fd774..c5449952f99 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 706dd7135f7..fc782ce6424 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 b7e2510e035..9c1baf870e1 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 2e713171ae0..57c88f4b0f9 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 c0a3ce84d52..54745b0d8c1 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 6749bc63327..5f95b6615bd 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 576b1c76823..ea17dd773c0 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 71a10ad3a0c..0d33aaa5d84 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 bb5087e864c..84d5ec4a1e5 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 0e9e9b48ab3..4973d848959 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 96b33bdd250..7b3c3ea2bb4 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 d43c65c0023..88dd40ba289 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 4218f4ef0c1..01b4a5649f1 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 9da57c330c5..b46b805f0a9 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 a86dede48bf..1805e2438af 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 c72f6201831..dc616576c9c 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 12623779956..6b430df8ed2 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 41f8465ae91..b4ba4d11221 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 c03a1f6240f..6bf0498a8b0 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 4e12db190fd..293a095b41d 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 b2501d647a5..681e8e36d58 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 7eb982a3179..d2789cc0fd6 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 43137397870..cc28b8780c6 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 88323db6dda..d5ccbdc11c8 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 ab50d9e86ef..4233896c372 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 036163b9f14..a0faa5e8429 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 f2d0b911731..bccde782264 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 43124f44ca6..71a0664bbdf 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 ad378367e30..c8433d0cb5b 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 85e949952f8..2f7f9148023 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 9ccd6746087..a41ad94f95e 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 4618c5d3849..ce6f7420e5b 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 1113f7f7095..ff41a080d62 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 77081548d11..7963688203a 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 4ec8d0b1f60..05c76b3c568 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 02fbd46173c..9d5184acb3c 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 6c4ad65be6a..1ca8b59db22 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 7c2a2b3fdf7..cd07666ca6c 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 b54e430a9d9..871d08137b3 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 1bf5b19d68d..dbcf9915790 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 82593dbc2b7..00600abb5f1 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 5d40b8ab2ee..02fb22bf782 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 ecd40a52e75..e449f110613 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 a67b404e6e1..c74158102c7 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 bae9defa687..59e38a882dd 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 0a5c52d65ec..59390b7e420 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 3ee908ba9bf..c0d3df17d77 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 154eb684f11..24689ea61d0 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 2c5deecd746..737b491ef57 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 7166c284c3d..11b430dd358 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 743ea33b20a..b84cc57234f 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 433f7542bd7..9450ce7ec44 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 1bd33475e60..8b6fcec3837 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 07bdc59756a..18a9002627a 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 697cb7cf37a..acc9a62326b 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 e195681bc92..081e7b1a43c 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 e4a733fcbce..1195c25e130 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 f578708b40c..e96db885131 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 95f18eaa7ef..696cc79bfeb 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 22291c9282d..c2225ea1e64 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 74038b24dcc..34d60d90be5 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 f7cae89852e..e60dcc807c9 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 875b6edb58c..23322be8f55 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 7788adb6e17..1fe44bd3d21 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 3842b7035e5..b8490da26f4 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 091773009e9..a618bae269f 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 9e7e96dddd7..57b614833af 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 886581bc35f..ad2f7f00fa5 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 039e21cb556..35fd4e588ef 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 e8d14b89d69..37032b53901 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 f35a5349ecb..d009687ef14 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 562000e28ac..bb25c5e8bd1 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 49fa21e50c0..ecfffb65fbc 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 e4f250ca4f5..d786d04b8f6 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 527d2e54e43..ac1ced2ed3c 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 62cac5b17bd..ac4399750f5 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 b752dbf3093..4601ddf678a 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 a0df74835bc..efe2386d014 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 79e178150de..a4b6f330b9d 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 2f72b44f6b6..7f3e3ce4781 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 34f461aac58..32d9469c296 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 9fcb16b0fca..dc63e1aa511 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 3d51ab1967d..0cdf1b98915 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 1d62a93e723..92ef3ab7a1d 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 5f7c30a33ab..8b424499724 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 5c146da03ac..390ff3de2fa 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 fcee2960979..bef59469179 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 135aa799060..45b8dafa907 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 e4628e4f837..5884e018f6a 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 f519a65fc27..aff40fa846b 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 eeaa3de3725..013819b0da8 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 152e6ec70a1..a667649f734 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 f8c30d1c881..f30f16997d7 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 8276e53648c..1279be34ed8 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 9569081ad08..bb445e0155f 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 8e2af6bf14a..d1ffbb6ffe2 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 42e1f7fd950..36baf492a54 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 10a84b1b2ff..d557a36c7ac 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 ae3acc1c4b1..d1782d582f4 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 5d93aceb33f..6ccea22e191 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 f822432cce6..f67d38d932b 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 5619cb0ab1b..ff75fcf2b41 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 9a73d0c0993..167377972db 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 752dbc0db4d..6d1c55d0693 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 e480805cac2..e6e3ea59a9f 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 8a74951ef63..906bbd006d4 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 47a5c19215b..1b39663f4f8 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 d3aade31f14..3cb47d8ef91 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 f5ad79a0027..021d43cefdd 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 1ac549b74ac..9df044f25eb 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 238f66d6675..173232c511a 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 26bea8d633a..98ba52f1270 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 860c0584acc..8eb45109d68 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 8206c75927b..f022598651b 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 2e6442156ef..e98c3c9698b 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 b7e37c1a876..e31b474c83f 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 9f3b0957eab..6f3a7d8cccc 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 5c40c945c69..e4360518b66 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 708980ac503..0a4e756096e 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 3221a04d2d0..56aead85e7c 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 91a5de16e96..1e9b29f567f 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 687272e550b..0498f317442 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 c1653b65e98..5b9df6c2bfd 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 d550c145466..f7e116c5310 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 3e5162ef458..1b28596d50d 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 30387ba62a7..76a0c0061e5 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 299f6d10112..518041177e9 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 5ccb5243e90..a80977459f2 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 20e4d233525..de37df2394d 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 4321dd6b0e0..8265c93bfe9 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 1252f7ccd35..b2705e1ffc2 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 162f0ac564d..5d0d4dae35f 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 78656ace831..35dd7c082c9 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 0a8eafad0e8..ccc5cd4fa41 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 6993150fb57..743aacf0588 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 2780c3f8af5..5664ffba1a0 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 b71f79f8482..e0905374dda 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 8d97d1c72a6..469fcccbe4f 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 193deafccf6..1a273f77fb7 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 6b39b753885..f5f404070ca 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 3b0dc506305..af619c9e3bb 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 7b1199ad1e2..68ffa81a278 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 4ab165a5528..97c8ce2bcdd 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 ed49233acb7..1bd48525f12 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 5b9e9e70e47..ca42a9ac04e 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 e7adf3b43ba..8e3cc9abe83 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 7af550fa7c6..9f4080100da 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 10112b62878..00690aca6d1 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 6dea1506d0e..5f88a7fd31f 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 dc50717112d..f84d0d6dff0 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 f0b29213e1e..fb4984914eb 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 7d72310c1c4..e80d99dca56 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 0aec26f1011..af466fe091c 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 82313257e5c..19152362fb5 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 e9ec23b1efa..675989156ca 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 18385ac9269..fdc0930e957 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 93e20f37ef8..90b27f5dbac 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 996251fdf16..6a1dc5e41a0 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 cc56df3a23d..cf407e51f7a 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 dad1e8a3d6a..448bb603cf2 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 22116505a1c..774a182d089 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 95403403217..73c31b83b51 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 65fd312b3a0..bc5e8fd2c25 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 91d023500ca..54e507655e9 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 a1cf16e6ce9..9f0ea84246d 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 29914d4379f..552135b15fd 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 3834087f797..694ad4f6347 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 e9779d437d4..9326b2adaff 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 790e0965198..cbf7b126632 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 2e97772407f..004ad03e708 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 207f2ef4563..16fe035802f 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 b3d26908093..c8e3c46f2f6 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 87478a120dd..67ceac92dbc 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 00b80e827d8..87f184e13ce 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 781f51aa9b0..d8305a62829 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 9b9a2ffbbc8..f870eb71e19 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 6bad78cf871..ce489054e16 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 eaeb754a23f..2e6fb7c4ce4 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 08c178ed229..252ac5e6768 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 dac1951489c..315c83507d0 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 05f85650769..30fdf22fdbb 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 59aaaa3d9fb..4f48fb3b8a9 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 db82c458f70..4f707e34abf 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 4bbf28115a6..9ee30094d60 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 79cc5066580..c4ba4c94c94 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 273c1b0defa..360c6251a57 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 088abd7c479..d5e0e2e3436 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 70910f5bf52..9b35ecee1dd 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 6bf48d5ba4e..54325f9776c 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 66caf382d89..3186d0cbc27 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 1a608734ada..f2c6b3f807f 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 c6bec4f77a0..84f6970c83a 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);
-- 
cgit 1.4.1-3-g733a5


From 661f99ba03738f1ee87888342aef920f3c0f7f48 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 3 Feb 2025 14:42:01 +1100
Subject: 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 +-
 .../rustc_borrowck/src/diagnostics/move_errors.rs  | 10 ++--
 compiler/rustc_hir/src/intravisit.rs               | 66 +++++++++++-----------
 compiler/rustc_hir_analysis/src/check/check.rs     |  4 +-
 compiler/rustc_hir_analysis/src/collect.rs         |  4 +-
 compiler/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 +++---
 compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs    |  4 +-
 compiler/rustc_incremental/src/assert_dep_graph.rs |  4 +-
 .../rustc_incremental/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 +++++------
 compiler/rustc_middle/src/hir/nested_filter.rs     | 10 ++--
 compiler/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 ++--
 .../src/error_reporting/infer/need_type_info.rs    |  4 +-
 .../infer/nice_region_error/find_anon_type.rs      |  9 ++-
 .../nice_region_error/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/clippy_lints/src/implicit_hasher.rs     |  4 +-
 .../clippy_lints/src/index_refutable_slice.rs      |  4 +-
 src/tools/clippy/clippy_lints/src/lifetimes.rs     |  8 +--
 src/tools/clippy/clippy_lints/src/loops/utils.rs   |  4 +-
 .../src/loops/while_let_on_iterator.rs             |  8 +--
 .../clippy_lints/src/methods/needless_collect.rs   |  4 +-
 .../src/methods/option_map_unwrap_or.rs            |  8 +--
 src/tools/clippy/clippy_lints/src/methods/utils.rs |  4 +-
 .../clippy_lints/src/mutable_debug_assertion.rs    |  4 +-
 src/tools/clippy/clippy_lints/src/ptr.rs           |  4 +-
 .../clippy_lints/src/redundant_closure_call.rs     |  4 +-
 .../clippy_lints/src/unconditional_recursion.rs    |  7 +--
 src/tools/clippy/clippy_lints/src/unused_async.rs  |  4 +-
 .../clippy/clippy_lints/src/unused_peekable.rs     |  4 +-
 src/tools/clippy/clippy_lints/src/unwrap.rs        |  4 +-
 .../utils/internal_lints/lint_without_lint_pass.rs |  2 +-
 .../clippy/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 4428d2246a1..59c76cb7f2b 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 976d14bb245..a88b27f2476 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 c5449952f99..38f22473edf 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 f57d1a5cc2c..949f8daa4dc 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 0d33aaa5d84..bc0fd4b705d 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 6b430df8ed2..75ea207a06b 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 b4ba4d11221..63c445fa6a3 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 6bf0498a8b0..5a8a2f1fe28 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 e2b9fe0f9f7..88d4acbdd8d 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 57df3127a02..34124a6aa11 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 7963688203a..c0af5ea7bbf 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 569034954c3..c2f9ebc5262 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 30590bf5d3c..a95599e7a86 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 c0d3df17d77..f17570e4a81 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 5a4ed68440a..7e13205bbf1 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 3ca4b3e235f..1ac2f6e81e5 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 737b491ef57..9bd35fdd6f0 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 adbe81bb22c..e18c28a8eac 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 081e7b1a43c..264995efe8f 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 e96db885131..396a0cbc889 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 34d60d90be5..43f2f892e77 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 600c46eb3d0..09d59e1f717 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 6eef0b926a1..0fd980af0b5 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 23322be8f55..cb17b0f6cf5 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 fd30d0d4867..d045e61d1d4 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 57b614833af..55eb3f777d6 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 b9f3abc2534..5a303c3cd03 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 bbcd28c0835..0695cc57978 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 d786d04b8f6..22d219cd64d 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 0cdf1b98915..e10a74221ae 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 390ff3de2fa..09e71f65c14 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 c4956bfd2b4..0d52e21419f 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 a15ac155123..fa2465c1926 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 599671bd4d4..dd9dbd7170e 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 5884e018f6a..f606a3d8a92 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 91ddbb44ff8..db3e6034c5b 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 36baf492a54..93c2b7a2d18 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 6ccea22e191..6a217b6182c 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 167377972db..41bf6e81916 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 1b39663f4f8..d2545e57652 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 15650c4f732..deac51ab4c4 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 8eb45109d68..f08812017b9 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 51fde5288ab..a5185d38e7c 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 e31b474c83f..6000ff7a360 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 5664ffba1a0..45f79dd44f2 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 7c4dc4ffb20..4a8a221e8c3 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 6e39e7be2c4..3611b341897 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 152635a5c35..13a23a13b9c 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 7fba4b6a6c8..9b241edf4cc 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 54e507655e9..1498a49a7a4 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 16fe035802f..529f85be372 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 d00bd7f2b3d..1c1c841e964 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 71aa57e0a14..0f9b05c84d4 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 6a952c0d97a..76b9bbbd32f 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 315c83507d0..e31da9e9f61 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 4df34891a2b..9bd00b1e5c8 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 c4ba4c94c94..ccf32f42a47 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 37f72966892..3bf518f7fe7 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 9b35ecee1dd..2ac0efd7e39 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>) {
-- 
cgit 1.4.1-3-g733a5


From f666361caa963c3f41934d5b431af24d8894d159 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Mon, 17 Feb 2025 13:24:07 +1100
Subject: 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 ea17dd773c0..093ee659bb4 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 9bd35fdd6f0..b44f14315d7 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 09e71f65c14..1ead87fd69d 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));
 
-- 
cgit 1.4.1-3-g733a5


From 9cbc31031444c1efee8ca9860f2b907c5c18d24e Mon Sep 17 00:00:00 2001
From: Nikita Popov 
Date: Mon, 17 Feb 2025 09:57:13 +0100
Subject: 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 110a7cc3424..bafa85c26e2 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].
-- 
cgit 1.4.1-3-g733a5


From 6fa3ad1e5e037d9b4f120573b852f06591bbe6f0 Mon Sep 17 00:00:00 2001
From: klensy 
Date: Mon, 17 Feb 2025 12:32:26 +0300
Subject: 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 1b5b791bb24..b8c73d25843 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,
-- 
cgit 1.4.1-3-g733a5


From f46c7652d54168dc617861d195e3ef87c08bd9c4 Mon Sep 17 00:00:00 2001
From: Miguel Ojeda 
Date: Mon, 17 Feb 2025 10:41:59 +0100
Subject: 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 3eb85ab215e..573821c3e59 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
 
-- 
cgit 1.4.1-3-g733a5


From b7a9a321265c0e9a597762c7c8107d4b7eba378b Mon Sep 17 00:00:00 2001
From: Chayim Refael Friedman 
Date: Mon, 17 Feb 2025 11:51:29 +0200
Subject: 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 +++++++++++++++++
 .../rust-analyzer/crates/hir-ty/src/infer/pat.rs   | 13 +++--------
 .../rust-analyzer/crates/hir-ty/src/infer/path.rs  | 26 ++++++++++++++++------
 .../ide-diagnostics/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 8c0446953a6..e4f5b5ed378 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 d0fe00ecebd..db93116f107 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 3794912ee98..6254bc12392 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 73dcbc13b79..7cf8282d052 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;
+}
+    "#,
+        );
+    }
 }
-- 
cgit 1.4.1-3-g733a5


From 33e7f9bc6681e32cc3b3b26ea85e21da225b89ee Mon Sep 17 00:00:00 2001
From: Pietro Albini 
Date: Mon, 17 Feb 2025 10:20:14 +0100
Subject: 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 ++++
 src/tools/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 3f5e701e7e1..2b17e02cae5 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 26d0f100ffd..c68b55f3589 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 59680af0062..1ec3e601cad 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 7cd8aacf0d6..e4a6e2b55e7 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 16c5b5e7104..b717bd53eb1 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 7b7cf0f4b69..79e90d88f44 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,
     )?;
-- 
cgit 1.4.1-3-g733a5


From a71de77ae9459e4f05ceb8695fce793b0ac00319 Mon Sep 17 00:00:00 2001
From: Pietro Albini 
Date: Mon, 17 Feb 2025 11:29:40 +0100
Subject: 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 f5395375afe..fd27b24e461 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 479327d6369..64a9b51ed5d 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 1291a634a6f..9d08adaae6b 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 62625fc3660..9389bed8e55 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 7cd8aacf0d6..2adb5993b4f 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 9b23cf1843e..f215c3f6d0b 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",
+    },
 ];
-- 
cgit 1.4.1-3-g733a5


From f6485ff6173c1077c0c960361cbf64039f2b5c15 Mon Sep 17 00:00:00 2001
From: Martin Nordholts 
Date: Mon, 17 Feb 2025 08:00:37 +0100
Subject: 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 bdbe3e21994..0af69dff05a 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"]
-- 
cgit 1.4.1-3-g733a5


From 19fa3deab30f89b0c5fb0b7144a074d95a35ab5e Mon Sep 17 00:00:00 2001
From: Laurențiu Nicola 
Date: Mon, 17 Feb 2025 13:20:07 +0200
Subject: 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 f414893b6cd..4006d06e4fe 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-d9a4a47b8b3dc0bdff83360cea2013200d60d49c
+273465e1f2932a30a5b56ac95859cdc86f3f33fa
-- 
cgit 1.4.1-3-g733a5


From 1873bd37201f1b9086fddab7a1a9b0acded7f10f Mon Sep 17 00:00:00 2001
From: WANG Rui 
Date: Mon, 17 Feb 2025 17:45:47 +0800
Subject: 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.
---
 .../dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig      | 2 ++
 .../dist-loongarch64-musl/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 576f3631cd5..aa33f72268e 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 3ab676ed971..3ccbc583c1b 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
-- 
cgit 1.4.1-3-g733a5


From 952bfae057206f01c3afd126752389eef353b56a Mon Sep 17 00:00:00 2001
From: Laurențiu Nicola 
Date: Mon, 17 Feb 2025 14:11:12 +0200
Subject: 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 44c628e8294..924ffb8dd21 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.
 
-- 
cgit 1.4.1-3-g733a5


From bce3d0ff1cc4182b096a86d31e5944b55c1a8105 Mon Sep 17 00:00:00 2001
From: Laurențiu Nicola 
Date: Mon, 17 Feb 2025 14:50:39 +0200
Subject: 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 98268d8f844..6d7f6042dec 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",
-- 
cgit 1.4.1-3-g733a5


From 711247413465fc015420574d6afe929186ab0bb4 Mon Sep 17 00:00:00 2001
From: Thalia Archibald 
Date: Sun, 16 Feb 2025 22:11:46 -0800
Subject: 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 83b009c86dc..6001a2e2f39 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 783623552bb..45fe7e093cd 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 cc424141ea8..70b5400bde4 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 9585ec24f68..45e93deffa3 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 00cfa7a7fcf..e13ce580d45 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 9585ec24f68..45e93deffa3 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 faf3edd5da6..513f038b554 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 62d4d727432..9b283a7a117 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()? })
     }
-- 
cgit 1.4.1-3-g733a5


From 92f31b95c92cb0a34413a52793a50c7d4334dbb2 Mon Sep 17 00:00:00 2001
From: Pietro Albini 
Date: Mon, 17 Feb 2025 10:29:51 +0100
Subject: 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 ae3761a97e5..c33f11f684f 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 c68b55f3589..410dbc04f03 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,
+}
-- 
cgit 1.4.1-3-g733a5


From 30c7956aed5438547334aa8c91d2921f8ad390e8 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez 
Date: Mon, 17 Feb 2025 17:06:26 +0100
Subject: 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 e9ee3c6b36e..4731b337067 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 c593cdcbcd2..c07cc4dc347 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" }
-- 
cgit 1.4.1-3-g733a5


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

---
 .../src/solve/assembly/mod.rs                      | 37 +++++++++++++++++-----
 1 file changed, 29 insertions(+), 8 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 b0f59ed1474..bfb590e8767 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
+
+                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 => candidates.iter().map(|c| c.result).collect(),
-        };
+            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);
+                }
 
-        self.try_merge_responses(&responses).map_or_else(|| self.flounder(&responses), Ok)
+                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)
+                }
+            }
+        }
     }
 }
-- 
cgit 1.4.1-3-g733a5


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

---
 .../src/check/compare_impl_item.rs                 | 64 ++++++++--------------
 .../issue-91883.current.stderr                     | 27 +++++++++
 .../issue-91883.next.stderr                        | 20 +++++++
 tests/ui/generic-associated-types/issue-91883.rs   |  4 ++
 .../ui/generic-associated-types/issue-91883.stderr | 27 ---------
 .../impl-trait/in-trait/default-body-with-rpit.rs  |  3 +
 .../ui/impl-trait/in-trait/nested-rpitit-bounds.rs |  3 +
 .../const-traits/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 +++++
 11 files changed, 111 insertions(+), 91 deletions(-)
 create mode 100644 tests/ui/generic-associated-types/issue-91883.current.stderr
 create mode 100644 tests/ui/generic-associated-types/issue-91883.next.stderr
 delete mode 100644 tests/ui/generic-associated-types/issue-91883.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 84d5ec4a1e5..79cf86191e0 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.current.stderr b/tests/ui/generic-associated-types/issue-91883.current.stderr
new file mode 100644
index 00000000000..0741cf9581d
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-91883.current.stderr
@@ -0,0 +1,27 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-91883.rs:34:24
+   |
+LL |     type Cursor<'tx>: Cursor<'tx>
+   |     ----------------------------- definition of `Cursor` from trait
+...
+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>;
+   |                 ^^^
+help: copy the `where` clause predicates from the trait
+   |
+LL |     type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: '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.next.stderr b/tests/ui/generic-associated-types/issue-91883.next.stderr
new file mode 100644
index 00000000000..b3ed2d81b63
--- /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 e870e08a3a2..d31e1736cf2 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/generic-associated-types/issue-91883.stderr b/tests/ui/generic-associated-types/issue-91883.stderr
deleted file mode 100644
index ac636ebb648..00000000000
--- a/tests/ui/generic-associated-types/issue-91883.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0478]: lifetime bound not satisfied
-  --> $DIR/issue-91883.rs:30:24
-   |
-LL |     type Cursor<'tx>: Cursor<'tx>
-   |     ----------------------------- definition of `Cursor` from trait
-...
-LL |     type Cursor<'tx> = CursorImpl<'tx>;
-   |                        ^^^^^^^^^^^^^^^
-   |
-note: lifetime parameter instantiated with the lifetime `'db` as defined here
-  --> $DIR/issue-91883.rs:29: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
-   |
-LL |     type Cursor<'tx> = CursorImpl<'tx>;
-   |                 ^^^
-help: copy the `where` clause predicates from the trait
-   |
-LL |     type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx;
-   |                                        +++++++++++++++++++++++++
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0478`.
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 c1a78bc2388..1bbff839ffa 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 10c2a811243..6954a7d8067 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 9c8d5a5e3f6..28ae21891f3 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 1d42dbdfe00..294fa0d7613 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 00000000000..ff6e2665ef3
--- /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 00000000000..620bca77e4b
--- /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`.
-- 
cgit 1.4.1-3-g733a5


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

---
 compiler/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 08b7d937661..e7bc57c9749 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());
+        }
     }
 }
 
-- 
cgit 1.4.1-3-g733a5


From a7a43cd37308b774e4d562f1dbaf2793461ae09e Mon Sep 17 00:00:00 2001
From: Yotam Ofek 
Date: Wed, 5 Feb 2025 12:54:31 +0000
Subject: 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 92ef3ab7a1d..dcc5fd12d81 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,
             })
-- 
cgit 1.4.1-3-g733a5


From 4a76615054efaea8a7c0a77ec4b77277da7c64be Mon Sep 17 00:00:00 2001
From: Yotam Ofek 
Date: Wed, 5 Feb 2025 13:03:12 +0000
Subject: 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 8a7d140bb1a..418e60fd972 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();
-- 
cgit 1.4.1-3-g733a5


From 32b1bffa11640f3ad88c4761e0ec9e5546940159 Mon Sep 17 00:00:00 2001
From: Eric Huss 
Date: Mon, 17 Feb 2025 10:47:48 -0800
Subject: 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 b31bf61a6fb..91f72e0d007 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 9f9846cdee0..c9d4d41d115 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"]
-- 
cgit 1.4.1-3-g733a5


From 2773456f5f3560bb0590d32452ca58f21b0181d0 Mon Sep 17 00:00:00 2001
From: Eric Huss 
Date: Mon, 17 Feb 2025 10:57:51 -0800
Subject: 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 e9ee3c6b36e..bb17717aceb 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 97e782d0df0..20a43aaaeeb 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 dbfd6f47dc6..34bf6bb7013 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 f4dac6e947e..54fe7f6eb5a 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 91f72e0d007..ddcf315a267 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 c9d4d41d115..6aec0bec0fa 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 e8e7dfe0d84..bfff5a8e17e 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)
-- 
cgit 1.4.1-3-g733a5


From 123217b3b8233ba0cc852f81fe6ca55c47bed8cc Mon Sep 17 00:00:00 2001
From: Eric Huss 
Date: Mon, 17 Feb 2025 10:58:57 -0800
Subject: 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 bfff5a8e17e..51e58b4e4fc 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 {
-- 
cgit 1.4.1-3-g733a5


From c0b1c6eed516ca39a88dcd7d6a11051fe645fd4a Mon Sep 17 00:00:00 2001
From: Yotam Ofek 
Date: Wed, 5 Feb 2025 17:48:26 +0000
Subject: 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 418e60fd972..c69d22001d9 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 d89caabefe3..4792bc525a5 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 d2d7415261b..f3201147039 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!( -- cgit 1.4.1-3-g733a5 From 59e9eb9b2bce23fb948a3944adb127206e73d1e4 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 11 Feb 2025 22:33:18 -0800 Subject: 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 521a250ab82..e2c9f40d147 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 425b2adf32a..bcc70f4567f 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 -- cgit 1.4.1-3-g733a5 From fd7b4bf4e19b19ebf9b536790ec1668a3e50fe6f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Feb 2025 14:17:57 +1100 Subject: 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 +- .../rustc_borrowck/src/diagnostics/move_errors.rs | 6 +- .../src/diagnostics/mutability_errors.rs | 23 ++- .../src/diagnostics/region_errors.rs | 3 +- .../rustc_borrowck/src/diagnostics/region_name.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_borrowck/src/universal_regions.rs | 2 +- compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- compiler/rustc_const_eval/src/check_consts/mod.rs | 2 +- compiler/rustc_driver_impl/src/pretty.rs | 7 +- compiler/rustc_hir/src/intravisit.rs | 6 +- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 5 +- compiler/rustc_hir_analysis/src/check/region.rs | 6 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/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 +- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 10 +- compiler/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 +- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 5 +- compiler/rustc_hir_typeck/src/fallback.rs | 4 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 13 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 6 +- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 8 +- compiler/rustc_incremental/src/assert_dep_graph.rs | 2 +- .../rustc_incremental/src/persist/dirty_clean.rs | 2 +- compiler/rustc_interface/src/limits.rs | 8 +- compiler/rustc_interface/src/passes.rs | 18 +-- .../rustc_lint/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 +- compiler/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 +- compiler/rustc_mir_transform/src/check_inline.rs | 2 +- .../rustc_mir_transform/src/ffi_unwind_calls.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 2 +- compiler/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 +- .../src/error_reporting/infer/need_type_info.rs | 2 +- .../infer/nice_region_error/static_impl_trait.rs | 4 +- .../nice_region_error/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 +- .../error_reporting/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 +- .../clippy_lints/src/default_numeric_fallback.rs | 3 +- src/tools/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 +- .../clippy_lints/src/needless_pass_by_ref_mut.rs | 2 +- .../src/operators/arithmetic_side_effects.rs | 8 +- .../src/operators/numeric_arithmetic.rs | 8 +- .../clippy/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 +- .../src/transmute/missing_transmute_annotations.rs | 4 +- .../clippy_lints/src/unconditional_recursion.rs | 4 +- src/tools/clippy/clippy_lints/src/utils/author.rs | 3 +- .../utils/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 59c76cb7f2b..e778340cb65 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 38f22473edf..ddf6187a662 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 fc782ce6424..be83e61f75d 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 d3c91cbdee9..55b6367f35f 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 ccd13badad7..b036e6e950b 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 53cf4f34ae7..22ce0fd1ea7 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 eb0079a3883..4e6f82ac849 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 54c5d445f66..4ffe551df09 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 bfa0a0319c3..52e000858b4 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 093ee659bb4..828a14e707c 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 949f8daa4dc..bd96fe9ee32 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 bc0fd4b705d..516ecbcfe0e 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 84d5ec4a1e5..0dd8296e66c 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 88dd40ba289..255f5fee52a 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 01b4a5649f1..edfa897860b 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 68b7b44c36d..750c09887a1 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 1805e2438af..c9a9180c5c9 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 70e7451a5fb..7b1fff157b5 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 5a8a2f1fe28..759c981a8f7 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 88d4acbdd8d..0c36888f363 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 cc28b8780c6..17de64db629 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 7dce8b9b60f..ec8343bb2bf 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 f5abcd23440..0b1be8e4f7a 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 886360dfb6c..66d7c9377ed 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 3d40c5ee804..38319862334 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 bccde782264..49ea2181b07 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 6fb5f6af091..dabae7b1d09 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 c8433d0cb5b..cf11bccae0a 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 2f7f9148023..4dc736f72cf 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 a41ad94f95e..b46d7c49063 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 860e619be71..9b85b2aeec6 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 ce6f7420e5b..e051fc7ac6c 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 c0af5ea7bbf..7ca44d23e3e 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 b77e6de52ff..42236ac6d80 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 05c76b3c568..347a6557c2a 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 1ca8b59db22..780ab8c1833 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 871d08137b3..762d04fdedd 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 dbcf9915790..8c50cc59c1d 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 c2f9ebc5262..d4407559202 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 a95599e7a86..118a6fed036 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 3de513797e3..8f01edec09f 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 d7d183e17ed..d70d9d344b9 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 59390b7e420..757fc1f58bd 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 f17570e4a81..d22515d62d6 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 7e13205bbf1..4ede9b44087 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 1ac2f6e81e5..88a88847e6b 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 b44f14315d7..3436c2f372f 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 0d2acf96d08..2a201e23015 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 b0df6c71014..1e3b8d029e1 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 cd81890598e..693823b4af4 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 ea2b610a727..35893ad953d 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 7beb6d84044..c52e774c8b7 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 b84cc57234f..17e90c15d41 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 e04c70b5883..fb0aa354913 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 8b6fcec3837..84f58f1968d 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 a01609012b8..7a9f6e46304 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 551ec5cf4e9..667d59d858e 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 497f4a660ea..83c3cda5a50 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 9a6a153c7ba..5d21d687a35 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 3dc4edaaa5a..da346dfc48c 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 46abdcb2a87..04c9375b831 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 396a0cbc889..5111a025f94 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 696cc79bfeb..7b4fecf2ed1 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 43f2f892e77..509c2f54775 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 e60dcc807c9..92ea49f18e5 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 09d59e1f717..e123fbac1be 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 60f7616a5fb..a7bca67e4e4 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 0fd980af0b5..8e59c0b3251 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 d045e61d1d4..a6585946656 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 0544d08f5b1..fae88fbba36 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 b8490da26f4..6faa2c1a00d 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 55eb3f777d6..2bb38f3ed14 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 35fd4e588ef..5b8d48e3ca9 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 0695cc57978..cc2ab1c3432 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 445937ad169..245764c94ab 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 bb25c5e8bd1..628888c8d45 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 6beb108bc3a..f15f1b78b52 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 ecfffb65fbc..a8ee4d61e65 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 ac1ced2ed3c..3d89b6ed2f0 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 32d9469c296..7ce72c76e5c 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 8b424499724..fc7c4b42047 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 8a7d140bb1a..6b1d1a2fcdd 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 1ead87fd69d..757a2a6e0dd 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 0d52e21419f..1ac3c040b59 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 fa2465c1926..658d5965b3d 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 bef59469179..9606ba76991 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 dd9dbd7170e..a36dcb0d30e 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 772268e7899..784214c29af 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 a090a987d4f..2e1f8ac615a 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 6d1c55d0693..cb83b1395d2 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 ac2e866e4ff..5ad83f886e2 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 052e6502da9..2a5aa12d126 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 4a8a221e8c3..b1107d8cc72 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 7f91e555054..ea1d7e5d438 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 6a1dc5e41a0..5e85d23718a 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 9d07a14718d..594101427f5 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 2083f2bf628..cda99a362dc 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 ebe3e7c2019..e15e1262920 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 83199ba0f70..a931e39bac9 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 fdbccbaa8a5..1a2fb77acc1 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 4961dd6b280..0b5d83ef58c 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 529f85be372..76a0b927df4 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 ce489054e16..5fc166438e8 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 e31da9e9f61..d6f10f1e4b8 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 ccf32f42a47..15e395731ad 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 85250f81dc4..637c0bafd96 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 a5374f6904e..8eef6a7f57e 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))), -- cgit 1.4.1-3-g733a5 From a1daa34ad005d0b34d30c878cb4e2e995346d300 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 11:24:57 +1100 Subject: 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. --- compiler/rustc_mir_transform/src/large_enums.rs | 186 ++++++++------------- tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff | 2 + tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff | 2 + tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff | 2 + tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff | 2 + 5 files changed, 82 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 1e546bfbeb3..47cb478fe33 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 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_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 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 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 const_assign = StatementKind::Assign(Box::new((place, rval))); + + 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(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(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(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 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 deinit_old = StatementKind::Deinit(Box::new(dst)); + + 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 727efe4b0d9..267a4c1cf6b 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 8d0cd97f786..8e5c403cd7e 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 6d1e2a72fdb..96c5aadd85f 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 4b1406d0d62..d20e2e08eaa 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; } -- cgit 1.4.1-3-g733a5 From e3316ae453a86eed28840a85b12df2ea1917aac7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 12:48:27 +1100 Subject: 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.) --- .../rustc_mir_transform/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 ab6aafab446..530c72ca549 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 b4f6fa514a4..d3d181f6cb2 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; -- cgit 1.4.1-3-g733a5 From 627e08c909168aa451c613570a7f624e05f72766 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 13:05:41 +1100 Subject: 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 795cfcef2d3..c78cde82e15 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 } } -- cgit 1.4.1-3-g733a5 From 69f5e342bf179c991e325587fb9b16a75851b372 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 13:31:08 +1100 Subject: 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 c78cde82e15..582941e7e04 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 afc49c5cc54..f3f3a65cd80 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 => { -- cgit 1.4.1-3-g733a5 From 9fc759099b20993e17a911e2fc7ffec83042b6f1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 17 Feb 2025 21:16:08 -0500 Subject: 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 850b052f564..8079212fac5 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 b1b234eb757..46e52e1f131 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 90191b7776f..5bc37e09f08 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>; } -- cgit 1.4.1-3-g733a5 From 04eeda47abd07a5ba6f3f93e586ecf75d5574545 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 13:40:58 +1100 Subject: 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 582941e7e04..74ecff72082 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 d345c99f902..690a907f9a3 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 c5e951eb8b2..02caa92ad3f 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; -- cgit 1.4.1-3-g733a5 From d2f15971de97eb4a18c2e54890c78c629858d51b Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Mon, 17 Feb 2025 20:21:05 -0800 Subject: 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 42aada131da..34f0e89f2f1 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) } -- cgit 1.4.1-3-g733a5 From 693f7035f1a98cc9a640b045c9e996c8bb1606cd Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Tue, 18 Feb 2025 04:50:11 +0000 Subject: Make E0599 a structured error --- compiler/rustc_hir_analysis/messages.ftl | 2 ++ compiler/rustc_hir_analysis/src/errors.rs | 9 +++++++++ compiler/rustc_hir_analysis/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 5560d087e96..47d5976be09 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 14ea10461cb..1a0b0edb257 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 88323db6dda..3b17d7fe6ff 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 8a529e9c686..2068b9f2dea 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 9ccd6746087..9000868ec27 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 { -- cgit 1.4.1-3-g733a5 From 2d2de181668bbfc50b3396f470da64cd46443c39 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 00:12:26 -0800 Subject: 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 ++++++++----------- compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 18 ++++++++++-------- compiler/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 28f423efc21..8c75125e009 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 59c3fe635d0..98d59f5a8ae 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 17f2d5f4e73..10819a53b1d 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 cebceef1b93..e79662ebc64 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 8b976885904..7e1a9d361e6 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() { -- cgit 1.4.1-3-g733a5 From fa53181f424f167b8aafc78bcb6b75356d3c5748 Mon Sep 17 00:00:00 2001 From: Jubilee Date: Tue, 18 Feb 2025 01:29:23 -0800 Subject: 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 e2c9f40d147..c74efeb59f3 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, )); } -- cgit 1.4.1-3-g733a5 From f910684616f357a8084151a162ed3c3fe0e512e6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 18 Feb 2025 10:29:16 +0100 Subject: don't ICE for alias-relate goals with error term --- .../rustc_next_trait_solver/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 d8c1dc8b4e9..0fc313e33b3 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 6924216bd26..9277226b718 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() { -- cgit 1.4.1-3-g733a5 From a72402a0f950e92758600aa7996899b5241bb6a5 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 18 Feb 2025 10:54:37 +0100 Subject: 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 94039089480..d155e95078b 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 ccfdbf0eb70..34f5c3e94bc 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 318c3508221..661c422811a 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 61801db072a..22776ae2bc4 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 fd0fd1cb755..bdd4844b651 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(); } -- cgit 1.4.1-3-g733a5 From 53effa4566dc1493e1dc5be206105dd99e3192b5 Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Tue, 18 Feb 2025 13:01:01 +0100 Subject: 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 d2268c4779d..e0e3e028c61 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. -- cgit 1.4.1-3-g733a5 From d0a5bbbb8e394095848e078a3fff72beaad14209 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 00:03:10 +0100 Subject: 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 bbb8a9fa671..2a058addf15 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 81dc7285254..c0adf9ec677 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 319c0de26a9..d64dee4e27f 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 00000000000..c0f8710c03c --- /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 00000000000..5fe38d4403a --- /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`. -- cgit 1.4.1-3-g733a5 From 802b7abab736166fcb12c2567c743e1da6d6806c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 20:26:07 +0100 Subject: 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 dcfa81dab25..0b3c0be1a4e 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 c53e3d54cc4..be8a3403ba9 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 2a058addf15..19fa8323574 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 c0adf9ec677..b87a1d2031d 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 d64dee4e27f..0daf2d3b9e7 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; -- cgit 1.4.1-3-g733a5 From 7a667d206c45b96676c260030a4e3d9be1cc8495 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 00:19:56 +0100 Subject: 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 8429e68b600..f9ce709d07c 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))); - } }) } -- cgit 1.4.1-3-g733a5 From 1d1ac3d310dfe90e1ec91c731f2cc306ddbd1eb4 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:02:18 +0100 Subject: 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 f9ce709d07c..5c5558053cc 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}`") } -- cgit 1.4.1-3-g733a5 From 67345f9203b451f21aa603329ab657f6e782267c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:17:08 +0100 Subject: 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 5c5558053cc..36dbddbb9d7 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 }; -- cgit 1.4.1-3-g733a5 From 2fbc413d832486106221253a2db7f4670473ee67 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:32:38 +0100 Subject: 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 36dbddbb9d7..556512e0236 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))); - } }) } -- cgit 1.4.1-3-g733a5 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: 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 2ab8750f727..98cc00c367c 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 54da6924db4..d0fca76fcf0 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 1e738801011..6dbb460d8b1 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 } => { -- cgit 1.4.1-3-g733a5 From 803feb5dc679556ba2d93fe616d1883d7ebc7775 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Jan 2025 12:23:15 +0100 Subject: x86-sse2 ABI: use SSE registers for floats and SIMD --- compiler/rustc_target/src/callconv/mod.rs | 118 +++++++++++++-------- compiler/rustc_target/src/callconv/x86.rs | 14 ++- tests/assembly/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 ++- tests/ui/sse-abi-checks.rs | 22 ---- tests/ui/sse-abi-checks.stderr | 25 ----- tests/ui/sse-simd-abi-checks.rs | 23 ++++ tests/ui/sse-simd-abi-checks.stderr | 25 +++++ 16 files changed, 316 insertions(+), 194 deletions(-) create mode 100644 tests/codegen/abi-x86-sse.rs delete mode 100644 tests/ui/sse-abi-checks.rs delete mode 100644 tests/ui/sse-abi-checks.stderr create mode 100644 tests/ui/sse-simd-abi-checks.rs create mode 100644 tests/ui/sse-simd-abi-checks.stderr diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 2bde1055622..c2a176facdf 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 { .. } => {} - - // 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; + BackendRepr::Memory { .. } => { + // Compute `Aggregate` ABI. + + 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. - - 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 }); + 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(); + } + } + + _ => {} } } } diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 5b9414536d8..5f4f4cd57f6 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 b629d8769ed..069204bbd34 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 ad760627b3a..2c39c830684 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 00000000000..837bf6134b0 --- /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 562a8e6c9e9..d87bab1172a 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 5c3a5893b9d..0c40606ad8a 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 fe68f183667..be45e4db90f 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 4d6895166f1..559e8d947fb 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 75f989d6e12..0d21d510557 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 1df09c96e6c..a27d5e3af45 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 92d40d8ac14..16022fad8af 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-abi-checks.rs deleted file mode 100644 index cb3128a890f..00000000000 --- a/tests/ui/sse-abi-checks.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! 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) -//@ needs-llvm-components: x86 -#![feature(no_core, lang_items, repr_simd)] -#![no_core] -#![allow(improper_ctypes_definitions)] - -extern crate minicore; -use minicore::*; - -#[repr(simd)] -pub struct SseVector([i64; 2]); - -#[no_mangle] -pub unsafe extern "C" fn f(_: SseVector) { - //~^ this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled - //~| WARNING this was previously accepted by the compiler -} diff --git a/tests/ui/sse-abi-checks.stderr b/tests/ui/sse-abi-checks.stderr deleted file mode 100644 index 9944aa093b4..00000000000 --- a/tests/ui/sse-abi-checks.stderr +++ /dev/null @@ -1,25 +0,0 @@ -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 - | -LL | pub unsafe extern "C" fn f(_: SseVector) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #116558 - = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`) - = note: `#[warn(abi_unsupported_vector_types)]` on by default - -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 - | -LL | pub unsafe extern "C" fn f(_: SseVector) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #116558 - = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`) - = note: `#[warn(abi_unsupported_vector_types)]` on by default - diff --git a/tests/ui/sse-simd-abi-checks.rs b/tests/ui/sse-simd-abi-checks.rs new file mode 100644 index 00000000000..396e9bf1318 --- /dev/null +++ b/tests/ui/sse-simd-abi-checks.rs @@ -0,0 +1,23 @@ +//! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled +//! 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 +//@ build-pass +//@ ignore-pass (test emits codegen-time warnings) +//@ needs-llvm-components: x86 +#![feature(no_core, lang_items, repr_simd)] +#![no_core] +#![allow(improper_ctypes_definitions)] + +extern crate minicore; +use minicore::*; + +#[repr(simd)] +pub struct SseVector([i64; 2]); + +#[no_mangle] +pub unsafe extern "C" fn f(_: SseVector) { + //~^ this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled + //~| WARNING this was previously accepted by the compiler +} diff --git a/tests/ui/sse-simd-abi-checks.stderr b/tests/ui/sse-simd-abi-checks.stderr new file mode 100644 index 00000000000..95486f480d2 --- /dev/null +++ b/tests/ui/sse-simd-abi-checks.stderr @@ -0,0 +1,25 @@ +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-simd-abi-checks.rs:20:1 + | +LL | pub unsafe extern "C" fn f(_: SseVector) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`) + = note: `#[warn(abi_unsupported_vector_types)]` on by default + +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-simd-abi-checks.rs:20:1 + | +LL | pub unsafe extern "C" fn f(_: SseVector) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`) + = note: `#[warn(abi_unsupported_vector_types)]` on by default + -- cgit 1.4.1-3-g733a5 From 0ffb771607ed2401bbe3d1d840f68d79aaea8c97 Mon Sep 17 00:00:00 2001 From: Xing Xue Date: Wed, 12 Feb 2025 13:04:43 -0500 Subject: 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 453e53379fc..3ecf271599d 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()); -- cgit 1.4.1-3-g733a5 From 35674eff6f69b04d55d22e31d879c8177abb3653 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 18 Feb 2025 17:26:33 +0100 Subject: 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 0707115cbdd..df877a035a9 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 /// -- cgit 1.4.1-3-g733a5 From ec2034d53d83379abaaa57e395d4d8827ff7c432 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 18 Feb 2025 17:31:10 +0100 Subject: 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 df877a035a9..36432b11f20 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. /// -- cgit 1.4.1-3-g733a5 From d93926cb5d1cb2da36757b137cfdbe9961d05625 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Tue, 18 Feb 2025 17:52:11 +0100 Subject: 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 0c388115908..8090c98e7ed 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: Add reference annotations for the `do_not_recommend` attribute --- .../do_not_recommend/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 +++--- .../do_not_recommend/does_not_acccept_args.next.stderr | 6 +++--- .../do_not_recommend/does_not_acccept_args.rs | 1 + .../incorrect-locations.current.stderr | 18 +++++++++--------- .../do_not_recommend/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 ++-- .../ui/diagnostic_namespace/do_not_recommend/nested.rs | 1 + .../do_not_recommend/simple.current.stderr | 4 ++-- .../do_not_recommend/simple.next.stderr | 4 ++-- .../ui/diagnostic_namespace/do_not_recommend/simple.rs | 1 + .../do_not_recommend/stacked.current.stderr | 4 ++-- .../do_not_recommend/stacked.next.stderr | 4 ++-- .../diagnostic_namespace/do_not_recommend/stacked.rs | 1 + .../supress_suggestions_in_help.current.stderr | 4 ++-- .../supress_suggestions_in_help.next.stderr | 4 ++-- .../do_not_recommend/supress_suggestions_in_help.rs | 1 + .../do_not_recommend/type_mismatch.current.stderr | 4 ++-- .../do_not_recommend/type_mismatch.next.stderr | 4 ++-- .../do_not_recommend/type_mismatch.rs | 1 + .../do_not_recommend/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 28e7975c7a2..305fbbd275f 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 4f685c508c7..90bb715a052 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 48c1ed2b02d..73a238ddf50 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 47597a5d405..8a478a5c733 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 47597a5d405..8a478a5c733 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 eeff5e2e6e8..5c21c045e10 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 ee6ebabadd9..e348f0c8902 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 ee6ebabadd9..e348f0c8902 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 1cf436aa2af..e716457eaed 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 b14c68d6897..cb1da8ff8be 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 b14c68d6897..cb1da8ff8be 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 6534157d1fb..3c96c760dfb 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 884b13c17b8..dd425f1e6ee 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 884b13c17b8..dd425f1e6ee 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 6bca2b724d2..a6fa7ac7949 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 d8605806395..d940c3fd477 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 d8605806395..d940c3fd477 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 842e04b9d90..fd7be35ff84 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 95ccbb92a89..0b07b073172 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 95ccbb92a89..0b07b073172 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 2c7c1516123..04cf8243a67 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 b53febbb71a..31a1ae991ec 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 b53febbb71a..31a1ae991ec 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 7f30fdb06c7..b5bd14745cd 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 a8429ff60f8..7e348842e19 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 a8429ff60f8..7e348842e19 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 6a67d83d5fe..98916ed061f 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 {} -- cgit 1.4.1-3-g733a5 From 5d1551b9c6ebaded328d2f10deb92f7a87cf928c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 17:48:27 +1100 Subject: 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 +- compiler/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 - .../rustc_mir_dataflow/src/move_paths/builder.rs | 1 - compiler/rustc_mir_dataflow/src/value_analysis.rs | 1 - compiler/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 59c76cb7f2b..0b27838beee 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 07ea369c5c7..7da089c5e8c 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 53cf4f34ae7..f3a99e0a75d 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 93081919ec7..84759a0ae04 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 eb4270ffe80..e32d298869b 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 795cfcef2d3..862661044c3 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 d345c99f902..8f5fd31411a 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 9cec8d832dd..45fcec41fde 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 862f78d7259..00000000000 --- 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 eab414e150f..19669021eef 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 b6c259aa4e0..8bbc89fdcec 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 a51af8c40fd..104a2e8c091 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 2de55e38052..9330a9481f5 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 } -- cgit 1.4.1-3-g733a5 From 20eb224a559c3bd74ed97efc7c98c0a25f5b5225 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 19 Feb 2025 05:06:01 +0000 Subject: 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 0ea62d4d850..a2a2f28ea71 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -d1fb81e8dd5354ddf7cb334d5a234cab7f64b3bb +17c1c329a5512d718b67ef6797538b154016cd34 -- cgit 1.4.1-3-g733a5 From c7981d64117a4e1228e94ddc47a16d171a011c0b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 12:17:09 +1000 Subject: 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 ++++++++++++++++++++++++-- compiler/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 60f8c6e1048..a2923d6448a 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 de9f049704a..47cf77cefa7 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 36a7b7d8789..661f2c3eca2 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 50f10d083a0..1b6d825a22c 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 595c8c3279f..1723b47798b 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 1de452dcf39..ecbc4e396ce 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 eefdb641da2..f102821adf7 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 00000000000..04f10ad0f98 --- /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 }); +} -- cgit 1.4.1-3-g733a5 From 76b04437be91069260c72a6d59d130a4e127a9a8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 17 Apr 2024 13:17:44 +1000 Subject: 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 ++++++++++++++++--- compiler/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 | 37 ++++++++++++++++++---- 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 +-- .../ui/parser/macro/trait-object-macro-matcher.rs | 1 + .../parser/macro/trait-object-macro-matcher.stderr | 10 +++++- 19 files changed, 109 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index a2923d6448a..346edc87c86 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 47cf77cefa7..40b29fdba25 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 661f2c3eca2..8ac6dc3b4d8 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 1b6d825a22c..1123ea3a449 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 1723b47798b..fa0c2c7da78 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 ecbc4e396ce..4b26100c46d 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 f102821adf7..e9cf8f1bbba 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 b241aa892db..b68eb9c99f5 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 dc5919b3630..c78c7bff9b5 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 9cc33d53f9c..048681f0477 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 dfe78b3d1f3..e154ae25de2 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,11 +22,15 @@ 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 +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 | LL | type_ascribe!(p, a>); - | ^ not found in this scope + | ^^^ + | + = 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 error[E0658]: associated const equality is incomplete --> $DIR/issue-93835.rs:4:28 @@ -25,8 +41,17 @@ 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` + +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 4 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0405, E0412, E0425, E0658. -For more information about an error, try `rustc --explain E0405`. +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 48c1f19e777..b5d2322c805 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 e6b39dfef85..bc24a158612 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 016e4def284..6cf9d54e826 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 3cfbd8ce82b..61758fb9d7d 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 0044aa5610f..e0957542f8f 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 1f2fe23106a..560329df5cc 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 560195977d0..d4ec199070e 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 40082564bad..81dca6f71c4 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`. -- cgit 1.4.1-3-g733a5 From 0f490b040af82820e423a7e71e0e2e1f6ca7ab57 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Feb 2025 16:47:07 +1100 Subject: 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 8ac6dc3b4d8..97d121909f8 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 fa0c2c7da78..721798b0ce4 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 4b26100c46d..bbd73dec2e4 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 e9cf8f1bbba..f202f85752e 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 b68eb9c99f5..c24305ea9a8 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 c78c7bff9b5..18af0a1c79a 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); } -- cgit 1.4.1-3-g733a5