diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5af70937f622c..bdbd53495f369 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -39,7 +39,7 @@ use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt}; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, - InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, + InitializationRequiringAction, MirBorrowckCtxt, WriteKind, }; use super::{ @@ -114,7 +114,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.buffer_error(err); } else { if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) { - if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) { + if used_place.is_prefix_of(*reported_place) { debug!( "report_use_of_moved_or_uninitialized place: error suppressed mois={:?}", move_out_indices @@ -422,8 +422,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (None, &[][..], 0) }; if let Some(def_id) = def_id - && let node = - self.infcx.tcx.hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) + && let node = self.infcx.tcx.hir_node_by_def_id(def_id) && let Some(fn_sig) = node.fn_sig() && let Some(ident) = node.ident() && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) @@ -1995,21 +1994,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { kind: Option, ) { let drop_span = place_span.1; - let root_place = - self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); + let borrowed_local = borrow.borrowed_place.local; let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.var_or_use_path_span(); - assert!(root_place.projection.is_empty()); - let proper_span = self.body.local_decls[root_place.local].source_info.span; - - let root_place_projection = self.infcx.tcx.mk_place_elems(root_place.projection); + let proper_span = self.body.local_decls[borrowed_local].source_info.span; - if self.access_place_error_reported.contains(&( - Place { local: root_place.local, projection: root_place_projection }, - borrow_span, - )) { + if self.access_place_error_reported.contains(&(Place::from(borrowed_local), borrow_span)) { debug!( "suppressing access_place error when borrow doesn't live long enough for {:?}", borrow_span @@ -2017,12 +2009,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } - self.access_place_error_reported.insert(( - Place { local: root_place.local, projection: root_place_projection }, - borrow_span, - )); + self.access_place_error_reported.insert((Place::from(borrowed_local), borrow_span)); - let borrowed_local = borrow.borrowed_place.local; if self.body.local_decls[borrowed_local].is_ref_to_thread_local() { let err = self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span); @@ -2544,9 +2532,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; (format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here")) } else { - let root_place = - self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); - let local = root_place.local; + let local = borrow.borrowed_place.local; match self.body.local_kind(local) { LocalKind::Arg => ( "function parameter".to_string(), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index ee2e3d20fe56e..a27d016e0ba51 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -672,11 +672,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; ( true, - td.as_local().and_then(|tld| match self.infcx.tcx.opt_hir_node_by_def_id(tld) { - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, _, _, items), - .. - })) => { + td.as_local().and_then(|tld| match self.infcx.tcx.hir_node_by_def_id(tld) { + Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, _, _, _, items), .. }) => { let mut f_in_trait_opt = None; for hir::TraitItemRef { id: fi, kind: k, .. } in *items { let hi = fi.hir_id(); @@ -1475,11 +1472,9 @@ fn get_mut_span_in_struct_field<'tcx>( if let ty::Ref(_, ty, _) = ty.kind() && let ty::Adt(def, _) = ty.kind() && let field = def.all_fields().nth(field.index())? - // Use the HIR types to construct the diagnostic message. - && let node = tcx.opt_hir_node_by_def_id(field.did.as_local()?)? // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. - && let hir::Node::Field(field) = node + && let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.as_local()?) && let hir::TyKind::Ref(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind { return Some(lt.ident.span.between(ty.span)); diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 8bb3dc88b3467..8a3a089d0eeba 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -1,7 +1,4 @@ -//! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an -//! place are formed by stripping away fields and derefs, except that -//! we stop when we reach the deref of a shared reference. [...] " -//! +//! From the NLL RFC: //! "Shallow prefixes are found by stripping away fields, but stop at //! any dereference. So: writing a path like `a` is illegal if `a.b` //! is borrowed. But: writing `a` is legal if `*a` is borrowed, @@ -9,9 +6,7 @@ use super::MirBorrowckCtxt; -use rustc_hir as hir; -use rustc_middle::mir::{Body, PlaceRef, ProjectionElem}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::mir::{PlaceRef, ProjectionElem}; pub trait IsPrefixOf<'tcx> { fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool; @@ -25,9 +20,7 @@ impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> { } } -pub(super) struct Prefixes<'cx, 'tcx> { - body: &'cx Body<'tcx>, - tcx: TyCtxt<'tcx>, +pub(super) struct Prefixes<'tcx> { kind: PrefixSet, next: Option>, } @@ -39,24 +32,18 @@ pub(super) enum PrefixSet { All, /// Stops at any dereference. Shallow, - /// Stops at the deref of a shared reference. - Supporting, } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Returns an iterator over the prefixes of `place` /// (inclusive) from longest to smallest, potentially /// terminating the iteration early based on `kind`. - pub(super) fn prefixes( - &self, - place_ref: PlaceRef<'tcx>, - kind: PrefixSet, - ) -> Prefixes<'cx, 'tcx> { - Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx } + pub(super) fn prefixes(&self, place_ref: PlaceRef<'tcx>, kind: PrefixSet) -> Prefixes<'tcx> { + Prefixes { next: Some(place_ref), kind } } } -impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { +impl<'tcx> Iterator for Prefixes<'tcx> { type Item = PlaceRef<'tcx>; fn next(&mut self) -> Option { let mut cursor = self.next?; @@ -91,57 +78,23 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { panic!("Subtype projection is not allowed before borrow check") } ProjectionElem::Deref => { - // (handled below) + match self.kind { + PrefixSet::Shallow => { + // Shallow prefixes are found by stripping away + // fields, but stop at *any* dereference. + // So we can just stop the traversal now. + self.next = None; + return Some(cursor); + } + PrefixSet::All => { + // All prefixes: just blindly enqueue the base + // of the projection. + self.next = Some(cursor_base); + return Some(cursor); + } + } } } - - assert_eq!(elem, ProjectionElem::Deref); - - match self.kind { - PrefixSet::Shallow => { - // Shallow prefixes are found by stripping away - // fields, but stop at *any* dereference. - // So we can just stop the traversal now. - self.next = None; - return Some(cursor); - } - PrefixSet::All => { - // All prefixes: just blindly enqueue the base - // of the projection. - self.next = Some(cursor_base); - return Some(cursor); - } - PrefixSet::Supporting => { - // Fall through! - } - } - - assert_eq!(self.kind, PrefixSet::Supporting); - // Supporting prefixes: strip away fields and - // derefs, except we stop at the deref of a shared - // reference. - - let ty = cursor_base.ty(self.body, self.tcx).ty; - match ty.kind() { - ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => { - // don't continue traversing over derefs of raw pointers or shared - // borrows. - self.next = None; - return Some(cursor); - } - - ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => { - self.next = Some(cursor_base); - return Some(cursor); - } - - ty::Adt(..) if ty.is_box() => { - self.next = Some(cursor_base); - return Some(cursor); - } - - _ => panic!("unknown type fed to Projection Deref."), - } } } } diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 3d803258c8e5e..d5908cf285118 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -42,8 +42,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir_node(hir_id) { + match tcx.hir_node_by_def_id(def_id.expect_local()) { Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { generics.params.is_empty().not().then_some(generics.span) } @@ -57,8 +56,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir_node(hir_id) { + match tcx.hir_node_by_def_id(def_id.expect_local()) { Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { Some(generics.where_clause_span) } @@ -79,8 +77,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir_node(hir_id) { + match tcx.hir_node_by_def_id(def_id.expect_local()) { Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => { Some(fn_sig.decl.output.span()) } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index f5bfc6b1b869d..22afddad6336d 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -130,7 +130,7 @@ fn get_owner_return_paths( ) -> Option<(LocalDefId, ReturnsVisitor<'_>)> { 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.opt_hir_node_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| { + tcx.hir_node_by_def_id(parent_id).body_id().map(|body_id| { let body = tcx.hir().body(body_id); let mut visitor = ReturnsVisitor::default(); visitor.visit_body(body); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index ae15efc0764b7..f525004534408 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1969,13 +1969,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { // Match the existing behavior. if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) { let pred = self.normalize(span, None, pred); - let hir_node = tcx.opt_hir_node_by_def_id(self.body_def_id); // only use the span of the predicate clause (#90869) - - if let Some(hir::Generics { predicates, .. }) = - hir_node.and_then(|node| node.generics()) - { + let hir_node = tcx.hir_node_by_def_id(self.body_def_id); + if let Some(hir::Generics { predicates, .. }) = hir_node.generics() { span = predicates .iter() // There seems to be no better way to find out which predicate we are in diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2675eacc06e19..6aae4aa21b878 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -609,10 +609,8 @@ pub(super) fn implied_predicates_with_filter( return tcx.super_predicates_of(trait_def_id); }; - let trait_hir_id = tcx.local_def_id_to_hir_id(trait_def_id); - - let Node::Item(item) = tcx.hir_node(trait_hir_id) else { - bug!("trait_node_id {} is not an item", trait_hir_id); + let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else { + bug!("trait_def_id {trait_def_id:?} is not an item"); }; let (generics, bounds) = match item.kind { 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 dcb01a117b047..b5765913cb857 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -371,11 +371,10 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( return mir_opaque_ty.ty; } - let scope = tcx.local_def_id_to_hir_id(owner_def_id); - debug!(?scope); + debug!(?owner_def_id); let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty }; - match tcx.hir_node(scope) { + match tcx.hir_node_by_def_id(owner_def_id) { Node::Item(it) => intravisit::walk_item(&mut locator, it), Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it), Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it), diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index c7343387dafc4..4b3359858f15d 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -234,11 +234,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Next, make sure that we have no type expectation. - let Some(ret) = self - .tcx - .opt_hir_node_by_def_id(self.body_id) - .and_then(|owner| owner.fn_decl()) - .map(|decl| decl.output.span()) + let Some(ret) = + self.tcx.hir_node_by_def_id(self.body_id).fn_decl().map(|decl| decl.output.span()) else { return; }; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7e19e577d7d0c..1a142f27809e1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -890,21 +890,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); - if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(..), - span: encl_fn_span, - .. - })) - | Some(hir::Node::TraitItem(hir::TraitItem { + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(..), span: encl_fn_span, .. + }) + | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), span: encl_fn_span, .. - })) - | Some(hir::Node::ImplItem(hir::ImplItem { + }) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), span: encl_fn_span, .. - })) = self.tcx.opt_hir_node_by_def_id(encl_item_id.def_id) + }) = self.tcx.hir_node_by_def_id(encl_item_id.def_id) { // We are inside a function body, so reporting "return statement // outside of function body" needs an explanation. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 1fa1da93018af..536d44a0ccb85 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2172,16 +2172,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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. let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] }; - let node = self - .tcx - .opt_local_def_id_to_hir_id( - self.tcx.hir().get_parent_item(call_expr.hir_id).def_id, - ) - .map(|hir_id| self.tcx.hir_node(hir_id)); - match node { - Some(hir::Node::Item(item)) => call_finder.visit_item(item), - Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item), - Some(hir::Node::ImplItem(item)) => call_finder.visit_impl_item(item), + let parent_def_id = self.tcx.hir().get_parent_item(call_expr.hir_id).def_id; + match self.tcx.hir_node_by_def_id(parent_def_id) { + hir::Node::Item(item) => call_finder.visit_item(item), + hir::Node::TraitItem(item) => call_finder.visit_trait_item(item), + hir::Node::ImplItem(item) => call_finder.visit_impl_item(item), _ => {} } let typeck = self.typeck_results.borrow(); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index ef4b88575fced..5d2a95593cd25 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2126,8 +2126,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let TypeError::FixedArraySize(sz) = terr else { return None; }; - let tykind = match self.tcx.opt_hir_node_by_def_id(trace.cause.body_id) { - Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { + let tykind = match self.tcx.hir_node_by_def_id(trace.cause.body_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => { let body = hir.body(*body_id); struct LetVisitor { span: Span, @@ -2156,7 +2156,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } LetVisitor { span }.visit_body(body).break_value() } - Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. })) => { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }) => { Some(&ty.peel_refs().kind) } _ => None, @@ -2527,15 +2527,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) .map(|p| p.name) .collect::>(); - if let Some(hir_id) = self.tcx.opt_local_def_id_to_hir_id(lifetime_scope) { - // consider late-bound lifetimes ... - used_names.extend(self.tcx.late_bound_vars(hir_id).into_iter().filter_map(|p| { - match p { - ty::BoundVariableKind::Region(lt) => lt.get_name(), - _ => None, - } - })) - } + let hir_id = self.tcx.local_def_id_to_hir_id(lifetime_scope); + // consider late-bound lifetimes ... + used_names.extend(self.tcx.late_bound_vars(hir_id).into_iter().filter_map( + |p| match p { + ty::BoundVariableKind::Region(lt) => lt.get_name(), + _ => None, + }, + )); (b'a'..=b'z') .map(|c| format!("'{}", c as char)) .find(|candidate| !used_names.iter().any(|e| e.as_str() == candidate)) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index afcb4a182fa4b..503645191aacf 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -459,7 +459,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { if let Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. - }) = tcx.opt_hir_node_by_def_id(impl_did)? + }) = tcx.hir_node_by_def_id(impl_did) && trait_objects.iter().all(|did| { // FIXME: we should check `self_ty` against the receiver // type in the `UnifyReceiver` context, but for now, use diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index d14cabfc429b5..24eaff08220d6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -804,23 +804,22 @@ fn foo(&self) -> Self::T { String::new() } ) -> bool { let tcx = self.tcx; - let Some(hir_id) = body_owner_def_id.as_local() else { - return false; - }; - let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(hir_id) else { + let Some(def_id) = body_owner_def_id.as_local() else { return false; }; + // When `body_owner` is an `impl` or `trait` item, look in its associated types for // `expected` and point at it. + let hir_id = tcx.local_def_id_to_hir_id(def_id); let parent_id = tcx.hir().get_parent_item(hir_id); - let item = tcx.opt_hir_node_by_def_id(parent_id.def_id); + let item = tcx.hir_node_by_def_id(parent_id.def_id); debug!("expected_projection parent item {:?}", item); let param_env = tcx.param_env(body_owner_def_id); match item { - Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. }) => { // FIXME: account for `#![feature(specialization)]` for item in &items[..] { match item.kind { @@ -845,10 +844,10 @@ fn foo(&self) -> Self::T { String::new() } } } } - Some(hir::Node::Item(hir::Item { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { items, .. }), .. - })) => { + }) => { for item in &items[..] { if let hir::AssocItemKind::Type = item.kind { let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 26226386ef721..d8cfceab460a0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1339,8 +1339,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_doc_hidden: false, }; let attr_iter = tcx - .opt_local_def_id_to_hir_id(def_id) - .map_or(Default::default(), |hir_id| tcx.hir().attrs(hir_id)) + .hir() + .attrs(tcx.local_def_id_to_hir_id(def_id)) .iter() .filter(|attr| analyze_attr(attr, &mut state)); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index cc940f2e74b8d..5043bd855ccb9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -158,12 +158,6 @@ impl<'tcx> TyCtxt<'tcx> { self.hir_owner_nodes(owner_id).node() } - /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. - #[inline] - pub fn opt_hir_node_by_def_id(self, id: LocalDefId) -> Option> { - Some(self.hir_node_by_def_id(id)) - } - /// 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 @@ -239,8 +233,7 @@ impl<'hir> Map<'hir> { } pub fn get_if_local(self, id: DefId) -> Option> { - id.as_local() - .and_then(|id| Some(self.tcx.hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?))) + id.as_local().map(|id| self.tcx.hir_node_by_def_id(id)) } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { @@ -304,7 +297,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 { - let node = self.tcx.opt_hir_node_by_def_id(id)?; + let node = self.tcx.hir_node_by_def_id(id); let (_, body_id) = associated_body(node)?; Some(body_id) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5362b6d8b24ca..17ba97c5fd3a7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1265,11 +1265,9 @@ impl<'tcx> TyCtxt<'tcx> { break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into()))); }; - let is_impl_item = match self.opt_hir_node_by_def_id(suitable_region_binding_scope) { - Some(Node::Item(..) | Node::TraitItem(..)) => false, - Some(Node::ImplItem(..)) => { - self.is_bound_region_in_impl_item(suitable_region_binding_scope) - } + let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) { + Node::Item(..) | Node::TraitItem(..) => false, + Node::ImplItem(..) => self.is_bound_region_in_impl_item(suitable_region_binding_scope), _ => false, }; @@ -2355,10 +2353,6 @@ impl<'tcx> TyCtxt<'tcx> { self.intrinsic_raw(def_id) } - pub fn opt_local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> Option { - Some(self.local_def_id_to_hir_id(local_def_id)) - } - pub fn next_trait_solver_globally(self) -> bool { self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally) } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 0371bab83c044..350f7e166bf9c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -33,15 +33,13 @@ use crate::errors::{ // may need to be marked as live. fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { matches!( - tcx.opt_hir_node_by_def_id(def_id), - Some( - Node::Item(..) - | Node::ImplItem(..) - | Node::ForeignItem(..) - | Node::TraitItem(..) - | Node::Variant(..) - | Node::AnonConst(..) - ) + tcx.hir_node_by_def_id(def_id), + Node::Item(..) + | Node::ImplItem(..) + | Node::ForeignItem(..) + | Node::TraitItem(..) + | Node::Variant(..) + | Node::AnonConst(..) ) } @@ -316,33 +314,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { // tuple struct constructor function let id = self.struct_constructors.get(&id).copied().unwrap_or(id); - if let Some(node) = self.tcx.opt_hir_node_by_def_id(id) { - // When using `#[allow]` or `#[expect]` of `dead_code`, we do a QOL improvement - // by declaring fn calls, statics, ... within said items as live, as well as - // the item itself, although technically this is not the case. - // - // This means that the lint for said items will never be fired. - // - // This doesn't make any difference for the item declared with `#[allow]`, as - // the lint firing will be a nop, as it will be silenced by the `#[allow]` of - // the item. - // - // However, for `#[expect]`, the presence or absence of the lint is relevant, - // so we don't add it to the list of live symbols when it comes from a - // `#[expect]`. This means that we will correctly report an item as live or not - // for the `#[expect]` case. - // - // Note that an item can and will be duplicated on the worklist with different - // `ComesFromAllowExpect`, particularly if it was added from the - // `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks, - // this "duplication" is essential as otherwise a function with `#[expect]` - // called from a `pub fn` may be falsely reported as not live, falsely - // triggering the `unfulfilled_lint_expectations` lint. - if comes_from_allow_expect != ComesFromAllowExpect::Yes { - self.live_symbols.insert(id); - } - self.visit_node(node); + // When using `#[allow]` or `#[expect]` of `dead_code`, we do a QOL improvement + // by declaring fn calls, statics, ... within said items as live, as well as + // the item itself, although technically this is not the case. + // + // This means that the lint for said items will never be fired. + // + // This doesn't make any difference for the item declared with `#[allow]`, as + // the lint firing will be a nop, as it will be silenced by the `#[allow]` of + // the item. + // + // However, for `#[expect]`, the presence or absence of the lint is relevant, + // so we don't add it to the list of live symbols when it comes from a + // `#[expect]`. This means that we will correctly report an item as live or not + // for the `#[expect]` case. + // + // Note that an item can and will be duplicated on the worklist with different + // `ComesFromAllowExpect`, particularly if it was added from the + // `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks, + // this "duplication" is essential as otherwise a function with `#[expect]` + // called from a `pub fn` may be falsely reported as not live, falsely + // triggering the `unfulfilled_lint_expectations` lint. + if comes_from_allow_expect != ComesFromAllowExpect::Yes { + self.live_symbols.insert(id); } + self.visit_node(self.tcx.hir_node_by_def_id(id)); } } @@ -739,8 +735,8 @@ fn check_item<'tcx>( for local_def_id in local_def_ids { // check the function may construct Self let mut may_construct_self = true; - if let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(local_def_id) - && let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) + if let Some(fn_sig) = + 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/entry.rs b/compiler/rustc_passes/src/entry.rs index 0bab13037e4ae..2af5a54a0cac7 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -127,7 +127,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, { // non-local main imports are handled below if let Some(def_id) = def_id.as_local() - && matches!(tcx.opt_hir_node_by_def_id(def_id), Some(Node::ForeignItem(_))) + && matches!(tcx.hir_node_by_def_id(def_id), Node::ForeignItem(_)) { tcx.dcx().emit_err(ExternMain { span: tcx.def_span(def_id) }); return None; diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 2a78f47c34f67..9fbae8f84b4aa 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -116,26 +116,25 @@ impl<'tcx> ReachableContext<'tcx> { return false; }; - match self.tcx.opt_hir_node_by_def_id(def_id) { - Some(Node::Item(item)) => match item.kind { + match self.tcx.hir_node_by_def_id(def_id) { + Node::Item(item) => match item.kind { hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()), _ => false, }, - Some(Node::TraitItem(trait_method)) => match trait_method.kind { + Node::TraitItem(trait_method) => match trait_method.kind { hir::TraitItemKind::Const(_, ref default) => default.is_some(), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, }, - Some(Node::ImplItem(impl_item)) => match impl_item.kind { + Node::ImplItem(impl_item) => match impl_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Fn(..) => { item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) } hir::ImplItemKind::Type(_) => false, }, - Some(_) => false, - None => false, // This will happen for default methods. + _ => false, } } @@ -147,9 +146,7 @@ impl<'tcx> ReachableContext<'tcx> { continue; } - if let Some(ref item) = self.tcx.opt_hir_node_by_def_id(search_item) { - self.propagate_node(item, search_item); - } + self.propagate_node(&self.tcx.hir_node_by_def_id(search_item), search_item); } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 4ff4ccf5e9845..0ebcad3cdb809 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -167,12 +167,13 @@ pub fn unindent_doc_fragments(docs: &mut [DocFragment]) { /// /// Note: remove the trailing newline where appropriate pub fn add_doc_fragment(out: &mut String, frag: &DocFragment) { - let s = frag.doc.as_str(); - let mut iter = s.lines(); - if s.is_empty() { + if frag.doc == kw::Empty { out.push('\n'); return; } + let s = frag.doc.as_str(); + let mut iter = s.lines(); + while let Some(line) = iter.next() { if line.chars().any(|c| !c.is_whitespace()) { assert!(line.len() >= frag.indent); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 126bc0c9ec0fc..745ddfc08af47 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -91,7 +91,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// Used to set on_unimplemented's `ItemContext` /// to be the enclosing (async) block/function/closure fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str> { - match self.tcx.opt_hir_node_by_def_id(def_id)? { + match self.tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) => Some("a function"), hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => { Some("a trait method") diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index e41b60767b983..067ca883bd8ad 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -261,7 +261,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we // don't suggest `T: Sized + ?Sized`. - while let Some(node) = self.tcx.opt_hir_node_by_def_id(body_id) { + loop { + let node = self.tcx.hir_node_by_def_id(body_id); match node { hir::Node::Item(hir::Item { ident, @@ -1725,8 +1726,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let hir = self.tcx.hir(); - let node = self.tcx.opt_hir_node_by_def_id(obligation.cause.body_id); - if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node + 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_id), .. }) = node && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind && sig.decl.output.span().overlaps(span) && blk.expr.is_none() @@ -1760,8 +1761,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option { - let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = - self.tcx.opt_hir_node_by_def_id(obligation.cause.body_id) + let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. }) = + self.tcx.hir_node_by_def_id(obligation.cause.body_id) else { return None; }; @@ -1853,10 +1854,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let hir = self.tcx.hir(); - let node = self.tcx.opt_hir_node_by_def_id(obligation.cause.body_id); - if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) = - node - { + let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); + if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) = node { let body = hir.body(*body_id); // Point at all the `return`s in the function as they have failed trait bounds. let mut visitor = ReturnsVisitor::default(); @@ -4490,7 +4489,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } return; }; - let Some(hir::Node::TraitItem(item)) = self.tcx.opt_hir_node_by_def_id(fn_def_id) else { + let hir::Node::TraitItem(item) = self.tcx.hir_node_by_def_id(fn_def_id) else { return; }; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index b85a05c774fa9..e8aab2360487b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2497,11 +2497,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.code(E0790); if let Some(local_def_id) = data.trait_ref.def_id.as_local() - && let Some(hir::Node::Item(hir::Item { + && let hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. - })) = self.tcx.opt_hir_node_by_def_id(local_def_id) + }) = self.tcx.hir_node_by_def_id(local_def_id) && let Some(method_ref) = trait_item_refs .iter() .find(|item_ref| item_ref.ident == *assoc_item_name) diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 4bcbf1c037499..50a8eb869b992 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -325,11 +325,7 @@ fn associated_type_for_impl_trait_in_impl( ) -> LocalDefId { let impl_local_def_id = tcx.local_parent(impl_fn_def_id); - let decl = tcx - .opt_hir_node_by_def_id(impl_fn_def_id) - .expect("expected item") - .fn_decl() - .expect("expected decl"); + let decl = tcx.hir_node_by_def_id(impl_fn_def_id).fn_decl().expect("expected decl"); let span = match decl.output { hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), hir::FnRetTy::Return(ty) => ty.span, diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 25c64240e7480..4ef1f1b695e60 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -51,6 +51,8 @@ use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; /// // We might want to use a BufReader here for efficiency, but let's /// // keep this example focused. /// let mut file = File::create("foo.txt")?; +/// // First, we need to allocate 10 bytes to be able to write into. +/// file.set_len(10)?; /// /// write_ten_bytes_at_end(&mut file)?; /// # Ok(()) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh old mode 100644 new mode 100755 index 324dd5fac161e..b22d60f2b1d10 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh @@ -1,9 +1,11 @@ -#!/bin/sh +#!/usr/bin/env bash set -ex cd $1 +source shared.sh + # Setting up folders for GCC git clone https://github.com/antoyo/gcc gcc-src cd gcc-src @@ -14,15 +16,17 @@ mkdir ../gcc-build ../gcc-install cd ../gcc-build # Building GCC. -../gcc-src/configure \ +hide_output \ + ../gcc-src/configure \ --enable-host-shared \ --enable-languages=jit \ --enable-checking=release \ --disable-bootstrap \ --disable-multilib \ - --prefix=$(pwd)/../gcc-install -make -make install + --prefix=$(pwd)/../gcc-install \ + +hide_output make -j$(nproc) +hide_output make install rm -rf ../gcc-src ln -s /scripts/gcc-install/lib/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile index 6540a500d3a58..4fc2b2e507e0d 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile @@ -59,8 +59,9 @@ ENV RUST_CONFIGURE_ARGS \ COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/ +COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ -RUN sh /scripts/build-gccjit.sh /scripts +RUN /scripts/build-gccjit.sh /scripts ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile index ed4e1978c5d40..7c2ecd198e234 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile @@ -58,8 +58,9 @@ ENV RUST_CONFIGURE_ARGS \ COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/ +COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ -RUN sh /scripts/build-gccjit.sh /scripts +RUN /scripts/build-gccjit.sh /scripts ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index a03577b45112b..6f72056989818 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -95,9 +95,10 @@ ENV RUST_CONFIGURE_ARGS \ ENV HOST_TARGET x86_64-unknown-linux-gnu +COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ -RUN sh /scripts/build-gccjit.sh /scripts +RUN /scripts/build-gccjit.sh /scripts ENV SCRIPT /tmp/checktools.sh ../x.py && \ NODE_PATH=`npm root -g` python3 ../x.py test tests/rustdoc-gui --stage 2 \ diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index b46d80eb362e2..fe5cb529c2638 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -427,3 +427,32 @@ This flag is **deprecated** and **has no effect**. Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. + +## `--test-builder`: `rustc`-like program to build tests + +Using this flag looks like this: + +```bash +$ rustdoc --test-builder /path/to/rustc src/lib.rs +``` + +Rustdoc will use the provided program to compile tests instead of the default `rustc` program from +the sysroot. + +## `--test-builder-wrapper`: wrap calls to the test builder + +Using this flag looks like this: + +```bash +$ rustdoc --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs +$ rustdoc \ + --test-builder-wrapper rustc-wrapper1 \ + --test-builder-wrapper rustc-wrapper2 \ + --test-builder rustc \ + src/lib.rs +``` + +Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program. +The first argument to the program will be the test builder program. + +This flag can be passed multiple times to nest wrappers. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b32d3ad562d03..b28e57a93591c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -149,8 +149,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< } fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool { - if let Some(node) = tcx.opt_hir_node_by_def_id(import_id) - && let hir::Node::Item(item) = node + if let hir::Node::Item(item) = tcx.hir_node_by_def_id(import_id) && let hir::ItemKind::Use(_, use_kind) = item.kind { use_kind == hir::UseKind::Glob @@ -1612,8 +1611,7 @@ fn first_non_private<'tcx>( 'reexps: for reexp in child.reexport_chain.iter() { if let Some(use_def_id) = reexp.id() && let Some(local_use_def_id) = use_def_id.as_local() - && let Some(hir::Node::Item(item)) = - cx.tcx.opt_hir_node_by_def_id(local_use_def_id) + && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id) && !item.ident.name.is_empty() && let hir::ItemKind::Use(path, _) = item.kind { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 57916ff0ff781..aed1d9c5a8337 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -664,9 +664,10 @@ pub(crate) fn inherits_doc_hidden( def_id = id; if tcx.is_doc_hidden(def_id.to_def_id()) { return true; - } else if let Some(node) = tcx.opt_hir_node_by_def_id(def_id) - && matches!(node, hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),) - { + } else if matches!( + tcx.hir_node_by_def_id(def_id), + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) + ) { // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly // on them, they don't inherit it from the parent context. return false; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 4b1a417b21127..be7e319bc79f4 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -130,6 +130,9 @@ pub(crate) struct Options { /// default to loading from `$sysroot/bin/rustc`. pub(crate) test_builder: Option, + /// Run these wrapper instead of rustc directly + pub(crate) test_builder_wrappers: Vec, + // Options that affect the documentation process /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items /// with and without documentation. @@ -204,6 +207,7 @@ impl fmt::Debug for Options { .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) + .field("test_builder_wrappers", &self.test_builder_wrappers) .field("nocapture", &self.nocapture) .field("scrape_examples_options", &self.scrape_examples_options) .field("unstable_features", &self.unstable_features) @@ -521,6 +525,8 @@ impl Options { dcx.fatal("the `--test` flag must be passed to enable `--no-run`"); } + let test_builder_wrappers = + matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect(); let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s)); let output = matches.opt_str("output").map(|s| PathBuf::from(&s)); let output = match (out_dir, output) { @@ -727,6 +733,7 @@ impl Options { test_builder, run_check, no_run, + test_builder_wrappers, nocapture, crate_name, output_format, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index d446b781bf139..c6eb7be08cd81 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -25,7 +25,7 @@ use tempfile::Builder as TempFileBuilder; use std::env; use std::io::{self, Write}; use std::panic; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::str; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -306,6 +306,18 @@ fn add_exe_suffix(input: String, target: &TargetTriple) -> String { input + &exe_suffix } +fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command { + let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter()); + + let exe = args.next().expect("unable to create rustc command"); + let mut command = Command::new(exe); + for arg in args { + command.arg(arg); + } + + command +} + fn run_test( test: &str, crate_name: &str, @@ -334,7 +346,7 @@ fn run_test( .test_builder .as_deref() .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc")); - let mut compiler = Command::new(&rustc_binary); + let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); compiler.arg("--crate-type").arg("bin"); for cfg in &rustdoc_options.cfgs { compiler.arg("--cfg").arg(&cfg); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index fe83095f944ab..bfd67ccbd3f9a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1698,9 +1698,10 @@ fn render_impl( let id = cx.derive_id(format!("{item_type}.{name}")); let source_id = trait_ .and_then(|trait_| { - trait_.items.iter().find(|item| { - item.name.map(|n| n.as_str().eq(name.as_str())).unwrap_or(false) - }) + trait_ + .items + .iter() + .find(|item| item.name.map(|n| n == *name).unwrap_or(false)) }) .map(|item| format!("{}.{name}", item.type_())); write!(w, "
"); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 39d27b104cdde..18651875130fc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -530,6 +530,14 @@ fn opts() -> Vec { unstable("test-builder", |o| { o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") }), + unstable("test-builder-wrapper", |o| { + o.optmulti( + "", + "test-builder-wrapper", + "Wrapper program to pass test-builder and arguments", + "PATH", + ) + }), unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), unstable("generate-redirect-map", |o| { o.optflagmulti( diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0603aae553609..e85b998bfbe1b 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -80,9 +80,8 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - // check if parent is trait impl if let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id) - && let Some(parent_node) = cx.tcx.opt_hir_node_by_def_id(parent_def_id) && matches!( - parent_node, + cx.tcx.hir_node_by_def_id(parent_def_id), hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }), .. diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 8857cb8e3827f..ad589dad350b3 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -76,10 +76,9 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { .hir() .get_parent_item(cx.tcx.local_def_id_to_hir_id(fn_def_id)) .def_id; - let parent_node = cx.tcx.opt_hir_node_by_def_id(parent_id); let mut trait_self_ty = None; - if let Some(Node::Item(item)) = parent_node { + if let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_id) { // If the method is an impl for a trait, don't warn. if let ItemKind::Impl(Impl { of_trait: Some(_), .. }) = item.kind { return; diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index 6603512c73cdf..106844dd43489 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit { && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id() && cx.tcx.is_diagnostic_item(sym::process_exit, def_id) && let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id - && let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.opt_hir_node_by_def_id(parent) + && let Node::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_node_by_def_id(parent) // If the next item up is a function we check if it is an entry point // and only then emit a linter warning && !is_entrypoint_fn(cx, parent.to_def_id()) diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 7f36f33fe708c..37fbf2c7d5960 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -92,7 +92,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty .expect("already checked this is adt") .did() .as_local() - && let Some(hir::Node::Item(item)) = cx.tcx.opt_hir_node_by_def_id(local_def_id) + && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id) && let hir::ItemKind::Enum(ref def, _) = item.kind { let variants_size = AdtVariantInfo::new(cx, *adt, subst); diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 4094d7ded7d82..ea6e662b4be36 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -225,10 +225,9 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def() && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name) && let Some(local_did) = field.did.as_local() - && let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(local_did) && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data() { - (hir_id, ident) + (cx.tcx.local_def_id_to_hir_id(local_did), ident) } else { return; } 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 88b331ddefdb7..3bf9f75e22619 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 @@ -220,7 +220,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { && let self_ty = cx.tcx.type_of(self_path_did).skip_binder().peel_refs() && let Some(self_adt) = self_ty.ty_adt_def() && let Some(self_def_id) = self_adt.did().as_local() - && let Some(Node::Item(self_item)) = cx.tcx.opt_hir_node_by_def_id(self_def_id) + && let Node::Item(self_item) = cx.tcx.hir_node_by_def_id(self_def_id) // NB: can't call cx.typeck_results() as we are not in a body && let typeck_results = cx.tcx.typeck_body(*body_id) && should_lint(cx, typeck_results, block) 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 a5b58f9910ad5..a450dee305005 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 @@ -112,10 +112,7 @@ fn check_closures<'tcx>( } ctx.prev_bind = None; ctx.prev_move_to_closure.clear(); - if let Some(body) = cx - .tcx - .opt_hir_node_by_def_id(closure) - .and_then(associated_body) + if let Some(body) = associated_body(cx.tcx.hir_node_by_def_id(closure)) .map(|(_, body_id)| hir.body(body_id)) { euv::ExprUseVisitor::new(ctx, infcx, closure, cx.param_env, cx.typeck_results()).consume_body(body); diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index fc5a45dd56d6b..85a2b1a673525 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -72,8 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { if let Some(self_def) = self_ty.ty_adt_def() && let Some(self_local_did) = self_def.did().as_local() - && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did) - && let Node::Item(x) = cx.tcx.hir_node(self_id) + && let Node::Item(x) = cx.tcx.hir_node_by_def_id(self_local_did) && let type_name = x.ident.name.as_str().to_lowercase() && (impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name) 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 223cbb3fae106..2ce7e714c6424 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -95,7 +95,7 @@ impl SingleCallFn { /// to be considered. fn is_valid_item_kind(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { matches!( - cx.tcx.hir_node(cx.tcx.local_def_id_to_hir_id(def_id)), + cx.tcx.hir_node_by_def_id(def_id), Node::Item(_) | Node::ImplItem(_) | Node::TraitItem(_) ) } diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 7882bfdd09fad..bdef82e9c5eed 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { _: Span, def_id: LocalDefId, ) { - let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.opt_hir_node_by_def_id( + let is_in_trait_impl = if let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id( cx.tcx .hir() .get_parent_item(cx.tcx.local_def_id_to_hir_id(def_id)) @@ -366,9 +366,9 @@ impl<'tcx> LateLintPass<'tcx> for Types { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) { match item.kind { ImplItemKind::Const(ty, _) => { - let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx + let is_in_trait_impl = if let hir::Node::Item(item) = cx .tcx - .opt_hir_node_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id) + .hir_node_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index 81d4a26e9da43..4aaf3b0a0b674 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -74,7 +74,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues { fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { let parent_id = cx.tcx.hir().get_parent_item(hir_id); let second_parent_id = cx.tcx.hir().get_parent_item(parent_id.into()).def_id; - if let Some(Node::Item(item)) = cx.tcx.opt_hir_node_by_def_id(second_parent_id) { + if let Node::Item(item) = cx.tcx.hir_node_by_def_id(second_parent_id) { if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { return true; } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index dc0725730322b..a38db0ebec0f5 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -330,8 +330,7 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) /// Checks if the `def_id` belongs to a function that is part of a trait impl. pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { - if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id) - && let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) + if let Node::Item(item) = cx.tcx.parent_hir_node(cx.tcx.local_def_id_to_hir_id(def_id)) && let ItemKind::Impl(imp) = item.kind { imp.of_trait.is_some() @@ -574,12 +573,12 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb let hir = tcx.hir(); let root_mod; - let item_kind = match tcx.opt_hir_node_by_def_id(local_id) { - Some(Node::Crate(r#mod)) => { + let item_kind = match tcx.hir_node_by_def_id(local_id) { + Node::Crate(r#mod) => { root_mod = ItemKind::Mod(r#mod); &root_mod }, - Some(Node::Item(item)) => &item.kind, + Node::Item(item) => &item.kind, _ => return Vec::new(), }; @@ -1254,12 +1253,10 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// Gets the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; - match cx.tcx.opt_hir_node_by_def_id(parent_id) { - Some( - Node::Item(Item { ident, .. }) - | Node::TraitItem(TraitItem { ident, .. }) - | Node::ImplItem(ImplItem { ident, .. }), - ) => Some(ident.name), + match cx.tcx.hir_node_by_def_id(parent_id) { + Node::Item(Item { ident, .. }) + | Node::TraitItem(TraitItem { ident, .. }) + | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name), _ => None, } } @@ -2667,11 +2664,10 @@ impl<'tcx> ExprUseNode<'tcx> { .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())), )), Self::Return(id) => { - let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id); if let Node::Expr(Expr { kind: ExprKind::Closure(c), .. - }) = cx.tcx.hir_node(hir_id) + }) = cx.tcx.hir_node_by_def_id(id.def_id) { match c.fn_decl.output { FnRetTy::DefaultReturn(_) => None, diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/issue-88756-default-output/output-default.stdout index 38a3965f0c53d..12c1b389fb340 100644 --- a/tests/run-make/issue-88756-default-output/output-default.stdout +++ b/tests/run-make/issue-88756-default-output/output-default.stdout @@ -147,6 +147,8 @@ Options: --test-builder PATH The rustc-like binary to use as the test builder + --test-builder-wrapper PATH + Wrapper program to pass test-builder and arguments --check Run rustdoc checks --generate-redirect-map Generate JSON file at the top level instead of