small refactor to region error handling
This commit is contained in:
parent
a1b38aa437
commit
e6349b414e
10 changed files with 95 additions and 131 deletions
|
@ -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={:?}",
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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, ..),
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue