about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvlastachu <vlastachu@gmail.com>2016-03-20 03:04:12 +0300
committervlastachu <vlastachu@gmail.com>2016-04-05 11:57:56 +0300
commit6c73134fc740a09e22db6a3c2438339c155ef577 (patch)
treecfc05f7c98e3b4016959af5f95ab8d100e6bf128
parent211c35afcbb7842f6f9d7fa45cee4cd192e4bfe6 (diff)
downloadrust-6c73134fc740a09e22db6a3c2438339c155ef577.tar.gz
rust-6c73134fc740a09e22db6a3c2438339c155ef577.zip
Fixes bug which accepting using `super` in use statemet.
Issue: #32225
-rw-r--r--src/librustc/lint/builtin.rs9
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs20
-rw-r--r--src/libsyntax/parse/parser.rs10
-rw-r--r--src/libsyntax/parse/token.rs2
-rw-r--r--src/test/compile-fail/use-super-global-path.rs22
6 files changed, 58 insertions, 9 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 879b8945620..1573d0c4292 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -179,6 +179,12 @@ declare_lint! {
     "lints that have been renamed or removed"
 }
 
+declare_lint! {
+    pub SUPER_OR_SELF_IN_GLOBAL_PATH,
+    Warn,
+    "detects super or self keywords at the beginning of global path"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -213,7 +219,8 @@ impl LintPass for HardwiredLints {
             RAW_POINTER_DERIVE,
             TRANSMUTE_FROM_FN_ITEM_TYPES,
             OVERLAPPING_INHERENT_IMPLS,
-            RENAMED_AND_REMOVED_LINTS
+            RENAMED_AND_REMOVED_LINTS,
+            SUPER_OR_SELF_IN_GLOBAL_PATH
         )
     }
 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 6e3a961caca..0780e4cd048 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -168,6 +168,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             reference: "PR 30742 <https://github.com/rust-lang/rust/pull/30724>",
         },
         FutureIncompatibleInfo {
+            id: LintId::of(SUPER_OR_SELF_IN_GLOBAL_PATH),
+            reference: "PR #32403 <https://github.com/rust-lang/rust/pull/32403>",
+        },
+        FutureIncompatibleInfo {
             id: LintId::of(MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT),
             reference: "RFC 218 <https://github.com/rust-lang/rfcs/blob/\
                         master/text/0218-empty-struct-with-braces.md>",
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 211bff352fe..ea0019c2bf9 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -24,13 +24,14 @@ use Resolver;
 use {resolve_error, resolve_struct_error, ResolutionError};
 
 use rustc::middle::cstore::{CrateStore, ChildItem, DlDef};
+use rustc::lint;
 use rustc::middle::def::*;
 use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::ty::VariantKind;
 
 use syntax::ast::{Name, NodeId};
 use syntax::attr::AttrMetaMethods;
-use syntax::parse::token::special_idents;
+use syntax::parse::token::{special_idents, SELF_KEYWORD_NAME, SUPER_KEYWORD_NAME};
 use syntax::codemap::{Span, DUMMY_SP};
 
 use rustc_front::hir;
@@ -117,8 +118,10 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                 // Extract and intern the module part of the path. For
                 // globs and lists, the path is found directly in the AST;
                 // for simple paths we have to munge the path a little.
-                let module_path = match view_path.node {
+                let is_global;
+                let module_path: Vec<Name> = match view_path.node {
                     ViewPathSimple(_, ref full_path) => {
+                        is_global = full_path.global;
                         full_path.segments
                                  .split_last()
                                  .unwrap()
@@ -130,6 +133,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
 
                     ViewPathGlob(ref module_ident_path) |
                     ViewPathList(ref module_ident_path, _) => {
+                        is_global = module_ident_path.global;
                         module_ident_path.segments
                                          .iter()
                                          .map(|seg| seg.identifier.name)
@@ -137,6 +141,18 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                     }
                 };
 
+                // Checking for special identifiers in path
+                // prevent `self` or `super` at beginning of global path
+                if is_global && (module_path.first() == Some(&SELF_KEYWORD_NAME) ||
+                                 module_path.first() == Some(&SUPER_KEYWORD_NAME)) {
+                    self.session.add_lint(
+                        lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
+                        item.id,
+                        item.span,
+                        format!("expected identifier, found keyword `{}`",
+                                module_path.first().unwrap().as_str()));
+                }
+
                 // Build up the import directives.
                 let is_prelude = item.attrs.iter().any(|attr| {
                     attr.name() == special_idents::prelude_import.name.as_str()
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9027a5b1074..75916b87c12 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6124,7 +6124,7 @@ impl<'a> Parser<'a> {
 
         // Allow a leading :: because the paths are absolute either way.
         // This occurs with "use $crate::..." in macros.
-        self.eat(&token::ModSep);
+        let is_global = self.eat(&token::ModSep);
 
         if self.check(&token::OpenDelim(token::Brace)) {
             // use {foo,bar}
@@ -6135,7 +6135,7 @@ impl<'a> Parser<'a> {
                 |p| p.parse_path_list_item())?;
             let path = ast::Path {
                 span: mk_sp(lo, self.span.hi),
-                global: false,
+                global: is_global,
                 segments: Vec::new()
             };
             return Ok(P(spanned(lo, self.span.hi, ViewPathList(path, idents))));
@@ -6164,7 +6164,7 @@ impl<'a> Parser<'a> {
                     )?;
                     let path = ast::Path {
                         span: mk_sp(lo, self.span.hi),
-                        global: false,
+                        global: is_global,
                         segments: path.into_iter().map(|identifier| {
                             ast::PathSegment {
                                 identifier: identifier,
@@ -6180,7 +6180,7 @@ impl<'a> Parser<'a> {
                     self.bump();
                     let path = ast::Path {
                         span: mk_sp(lo, self.span.hi),
-                        global: false,
+                        global: is_global,
                         segments: path.into_iter().map(|identifier| {
                             ast::PathSegment {
                                 identifier: identifier,
@@ -6203,7 +6203,7 @@ impl<'a> Parser<'a> {
         let mut rename_to = path[path.len() - 1];
         let path = ast::Path {
             span: mk_sp(lo, self.last_span.hi),
-            global: false,
+            global: is_global,
             segments: path.into_iter().map(|identifier| {
                 ast::PathSegment {
                     identifier: identifier,
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index a02a10aa003..16417ac0044 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -514,7 +514,7 @@ macro_rules! declare_special_idents_and_keywords {(
 // If the special idents get renumbered, remember to modify these two as appropriate
 pub const SELF_KEYWORD_NAME: ast::Name = ast::Name(SELF_KEYWORD_NAME_NUM);
 const STATIC_KEYWORD_NAME: ast::Name = ast::Name(STATIC_KEYWORD_NAME_NUM);
-const SUPER_KEYWORD_NAME: ast::Name = ast::Name(SUPER_KEYWORD_NAME_NUM);
+pub const SUPER_KEYWORD_NAME: ast::Name = ast::Name(SUPER_KEYWORD_NAME_NUM);
 const SELF_TYPE_KEYWORD_NAME: ast::Name = ast::Name(SELF_TYPE_KEYWORD_NAME_NUM);
 
 pub const SELF_KEYWORD_NAME_NUM: u32 = 1;
diff --git a/src/test/compile-fail/use-super-global-path.rs b/src/test/compile-fail/use-super-global-path.rs
new file mode 100644
index 00000000000..d721d428f29
--- /dev/null
+++ b/src/test/compile-fail/use-super-global-path.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+#![feature(rustc_attrs)]
+
+mod foo {
+    pub fn g() {
+        use ::super::main; //~ WARN expected identifier, found keyword `super`
+        //~^ WARN this was previously accepted by the compiler but is being phased out
+        main();
+    }
+}
+
+#[rustc_error]
+fn main() { foo::g(); } //~ ERROR compilation successful