1
Fork 0

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

@ -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,