diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 168285b455f0..97b1978cb2eb 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -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; diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs index e3faf755672a..10a2d179dd56 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -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) { diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 4e26a4178b95..0eb634ea2cc8 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -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 diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index d25dcd5b045c..2f7c6adfd218 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -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(); diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 30406f1fec55..afc50fe11516 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -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 { - 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 - } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 83d6b715e95b..c1ae7bba50a2 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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 { + 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> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a48aabc3cd7c..3732e7d8fd2f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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};