small refactor to region error handling

This commit is contained in:
lcnr 2024-12-06 14:23:18 +01:00
parent a1b38aa437
commit e6349b414e
10 changed files with 95 additions and 131 deletions

View file

@ -63,26 +63,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
}
// Determine whether the sub and sup consist of both anonymous (elided) regions.
let anon_reg_sup = self.tcx().is_suitable_region(self.generic_param_scope, sup)?;
let sup_info = self.tcx().is_suitable_region(self.generic_param_scope, sup)?;
let anon_reg_sub = self.tcx().is_suitable_region(self.generic_param_scope, sub)?;
let scope_def_id_sup = anon_reg_sup.def_id;
let bregion_sup = anon_reg_sup.bound_region;
let scope_def_id_sub = anon_reg_sub.def_id;
let bregion_sub = anon_reg_sub.bound_region;
let sub_info = self.tcx().is_suitable_region(self.generic_param_scope, sub)?;
let ty_sup = find_anon_type(self.tcx(), self.generic_param_scope, sup, &bregion_sup)?;
let ty_sup = find_anon_type(self.tcx(), self.generic_param_scope, sup)?;
let ty_sub = find_anon_type(self.tcx(), self.generic_param_scope, sub, &bregion_sub)?;
let ty_sub = find_anon_type(self.tcx(), self.generic_param_scope, sub)?;
debug!(
"try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
ty_sub, sup, bregion_sup
);
debug!(
"try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
ty_sup, sub, bregion_sub
);
debug!("try_report_anon_anon_conflict: found_param1={:?} sup={:?}", ty_sub, sup);
debug!("try_report_anon_anon_conflict: found_param2={:?} sub={:?}", ty_sup, sub);
let (ty_sup, ty_fndecl_sup) = ty_sup;
let (ty_sub, ty_fndecl_sub) = ty_sub;
@ -93,9 +83,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
self.find_param_with_region(sub, sub)?;
let sup_is_ret_type =
self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
self.is_return_type_anon(sup_info.scope, sup_info.region_def_id, ty_fndecl_sup);
let sub_is_ret_type =
self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
self.is_return_type_anon(sub_info.scope, sub_info.region_def_id, ty_fndecl_sub);
debug!(
"try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}",

View file

@ -1,7 +1,7 @@
use core::ops::ControlFlow;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
@ -28,16 +28,15 @@ pub fn find_anon_type<'tcx>(
tcx: TyCtxt<'tcx>,
generic_param_scope: LocalDefId,
region: Region<'tcx>,
br: &ty::BoundRegionKind,
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> {
let anon_reg = tcx.is_suitable_region(generic_param_scope, region)?;
let fn_sig = tcx.hir_node_by_def_id(anon_reg.def_id).fn_sig()?;
let fn_sig = tcx.hir_node_by_def_id(anon_reg.scope).fn_sig()?;
fn_sig
.decl
.inputs
.iter()
.find_map(|arg| find_component_for_bound_region(tcx, arg, br))
.find_map(|arg| find_component_for_bound_region(tcx, arg, anon_reg.region_def_id))
.map(|ty| (ty, fn_sig))
}
@ -46,9 +45,9 @@ pub fn find_anon_type<'tcx>(
fn find_component_for_bound_region<'tcx>(
tcx: TyCtxt<'tcx>,
arg: &'tcx hir::Ty<'tcx>,
br: &ty::BoundRegionKind,
region_def_id: DefId,
) -> Option<&'tcx hir::Ty<'tcx>> {
FindNestedTypeVisitor { tcx, bound_region: *br, current_index: ty::INNERMOST }
FindNestedTypeVisitor { tcx, region_def_id, current_index: ty::INNERMOST }
.visit_ty(arg)
.break_value()
}
@ -62,9 +61,8 @@ fn find_component_for_bound_region<'tcx>(
// specific part of the type in the error message.
struct FindNestedTypeVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
// The bound_region corresponding to the Refree(freeregion)
// associated with the anonymous region we are looking for.
bound_region: ty::BoundRegionKind,
// The `DefId` of the region we're looking for.
region_def_id: DefId,
current_index: ty::DebruijnIndex,
}
@ -96,16 +94,13 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
hir::TyKind::Ref(lifetime, _) => {
// the lifetime of the Ref
let hir_id = lifetime.hir_id;
match (self.tcx.named_bound_var(hir_id), self.bound_region) {
match self.tcx.named_bound_var(hir_id) {
// Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(
Some(rbv::ResolvedArg::EarlyBound(id)),
ty::BoundRegionKind::Named(def_id, _),
) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id.to_def_id() == def_id {
Some(rbv::ResolvedArg::EarlyBound(id)) => {
debug!("EarlyBound id={:?}", id);
if id.to_def_id() == self.region_def_id {
return ControlFlow::Break(arg);
}
}
@ -113,31 +108,25 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(
Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
ty::BoundRegionKind::Named(def_id, _),
) => {
Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)) => {
debug!(
"FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
debruijn_index
);
debug!("LateBound id={:?} def_id={:?}", id, def_id);
if debruijn_index == self.current_index && id.to_def_id() == def_id {
debug!("LateBound id={:?}", id);
if debruijn_index == self.current_index
&& id.to_def_id() == self.region_def_id
{
return ControlFlow::Break(arg);
}
}
(
Some(
rbv::ResolvedArg::StaticLifetime
| rbv::ResolvedArg::Free(_, _)
| rbv::ResolvedArg::EarlyBound(_)
| rbv::ResolvedArg::LateBound(_, _, _)
| rbv::ResolvedArg::Error(_),
)
| None,
_,
) => {
Some(
rbv::ResolvedArg::StaticLifetime
| rbv::ResolvedArg::Free(_, _)
| rbv::ResolvedArg::Error(_),
)
| None => {
debug!("no arg found");
}
}
@ -151,7 +140,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
return if intravisit::walk_ty(
&mut TyPathVisitor {
tcx: self.tcx,
bound_region: self.bound_region,
region_def_id: self.region_def_id,
current_index: self.current_index,
},
arg,
@ -179,7 +168,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// specific part of the type in the error message.
struct TyPathVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
bound_region: ty::BoundRegionKind,
region_def_id: DefId,
current_index: ty::DebruijnIndex,
}
@ -192,38 +181,29 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
}
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
match self.tcx.named_bound_var(lifetime.hir_id) {
// the lifetime of the TyPath!
(Some(rbv::ResolvedArg::EarlyBound(id)), ty::BoundRegionKind::Named(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id.to_def_id() == def_id {
Some(rbv::ResolvedArg::EarlyBound(id)) => {
debug!("EarlyBound id={:?}", id);
if id.to_def_id() == self.region_def_id {
return ControlFlow::Break(());
}
}
(
Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
ty::BoundRegionKind::Named(def_id, _),
) => {
Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)) => {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id);
debug!("def_id={:?}", def_id);
if debruijn_index == self.current_index && id.to_def_id() == def_id {
if debruijn_index == self.current_index && id.to_def_id() == self.region_def_id {
return ControlFlow::Break(());
}
}
(
Some(
rbv::ResolvedArg::StaticLifetime
| rbv::ResolvedArg::EarlyBound(_)
| rbv::ResolvedArg::LateBound(_, _, _)
| rbv::ResolvedArg::Free(_, _)
| rbv::ResolvedArg::Error(_),
)
| None,
_,
) => {
Some(
rbv::ResolvedArg::StaticLifetime
| rbv::ResolvedArg::Free(_, _)
| rbv::ResolvedArg::Error(_),
)
| None => {
debug!("no arg found");
}
}

View file

@ -54,9 +54,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let param = anon_param_info.param;
let new_ty = anon_param_info.param_ty;
let new_ty_span = anon_param_info.param_ty_span;
let br = anon_param_info.bound_region;
let br = anon_param_info.br;
let is_first = anon_param_info.is_first;
let scope_def_id = region_info.def_id;
let scope_def_id = region_info.scope;
let is_impl_item = region_info.is_impl_item;
match br {
@ -73,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
return None;
}
if find_anon_type(self.tcx(), self.generic_param_scope, anon, &br).is_some()
if find_anon_type(self.tcx(), self.generic_param_scope, anon).is_some()
&& self.is_self_anon(is_first, scope_def_id)
{
return None;

View file

@ -50,7 +50,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// This may have a closure and it would cause ICE
// through `find_param_with_region` (#78262).
let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.scope);
if fn_returns.is_empty() {
return None;
}
@ -196,7 +196,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let mut err = self.tcx().dcx().create_err(diag);
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.scope);
let mut override_error_code = None;
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin
@ -250,7 +250,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
Some(arg),
captures,
Some((param.param_ty_span, param.param_ty.to_string())),
Some(anon_reg_sup.def_id),
Some(anon_reg_sup.scope),
);
let reported = err.emit();

View file

@ -2,7 +2,7 @@
//! anonymous regions.
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
@ -17,8 +17,8 @@ pub struct AnonymousParamInfo<'tcx> {
pub param: &'tcx hir::Param<'tcx>,
/// The type corresponding to the anonymous region parameter.
pub param_ty: Ty<'tcx>,
/// The ty::BoundRegionKind corresponding to the anonymous region.
pub bound_region: ty::BoundRegionKind,
/// The `ty::BoundRegionKind` corresponding to the anonymous region.
pub br: ty::BoundRegionKind,
/// The `Span` of the parameter type.
pub param_ty_span: Span,
/// Signals that the argument is the first parameter in the declaration.
@ -43,7 +43,7 @@ pub fn find_param_with_region<'tcx>(
anon_region: Region<'tcx>,
replace_region: Region<'tcx>,
) -> Option<AnonymousParamInfo<'tcx>> {
let (id, bound_region) = match *anon_region {
let (id, br) = match *anon_region {
ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region),
ty::ReEarlyParam(ebr) => {
let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id;
@ -96,13 +96,7 @@ pub fn find_param_with_region<'tcx>(
let ty_hir_id = fn_decl.inputs[index].hir_id;
let param_ty_span = hir.span(ty_hir_id);
let is_first = index == 0;
AnonymousParamInfo {
param,
param_ty: new_param_ty,
param_ty_span,
bound_region,
is_first,
}
AnonymousParamInfo { param, param_ty: new_param_ty, param_ty_span, br, is_first }
})
})
}
@ -122,7 +116,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
pub(super) fn is_return_type_anon(
&self,
scope_def_id: LocalDefId,
br: ty::BoundRegionKind,
region_def_id: DefId,
hir_sig: &hir::FnSig<'_>,
) -> Option<Span> {
let fn_ty = self.tcx().type_of(scope_def_id).instantiate_identity();
@ -135,8 +129,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
None
};
return match future_output {
Some(output) if self.includes_region(output, br) => Some(span),
None if self.includes_region(ret_ty, br) => Some(span),
Some(output) if self.includes_region(output, region_def_id) => Some(span),
None if self.includes_region(ret_ty, region_def_id) => Some(span),
_ => None,
};
}
@ -146,12 +140,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
fn includes_region(
&self,
ty: Binder<'tcx, impl TypeFoldable<TyCtxt<'tcx>>>,
region: ty::BoundRegionKind,
region_def_id: DefId,
) -> bool {
let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(ty);
// We are only checking is any region meets the condition so order doesn't matter
#[allow(rustc::potential_query_instability)]
late_bound_regions.iter().any(|r| *r == region)
late_bound_regions.iter().any(|r| match *r {
ty::BoundRegionKind::Named(def_id, _) => def_id == region_def_id,
_ => false,
})
}
// Here we check for the case where anonymous region

View file

@ -790,7 +790,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let lifetime_scope = match sub.kind() {
ty::ReStatic => hir::def_id::CRATE_DEF_ID,
_ => match self.tcx.is_suitable_region(generic_param_scope, sub) {
Some(info) => info.def_id,
Some(info) => info.scope,
None => generic_param_scope,
},
};
@ -864,13 +864,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
let (lifetime_def_id, lifetime_scope) =
match self.tcx.is_suitable_region(generic_param_scope, lifetime) {
Some(info) if !lifetime.has_name() => {
(info.bound_region.get_id().unwrap().expect_local(), info.def_id)
}
_ => return lifetime.get_name_or_anon().to_string(),
};
let (lifetime_def_id, lifetime_scope) = match self
.tcx
.is_suitable_region(generic_param_scope, lifetime)
{
Some(info) if !lifetime.has_name() => (info.region_def_id.expect_local(), info.scope),
_ => return lifetime.get_name_or_anon().to_string(),
};
let new_lt = {
let generics = self.tcx.generics_of(lifetime_scope);
@ -1097,8 +1097,7 @@ fn msg_span_from_named_region<'tcx>(
}
ty::ReLateParam(ref fr) => {
if !fr.bound_region.is_named()
&& let Some((ty, _)) =
find_anon_type(tcx, generic_param_scope, region, &fr.bound_region)
&& let Some((ty, _)) = find_anon_type(tcx, generic_param_scope, region)
{
("the anonymous lifetime defined here".to_string(), Some(ty.span))
} else {

View file

@ -517,7 +517,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
return false;
};
let node = self.tcx.hir_node_by_def_id(anon_reg.def_id);
let node = self.tcx.hir_node_by_def_id(anon_reg.scope);
let is_impl = matches!(&node, hir::Node::ImplItem(_));
let (generics, parent_generics) = match node {
hir::Node::Item(&hir::Item {
@ -527,7 +527,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
| hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
| hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => (
generics,
match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.def_id))
match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope))
{
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Trait(_, _, ref generics, ..),

View file

@ -41,8 +41,7 @@ impl<'a> DescriptionCtx<'a> {
}
ty::ReLateParam(ref fr) => {
if !fr.bound_region.is_named()
&& let Some((ty, _)) =
find_anon_type(tcx, generic_param_scope, region, &fr.bound_region)
&& let Some((ty, _)) = find_anon_type(tcx, generic_param_scope, region)
{
(Some(ty.span), "defined_here", String::new())
} else {