Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctly walk import lists in AST visitors #28364

Merged
merged 5 commits into from
Sep 22, 2015
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
#![cfg_attr(stage0, feature(alloc_system))]
#![cfg_attr(not(stage0), feature(needs_allocator))]

#![cfg_attr(test, feature(test, rustc_private))]
#![cfg_attr(test, feature(test, rustc_private, box_heap))]

#[cfg(stage0)]
extern crate alloc_system;
Expand Down
4 changes: 4 additions & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#![feature(core_intrinsics)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(fmt_internals)]
#![feature(fmt_radix)]
#![feature(heap_api)]
#![feature(iter_order)]
#![feature(iter_arith)]
Expand All @@ -47,6 +49,8 @@
#![feature(oom)]
#![feature(pattern)]
#![feature(ptr_as_ref)]
#![feature(ref_slice)]
#![feature(slice_bytes)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(step_by)]
Expand Down
1 change: 1 addition & 0 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use slice::SliceConcatExt;
use boxed::Box;

pub use core::str::{FromStr, Utf8Error};
#[allow(deprecated)]
pub use core::str::{Lines, LinesAny, CharRange};
pub use core::str::{Split, RSplit};
pub use core::str::{SplitN, RSplitN};
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,11 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
hir_visit::walk_path(self, p);
}

fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
run_lints!(self, check_path_list_item, late_passes, item);
hir_visit::walk_path_list_item(self, prefix, item);
}

fn visit_attribute(&mut self, attr: &ast::Attribute) {
run_lints!(self, check_attribute, late_passes, attr);
}
Expand Down Expand Up @@ -915,6 +920,11 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
ast_visit::walk_path(self, p);
}

fn visit_path_list_item(&mut self, prefix: &ast::Path, item: &ast::PathListItem) {
run_lints!(self, check_path_list_item, early_passes, item);
ast_visit::walk_path_list_item(self, prefix, item);
}

fn visit_attribute(&mut self, attr: &ast::Attribute) {
run_lints!(self, check_attribute, early_passes, attr);
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ pub trait LateLintPass: LintPass {
// because then your lint will be called twice. Prefer check_ast_mac.
fn check_mac(&mut self, _: &LateContext, _: &ast::Mac) { }
fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { }
fn check_path_list_item(&mut self, _: &LateContext, _: &hir::PathListItem) { }
fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { }

/// Called when entering a syntax node that can have lint attributes such
Expand Down Expand Up @@ -211,6 +212,7 @@ pub trait EarlyLintPass: LintPass {
fn check_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { }
fn check_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { }
fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { }
fn check_path_list_item(&mut self, _: &EarlyContext, _: &ast::PathListItem) { }
fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { }

/// Called when entering a syntax node that can have lint attributes such
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
visit::walk_path(self, path);
}

fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) {
self.lookup_and_handle_definition(&item.node.id());
visit::walk_path_list_item(self, path, item);
}

fn visit_item(&mut self, _: &hir::Item) {
// Do not recurse into items. These items will be added to the
// worklist and recursed into manually if necessary.
Expand Down
16 changes: 16 additions & 0 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,12 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
visit::walk_path(self, path)
}

fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
check_path_list_item(self.tcx, item,
&mut |id, sp, stab| self.check(id, sp, stab));
visit::walk_path_list_item(self, prefix, item)
}

fn visit_pat(&mut self, pat: &hir::Pat) {
check_pat(self.tcx, pat,
&mut |id, sp, stab| self.check(id, sp, stab));
Expand Down Expand Up @@ -470,7 +476,17 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
}
None => {}
}
}

pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
Some(def::DefPrimTy(..)) => {}
Some(def) => {
maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
}
None => {}
}
}

pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_back/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ mod svh_visitor {
SawPath.hash(self.st); visit::walk_path(self, path)
}

fn visit_path_list_item(&mut self, prefix: &Path, item: &'v PathListItem) {
SawPath.hash(self.st); visit::walk_path_list_item(self, prefix, item)
}

fn visit_block(&mut self, b: &Block) {
SawBlock.hash(self.st); visit::walk_block(self, b)
}
Expand Down
32 changes: 20 additions & 12 deletions src/librustc_front/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ pub trait Visitor<'v> : Sized {
fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
walk_path(self, path)
}
fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
walk_path_list_item(self, prefix, item)
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
Expand Down Expand Up @@ -203,26 +206,20 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
ItemExternCrate(..) => {}
ItemUse(ref vp) => {
match vp.node {
ViewPathSimple(ident, ref path) => {
visitor.visit_ident(vp.span, ident);
ViewPathSimple(_ident, ref path) => {
visitor.visit_path(path, item.id);
}
ViewPathGlob(ref path) => {
visitor.visit_path(path, item.id);
}
ViewPathList(ref prefix, ref list) => {
for id in list {
match id.node {
PathListIdent { name, .. } => {
visitor.visit_ident(id.span, name);
}
PathListMod { .. } => ()
if !list.is_empty() {
for item in list {
visitor.visit_path_list_item(prefix, item)
}
} else {
visitor.visit_path(prefix, item.id);
}

// Note that the `prefix` here is not a complete
// path, so we don't use `visit_path`.
walk_path(visitor, prefix);
}
}
}
Expand Down Expand Up @@ -400,6 +397,17 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
}
}

pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, prefix: &'v Path,
item: &'v PathListItem) {
for segment in &prefix.segments {
visitor.visit_path_segment(prefix.span, segment);
}

if let PathListIdent { name, .. } = item.node {
visitor.visit_ident(item.span, name);
}
}

pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,13 @@ impl LateLintPass for Stability {
&stab.map(|s| hir_to_ast_stability(s)).as_ref()));
}

fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
stability::check_path_list_item(cx.tcx, item,
&mut |id, sp, stab|
self.lint(cx, id, sp,
&stab.map(|s| hir_to_ast_stability(s)).as_ref()));
}

fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
stability::check_pat(cx.tcx, pat,
&mut |id, sp, stab|
Expand Down
35 changes: 16 additions & 19 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,23 +859,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {

impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if let hir::ItemUse(ref vpath) = item.node {
if let hir::ViewPathList(ref prefix, ref list) = vpath.node {
for pid in list {
match pid.node {
hir::PathListIdent { id, name, .. } => {
debug!("privacy - ident item {}", id);
self.check_path(pid.span, id, name.name);
}
hir::PathListMod { id, .. } => {
debug!("privacy - mod item {}", id);
let name = prefix.segments.last().unwrap().identifier.name;
self.check_path(pid.span, id, name);
}
}
}
}
}
let orig_curitem = replace(&mut self.curitem, item.id);
visit::walk_item(self, item);
self.curitem = orig_curitem;
Expand Down Expand Up @@ -997,8 +980,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}

fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
self.check_path(path.span, id, path.segments.last().unwrap().identifier.name);
visit::walk_path(self, path);
if !path.segments.is_empty() {
self.check_path(path.span, id, path.segments.last().unwrap().identifier.name);
visit::walk_path(self, path);
}
}

fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
let name = if let hir::PathListIdent { name, .. } = item.node {
name.name
} else if !prefix.segments.is_empty() {
prefix.segments.last().unwrap().identifier.name
} else {
self.tcx.sess.bug("`self` import in an import list with empty prefix");
};
self.check_path(item.span, item.node.id(), name);
visit::walk_path_list_item(self, prefix, item);
}
}

Expand Down
28 changes: 22 additions & 6 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2210,23 +2210,39 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

ItemUse(ref view_path) => {
// check for imports shadowing primitive types
let check_rename = |id, ident: Ident| {
match self.def_map.borrow().get(&id).map(|d| d.full_def()) {
let check_rename = |this: &Self, id, ident: Ident| {
match this.def_map.borrow().get(&id).map(|d| d.full_def()) {
Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
self.check_if_primitive_type_name(ident.name, item.span);
this.check_if_primitive_type_name(ident.name, item.span);
}
_ => {}
}
};

match view_path.node {
hir::ViewPathSimple(ident, _) => {
check_rename(item.id, ident);
check_rename(self, item.id, ident);
}
hir::ViewPathList(_, ref items) => {
hir::ViewPathList(ref prefix, ref items) => {
for item in items {
if let Some(ident) = item.node.rename() {
check_rename(item.node.id(), ident);
check_rename(self, item.node.id(), ident);
}
}

// Resolve prefix of an import with empty braces (issue #28388)
if items.is_empty() && !prefix.segments.is_empty() {
match self.resolve_crate_relative_path(prefix.span,
&prefix.segments,
TypeNS) {
Some((def, lp)) => self.record_def(item.id,
PathResolution::new(def, lp, 0)),
None => {
resolve_error(self,
prefix.span,
ResolutionError::FailedToResolve(
&path_names_to_string(prefix, 0)));
}
}
}
}
Expand Down
39 changes: 20 additions & 19 deletions src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ pub trait Visitor<'v> : Sized {
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
walk_path(self, path)
}
fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
walk_path_list_item(self, prefix, item)
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
Expand Down Expand Up @@ -209,33 +212,20 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
ItemExternCrate(..) => {}
ItemUse(ref vp) => {
match vp.node {
ViewPathSimple(ident, ref path) => {
visitor.visit_ident(vp.span, ident);
ViewPathSimple(_ident, ref path) => {
visitor.visit_path(path, item.id);
}
ViewPathGlob(ref path) => {
visitor.visit_path(path, item.id);
}
ViewPathList(ref prefix, ref list) => {
for id in list {
match id.node {
PathListIdent { name, rename, .. } => {
visitor.visit_ident(id.span, name);
if let Some(ident) = rename {
visitor.visit_ident(id.span, ident);
}
}
PathListMod { rename, .. } => {
if let Some(ident) = rename {
visitor.visit_ident(id.span, ident);
}
}
if !list.is_empty() {
for item in list {
visitor.visit_path_list_item(prefix, item)
}
} else {
visitor.visit_path(prefix, item.id);
}

// Note that the `prefix` here is not a complete
// path, so we don't use `visit_path`.
walk_path(visitor, prefix);
}
}
}
Expand Down Expand Up @@ -417,6 +407,17 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
}
}

pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, prefix: &'v Path,
item: &'v PathListItem) {
for segment in &prefix.segments {
visitor.visit_path_segment(prefix.span, segment);
}

if let PathListIdent { name, .. } = item.node {
visitor.visit_ident(item.span, name);
}
}

pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
Expand Down
21 changes: 21 additions & 0 deletions src/test/compile-fail/issue-28075.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2015 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.

// Unstable entities should be caught in import lists

#![allow(unused_imports)]

use std::thread::{catch_panic, ScopedKey}; //~ ERROR use of unstable library feature 'catch_panic'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to down below, can you make an auxiliary file for this instead of relying on particular features in the standard library being unstable? (these will change over time)

//~^ ERROR use of unstable library feature 'scoped_tls'

use std::rt::{self}; //~ ERROR use of unstable library feature 'rt'

fn main() {
}
Loading