1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Helper functions corresponding to lifetime errors due to
12 //! anonymous regions.
15 use ty::{self, Region};
16 use hir::def_id::DefId;
17 use hir::map as hir_map;
19 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
20 // This method walks the Type of the function body arguments using
21 // `fold_regions()` function and returns the
22 // &hir::Arg of the function argument corresponding to the anonymous
23 // region and the Ty corresponding to the named region.
24 // Currently only the case where the function declaration consists of
25 // one named region and one anonymous region is handled.
26 // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
27 // Here, we would return the hir::Arg for y, we return the type &'a
28 // i32, which is the type of y but with the anonymous region replaced
29 // with 'a, the corresponding bound region and is_first which is true if
30 // the hir::Arg is the first argument in the function declaration.
31 pub fn find_arg_with_anonymous_region
33 anon_region: Region<'tcx>,
34 replace_region: Region<'tcx>)
35 -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> {
37 if let ty::ReFree(ref free_region) = *anon_region {
39 let id = free_region.scope;
40 let hir = &self.tcx.hir;
41 if let Some(node_id) = hir.as_local_node_id(id) {
42 if let Some(body_id) = hir.maybe_body_owned_by(node_id) {
43 let body = hir.body(body_id);
44 if let Some(tables) = self.in_progress_tables {
48 .filter_map(|(index, arg)| {
49 let ty = tables.borrow().node_id_to_type(arg.hir_id);
50 let mut found_anon_region = false;
51 let new_arg_ty = self.tcx
52 .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region {
53 found_anon_region = true;
58 if found_anon_region {
59 let is_first = index == 0;
60 Some((arg, new_arg_ty, free_region.bound_region, is_first))
80 // This method returns whether the given Region is Anonymous
81 // and returns the DefId and the BoundRegion corresponding to the given region.
82 pub fn is_suitable_anonymous_region(&self,
84 -> Option<(DefId, ty::BoundRegion)> {
85 if let ty::ReFree(ref free_region) = *region {
86 if let ty::BrAnon(..) = free_region.bound_region{
87 let anonymous_region_binding_scope = free_region.scope;
88 let node_id = self.tcx
90 .as_local_node_id(anonymous_region_binding_scope)
92 match self.tcx.hir.find(node_id) {
93 Some(hir_map::NodeItem(..)) |
94 Some(hir_map::NodeTraitItem(..)) => {
95 // Success -- proceed to return Some below
97 Some(hir_map::NodeImplItem(..)) => {
98 let container_id = self.tcx
99 .associated_item(anonymous_region_binding_scope)
102 if self.tcx.impl_trait_ref(container_id).is_some() {
103 // For now, we do not try to target impls of traits. This is
104 // because this message is going to suggest that the user
105 // change the fn signature, but they may not be free to do so,
106 // since the signature must match the trait.
108 // FIXME(#42706) -- in some cases, we could do better here.
112 _ => return None, // inapplicable
113 // we target only top-level functions
115 return Some((anonymous_region_binding_scope, free_region.bound_region));