Moved helper functions from NiceRegionError to TyCtxt.

This commit is contained in:
David Wood 2018-09-02 00:42:51 +02:00
parent 994cdd9185
commit 78b21643a8
No known key found for this signature in database
GPG key ID: 01760B4F9F53F154
7 changed files with 88 additions and 90 deletions

View file

@ -56,9 +56,9 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
let (span, sub, sup) = self.get_regions();
// Determine whether the sub and sup consist of both anonymous (elided) regions.
let anon_reg_sup = self.is_suitable_region(sup)?;
let anon_reg_sup = self.tcx.is_suitable_region(sup)?;
let anon_reg_sub = self.is_suitable_region(sub)?;
let anon_reg_sub = self.tcx.is_suitable_region(sub)?;
let scope_def_id_sup = anon_reg_sup.def_id;
let bregion_sup = anon_reg_sup.boundregion;
let scope_def_id_sub = anon_reg_sub.def_id;

View file

@ -36,7 +36,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
region: Region<'tcx>,
br: &ty::BoundRegion,
) -> Option<(&hir::Ty, &hir::FnDecl)> {
if let Some(anon_reg) = self.is_suitable_region(region) {
if let Some(anon_reg) = self.tcx.is_suitable_region(region) {
let def_id = anon_reg.def_id;
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
let fndecl = match self.tcx.hir.get(node_id) {

View file

@ -33,23 +33,23 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
// version new_ty of its type where the anonymous region is replaced
// with the named one.//scope_def_id
let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub)
&& self.is_suitable_region(sup).is_some()
&& self.tcx.is_suitable_region(sup).is_some()
&& self.find_arg_with_region(sup, sub).is_some()
{
(
sub,
sup,
self.find_arg_with_region(sup, sub).unwrap(),
self.is_suitable_region(sup).unwrap(),
self.tcx.is_suitable_region(sup).unwrap(),
)
} else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some()
} else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some()
&& self.find_arg_with_region(sub, sup).is_some()
{
(
sup,
sub,
self.find_arg_with_region(sub, sup).unwrap(),
self.is_suitable_region(sub).unwrap(),
self.tcx.is_suitable_region(sub).unwrap(),
)
} else {
return None; // inapplicable

View file

@ -27,9 +27,9 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
sup_origin,
sup_r,
) => {
let anon_reg_sup = self.is_suitable_region(sup_r)?;
let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?;
if sub_r == &RegionKind::ReStatic &&
self.is_return_type_impl_trait(anon_reg_sup.def_id)
self.tcx.is_return_type_impl_trait(anon_reg_sup.def_id)
{
let sp = var_origin.span();
let return_sp = sub_origin.span();

View file

@ -15,7 +15,6 @@ use hir;
use infer::error_reporting::nice_region_error::NiceRegionError;
use ty::{self, Region, Ty};
use hir::def_id::DefId;
use hir::Node;
use syntax_pos::Span;
// The struct contains the information about the anonymous region
@ -35,18 +34,6 @@ pub(super) struct AnonymousArgInfo<'tcx> {
pub is_first: bool,
}
// This struct contains information regarding the
// Refree((FreeRegion) corresponding to lifetime conflict
#[derive(Debug)]
pub(super) struct FreeRegionInfo {
// def id corresponding to FreeRegion
pub def_id: DefId,
// the bound region corresponding to FreeRegion
pub boundregion: ty::BoundRegion,
// checks if bound region is in Impl Item
pub is_impl_item: bool,
}
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
// This method walks the Type of the function body arguments using
// `fold_regions()` function and returns the
@ -122,36 +109,6 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
}
}
// This method returns the DefId and the BoundRegion corresponding to the given region.
pub(super) fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
let (suitable_region_binding_scope, bound_region) = match *region {
ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
ty::ReEarlyBound(ref ebr) => (
self.tcx.parent_def_id(ebr.def_id).unwrap(),
ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
),
_ => return None, // not a free region
};
let node_id = self.tcx
.hir
.as_local_node_id(suitable_region_binding_scope)
.unwrap();
let is_impl_item = match self.tcx.hir.find(node_id) {
Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false,
Some(Node::ImplItem(..)) => {
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
}
_ => return None,
};
return Some(FreeRegionInfo {
def_id: suitable_region_binding_scope,
boundregion: bound_region,
is_impl_item: is_impl_item,
});
}
// Here, we check for the case where the anonymous region
// is in the return type.
// FIXME(#42703) - Need to handle certain cases here.
@ -176,22 +133,6 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
None
}
pub(super) fn is_return_type_impl_trait(
&self,
scope_def_id: DefId,
) -> bool {
let ret_ty = self.tcx.type_of(scope_def_id);
match ret_ty.sty {
ty::FnDef(_, _) => {
let sig = ret_ty.fn_sig(self.tcx);
let output = self.tcx.erase_late_bound_regions(&sig.output());
return output.is_impl_trait();
}
_ => {}
}
false
}
// Here we check for the case where anonymous region
// corresponds to self and if yes, we display E0312.
// FIXME(#42700) - Need to format self properly to
@ -203,24 +144,4 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
.map(|i| i.method_has_self_argument) == Some(true)
}
// Here we check if the bound region is in Impl Item.
pub(super) fn is_bound_region_in_impl_item(
&self,
suitable_region_binding_scope: DefId,
) -> bool {
let container_id = self.tcx
.associated_item(suitable_region_binding_scope)
.container
.id();
if self.tcx.impl_trait_ref(container_id).is_some() {
// For now, we do not try to target impls of traits. This is
// because this message is going to suggest that the user
// change the fn signature, but they may not be free to do so,
// since the signature must match the trait.
//
// FIXME(#42706) -- in some cases, we could do better here.
return true;
}
false
}
}

View file

@ -17,7 +17,7 @@ use session::Session;
use session::config::{BorrowckMode, OutputFilenames};
use session::config::CrateType;
use middle;
use hir::{TraitCandidate, HirId, ItemLocalId};
use hir::{TraitCandidate, HirId, ItemLocalId, Node};
use hir::def::{Def, Export};
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use hir::map as hir_map;
@ -870,6 +870,18 @@ impl<'tcx> CommonTypes<'tcx> {
}
}
// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
// conflict.
#[derive(Debug)]
pub struct FreeRegionInfo {
// def id corresponding to FreeRegion
pub def_id: DefId,
// the bound region corresponding to FreeRegion
pub boundregion: ty::BoundRegion,
// checks if bound region is in Impl Item
pub is_impl_item: bool,
}
/// The central data structure of the compiler. It stores references
/// to the various **arenas** and also houses the results of the
/// various **compiler queries** that have been performed. See the
@ -1545,6 +1557,71 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
})
}
// This method returns the DefId and the BoundRegion corresponding to the given region.
pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
let (suitable_region_binding_scope, bound_region) = match *region {
ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
ty::ReEarlyBound(ref ebr) => (
self.parent_def_id(ebr.def_id).unwrap(),
ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
),
_ => return None, // not a free region
};
let node_id = self.hir
.as_local_node_id(suitable_region_binding_scope)
.unwrap();
let is_impl_item = match self.hir.find(node_id) {
Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false,
Some(Node::ImplItem(..)) => {
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
}
_ => return None,
};
return Some(FreeRegionInfo {
def_id: suitable_region_binding_scope,
boundregion: bound_region,
is_impl_item: is_impl_item,
});
}
pub fn is_return_type_impl_trait(
&self,
scope_def_id: DefId,
) -> bool {
let ret_ty = self.type_of(scope_def_id);
match ret_ty.sty {
ty::FnDef(_, _) => {
let sig = ret_ty.fn_sig(*self);
let output = self.erase_late_bound_regions(&sig.output());
return output.is_impl_trait();
}
_ => {}
}
false
}
// Here we check if the bound region is in Impl Item.
pub fn is_bound_region_in_impl_item(
&self,
suitable_region_binding_scope: DefId,
) -> bool {
let container_id = self.associated_item(suitable_region_binding_scope)
.container
.id();
if self.impl_trait_ref(container_id).is_some() {
// For now, we do not try to target impls of traits. This is
// because this message is going to suggest that the user
// change the fn signature, but they may not be free to do so,
// since the signature must match the trait.
//
// FIXME(#42706) -- in some cases, we could do better here.
return true;
}
false
}
}
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {

View file

@ -80,7 +80,7 @@ pub use self::sty::TyKind::*;
pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
pub use self::context::{TyCtxt, GlobalArenas, AllArenas, tls, keep_local};
pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
pub use self::context::{Lift, TypeckTables};
pub use self::instance::{Instance, InstanceDef};