diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 5628dffd51358..c49961784d6a9 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -201,15 +201,9 @@ impl<'hir> LoweringContext<'_, 'hir> { anon_const: self.lower_const_block(anon_const), }, InlineAsmOperand::Sym { sym } => { - let static_def_id = self - .get_partial_res(sym.id) - .and_then(|res| res.full_res()) - .and_then(|res| match res { - Res::Def(DefKind::Static { .. }, def_id) => Some(def_id), - _ => None, - }); - - if let Some(def_id) = static_def_id { + if let Some(Res::Def(DefKind::Static { .. }, def_id)) = + self.get_full_res(sym.id) + { let path = self.lower_qpath( sym.id, &sym.qself, diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index 4d9bc09faeecb..d5551a16714f3 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -300,8 +300,8 @@ impl<'hir> DelegationResolver<'_, 'hir> { let qself_is_none = delegation.qself.is_none(); let parent_args = if let [.., parent_segment, _] = &delegation.path.segments[..] { - let res = self.get_resolution_id(parent_segment.id)?; - if matches!(tcx.def_kind(res), DefKind::Trait | DefKind::TraitAlias) { + let (_, kind) = self.get_resolution(parent_segment.id)?; + if matches!(kind, DefKind::Trait | DefKind::TraitAlias) { sig_parent_params = &tcx.generics_of(sig_parent).own_params; self.get_user_args(parent_segment) .map(|args| ParentSegmentArgs::Specified(args)) diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs index 08429a6025456..29e5dbda26ec9 100644 --- a/compiler/rustc_ast_lowering/src/delegation/mod.rs +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -589,8 +589,7 @@ struct SelfResolver<'a, 'b, 'hir> { impl SelfResolver<'_, '_, '_> { fn try_replace_id(&mut self, id: NodeId) { - if let Some(res) = self.ctxt.get_partial_res(id) - && let Some(Res::Local(sig_id)) = res.full_res() + if let Some(Res::Local(sig_id)) = self.ctxt.get_full_res(id) && sig_id == self.path_id { self.overwrites.push(id); diff --git a/compiler/rustc_ast_lowering/src/delegation/resolution.rs b/compiler/rustc_ast_lowering/src/delegation/resolution.rs index 21fbed81b3e0b..469a17717c486 100644 --- a/compiler/rustc_ast_lowering/src/delegation/resolution.rs +++ b/compiler/rustc_ast_lowering/src/delegation/resolution.rs @@ -50,6 +50,7 @@ pub(super) struct DelegationResolution { pub(super) mod resolver { use rustc_ast::NodeId; + use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::TyCtxt; use rustc_span::ErrorGuaranteed; @@ -95,10 +96,14 @@ pub(super) mod resolver { } #[inline] - pub(crate) fn get_resolution_id(&self, id: NodeId) -> Result { - self.0.get_partial_res(id).and_then(|r| r.expect_full_res().opt_def_id()).ok_or_else( - || self.tcx().dcx().delayed_bug(format!("failed to resolve node {id:?}")), - ) + pub(crate) fn get_resolution( + &self, + id: NodeId, + ) -> Result<(DefId, DefKind), ErrorGuaranteed> { + let Res::Def(kind, id) = self.0.expect_full_res(id) else { + return Err(self.tcx().dcx().delayed_bug(format!("failed to resolve node {id:?}"))); + }; + Ok((id, kind)) } } } @@ -149,7 +154,7 @@ impl<'tcx> DelegationResolver<'_, 'tcx> { // FIXME(splat): use `sig.splatted()` once FnSig has it param_info: ParamInfo { param_count, c_variadic: sig.c_variadic(), splatted: None }, source: delegation.source, - call_path_res: self.get_resolution_id(delegation.id)?, + call_path_res: self.get_resolution(delegation.id).map(|(id, _)| id)?, sig_mapping: self.create_self_mapping( delegation, span, @@ -306,7 +311,7 @@ impl<'tcx> DelegationResolver<'_, 'tcx> { // Check that delegation path resolves to a trait AssocFn, not to a free method. // After previous check we are sure that `sig_id` and `delegation.id` // point to the same function. - let id = self.get_resolution_id(delegation.id)?; - Ok(tcx.def_kind(id) == DefKind::AssocFn && tcx.def_kind(tcx.parent(id)) == DefKind::Trait) + let (id, kind) = self.get_resolution(delegation.id)?; + Ok(kind == DefKind::AssocFn && tcx.def_kind(tcx.parent(id)) == DefKind::Trait) } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f66d1ac16c907..deff4a0e1a6dd 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1226,12 +1226,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> Option<(&'a Option>, &'a Path)> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a tuple struct/variant pattern? - if let Some(partial_res) = self.get_partial_res(expr.id) { - if let Some(res) = partial_res.full_res() - && !res.expected_in_tuple_struct_pat() - { - return None; - } + if let Some(res) = self.get_full_res(expr.id) + && !res.expected_in_tuple_struct_pat() + { + return None; } return Some((qself, path)); } @@ -1248,12 +1246,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> Option<(&'a Option>, &'a Path)> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a unit struct/variant pattern? - if let Some(partial_res) = self.get_partial_res(expr.id) { - if let Some(res) = partial_res.full_res() - && !res.expected_in_unit_struct_pat() - { - return None; - } + if let Some(res) = self.get_full_res(expr.id) + && !res.expected_in_unit_struct_pat() + { + return None; } return Some((qself, path)); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8ebecb222b940..5dd9f12b36289 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -583,8 +583,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_path_simple_eii(&mut self, id: NodeId, path: &Path) -> Option { - let res = self.get_partial_res(id)?; - let Some(did) = res.expect_full_res().opt_def_id() else { + let Some(did) = self.expect_full_res(id).opt_def_id() else { self.dcx().span_delayed_bug(path.span, "should have errored in resolve"); return None; }; @@ -1280,13 +1279,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let span = self.lower_span(i.span); let (effective_ident, impl_kind) = if is_in_trait_impl { - let trait_item_def_id = self - .get_partial_res(i.id) - .and_then(|r| r.expect_full_res().opt_def_id()) - .ok_or_else(|| { - self.dcx() - .span_delayed_bug(span, "could not resolve trait item being implemented") - }); + let trait_item_def_id = self.expect_full_res(i.id).opt_def_id().ok_or_else(|| { + self.dcx().span_delayed_bug(span, "could not resolve trait item being implemented") + }); let effective_ident = self.check_pin_drop_sugar_impl_item(i, ident, trait_item_def_id); (effective_ident, ImplItemImplKind::Trait { defaultness, trait_item_def_id }) } else { @@ -1802,8 +1797,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &r.kind { RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted, RestrictionKind::Restricted { path, id, shorthand: _ } => { - let res = self.get_partial_res(*id); - if let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) { + let res = self.expect_full_res(*id); + if let Some(did) = res.opt_def_id() { hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path { res: did, segments: self.arena.alloc_from_iter(path.segments.iter().map(|segment| { @@ -1910,8 +1905,8 @@ impl<'hir> LoweringContext<'_, 'hir> { return; }; let define_opaque = define_opaque.iter().filter_map(|(id, path)| { - let res = self.get_partial_res(*id); - let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else { + let res = self.expect_full_res(*id); + let Some(did) = res.opt_def_id() else { self.dcx().span_delayed_bug(path.span, "should have errored in resolve"); return None; }; @@ -2013,8 +2008,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds, }) => { let rbp = if bound_generic_params.is_empty() - && let Some(res) = - self.get_partial_res(bounded_ty.id).and_then(|r| r.full_res()) + && let Some(res) = self.get_full_res(bounded_ty.id) && let Res::Def(DefKind::TyParam, def_id) = res && params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id()) { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dc1acade85ed5..600d10bfccdb2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -812,6 +812,12 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } + fn get_full_res(&self, id: NodeId) -> Option> { + self.get_partial_res(id)?.full_res() + } + + /// Unless you're manually handling path resolutions, you do not want to use this function. + /// Prefer [Self::get_full_res] or [Self::expect_full_res] instead. fn get_partial_res(&self, id: NodeId) -> Option { match self.partial_res_overrides.get(&id) { Some(self_param_id) => Some(PartialRes::new(Res::Local(*self_param_id))), @@ -1010,7 +1016,13 @@ impl<'hir> LoweringContext<'_, 'hir> { res.unwrap_or(Res::Err) } - fn expect_full_res(&mut self, id: NodeId) -> Res { + /// The common entry point to obtaining resolution information. + /// + /// ## Panics + /// + /// If the resolution still has unresolved segments, this function will panic. + /// So lowering paths always needs to go through `get_full_res`. + fn expect_full_res(&self, id: NodeId) -> Res { self.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } @@ -1460,10 +1472,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // FIXME: Should we be handling `(PATH_TO_CONST)`? TyKind::Path(None, path) => { - if let Some(res) = self - .get_partial_res(ty.id) - .and_then(|partial_res| partial_res.full_res()) - { + if let Some(res) = self.get_full_res(ty.id) { if !res.matches_ns(Namespace::TypeNS) && path.is_potential_trivial_const_arg() { @@ -1511,8 +1520,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // The other cases when a qpath should be opportunistically made a trait object are handled // by `ty_path`. if qself.is_none() - && let Some(partial_res) = self.get_partial_res(t.id) - && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() + && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = self.get_full_res(t.id) { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { let bound = this.lower_poly_trait_ref( @@ -1877,9 +1885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let [segment] = path.segments.as_slice() else { panic!(); }; - let res = self.get_partial_res(*id).map_or(Res::Err, |partial_res| { - partial_res.full_res().expect("no partial res expected for precise capture arg") - }); + let res = self.expect_full_res(*id); hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg { hir_id: self.lower_node_id(*id), ident: self.lower_ident(segment.ident), @@ -2890,8 +2896,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &anon.value }; - let maybe_res = - self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); + let maybe_res = self.get_full_res(expr.id); if let ExprKind::Path(qself, path) = &expr.kind && path.is_potential_trivial_const_arg() && matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))) diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 8780b70fadfa4..28533497d1a53 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -288,11 +288,12 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: hir::HirId, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, ) -> hir::PatKind<'hir> { - match self.get_partial_res(p.id).map(|d| d.expect_full_res()) { - // `None` can occur in body-less function signatures - res @ (None | Some(Res::Local(_))) => { + let res = self.expect_full_res(p.id); + match res { + // `Err` can occur in body-less function signatures + Res::Local(_) | Res::Err => { let binding_id = match res { - Some(Res::Local(id)) => { + Res::Local(id) => { // In `Or` patterns like `VariantA(s) | VariantB(s, _)`, multiple identifier patterns // will be resolved to the same `Res::Local`. Thus they just share a single // `HirId`. @@ -318,7 +319,7 @@ impl<'hir> LoweringContext<'_, 'hir> { lower_sub(self), ) } - Some(res) => { + res => { let res = self.lower_res(res); let span = self.lower_span(ident.span); hir::PatKind::Expr(self.arena.alloc(hir::PatExpr {