about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-14 09:31:03 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-22 01:52:04 +0000
commitfa8c53bae4592395565fc3c06cdcc093fc4b0dbe (patch)
tree37136941ac391831a41f3132b7c3fdd40e17f35e /src
parent808a7ca805e25fd60bfbdfce5780a05e98b5f1b1 (diff)
downloadrust-fa8c53bae4592395565fc3c06cdcc093fc4b0dbe.tar.gz
rust-fa8c53bae4592395565fc3c06cdcc093fc4b0dbe.zip
Start warning cycle.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lint/builtin.rs10
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_passes/ast_validation.rs7
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs46
-rw-r--r--src/test/compile-fail/directory_ownership/backcompat-warnings.rs21
-rw-r--r--src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs13
8 files changed, 92 insertions, 13 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 82a46f76401..c369bc10e94 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -204,6 +204,13 @@ declare_lint! {
     "detects extra requirements in impls that were erroneously allowed"
 }
 
+declare_lint! {
+    pub LEGACY_DIRECTORY_OWNERSHIP,
+    Warn,
+    "non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files \
+     not named `mod.rs`"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -242,7 +249,8 @@ impl LintPass for HardwiredLints {
             LIFETIME_UNDERSCORE,
             SAFE_EXTERN_STATICS,
             PATTERNS_IN_FNS_WITHOUT_BODY,
-            EXTRA_REQUIREMENT_IN_IMPL
+            EXTRA_REQUIREMENT_IN_IMPL,
+            LEGACY_DIRECTORY_OWNERSHIP
         )
     }
 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 114c0ea556e..1a3ea5db871 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -232,6 +232,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             id: LintId::of(EXTRA_REQUIREMENT_IN_IMPL),
             reference: "issue #37166 <https://github.com/rust-lang/rust/issues/37166>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
+            reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
+        },
         ]);
 
     // Register renamed and removed lints
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 89c3efaafcd..105155d75ab 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -207,6 +207,13 @@ impl<'a> Visitor for AstValidator<'a> {
             ItemKind::Mod(_) => {
                 // Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
                 attr::first_attr_value_str_by_name(&item.attrs, "path");
+                if let Some(attr) =
+                        item.attrs.iter().find(|attr| attr.name() == "warn_directory_ownership") {
+                    let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
+                    let msg = "cannot declare a new module at this location";
+                    self.session.add_lint(lint, item.id, item.span, msg.to_string());
+                    attr::mark_used(attr);
+                }
             }
             ItemKind::Union(ref vdata, _) => {
                 if !vdata.is_struct() {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 3e8f118ce62..fd6cae1e1b6 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -790,7 +790,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
                         PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner));
                     let directory_ownership = match path.file_name().unwrap().to_str() {
                         Some("mod.rs") => DirectoryOwnership::Owned,
-                        _ => DirectoryOwnership::UnownedViaMod,
+                        _ => DirectoryOwnership::UnownedViaMod(false),
                     };
                     path.pop();
                     module.directory = path;
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index f969e45b83a..bfaf00a3d3f 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -86,7 +86,7 @@ pub struct Directory {
 pub enum DirectoryOwnership {
     Owned,
     UnownedViaBlock,
-    UnownedViaMod,
+    UnownedViaMod(bool /* legacy warnings? */),
 }
 
 // a bunch of utility functions of the form parse_<thing>_from_<source>
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ee69125ffae..b00e6b5d58f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -38,7 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
 use ast::{BinOpKind, UnOp};
-use ast;
+use {ast, attr};
 use codemap::{self, CodeMap, Spanned, spanned, respan};
 use syntax_pos::{self, Span, BytePos, mk_sp};
 use errors::{self, DiagnosticBuilder};
@@ -243,6 +243,7 @@ pub struct ModulePath {
 pub struct ModulePathSuccess {
     pub path: PathBuf,
     pub directory_ownership: DirectoryOwnership,
+    warn: bool,
 }
 
 pub struct ModulePathError {
@@ -5268,10 +5269,25 @@ impl<'a> Parser<'a> {
             self.bump();
             if in_cfg {
                 // This mod is in an external file. Let's go get it!
-                let ModulePathSuccess { path, directory_ownership } =
+                let ModulePathSuccess { path, directory_ownership, warn } =
                     self.submod_path(id, &outer_attrs, id_span)?;
-                let (module, attrs) =
+                let (module, mut attrs) =
                     self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
+                if warn {
+                    let attr = ast::Attribute {
+                        id: attr::mk_attr_id(),
+                        style: ast::AttrStyle::Outer,
+                        value: ast::MetaItem {
+                            name: Symbol::intern("warn_directory_ownership"),
+                            node: ast::MetaItemKind::Word,
+                            span: syntax_pos::DUMMY_SP,
+                        },
+                        is_sugared_doc: false,
+                        span: syntax_pos::DUMMY_SP,
+                    };
+                    attr::mark_known(&attr);
+                    attrs.push(attr);
+                }
                 Ok((id, module, Some(attrs)))
             } else {
                 let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() };
@@ -5290,7 +5306,7 @@ impl<'a> Parser<'a> {
     }
 
     fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
-        if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") {
+        if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
             self.directory.path.push(&*path.as_str());
             self.directory.ownership = DirectoryOwnership::Owned;
         } else {
@@ -5299,7 +5315,7 @@ impl<'a> Parser<'a> {
     }
 
     pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
-        ::attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d.as_str()))
+        attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d.as_str()))
     }
 
     /// Returns either a path to a module, or .
@@ -5316,11 +5332,13 @@ impl<'a> Parser<'a> {
         let result = match (default_exists, secondary_exists) {
             (true, false) => Ok(ModulePathSuccess {
                 path: default_path,
-                directory_ownership: DirectoryOwnership::UnownedViaMod,
+                directory_ownership: DirectoryOwnership::UnownedViaMod(false),
+                warn: false,
             }),
             (false, true) => Ok(ModulePathSuccess {
                 path: secondary_path,
                 directory_ownership: DirectoryOwnership::Owned,
+                warn: false,
             }),
             (false, false) => Err(ModulePathError {
                 err_msg: format!("file not found for module `{}`", mod_name),
@@ -5353,9 +5371,10 @@ impl<'a> Parser<'a> {
             return Ok(ModulePathSuccess {
                 directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
                     Some("mod.rs") => DirectoryOwnership::Owned,
-                    _ => DirectoryOwnership::UnownedViaMod,
+                    _ => DirectoryOwnership::UnownedViaMod(true),
                 },
                 path: path,
+                warn: false,
             });
         }
 
@@ -5371,7 +5390,12 @@ impl<'a> Parser<'a> {
                 err.span_note(id_sp, &msg);
             }
             return Err(err);
-        } else if let DirectoryOwnership::UnownedViaMod = self.directory.ownership {
+        } else if let DirectoryOwnership::UnownedViaMod(warn) = self.directory.ownership {
+            if warn {
+                if let Ok(result) = paths.result {
+                    return Ok(ModulePathSuccess { warn: true, ..result });
+                }
+            }
             let mut err = self.diagnostic().struct_span_err(id_sp,
                 "cannot declare a new module at this location");
             let this_module = match self.directory.path.file_name() {
@@ -5387,8 +5411,10 @@ impl<'a> Parser<'a> {
                               &format!("... or maybe `use` the module `{}` instead \
                                         of possibly redeclaring it",
                                        paths.name));
-            }
-            return Err(err);
+                return Err(err);
+            } else {
+                return Err(err);
+            };
         }
 
         match paths.result {
diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
new file mode 100644
index 00000000000..75e3426a399
--- /dev/null
+++ b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
@@ -0,0 +1,21 @@
+// 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.
+
+// error-pattern: cannot declare a new module at this location
+// error-pattern: will become a hard error
+// error-pattern: compilation successful
+
+#![feature(rustc_attrs)]
+
+#[path="mod_file_not_owning_aux3.rs"]
+mod foo;
+
+#[rustc_error]
+fn main() {}
diff --git a/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs
new file mode 100644
index 00000000000..3a164fd55d9
--- /dev/null
+++ b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs
@@ -0,0 +1,13 @@
+// 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.
+
+// ignore-test this is not a test
+
+mod mod_file_not_owning_aux2;