Skip to content

Commit 0659be9

Browse files
committed
extract find_anon_type into its own module
1 parent 6409515 commit 0659be9

File tree

3 files changed

+296
-263
lines changed

3 files changed

+296
-263
lines changed

src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs

Lines changed: 0 additions & 263 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,9 @@
1010

1111
//! Error Reporting for Anonymous Region Lifetime Errors
1212
//! where both the regions are anonymous.
13-
use hir;
1413
use infer::InferCtxt;
15-
use ty::{self, Region};
1614
use infer::lexical_region_resolve::RegionResolutionError::*;
1715
use infer::lexical_region_resolve::RegionResolutionError;
18-
use hir::map as hir_map;
19-
use middle::resolve_lifetime as rl;
20-
use hir::intravisit::{self, Visitor, NestedVisitorMap};
2116
use infer::error_reporting::nice_region_error::util::AnonymousArgInfo;
2217

2318
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
@@ -153,263 +148,5 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
153148
.emit();
154149
return true;
155150
}
156-
157-
/// This function calls the `visit_ty` method for the parameters
158-
/// corresponding to the anonymous regions. The `nested_visitor.found_type`
159-
/// contains the anonymous type.
160-
///
161-
/// # Arguments
162-
/// region - the anonymous region corresponding to the anon_anon conflict
163-
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
164-
///
165-
/// # Example
166-
/// ```
167-
/// fn foo(x: &mut Vec<&u8>, y: &u8)
168-
/// { x.push(y); }
169-
/// ```
170-
/// The function returns the nested type corresponding to the anonymous region
171-
/// for e.g. `&u8` and Vec<`&u8`.
172-
pub fn find_anon_type(&self,
173-
region: Region<'tcx>,
174-
br: &ty::BoundRegion)
175-
-> Option<(&hir::Ty, &hir::FnDecl)> {
176-
if let Some(anon_reg) = self.is_suitable_region(region) {
177-
let def_id = anon_reg.def_id;
178-
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
179-
let fndecl = match self.tcx.hir.get(node_id) {
180-
hir_map::NodeItem(&hir::Item { node: hir::ItemFn(ref fndecl, ..), .. }) => {
181-
&fndecl
182-
}
183-
hir_map::NodeTraitItem(&hir::TraitItem {
184-
node: hir::TraitItemKind::Method(ref m, ..), ..
185-
}) |
186-
hir_map::NodeImplItem(&hir::ImplItem {
187-
node: hir::ImplItemKind::Method(ref m, ..), ..
188-
}) => &m.decl,
189-
_ => return None,
190-
};
191-
192-
return fndecl
193-
.inputs
194-
.iter()
195-
.filter_map(|arg| self.find_component_for_bound_region(arg, br))
196-
.next()
197-
.map(|ty| (ty, &**fndecl));
198-
}
199-
}
200-
None
201-
}
202-
203-
// This method creates a FindNestedTypeVisitor which returns the type corresponding
204-
// to the anonymous region.
205-
fn find_component_for_bound_region(&self,
206-
arg: &'gcx hir::Ty,
207-
br: &ty::BoundRegion)
208-
-> Option<(&'gcx hir::Ty)> {
209-
let mut nested_visitor = FindNestedTypeVisitor {
210-
infcx: &self,
211-
hir_map: &self.tcx.hir,
212-
bound_region: *br,
213-
found_type: None,
214-
depth: 1,
215-
};
216-
nested_visitor.visit_ty(arg);
217-
nested_visitor.found_type
218-
}
219-
}
220-
221-
// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
222-
// anonymous region. The example above would lead to a conflict between
223-
// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
224-
// would be invoked twice, once for each lifetime, and would
225-
// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
226-
// where that lifetime appears. This allows us to highlight the
227-
// specific part of the type in the error message.
228-
struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
229-
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
230-
hir_map: &'a hir::map::Map<'gcx>,
231-
// The bound_region corresponding to the Refree(freeregion)
232-
// associated with the anonymous region we are looking for.
233-
bound_region: ty::BoundRegion,
234-
// The type where the anonymous lifetime appears
235-
// for e.g. Vec<`&u8`> and <`&u8`>
236-
found_type: Option<&'gcx hir::Ty>,
237-
depth: u32,
238-
}
239-
240-
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
241-
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
242-
NestedVisitorMap::OnlyBodies(&self.hir_map)
243-
}
244-
245-
fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
246-
match arg.node {
247-
hir::TyBareFn(_) => {
248-
self.depth += 1;
249-
intravisit::walk_ty(self, arg);
250-
self.depth -= 1;
251-
return;
252-
}
253-
254-
hir::TyTraitObject(ref bounds, _) => {
255-
for bound in bounds {
256-
self.depth += 1;
257-
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
258-
self.depth -= 1;
259-
}
260-
}
261-
262-
hir::TyRptr(ref lifetime, _) => {
263-
// the lifetime of the TyRptr
264-
let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
265-
match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
266-
// Find the index of the anonymous region that was part of the
267-
// error. We will then search the function parameters for a bound
268-
// region at the right depth with the same index
269-
(Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
270-
ty::BrAnon(br_index)) => {
271-
debug!("LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
272-
debruijn_index.depth,
273-
anon_index,
274-
br_index);
275-
if debruijn_index.depth == self.depth && anon_index == br_index {
276-
self.found_type = Some(arg);
277-
return; // we can stop visiting now
278-
}
279-
}
280-
281-
// Find the index of the named region that was part of the
282-
// error. We will then search the function parameters for a bound
283-
// region at the right depth with the same index
284-
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
285-
debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
286-
def_id={:?}", id, def_id);
287-
if id == def_id {
288-
self.found_type = Some(arg);
289-
return; // we can stop visiting now
290-
}
291-
}
292-
293-
// Find the index of the named region that was part of the
294-
// error. We will then search the function parameters for a bound
295-
// region at the right depth with the same index
296-
(
297-
Some(rl::Region::LateBound(debruijn_index, id, _)),
298-
ty::BrNamed(def_id, _)
299-
) => {
300-
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
301-
debruijn_index.depth);
302-
debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
303-
debug!("def_id={:?}", def_id);
304-
if debruijn_index.depth == self.depth && id == def_id {
305-
self.found_type = Some(arg);
306-
return; // we can stop visiting now
307-
}
308-
}
309-
310-
(Some(rl::Region::Static), _) |
311-
(Some(rl::Region::Free(_, _)), _) |
312-
(Some(rl::Region::EarlyBound(_, _, _)), _) |
313-
(Some(rl::Region::LateBound(_, _, _)), _) |
314-
(Some(rl::Region::LateBoundAnon(_, _)), _) |
315-
(None, _) => {
316-
debug!("no arg found");
317-
}
318-
}
319-
}
320-
// Checks if it is of type `hir::TyPath` which corresponds to a struct.
321-
hir::TyPath(_) => {
322-
let subvisitor = &mut TyPathVisitor {
323-
infcx: self.infcx,
324-
found_it: false,
325-
bound_region: self.bound_region,
326-
hir_map: self.hir_map,
327-
depth: self.depth,
328-
};
329-
intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
330-
// this will visit only outermost type
331-
if subvisitor.found_it {
332-
self.found_type = Some(arg);
333-
}
334-
}
335-
_ => {}
336-
}
337-
// walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
338-
// go on to visit `&Foo`
339-
intravisit::walk_ty(self, arg);
340-
}
341151
}
342152

343-
// The visitor captures the corresponding `hir::Ty` of the anonymous region
344-
// in the case of structs ie. `hir::TyPath`.
345-
// This visitor would be invoked for each lifetime corresponding to a struct,
346-
// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
347-
// where that lifetime appears. This allows us to highlight the
348-
// specific part of the type in the error message.
349-
struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
350-
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
351-
hir_map: &'a hir::map::Map<'gcx>,
352-
found_it: bool,
353-
bound_region: ty::BoundRegion,
354-
depth: u32,
355-
}
356-
357-
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
358-
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
359-
NestedVisitorMap::OnlyBodies(&self.hir_map)
360-
}
361-
362-
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
363-
364-
let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
365-
match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
366-
// the lifetime of the TyPath!
367-
(Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
368-
if debruijn_index.depth == self.depth && anon_index == br_index {
369-
self.found_it = true;
370-
return;
371-
}
372-
}
373-
374-
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
375-
debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
376-
def_id={:?}", id, def_id);
377-
if id == def_id {
378-
self.found_it = true;
379-
return; // we can stop visiting now
380-
}
381-
}
382-
383-
(Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
384-
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
385-
debruijn_index.depth);
386-
debug!("id={:?}", id);
387-
debug!("def_id={:?}", def_id);
388-
if debruijn_index.depth == self.depth && id == def_id {
389-
self.found_it = true;
390-
return; // we can stop visiting now
391-
}
392-
}
393-
394-
(Some(rl::Region::Static), _) |
395-
(Some(rl::Region::EarlyBound(_, _, _)), _) |
396-
(Some(rl::Region::LateBound(_, _, _)), _) |
397-
(Some(rl::Region::LateBoundAnon(_, _)), _) |
398-
(Some(rl::Region::Free(_, _)), _) |
399-
(None, _) => {
400-
debug!("no arg found");
401-
}
402-
}
403-
}
404-
405-
fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
406-
// ignore nested types
407-
//
408-
// If you have a type like `Foo<'a, &Ty>` we
409-
// are only interested in the immediate lifetimes ('a).
410-
//
411-
// Making `visit_ty` empty will ignore the `&Ty` embedded
412-
// inside, it will get reached by the outer visitor.
413-
debug!("`Ty` corresponding to a struct is {:?}", arg);
414-
}
415-
}

0 commit comments

Comments
 (0)