about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-01-15 17:28:28 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-01-15 17:28:28 +0530
commit56cae9f507796c7c0f9fa6ee4caab6fc63a79960 (patch)
tree8f61820aab7a6f9bdbe6d36abb7e8c8ffb9b76ba
parent8637da87b6f7c025e29caf76d168dbfad2ec9964 (diff)
parent0704279dd366d09f107014027647a64f8bfefed9 (diff)
downloadrust-56cae9f507796c7c0f9fa6ee4caab6fc63a79960.tar.gz
rust-56cae9f507796c7c0f9fa6ee4caab6fc63a79960.zip
Rollup merge of #30787 - nikomatsakis:future-incompatible-lint, r=brson
There is now more structure to the report, so that you can specify e.g. an RFC/PR/issue number and other explanatory details.

Example message:

```
type-parameter-invalid-lint.rs:14:8: 14:9 error: defaults for type parameters are only allowed on type definitions, like `struct` or `enum`
type-parameter-invalid-lint.rs:14 fn avg<T=i32>(_: T) {}
                                         ^
type-parameter-invalid-lint.rs:14:8: 14:9 warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
type-parameter-invalid-lint.rs:14:8: 14:9 note: for more information, see PR 30742 <https://github.com/rust-lang/rust/pull/30724>
type-parameter-invalid-lint.rs:11:9: 11:28 note: lint level defined here
type-parameter-invalid-lint.rs:11 #![deny(future_incompatible)]
                                          ^~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
```

r? @brson

I would really like feedback also on the specific messages!

Fixes #30746
-rw-r--r--src/librustc/lint/builtin.rs3
-rw-r--r--src/librustc/lint/context.rs43
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc_lint/lib.rs27
-rw-r--r--src/librustc_privacy/lib.rs2
-rw-r--r--src/librustc_typeck/check/_match.rs6
-rw-r--r--src/librustc_typeck/collect.rs4
-rw-r--r--src/libsyntax/errors/mod.rs18
-rw-r--r--src/test/compile-fail/empty-struct-unit-pat.rs2
-rw-r--r--src/test/compile-fail/private-in-public-warn.rs36
-rw-r--r--src/test/compile-fail/private-variant-reexport.rs4
-rw-r--r--src/test/compile-fail/type-parameter-invalid-lint.rs2
12 files changed, 127 insertions, 22 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 93a46090b90..3689312bed1 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -16,9 +16,6 @@
 
 use lint::{LintPass, LateLintPass, LintArray};
 
-// name of the future-incompatible group
-pub const FUTURE_INCOMPATIBLE: &'static str = "future_incompatible";
-
 declare_lint! {
     pub CONST_ERR,
     Warn,
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index d7eacbfff90..1abfa2bfc59 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -76,10 +76,22 @@ pub struct LintStore {
     /// is true if the lint group was added by a plugin.
     lint_groups: FnvHashMap<&'static str, (Vec<LintId>, bool)>,
 
+    /// Extra info for future incompatibility lints, descibing the
+    /// issue or RFC that caused the incompatibility.
+    future_incompatible: FnvHashMap<LintId, FutureIncompatibleInfo>,
+
     /// Maximum level a lint can be
     lint_cap: Option<Level>,
 }
 
+/// Extra information for a future incompatibility lint. See the call
+/// to `register_future_incompatible` in `librustc_lint/lib.rs` for
+/// guidelines.
+pub struct FutureIncompatibleInfo {
+    pub id: LintId,
+    pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code
+}
+
 /// The targed of the `by_name` map, which accounts for renaming/deprecation.
 enum TargetLint {
     /// A direct lint target
@@ -124,6 +136,7 @@ impl LintStore {
             late_passes: Some(vec!()),
             by_name: FnvHashMap(),
             levels: FnvHashMap(),
+            future_incompatible: FnvHashMap(),
             lint_groups: FnvHashMap(),
             lint_cap: None,
         }
@@ -183,6 +196,20 @@ impl LintStore {
         }
     }
 
+    pub fn register_future_incompatible(&mut self,
+                                        sess: Option<&Session>,
+                                        lints: Vec<FutureIncompatibleInfo>) {
+        let ids = lints.iter().map(|f| f.id).collect();
+        self.register_group(sess, false, "future_incompatible", ids);
+        for info in lints {
+            self.future_incompatible.insert(info.id, info);
+        }
+    }
+
+    pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
+        self.future_incompatible.get(&id)
+    }
+
     pub fn register_group(&mut self, sess: Option<&Session>,
                           from_plugin: bool, name: &'static str,
                           to: Vec<LintId>) {
@@ -418,14 +445,18 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
     };
 
     // Check for future incompatibility lints and issue a stronger warning.
-    let future_incompat_lints = &lints.lint_groups[builtin::FUTURE_INCOMPATIBLE];
-    let this_id = LintId::of(lint);
-    if future_incompat_lints.0.iter().any(|&id| id == this_id) {
-        let msg = "this lint will become a HARD ERROR in a future release!";
+    if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
+        let explanation = format!("this was previously accepted by the compiler \
+                                   but is being phased out; \
+                                   it will become a hard error in a future release!");
+        let citation = format!("for more information, see {}",
+                               future_incompatible.reference);
         if let Some(sp) = span {
-            err.span_note(sp, msg);
+            err.fileline_warn(sp, &explanation);
+            err.fileline_note(sp, &citation);
         } else {
-            err.note(msg);
+            err.warn(&explanation);
+            err.note(&citation);
         }
     }
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 9c689daab86..6061525ef39 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -41,7 +41,7 @@ use rustc_front::hir;
 
 pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
                         raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
-                        raw_struct_lint, GatherNodeLevels};
+                        raw_struct_lint, GatherNodeLevels, FutureIncompatibleInfo};
 
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 825dee9f659..53acbe3af67 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -54,6 +54,7 @@ pub use rustc::util as util;
 
 use session::Session;
 use lint::LintId;
+use lint::FutureIncompatibleInfo;
 
 mod bad_style;
 mod builtin;
@@ -144,9 +145,29 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                     UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
                     UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
 
-    add_lint_group!(sess, FUTURE_INCOMPATIBLE,
-                    PRIVATE_IN_PUBLIC, INVALID_TYPE_PARAM_DEFAULT,
-                    MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT);
+    // Guidelines for creating a future incompatibility lint:
+    //
+    // - Create a lint defaulting to warn as normal, with ideally the same error
+    //   message you would normally give
+    // - Add a suitable reference, typically an RFC or tracking issue. Go ahead
+    //   and include the full URL.
+    // - Later, change lint to error
+    // - Eventually, remove lint
+    store.register_future_incompatible(sess, vec![
+        FutureIncompatibleInfo {
+            id: LintId::of(PRIVATE_IN_PUBLIC),
+            reference: "the explanation for E0446 (`--explain E0446`)",
+        },
+        FutureIncompatibleInfo {
+            id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
+            reference: "PR 30742 <https://github.com/rust-lang/rust/pull/30724>",
+        },
+        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>",
+        },
+        ]);
 
     // We have one lint pass defined specially
     store.register_late_pass(sess, false, box lint::GatherNodeLevels);
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 955e68be0b0..73a1ecf7fc5 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1528,7 +1528,7 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
                                         lint::builtin::PRIVATE_IN_PUBLIC,
                                         node_id,
                                         ty.span,
-                                        "private type in public interface (error E0446)".to_string()
+                                        format!("private type in public interface"),
                                     );
                                 }
                             }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 93ceaf8b11f..dfa144699b2 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -595,14 +595,10 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
     let name = pprust::path_to_string(path);
     let msg = format!("`{}` does not name a tuple variant or a tuple struct", name);
     if lint {
-        let expanded_msg =
-            format!("{}; RFC 218 disallowed matching of unit variants or unit structs via {}(..)",
-                    msg,
-                    name);
         sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
                       pat.id,
                       pat.span,
-                      expanded_msg);
+                      msg);
     } else {
         span_err!(sess, pat.span, E0164, "{}", msg);
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fbbd2f02908..af2824d0930 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1917,8 +1917,8 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
                 param.id,
                 param.span,
-                format!("defaults for type parameters are only allowed \
-                         on `struct` or `enum` definitions (see issue #27336)"));
+                format!("defaults for type parameters are only allowed on type definitions, \
+                         like `struct` or `enum`"));
         }
     }
 
diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs
index f269dee31d9..6983c74696a 100644
--- a/src/libsyntax/errors/mod.rs
+++ b/src/libsyntax/errors/mod.rs
@@ -161,6 +161,17 @@ impl<'a> DiagnosticBuilder<'a> {
         self.sub(Level::Note, msg, Some(sp), None);
         self
     }
+    pub fn warn(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a>  {
+        self.sub(Level::Warning, msg, None, None);
+        self
+    }
+    pub fn span_warn(&mut self,
+                     sp: Span,
+                     msg: &str)
+                     -> &mut DiagnosticBuilder<'a> {
+        self.sub(Level::Warning, msg, Some(sp), None);
+        self
+    }
     pub fn help(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a>  {
         self.sub(Level::Help, msg, None, None);
         self
@@ -190,6 +201,13 @@ impl<'a> DiagnosticBuilder<'a> {
         self.sub(Level::Note, msg, Some(sp), Some(EndSpan(sp)));
         self
     }
+    pub fn fileline_warn(&mut self ,
+                         sp: Span,
+                         msg: &str)
+                         -> &mut DiagnosticBuilder<'a>  {
+        self.sub(Level::Warning, msg, Some(sp), Some(FileLine(sp)));
+        self
+    }
     pub fn fileline_note(&mut self ,
                          sp: Span,
                          msg: &str)
diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs
index 7e13f539bb0..cffd9fd9b49 100644
--- a/src/test/compile-fail/empty-struct-unit-pat.rs
+++ b/src/test/compile-fail/empty-struct-unit-pat.rs
@@ -32,6 +32,7 @@ fn main() { //~ ERROR: compilation successful
     // }
     match e1 {
         Empty1(..) => () //~ WARN `Empty1` does not name a tuple variant or a tuple struct
+            //~^ WARN hard error
     }
     // Rejected by parser as yet
     // match e2 {
@@ -39,5 +40,6 @@ fn main() { //~ ERROR: compilation successful
     // }
     match e2 {
         E::Empty2(..) => () //~ WARN `E::Empty2` does not name a tuple variant or a tuple struct
+            //~^ WARN hard error
     }
 }
diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs
index 2d1de3ca282..9aab06ce14e 100644
--- a/src/test/compile-fail/private-in-public-warn.rs
+++ b/src/test/compile-fail/private-in-public-warn.rs
@@ -26,23 +26,34 @@ mod types {
     }
 
     pub type Alias = Priv; //~ WARN private type in public interface
+    //~^ WARNING hard error
     pub enum E {
         V1(Priv), //~ WARN private type in public interface
+        //~^ WARNING hard error
         V2 { field: Priv }, //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
     pub trait Tr {
         const C: Priv = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
         type Alias = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
         fn f1(arg: Priv) {} //~ WARN private type in public interface
+        //~^ WARNING hard error
         fn f2() -> Priv { panic!() } //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
     extern {
         pub static ES: Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
         pub fn ef1(arg: Priv); //~ WARN private type in public interface
+        //~^ WARNING hard error
         pub fn ef2() -> Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
     impl PubTr for Pub {
         type Alias = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
 }
 
@@ -53,14 +64,21 @@ mod traits {
 
     pub type Alias<T: PrivTr> = T; //~ WARN private trait in public interface
     //~^ WARN trait bounds are not (yet) enforced in type definitions
+    //~| WARNING hard error
     pub trait Tr1: PrivTr {} //~ WARN private trait in public interface
+    //~^ WARNING hard error
     pub trait Tr2<T: PrivTr> {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     pub trait Tr3 {
         type Alias: PrivTr; //~ WARN private trait in public interface
+        //~^ WARNING hard error
         fn f<T: PrivTr>(arg: T) {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     }
     impl<T: PrivTr> Pub<T> {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     impl<T: PrivTr> PubTr for Pub<T> {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
 }
 
 mod traits_where {
@@ -69,12 +87,17 @@ mod traits_where {
     pub trait PubTr {}
 
     pub type Alias<T> where T: PrivTr = T; //~ WARN private trait in public interface
+        //~^ WARNING hard error
     pub trait Tr2<T> where T: PrivTr {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     pub trait Tr3 {
         fn f<T>(arg: T) where T: PrivTr {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     }
     impl<T> Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     impl<T> PubTr for Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
 }
 
 mod generics {
@@ -84,9 +107,13 @@ mod generics {
     pub trait PubTr<T> {}
 
     pub trait Tr1: PrivTr<Pub> {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     pub trait Tr2: PubTr<Priv> {} //~ WARN private type in public interface
+        //~^ WARNING hard error
     pub trait Tr3: PubTr<[Priv; 1]> {} //~ WARN private type in public interface
+        //~^ WARNING hard error
     pub trait Tr4: PubTr<Pub<Priv>> {} //~ WARN private type in public interface
+        //~^ WARNING hard error
 }
 
 mod impls {
@@ -113,6 +140,7 @@ mod impls {
     }
     impl PubTr for Pub {
         type Alias = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
 }
 
@@ -179,9 +207,11 @@ mod aliases_pub {
     pub trait Tr1: PrivUseAliasTr {} // OK
     // This should be OK, if type aliases are substituted
     pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private type in public interface
+        //~^ WARNING hard error
 
     impl PrivAlias {
         pub fn f(arg: Priv) {} //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
     // This doesn't even parse
     // impl <Priv as PrivTr>::AssocAlias {
@@ -189,12 +219,15 @@ mod aliases_pub {
     // }
     impl PrivUseAliasTr for PrivUseAlias {
         type Check = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
     impl PrivUseAliasTr for PrivAlias {
         type Check = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
     impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
         type Check = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
     }
 }
 
@@ -217,8 +250,11 @@ mod aliases_priv {
     impl PrivTr for Priv {}
 
     pub trait Tr1: PrivUseAliasTr {} //~ WARN private trait in public interface
+        //~^ WARNING hard error
     pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private trait in public interface
      //~^ WARN private type in public interface
+        //~| WARNING hard error
+        //~| WARNING hard error
 
     impl PrivUseAlias {
         pub fn f(arg: Priv) {} // OK
diff --git a/src/test/compile-fail/private-variant-reexport.rs b/src/test/compile-fail/private-variant-reexport.rs
index 39698fa593a..06f08dc13c6 100644
--- a/src/test/compile-fail/private-variant-reexport.rs
+++ b/src/test/compile-fail/private-variant-reexport.rs
@@ -13,18 +13,22 @@
 
 mod m1 {
     pub use ::E::V; //~ WARN variant `V` is private, and cannot be reexported
+    //~^ WARNING hard error
 }
 
 mod m2 {
     pub use ::E::{V}; //~ WARN variant `V` is private, and cannot be reexported
+    //~^ WARNING hard error
 }
 
 mod m3 {
     pub use ::E::V::{self}; //~ WARN variant `V` is private, and cannot be reexported
+    //~^ WARNING hard error
 }
 
 mod m4 {
     pub use ::E::*; //~ WARN variant `V` is private, and cannot be reexported
+    //~^ WARNING hard error
 }
 
 enum E { V }
diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/compile-fail/type-parameter-invalid-lint.rs
index a3ecbfa84f0..9291329fac3 100644
--- a/src/test/compile-fail/type-parameter-invalid-lint.rs
+++ b/src/test/compile-fail/type-parameter-invalid-lint.rs
@@ -13,5 +13,5 @@
 
 fn avg<T=i32>(_: T) {}
 //~^ ERROR defaults for type parameters are only allowed
-//~| NOTE HARD ERROR
+//~| WARNING hard error
 fn main() {}