//! Error Reporting for Anonymous Region Lifetime Errors
//! where both the regions are anonymous.
-use hir;
use infer::InferCtxt;
-use ty::{self, Region};
use infer::lexical_region_resolve::RegionResolutionError::*;
use infer::lexical_region_resolve::RegionResolutionError;
-use hir::map as hir_map;
-use middle::resolve_lifetime as rl;
-use hir::intravisit::{self, Visitor, NestedVisitorMap};
use infer::error_reporting::nice_region_error::util::AnonymousArgInfo;
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.emit();
return true;
}
-
- /// This function calls the `visit_ty` method for the parameters
- /// corresponding to the anonymous regions. The `nested_visitor.found_type`
- /// contains the anonymous type.
- ///
- /// # Arguments
- /// region - the anonymous region corresponding to the anon_anon conflict
- /// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
- ///
- /// # Example
- /// ```
- /// fn foo(x: &mut Vec<&u8>, y: &u8)
- /// { x.push(y); }
- /// ```
- /// The function returns the nested type corresponding to the anonymous region
- /// for e.g. `&u8` and Vec<`&u8`.
- pub fn find_anon_type(&self,
- region: Region<'tcx>,
- br: &ty::BoundRegion)
- -> Option<(&hir::Ty, &hir::FnDecl)> {
- if let Some(anon_reg) = self.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) {
- hir_map::NodeItem(&hir::Item { node: hir::ItemFn(ref fndecl, ..), .. }) => {
- &fndecl
- }
- hir_map::NodeTraitItem(&hir::TraitItem {
- node: hir::TraitItemKind::Method(ref m, ..), ..
- }) |
- hir_map::NodeImplItem(&hir::ImplItem {
- node: hir::ImplItemKind::Method(ref m, ..), ..
- }) => &m.decl,
- _ => return None,
- };
-
- return fndecl
- .inputs
- .iter()
- .filter_map(|arg| self.find_component_for_bound_region(arg, br))
- .next()
- .map(|ty| (ty, &**fndecl));
- }
- }
- None
- }
-
- // This method creates a FindNestedTypeVisitor which returns the type corresponding
- // to the anonymous region.
- fn find_component_for_bound_region(&self,
- arg: &'gcx hir::Ty,
- br: &ty::BoundRegion)
- -> Option<(&'gcx hir::Ty)> {
- let mut nested_visitor = FindNestedTypeVisitor {
- infcx: &self,
- hir_map: &self.tcx.hir,
- bound_region: *br,
- found_type: None,
- depth: 1,
- };
- nested_visitor.visit_ty(arg);
- nested_visitor.found_type
- }
-}
-
-// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
-// anonymous region. The example above would lead to a conflict between
-// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
-// would be invoked twice, once for each lifetime, and would
-// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
-// where that lifetime appears. This allows us to highlight the
-// specific part of the type in the error message.
-struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
- infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- hir_map: &'a hir::map::Map<'gcx>,
- // The bound_region corresponding to the Refree(freeregion)
- // associated with the anonymous region we are looking for.
- bound_region: ty::BoundRegion,
- // The type where the anonymous lifetime appears
- // for e.g. Vec<`&u8`> and <`&u8`>
- found_type: Option<&'gcx hir::Ty>,
- depth: u32,
-}
-
-impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
- NestedVisitorMap::OnlyBodies(&self.hir_map)
- }
-
- fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
- match arg.node {
- hir::TyBareFn(_) => {
- self.depth += 1;
- intravisit::walk_ty(self, arg);
- self.depth -= 1;
- return;
- }
-
- hir::TyTraitObject(ref bounds, _) => {
- for bound in bounds {
- self.depth += 1;
- self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
- self.depth -= 1;
- }
- }
-
- hir::TyRptr(ref lifetime, _) => {
- // the lifetime of the TyRptr
- let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
- match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
- // Find the index of the anonymous 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(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
- ty::BrAnon(br_index)) => {
- debug!("LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
- debruijn_index.depth,
- anon_index,
- br_index);
- if debruijn_index.depth == self.depth && anon_index == br_index {
- self.found_type = Some(arg);
- return; // we can stop visiting now
- }
- }
-
- // 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(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
- debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
- def_id={:?}", id, def_id);
- if id == def_id {
- self.found_type = Some(arg);
- return; // we can stop visiting now
- }
- }
-
- // 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(rl::Region::LateBound(debruijn_index, id, _)),
- ty::BrNamed(def_id, _)
- ) => {
- debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
- debruijn_index.depth);
- debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
- debug!("def_id={:?}", def_id);
- if debruijn_index.depth == self.depth && id == def_id {
- self.found_type = Some(arg);
- return; // we can stop visiting now
- }
- }
-
- (Some(rl::Region::Static), _) |
- (Some(rl::Region::Free(_, _)), _) |
- (Some(rl::Region::EarlyBound(_, _, _)), _) |
- (Some(rl::Region::LateBound(_, _, _)), _) |
- (Some(rl::Region::LateBoundAnon(_, _)), _) |
- (None, _) => {
- debug!("no arg found");
- }
- }
- }
- // Checks if it is of type `hir::TyPath` which corresponds to a struct.
- hir::TyPath(_) => {
- let subvisitor = &mut TyPathVisitor {
- infcx: self.infcx,
- found_it: false,
- bound_region: self.bound_region,
- hir_map: self.hir_map,
- depth: self.depth,
- };
- intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
- // this will visit only outermost type
- if subvisitor.found_it {
- self.found_type = Some(arg);
- }
- }
- _ => {}
- }
- // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
- // go on to visit `&Foo`
- intravisit::walk_ty(self, arg);
- }
}
-// The visitor captures the corresponding `hir::Ty` of the anonymous region
-// in the case of structs ie. `hir::TyPath`.
-// This visitor would be invoked for each lifetime corresponding to a struct,
-// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
-// where that lifetime appears. This allows us to highlight the
-// specific part of the type in the error message.
-struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
- infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- hir_map: &'a hir::map::Map<'gcx>,
- found_it: bool,
- bound_region: ty::BoundRegion,
- depth: u32,
-}
-
-impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
- NestedVisitorMap::OnlyBodies(&self.hir_map)
- }
-
- fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
-
- let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
- match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
- // the lifetime of the TyPath!
- (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
- if debruijn_index.depth == self.depth && anon_index == br_index {
- self.found_it = true;
- return;
- }
- }
-
- (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
- debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
- def_id={:?}", id, def_id);
- if id == def_id {
- self.found_it = true;
- return; // we can stop visiting now
- }
- }
-
- (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
- debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
- debruijn_index.depth);
- debug!("id={:?}", id);
- debug!("def_id={:?}", def_id);
- if debruijn_index.depth == self.depth && id == def_id {
- self.found_it = true;
- return; // we can stop visiting now
- }
- }
-
- (Some(rl::Region::Static), _) |
- (Some(rl::Region::EarlyBound(_, _, _)), _) |
- (Some(rl::Region::LateBound(_, _, _)), _) |
- (Some(rl::Region::LateBoundAnon(_, _)), _) |
- (Some(rl::Region::Free(_, _)), _) |
- (None, _) => {
- debug!("no arg found");
- }
- }
- }
-
- fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
- // ignore nested types
- //
- // If you have a type like `Foo<'a, &Ty>` we
- // are only interested in the immediate lifetimes ('a).
- //
- // Making `visit_ty` empty will ignore the `&Ty` embedded
- // inside, it will get reached by the outer visitor.
- debug!("`Ty` corresponding to a struct is {:?}", arg);
- }
-}
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use hir;
+use infer::InferCtxt;
+use ty::{self, Region};
+use hir::map as hir_map;
+use middle::resolve_lifetime as rl;
+use hir::intravisit::{self, Visitor, NestedVisitorMap};
+
+impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
+ /// This function calls the `visit_ty` method for the parameters
+ /// corresponding to the anonymous regions. The `nested_visitor.found_type`
+ /// contains the anonymous type.
+ ///
+ /// # Arguments
+ /// region - the anonymous region corresponding to the anon_anon conflict
+ /// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
+ ///
+ /// # Example
+ /// ```
+ /// fn foo(x: &mut Vec<&u8>, y: &u8)
+ /// { x.push(y); }
+ /// ```
+ /// The function returns the nested type corresponding to the anonymous region
+ /// for e.g. `&u8` and Vec<`&u8`.
+ pub(super) fn find_anon_type(
+ &self,
+ region: Region<'tcx>,
+ br: &ty::BoundRegion,
+ ) -> Option<(&hir::Ty, &hir::FnDecl)> {
+ if let Some(anon_reg) = self.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) {
+ hir_map::NodeItem(&hir::Item {
+ node: hir::ItemFn(ref fndecl, ..),
+ ..
+ }) => &fndecl,
+ hir_map::NodeTraitItem(&hir::TraitItem {
+ node: hir::TraitItemKind::Method(ref m, ..),
+ ..
+ })
+ | hir_map::NodeImplItem(&hir::ImplItem {
+ node: hir::ImplItemKind::Method(ref m, ..),
+ ..
+ }) => &m.decl,
+ _ => return None,
+ };
+
+ return fndecl
+ .inputs
+ .iter()
+ .filter_map(|arg| self.find_component_for_bound_region(arg, br))
+ .next()
+ .map(|ty| (ty, &**fndecl));
+ }
+ }
+ None
+ }
+
+ // This method creates a FindNestedTypeVisitor which returns the type corresponding
+ // to the anonymous region.
+ fn find_component_for_bound_region(
+ &self,
+ arg: &'gcx hir::Ty,
+ br: &ty::BoundRegion,
+ ) -> Option<(&'gcx hir::Ty)> {
+ let mut nested_visitor = FindNestedTypeVisitor {
+ infcx: &self,
+ hir_map: &self.tcx.hir,
+ bound_region: *br,
+ found_type: None,
+ depth: 1,
+ };
+ nested_visitor.visit_ty(arg);
+ nested_visitor.found_type
+ }
+}
+
+// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
+// anonymous region. The example above would lead to a conflict between
+// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
+// would be invoked twice, once for each lifetime, and would
+// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
+// where that lifetime appears. This allows us to highlight the
+// specific part of the type in the error message.
+struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+ infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+ hir_map: &'a hir::map::Map<'gcx>,
+ // The bound_region corresponding to the Refree(freeregion)
+ // associated with the anonymous region we are looking for.
+ bound_region: ty::BoundRegion,
+ // The type where the anonymous lifetime appears
+ // for e.g. Vec<`&u8`> and <`&u8`>
+ found_type: Option<&'gcx hir::Ty>,
+ depth: u32,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
+ NestedVisitorMap::OnlyBodies(&self.hir_map)
+ }
+
+ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
+ match arg.node {
+ hir::TyBareFn(_) => {
+ self.depth += 1;
+ intravisit::walk_ty(self, arg);
+ self.depth -= 1;
+ return;
+ }
+
+ hir::TyTraitObject(ref bounds, _) => for bound in bounds {
+ self.depth += 1;
+ self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
+ self.depth -= 1;
+ },
+
+ hir::TyRptr(ref lifetime, _) => {
+ // the lifetime of the TyRptr
+ let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
+ match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
+ // Find the index of the anonymous 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(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
+ ty::BrAnon(br_index),
+ ) => {
+ debug!(
+ "LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
+ debruijn_index.depth,
+ anon_index,
+ br_index
+ );
+ if debruijn_index.depth == self.depth && anon_index == br_index {
+ self.found_type = Some(arg);
+ return; // we can stop visiting now
+ }
+ }
+
+ // 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(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
+ debug!(
+ "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
+ def_id={:?}",
+ id,
+ def_id
+ );
+ if id == def_id {
+ self.found_type = Some(arg);
+ return; // we can stop visiting now
+ }
+ }
+
+ // 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(rl::Region::LateBound(debruijn_index, id, _)),
+ ty::BrNamed(def_id, _),
+ ) => {
+ debug!(
+ "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
+ debruijn_index.depth
+ );
+ debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
+ debug!("def_id={:?}", def_id);
+ if debruijn_index.depth == self.depth && id == def_id {
+ self.found_type = Some(arg);
+ return; // we can stop visiting now
+ }
+ }
+
+ (Some(rl::Region::Static), _)
+ | (Some(rl::Region::Free(_, _)), _)
+ | (Some(rl::Region::EarlyBound(_, _, _)), _)
+ | (Some(rl::Region::LateBound(_, _, _)), _)
+ | (Some(rl::Region::LateBoundAnon(_, _)), _)
+ | (None, _) => {
+ debug!("no arg found");
+ }
+ }
+ }
+ // Checks if it is of type `hir::TyPath` which corresponds to a struct.
+ hir::TyPath(_) => {
+ let subvisitor = &mut TyPathVisitor {
+ infcx: self.infcx,
+ found_it: false,
+ bound_region: self.bound_region,
+ hir_map: self.hir_map,
+ depth: self.depth,
+ };
+ intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
+ // this will visit only outermost type
+ if subvisitor.found_it {
+ self.found_type = Some(arg);
+ }
+ }
+ _ => {}
+ }
+ // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
+ // go on to visit `&Foo`
+ intravisit::walk_ty(self, arg);
+ }
+}
+
+// The visitor captures the corresponding `hir::Ty` of the anonymous region
+// in the case of structs ie. `hir::TyPath`.
+// This visitor would be invoked for each lifetime corresponding to a struct,
+// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
+// where that lifetime appears. This allows us to highlight the
+// specific part of the type in the error message.
+struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+ infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+ hir_map: &'a hir::map::Map<'gcx>,
+ found_it: bool,
+ bound_region: ty::BoundRegion,
+ depth: u32,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
+ NestedVisitorMap::OnlyBodies(&self.hir_map)
+ }
+
+ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
+ let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
+ match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
+ // the lifetime of the TyPath!
+ (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
+ if debruijn_index.depth == self.depth && anon_index == br_index {
+ self.found_it = true;
+ return;
+ }
+ }
+
+ (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
+ debug!(
+ "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
+ def_id={:?}",
+ id,
+ def_id
+ );
+ if id == def_id {
+ self.found_it = true;
+ return; // we can stop visiting now
+ }
+ }
+
+ (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
+ debug!(
+ "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
+ debruijn_index.depth
+ );
+ debug!("id={:?}", id);
+ debug!("def_id={:?}", def_id);
+ if debruijn_index.depth == self.depth && id == def_id {
+ self.found_it = true;
+ return; // we can stop visiting now
+ }
+ }
+
+ (Some(rl::Region::Static), _)
+ | (Some(rl::Region::EarlyBound(_, _, _)), _)
+ | (Some(rl::Region::LateBound(_, _, _)), _)
+ | (Some(rl::Region::LateBoundAnon(_, _)), _)
+ | (Some(rl::Region::Free(_, _)), _)
+ | (None, _) => {
+ debug!("no arg found");
+ }
+ }
+ }
+
+ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
+ // ignore nested types
+ //
+ // If you have a type like `Foo<'a, &Ty>` we
+ // are only interested in the immediate lifetimes ('a).
+ //
+ // Making `visit_ty` empty will ignore the `&Ty` embedded
+ // inside, it will get reached by the outer visitor.
+ debug!("`Ty` corresponding to a struct is {:?}", arg);
+ }
+}