diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 05fa619ce41e4..930c9e284f6f2 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -1066,7 +1066,9 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, } } -fn resolve_item<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, item: &'tcx hir::Item) { +fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, id: ast::NodeId, walk: F) + where F: FnOnce(&mut RegionResolutionVisitor<'tcx, 'a>) +{ // Items create a new outer block scope as far as we're concerned. let prev_cx = visitor.cx; let prev_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet()); @@ -1075,8 +1077,8 @@ fn resolve_item<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, item: var_parent: ROOT_CODE_EXTENT, parent: ROOT_CODE_EXTENT }; - intravisit::walk_item(visitor, item); - visitor.create_item_scope_if_needed(item.id); + walk(visitor); + visitor.create_item_scope_if_needed(id); visitor.cx = prev_cx; visitor.terminating_scopes = prev_ts; } @@ -1179,17 +1181,15 @@ impl<'ast, 'a> Visitor<'ast> for RegionResolutionVisitor<'ast, 'a> { } fn visit_item(&mut self, i: &'ast Item) { - resolve_item(self, i); + resolve_item_like(self, i.id, |this| intravisit::walk_item(this, i)); } fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) { - intravisit::walk_impl_item(self, ii); - self.create_item_scope_if_needed(ii.id); + resolve_item_like(self, ii.id, |this| intravisit::walk_impl_item(this, ii)); } fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) { - intravisit::walk_trait_item(self, ti); - self.create_item_scope_if_needed(ti.id); + resolve_item_like(self, ti.id, |this| intravisit::walk_trait_item(this, ti)); } fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, diff --git a/src/test/run-pass/issue-37290/auxiliary/lint.rs b/src/test/run-pass/issue-37290/auxiliary/lint.rs new file mode 100644 index 0000000000000..33d072eb6a890 --- /dev/null +++ b/src/test/run-pass/issue-37290/auxiliary/lint.rs @@ -0,0 +1,68 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This flag is needed for plugins to work: +// compile-flags: -C prefer-dynamic + +#![feature(plugin_registrar, rustc_private)] +#![crate_type = "dylib"] +#![deny(region_hierarchy)] + +extern crate syntax; +#[macro_use] +extern crate rustc; +extern crate rustc_plugin; + +use rustc::lint::{LateContext, LintPass, LateLintPass, LintArray, LintContext}; +use rustc::hir; +use rustc::hir::intravisit::FnKind; +use rustc::middle::region::CodeExtent; +use rustc::util::nodemap::FxHashMap; + +use syntax::ast::{self, NodeId}; +use syntax::codemap::Span; + +declare_lint!(REGION_HIERARCHY, Warn, "warn about bogus region hierarchy"); + +struct Pass { + map: FxHashMap +} + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { lint_array!(REGION_HIERARCHY) } +} + +impl LateLintPass for Pass { + fn check_fn(&mut self, cx: &LateContext, + fk: FnKind, _: &hir::FnDecl, expr: &hir::Expr, + span: Span, node: ast::NodeId) + { + if let FnKind::Closure(..) = fk { return } + + let mut extent = cx.tcx.region_maps.node_extent(expr.id); + while let Some(parent) = cx.tcx.region_maps.opt_encl_scope(extent) { + extent = parent; + } + if let Some(other) = self.map.insert(extent, node) { + cx.span_lint(REGION_HIERARCHY, span, &format!( + "different fns {:?}, {:?} with the same root extent {:?}", + cx.tcx.map.local_def_id(other), + cx.tcx.map.local_def_id(node), + extent)); + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut ::rustc_plugin::Registry) { + reg.register_late_lint_pass(Box::new( + Pass { map: FxHashMap() } + )); +} diff --git a/src/test/run-pass/issue-37290/main.rs b/src/test/run-pass/issue-37290/main.rs new file mode 100644 index 0000000000000..394ad92b1d8c0 --- /dev/null +++ b/src/test/run-pass/issue-37290/main.rs @@ -0,0 +1,30 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:lint.rs + +#![feature(plugin)] +#![plugin(lint)] + +struct Foo { +} + +impl Foo { + fn bar(&self) -> usize { + 22 + } + + fn baz(&self) -> usize { + 22 + } +} + +fn main() { } +