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:
parent
a933de8398
commit
5b5964f569
50 changed files with 162 additions and 176 deletions
|
@ -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,
|
||||
|
|
|
@ -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()`
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue