rustc: Panic by default in DefIdTree::parent

Only crate root def-ids don't have a parent, and in majority of cases the argument of `DefIdTree::parent` cannot be a crate root.
So we now panic by default in `parent` and introduce a new non-panicing function `opt_parent` for cases where the argument can be a crate root.

Same applies to `local_parent`/`opt_local_parent`.
This commit is contained in:
Vadim Petrochenkov 2022-04-25 22:08:45 +03:00
parent a933de8398
commit 5b5964f569
50 changed files with 162 additions and 176 deletions

View File

@ -90,7 +90,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
{
if let ty::FnDef(id, _) = *literal.ty().kind() {
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
let closure = match args.first() {
Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place))
if target == place.local_or_deref_local() =>

View File

@ -46,7 +46,7 @@ pub fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> {
}
pub fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
item_namespace(cx, cx.tcx.parent(def_id).expect("get_namespace_for_item: missing parent?"))
item_namespace(cx, cx.tcx.parent(def_id))
}
#[derive(Debug, PartialEq, Eq)]

View File

@ -17,7 +17,7 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
}
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
let parent_id = tcx.local_parent(def_id).unwrap();
let parent_id = tcx.local_parent(def_id);
tcx.def_kind(parent_id) == DefKind::Impl
&& tcx.impl_constness(parent_id) == hir::Constness::Const
}

View File

@ -128,9 +128,9 @@ pub fn call_kind<'tcx>(
} else {
None
};
let parent_self_ty = tcx
.parent(method_did)
.filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
let parent_did = tcx.parent(method_did);
let parent_self_ty = (tcx.def_kind(parent_did) == rustc_hir::def::DefKind::Impl)
.then_some(parent_did)
.and_then(|did| match tcx.type_of(did).kind() {
ty::Adt(def, ..) => Some(def.did()),
_ => None,

View File

@ -341,7 +341,7 @@ impl InferenceDiagnosticsData {
impl InferenceDiagnosticsParentData {
fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<InferenceDiagnosticsParentData> {
let parent_def_id = tcx.parent(def_id)?;
let parent_def_id = tcx.parent(def_id);
let parent_name =
tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
@ -854,10 +854,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
if let Some((DefKind::AssocFn, def_id)) =
self.in_progress_typeck_results?.borrow().type_dependent_def(hir_id)
{
return self
.tcx
.parent(def_id)
.filter(|&parent_def_id| self.tcx.is_trait(parent_def_id));
let parent_def_id = self.tcx.parent(def_id);
return self.tcx.is_trait(parent_def_id).then_some(parent_def_id);
}
None

View File

@ -42,7 +42,7 @@ pub fn find_param_with_region<'tcx>(
let (id, bound_region) = match *anon_region {
ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
ty::ReEarlyBound(ebr) => {
(tcx.parent(ebr.def_id).unwrap(), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name))
(tcx.parent(ebr.def_id), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name))
}
_ => return None, // not a free region
};

View File

@ -1471,7 +1471,7 @@ impl InvalidAtomicOrdering {
&& let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def()
// skip extension traits, only lint functions from the standard library
&& cx.tcx.trait_id_of_impl(impl_did).is_none()
&& let Some(parent) = cx.tcx.parent(adt.did())
&& let parent = cx.tcx.parent(adt.did())
&& cx.tcx.is_diagnostic_item(sym::atomic_mod, parent)
&& ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did()))
{
@ -1486,9 +1486,9 @@ impl InvalidAtomicOrdering {
orderings.iter().any(|ordering| {
tcx.item_name(did) == *ordering && {
let parent = tcx.parent(did);
parent == atomic_ordering
Some(parent) == atomic_ordering
// needed in case this is a ctor, not a variant
|| parent.map_or(false, |parent| tcx.parent(parent) == atomic_ordering)
|| tcx.opt_parent(parent) == atomic_ordering
}
})
}

View File

@ -546,7 +546,7 @@ impl<'hir> Map<'hir> {
let def_kind = self.tcx.def_kind(def_id);
match def_kind {
DefKind::Trait | DefKind::TraitAlias => def_id,
DefKind::TyParam | DefKind::ConstParam => self.tcx.local_parent(def_id).unwrap(),
DefKind::TyParam | DefKind::ConstParam => self.tcx.local_parent(def_id),
_ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
}
}

View File

@ -289,7 +289,7 @@ fn suggestion_for_allocator_api(
feature: Symbol,
) -> Option<(Span, String, String, Applicability)> {
if feature == sym::allocator_api {
if let Some(trait_) = tcx.parent(def_id) {
if let Some(trait_) = tcx.opt_parent(def_id) {
if tcx.is_diagnostic_item(sym::Vec, trait_) {
let sm = tcx.sess.parse_sess.source_map();
let inner_types = sm.span_extend_to_prev_char(span, '<', true);

View File

@ -1491,7 +1491,7 @@ impl<'tcx> TyCtxt<'tcx> {
(free_region.scope.expect_local(), free_region.bound_region)
}
ty::ReEarlyBound(ref ebr) => (
self.parent(ebr.def_id).unwrap().expect_local(),
self.local_parent(ebr.def_id.expect_local()),
ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
),
_ => return None, // not a free region

View File

@ -108,7 +108,7 @@ impl<'tcx> Ty<'tcx> {
| Placeholder(_)
| Error(_) => false,
Opaque(did, substs) => {
let parent = tcx.parent(*did).expect("opaque types always have a parent");
let parent = tcx.parent(*did);
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = tcx.def_kind(parent)
&& let Opaque(parent_did, _) = tcx.type_of(parent).kind()
&& parent_did == did

View File

@ -290,11 +290,28 @@ pub struct ClosureSizeProfileData<'tcx> {
}
pub trait DefIdTree: Copy {
fn parent(self, id: DefId) -> Option<DefId>;
fn opt_parent(self, id: DefId) -> Option<DefId>;
#[inline]
fn local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
Some(self.parent(id.to_def_id())?.expect_local())
#[track_caller]
fn parent(self, id: DefId) -> DefId {
match self.opt_parent(id) {
Some(id) => id,
// not `unwrap_or_else` to avoid breaking caller tracking
None => bug!("{id:?} doesn't have a parent"),
}
}
#[inline]
#[track_caller]
fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
self.opt_parent(id.to_def_id()).map(DefId::expect_local)
}
#[inline]
#[track_caller]
fn local_parent(self, id: LocalDefId) -> LocalDefId {
self.parent(id.to_def_id()).expect_local()
}
fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
@ -303,7 +320,7 @@ pub trait DefIdTree: Copy {
}
while descendant != ancestor {
match self.parent(descendant) {
match self.opt_parent(descendant) {
Some(parent) => descendant = parent,
None => return false,
}
@ -313,7 +330,8 @@ pub trait DefIdTree: Copy {
}
impl<'tcx> DefIdTree for TyCtxt<'tcx> {
fn parent(self, id: DefId) -> Option<DefId> {
#[inline]
fn opt_parent(self, id: DefId) -> Option<DefId> {
self.def_key(id).parent.map(|index| DefId { index, ..id })
}
}
@ -2123,17 +2141,17 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef {
match res {
Res::Def(DefKind::Variant, did) => {
let enum_did = self.parent(did).unwrap();
let enum_did = self.parent(did);
self.adt_def(enum_did).variant_with_id(did)
}
Res::Def(DefKind::Struct | DefKind::Union, did) => self.adt_def(did).non_enum_variant(),
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => {
let variant_did = self.parent(variant_ctor_did).unwrap();
let enum_did = self.parent(variant_did).unwrap();
let variant_did = self.parent(variant_ctor_did);
let enum_did = self.parent(variant_did);
self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
}
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => {
let struct_did = self.parent(ctor_did).expect("struct ctor has no parent");
let struct_did = self.parent(ctor_did);
self.adt_def(struct_did).non_enum_variant()
}
_ => bug!("expect_variant_res used with unexpected res {:?}", res),

View File

@ -235,11 +235,11 @@ pub trait Printer<'tcx>: Sized {
// as the trait.
let in_self_mod = match characteristic_def_id_of_type(self_ty) {
None => false,
Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id),
Some(ty_def_id) => self.tcx().parent(ty_def_id) == parent_def_id,
};
let in_trait_mod = match impl_trait_ref {
None => false,
Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id),
Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == parent_def_id,
};
if !in_self_mod && !in_trait_mod {

View File

@ -408,7 +408,7 @@ pub trait PrettyPrinter<'tcx>:
return Ok((self, false));
};
let actual_parent = self.tcx().parent(def_id);
let actual_parent = self.tcx().opt_parent(def_id);
debug!(
"try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
visible_parent, actual_parent,
@ -643,7 +643,7 @@ pub trait PrettyPrinter<'tcx>:
return Ok(self);
}
let parent = self.tcx().parent(def_id).expect("opaque types always have a parent");
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {

View File

@ -1798,7 +1798,7 @@ impl<'tcx> Region<'tcx> {
/// function might return the `DefId` of a closure.
pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId {
match *self {
ty::ReEarlyBound(br) => tcx.parent(br.def_id).unwrap(),
ty::ReEarlyBound(br) => tcx.parent(br.def_id),
ty::ReFree(fr) => fr.scope,
_ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self),
}

View File

@ -142,10 +142,10 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
match res {
Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => {
Some(self.parent(def_id).and_then(|def_id| self.parent(def_id)).unwrap())
Some(self.parent(self.parent(def_id)))
}
Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
Some(self.parent(def_id).unwrap())
Some(self.parent(def_id))
}
// Other `DefKind`s don't have generics and would ICE when calling
// `generics_of`.
@ -500,9 +500,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn typeck_root_def_id(self, def_id: DefId) -> DefId {
let mut def_id = def_id;
while self.is_typeck_child(def_id) {
def_id = self.parent(def_id).unwrap_or_else(|| {
bug!("closure {:?} has no parent", def_id);
});
def_id = self.parent(def_id);
}
def_id
}

View File

@ -377,7 +377,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
) -> PatKind<'tcx> {
let res = match res {
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
let variant_id = self.tcx.parent(variant_ctor_id);
Res::Def(DefKind::Variant, variant_id)
}
res => res,
@ -385,7 +385,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let mut kind = match res {
Res::Def(DefKind::Variant, variant_id) => {
let enum_id = self.tcx.parent(variant_id).unwrap();
let enum_id = self.tcx.parent(variant_id);
let adt_def = self.tcx.adt_def(enum_id);
if adt_def.is_enum() {
let substs = match ty.kind() {

View File

@ -352,7 +352,7 @@ fn compute_codegen_unit_name(
cgu_def_id = None;
}
current_def_id = tcx.parent(current_def_id).unwrap();
current_def_id = tcx.parent(current_def_id);
}
let cgu_def_id = cgu_def_id.unwrap();

View File

@ -88,15 +88,15 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
_ if self.in_pat => {}
Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {}
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => {
let variant_id = self.tcx.parent(ctor_def_id).unwrap();
let enum_id = self.tcx.parent(variant_id).unwrap();
let variant_id = self.tcx.parent(ctor_def_id);
let enum_id = self.tcx.parent(variant_id);
self.check_def_id(enum_id);
if !self.ignore_variant_stack.contains(&ctor_def_id) {
self.check_def_id(variant_id);
}
}
Res::Def(DefKind::Variant, variant_id) => {
let enum_id = self.tcx.parent(variant_id).unwrap();
let enum_id = self.tcx.parent(variant_id);
self.check_def_id(enum_id);
if !self.ignore_variant_stack.contains(&variant_id) {
self.check_def_id(variant_id);

View File

@ -27,7 +27,7 @@ struct EntryContext<'tcx> {
impl<'tcx> ItemLikeVisitor<'tcx> for EntryContext<'tcx> {
fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
let at_root = self.tcx.local_parent(item.def_id) == Some(CRATE_DEF_ID);
let at_root = self.tcx.opt_local_parent(item.def_id) == Some(CRATE_DEF_ID);
find_item(item, self, at_root);
}

View File

@ -332,9 +332,9 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
let def_id = local_def_id.to_def_id();
// Don't run unused pass for #[derive()]
if let Some(parent) = self.tcx.parent(def_id)
&& let DefKind::Impl = self.tcx.def_kind(parent.expect_local())
&& self.tcx.has_attr(parent, sym::automatically_derived)
let parent = self.tcx.local_parent(local_def_id);
if let DefKind::Impl = self.tcx.def_kind(parent)
&& self.tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
{
return;
}

View File

@ -280,8 +280,7 @@ impl<'tcx> ReachableContext<'tcx> {
self.visit_nested_body(body);
}
hir::ImplItemKind::Fn(_, body) => {
let impl_def_id =
self.tcx.parent(search_item.to_def_id()).unwrap().expect_local();
let impl_def_id = self.tcx.local_parent(search_item);
if method_might_be_inlined(self.tcx, impl_item, impl_def_id) {
self.visit_nested_body(body)
}

View File

@ -24,7 +24,8 @@ use rustc_middle::thir::abstract_const::Node as ACNode;
use rustc_middle::ty::fold::TypeVisitor;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeFoldable};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
use rustc_span::symbol::{kw, Ident};
@ -456,9 +457,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
return;
}
let item_def_id = local_def_id.to_def_id();
let macro_module_def_id =
ty::DefIdTree::parent(self.tcx, item_def_id).unwrap().expect_local();
let macro_module_def_id = self.tcx.local_parent(local_def_id);
if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) {
// The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
return;
@ -477,8 +476,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
if changed_reachability || module_def_id == CRATE_DEF_ID {
break;
}
module_def_id =
ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local();
module_def_id = self.tcx.local_parent(module_def_id);
}
}

View File

@ -1388,7 +1388,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
&& self
.r
.trait_impl_items
.contains(&ty::DefIdTree::parent(&*self.r, def_id).unwrap().expect_local()))
.contains(&ty::DefIdTree::local_parent(&*self.r, local_def_id)))
{
// Trait impl item visibility is inherited from its trait when not specified
// explicitly. In that case we cannot determine it here in early resolve,

View File

@ -1321,7 +1321,7 @@ impl<'a> Resolver<'a> {
segms.push(ast::PathSegment::from_ident(ident));
let path = Path { span: name_binding.span, segments: segms, tokens: None };
let did = match res {
Res::Def(DefKind::Ctor(..), did) => this.parent(did),
Res::Def(DefKind::Ctor(..), did) => this.opt_parent(did),
_ => res.opt_def_id(),
};
@ -1707,7 +1707,7 @@ impl<'a> Resolver<'a> {
_,
) = binding.kind
{
let def_id = self.parent(ctor_def_id).expect("no parent for a constructor");
let def_id = self.parent(ctor_def_id);
let fields = self.field_names.get(&def_id)?;
return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()`
}

View File

@ -13,7 +13,6 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
use rustc_hir::def::{self, PartialRes};
use rustc_hir::def_id::DefId;
use rustc_middle::metadata::ModChild;
use rustc_middle::span_bug;
use rustc_middle::ty;
@ -345,12 +344,6 @@ pub struct ImportResolver<'a, 'b> {
pub r: &'a mut Resolver<'b>,
}
impl<'a, 'b> ty::DefIdTree for &'a ImportResolver<'a, 'b> {
fn parent(self, id: DefId) -> Option<DefId> {
self.r.parent(id)
}
}
impl<'a, 'b> ImportResolver<'a, 'b> {
// Import resolution
//
@ -696,7 +689,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
if !is_prelude &&
max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
!max_vis.get().is_at_least(import.vis.get(), &*self)
!max_vis.get().is_at_least(import.vis.get(), &*self.r)
{
let msg = "glob import doesn't reexport anything because no candidate is public enough";
self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);

View File

@ -1313,12 +1313,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Figure out if this is a type/trait segment,
// which may need lifetime elision performed.
let type_def_id = match partial_res.base_res() {
Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
self.r.parent(def_id).unwrap()
}
Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
self.r.parent(def_id).unwrap()
}
Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => self.r.parent(def_id),
Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => self.r.parent(def_id),
Res::Def(DefKind::Struct, def_id)
| Res::Def(DefKind::Union, def_id)
| Res::Def(DefKind::Enum, def_id)

View File

@ -534,21 +534,17 @@ fn is_late_bound_map<'tcx>(
) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
match tcx.def_kind(def_id) {
DefKind::AnonConst | DefKind::InlineConst => {
let mut def_id = tcx
.parent(def_id.to_def_id())
.unwrap_or_else(|| bug!("anon const or closure without a parent"));
let mut def_id = tcx.local_parent(def_id);
// We search for the next outer anon const or fn here
// while skipping closures.
//
// Note that for `AnonConst` we still just recurse until we
// find a function body, but who cares :shrug:
while tcx.is_closure(def_id) {
def_id = tcx
.parent(def_id)
.unwrap_or_else(|| bug!("anon const or closure without a parent"));
while tcx.is_closure(def_id.to_def_id()) {
def_id = tcx.local_parent(def_id);
}
tcx.is_late_bound_map(def_id.expect_local())
tcx.is_late_bound_map(def_id)
}
_ => resolve_lifetimes_for(tcx, def_id).late_bound.get(&def_id).map(|lt| (def_id, lt)),
}
@ -1864,7 +1860,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let remove_decl = self
.tcx
.parent(def_id)
.and_then(|parent_def_id| parent_def_id.as_local())
.as_local()
.and_then(|parent_def_id| self.tcx.hir().get_generics(parent_def_id))
.and_then(|generics| self.lifetime_deletion_span(name, generics));
@ -2003,37 +1999,36 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
continue;
}
if let Some(parent_def_id) = self.tcx.parent(def_id) {
if let Some(def_id) = parent_def_id.as_local() {
// lifetimes in `derive` expansions don't count (Issue #53738)
if self
.tcx
.get_attrs(def_id.to_def_id())
.iter()
.any(|attr| attr.has_name(sym::automatically_derived))
{
continue;
}
let parent_def_id = self.tcx.parent(def_id);
if let Some(def_id) = parent_def_id.as_local() {
// lifetimes in `derive` expansions don't count (Issue #53738)
if self
.tcx
.get_attrs(def_id.to_def_id())
.iter()
.any(|attr| attr.has_name(sym::automatically_derived))
{
continue;
}
// opaque types generated when desugaring an async function can have a single
// use lifetime even if it is explicitly denied (Issue #77175)
if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(ref opaque),
..
}) = self.tcx.hir().get_by_def_id(def_id)
{
if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) {
// opaque types generated when desugaring an async function can have a single
// use lifetime even if it is explicitly denied (Issue #77175)
if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(ref opaque),
..
}) = self.tcx.hir().get_by_def_id(def_id)
{
if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) {
continue 'lifetimes;
}
// We want to do this only if the lifetime identifier is already defined
// in the async function that generated this. Otherwise it could be
// an opaque type defined by the developer and we still want this
// lint to fail compilation
for p in opaque.generics.params {
if defined_by.contains_key(&p.name) {
continue 'lifetimes;
}
// We want to do this only if the lifetime identifier is already defined
// in the async function that generated this. Otherwise it could be
// an opaque type defined by the developer and we still want this
// lint to fail compilation
for p in opaque.generics.params {
if defined_by.contains_key(&p.name) {
continue 'lifetimes;
}
}
}
}
}
@ -2087,20 +2082,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|lint| {
let mut err = lint
.build(&format!("lifetime parameter `{}` never used", name));
if let Some(parent_def_id) = self.tcx.parent(def_id) {
if let Some(generics) =
self.tcx.hir().get_generics(parent_def_id.expect_local())
{
let unused_lt_span =
self.lifetime_deletion_span(name, generics);
if let Some(span) = unused_lt_span {
err.span_suggestion(
span,
"elide the unused lifetime",
String::new(),
Applicability::MachineApplicable,
);
}
let parent_def_id = self.tcx.parent(def_id);
if let Some(generics) =
self.tcx.hir().get_generics(parent_def_id.expect_local())
{
let unused_lt_span =
self.lifetime_deletion_span(name, generics);
if let Some(span) = unused_lt_span {
err.span_suggestion(
span,
"elide the unused lifetime",
String::new(),
Applicability::MachineApplicable,
);
}
}
err.emit();

View File

@ -1109,7 +1109,8 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
}
impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
fn parent(self, id: DefId) -> Option<DefId> {
#[inline]
fn opt_parent(self, id: DefId) -> Option<DefId> {
match id.as_local() {
Some(id) => self.definitions.def_key(id).parent,
None => self.cstore().def_key(id).parent,

View File

@ -1138,8 +1138,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
let access = access_from!(self.save_ctxt, item.def_id);
let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id);
let span = self.span_from_span(sub_span);
let parent =
self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
let parent = self.save_ctxt.tcx.local_parent(item.def_id);
self.dumper.import(
&access,
Import {
@ -1149,7 +1148,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
alias_span: None,
name: item.ident.to_string(),
value: String::new(),
parent,
parent: Some(id_from_def_id(parent.to_def_id())),
},
);
self.write_sub_paths_truncated(&path);
@ -1166,8 +1165,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
if !self.span.filter_generated(item.span) {
let access = access_from!(self.save_ctxt, item.def_id);
let span = self.span_from_span(sub_span);
let parent =
self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
let parent = self.save_ctxt.tcx.local_parent(item.def_id);
self.dumper.import(
&access,
Import {
@ -1177,7 +1175,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
alias_span: None,
name: "*".to_owned(),
value: names.join(", "),
parent,
parent: Some(id_from_def_id(parent.to_def_id())),
},
);
self.write_sub_paths(&path);
@ -1188,8 +1186,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
let name_span = item.ident.span;
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
let parent =
self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
let parent = self.save_ctxt.tcx.local_parent(item.def_id);
self.dumper.import(
&Access { public: false, reachable: false },
Import {
@ -1199,7 +1196,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
alias_span: None,
name: item.ident.to_string(),
value: String::new(),
parent,
parent: Some(id_from_def_id(parent.to_def_id())),
},
);
}

View File

@ -690,7 +690,7 @@ impl<'tcx> SaveContext<'tcx> {
// This is a reference to a tuple struct or an enum variant where the def_id points
// to an invisible constructor function. That is not a very useful
// def, so adjust to point to the tuple struct or enum variant itself.
let parent_def_id = self.tcx.parent(def_id).unwrap();
let parent_def_id = self.tcx.parent(def_id);
Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(parent_def_id) })
}
Res::Def(HirDefKind::Static(_) | HirDefKind::Const | HirDefKind::AssocConst, _) => {

View File

@ -1906,7 +1906,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
GeneratorKind::Async(AsyncGeneratorKind::Fn) => self
.tcx
.parent(generator_did)
.and_then(|parent_did| parent_did.as_local())
.as_local()
.map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
.and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
.map(|name| {

View File

@ -1952,7 +1952,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) -> Ty<'tcx> {
let tcx = self.tcx();
let trait_def_id = tcx.parent(item_def_id).unwrap();
let trait_def_id = tcx.parent(item_def_id);
debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
@ -2159,11 +2159,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// `DefKind::Ctor` -> `DefKind::Variant`
if let DefKind::Ctor(..) = kind {
def_id = tcx.parent(def_id).unwrap()
def_id = tcx.parent(def_id);
}
// `DefKind::Variant` -> `DefKind::Enum`
let enum_def_id = tcx.parent(def_id).unwrap();
let enum_def_id = tcx.parent(def_id);
(enum_def_id, last - 1)
} else {
// FIXME: lint here recommending `Enum::<...>::Variant` form

View File

@ -838,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let def_kind = self.tcx.def_kind(def_id);
let item_ty = if let DefKind::Variant = def_kind {
self.tcx.type_of(self.tcx.parent(def_id).expect("variant w/out parent"))
self.tcx.type_of(self.tcx.parent(def_id))
} else {
self.tcx.type_of(def_id)
};

View File

@ -1542,7 +1542,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| {
if let Some(parent_did) = parent_map.get(trait_did) {
// If the item is re-exported as `_`, we should suggest a glob-import instead.
if Some(*parent_did) != self.tcx.parent(*trait_did)
if *parent_did != self.tcx.parent(*trait_did)
&& self
.tcx
.module_children(*parent_did)

View File

@ -3162,7 +3162,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
// #73631: closures inherit `#[target_feature]` annotations
if tcx.features().target_feature_11 && tcx.is_closure(id) {
let owner_id = tcx.parent(id).expect("closure should have a parent");
let owner_id = tcx.parent(id);
codegen_fn_attrs
.target_features
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied())

View File

@ -683,7 +683,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
Some(hidden) => hidden.ty,
None => {
let span = tcx.def_span(def_id);
let name = tcx.item_name(tcx.parent(def_id.to_def_id()).unwrap());
let name = tcx.item_name(tcx.local_parent(def_id).to_def_id());
let label = format!(
"`{}` must be used in combination with a concrete type within the same module",
name

View File

@ -421,7 +421,7 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
// `self_def_id` set, we override it here.
// See https://github.com/rust-lang/rust/issues/85454
if let QPath { ref mut self_def_id, .. } = default {
*self_def_id = cx.tcx.parent(self.def_id);
*self_def_id = Some(cx.tcx.parent(self.def_id));
}
Some(default)
@ -1068,7 +1068,7 @@ impl Clean<Item> for hir::ImplItem<'_> {
let mut what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
let impl_ref = cx.tcx.parent(local_did).and_then(|did| cx.tcx.impl_trait_ref(did));
let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(self.def_id));
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
@ -1260,7 +1260,7 @@ impl Clean<Item> for ty::AssocItem {
let mut what_rustc_thinks =
Item::from_def_id_and_parts(self.def_id, Some(self.name), kind, cx);
let impl_ref = tcx.parent(self.def_id).and_then(|did| tcx.impl_trait_ref(did));
let impl_ref = tcx.impl_trait_ref(tcx.parent(self.def_id));
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
@ -1742,9 +1742,7 @@ fn clean_field(def_id: DefId, name: Symbol, ty: Type, cx: &mut DocContext<'_>) -
}
fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let parent = tcx
.parent(def_id)
.expect("is_field_vis_inherited can only be called on struct or variant fields");
let parent = tcx.parent(def_id);
match tcx.def_kind(parent) {
DefKind::Struct | DefKind::Union => false,
DefKind::Variant => true,

View File

@ -455,7 +455,7 @@ crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<De
let mut current = def_id;
// The immediate parent might not always be a module.
// Find the first parent which is.
while let Some(parent) = tcx.parent(current) {
while let Some(parent) = tcx.opt_parent(current) {
if tcx.def_kind(parent) == DefKind::Mod {
return Some(parent);
}

View File

@ -563,7 +563,7 @@ crate fn href_with_root_path(
let did = match def_kind {
DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => {
// documented on their parent's page
tcx.parent(did).unwrap()
tcx.parent(did)
}
_ => did,
};

View File

@ -239,7 +239,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
let should_be_ignored = i
.item_id
.as_def_id()
.and_then(|def_id| self.ctx.tcx.parent(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))
.map(|node| {
matches!(

View File

@ -333,7 +333,7 @@ impl ItemFragment {
FragmentKind::StructField => write!(s, "structfield.{}", name),
FragmentKind::Variant => write!(s, "variant.{}", name),
FragmentKind::VariantField => {
let variant = tcx.item_name(tcx.parent(def_id).unwrap());
let variant = tcx.item_name(tcx.parent(def_id));
write!(s, "variant.{}.field.{}", variant, name)
}
}
@ -508,10 +508,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
| DefKind::AssocTy
| DefKind::Variant
| DefKind::Field) => {
let parent_def_id = tcx.parent(def_id).expect("nested item has no parent");
let parent_def_id = tcx.parent(def_id);
if def_kind == DefKind::Field && tcx.def_kind(parent_def_id) == DefKind::Variant
{
tcx.parent(parent_def_id).expect("variant has no parent")
tcx.parent(parent_def_id)
} else {
parent_def_id
}
@ -2333,14 +2333,10 @@ fn handle_variant(
cx: &DocContext<'_>,
res: Res,
) -> Result<(Res, Option<ItemFragment>), ErrorKind<'static>> {
cx.tcx
.parent(res.def_id(cx.tcx))
.map(|parent| {
let parent_def = Res::Def(DefKind::Enum, parent);
let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
(parent_def, Some(ItemFragment(FragmentKind::Variant, variant.def_id)))
})
.ok_or_else(|| ResolutionFailure::NoParentItem.into())
let parent = cx.tcx.parent(res.def_id(cx.tcx));
let parent_def = Res::Def(DefKind::Enum, parent);
let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
Ok((parent_def, Some(ItemFragment(FragmentKind::Variant, variant.def_id))))
}
/// Resolve a primitive type or value.

View File

@ -188,7 +188,7 @@ impl EarlyDocLinkResolver<'_, '_> {
return;
}
// FIXME: actually resolve links, not just add traits in scope.
if let Some(parent_id) = self.resolver.parent(scope_id) {
if let Some(parent_id) = self.resolver.opt_parent(scope_id) {
self.add_traits_in_scope(parent_id);
}
}
@ -253,7 +253,7 @@ impl EarlyDocLinkResolver<'_, '_> {
{
if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
let scope_id = match child.res {
Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id).unwrap(),
Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id),
_ => def_id,
};
self.resolve_doc_links_extern_outer(def_id, scope_id); // Outer attribute scope

View File

@ -49,7 +49,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
let mut attr_buf = Vec::new();
for &impl_def_id in all_trait_impls.iter().take_while(|def_id| def_id.is_local()) {
let mut parent = cx.tcx.parent(impl_def_id);
let mut parent = Some(cx.tcx.parent(impl_def_id));
while let Some(did) = parent {
attr_buf.extend(
cx.tcx
@ -65,7 +65,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
})
.cloned(),
);
parent = cx.tcx.parent(did);
parent = cx.tcx.opt_parent(did);
}
inline::build_impl(cx, None, impl_def_id, Some(&attr_buf), &mut new_items_local);
attr_buf.clear();

View File

@ -193,7 +193,7 @@ fn find_sugg_for_if_let<'tcx>(
PatKind::TupleStruct(ref qpath, [sub_pat], _) => {
if let PatKind::Wild = sub_pat.kind {
let res = cx.typeck_results().qpath_res(qpath, check_pat.hir_id);
let Some(id) = res.opt_def_id().and_then(|ctor_id| cx.tcx.parent(ctor_id)) else { return };
let Some(id) = res.opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id)) else { return };
let lang_items = cx.tcx.lang_items();
if Some(id) == lang_items.result_ok_variant() {
("is_ok()", try_get_generic_ty(op_ty, 0).unwrap_or(op_ty))

View File

@ -42,7 +42,7 @@ pub(crate) trait BindInsteadOfMap {
fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
let item_id = cx.tcx.parent(variant_id)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}({})`, which is a no-op",
cx.tcx.item_name(item_id),
@ -53,7 +53,7 @@ pub(crate) trait BindInsteadOfMap {
fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
let item_id = cx.tcx.parent(variant_id)?;
let item_id = cx.tcx.parent(variant_id);
Some(format!(
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
cx.tcx.item_name(item_id),
@ -145,7 +145,7 @@ pub(crate) trait BindInsteadOfMap {
if_chain! {
if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM);
if Some(adt.did()) == cx.tcx.parent(vid);
if adt.did() == cx.tcx.parent(vid);
then {} else { return false; }
}
@ -182,7 +182,7 @@ pub(crate) trait BindInsteadOfMap {
fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
if let Ok(variant_id) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM) {
return cx.tcx.parent(id) == Some(variant_id);
return cx.tcx.parent(id) == variant_id;
}
}
false

View File

@ -19,7 +19,7 @@ pub(super) fn check(
if_chain! {
if let Some(args) = method_chain_args(info.chain, chain_methods);
if let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind;
if let Some(id) = path_def_id(cx, fun).and_then(|ctor_id| cx.tcx.parent(ctor_id));
if let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id));
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let mut applicability = Applicability::MachineApplicable;

View File

@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(
let arg_snippet = snippet(cx, span, "..");
let body = cx.tcx.hir().body(id);
if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);
if let Some(id) = path_def_id(cx, func).and_then(|ctor_id| cx.tcx.parent(ctor_id));
if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let func_snippet = snippet(cx, arg_char.span, "..");

View File

@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
hir::ItemKind::Fn(..) => {
// ignore main()
if it.ident.name == sym::main {
let at_root = cx.tcx.local_parent(it.def_id) == Some(CRATE_DEF_ID);
let at_root = cx.tcx.local_parent(it.def_id) == CRATE_DEF_ID;
if at_root {
return;
}

View File

@ -235,7 +235,7 @@ pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem
if let QPath::Resolved(_, path) = qpath {
if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) {
return cx.tcx.parent(ctor_id) == Some(item_id);
return cx.tcx.parent(ctor_id) == item_id;
}
}
}