diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2016-01-15 17:28:28 +0530 |
|---|---|---|
| committer | Manish Goregaokar <manishsmail@gmail.com> | 2016-01-15 17:28:28 +0530 |
| commit | 56cae9f507796c7c0f9fa6ee4caab6fc63a79960 (patch) | |
| tree | 8f61820aab7a6f9bdbe6d36abb7e8c8ffb9b76ba | |
| parent | 8637da87b6f7c025e29caf76d168dbfad2ec9964 (diff) | |
| parent | 0704279dd366d09f107014027647a64f8bfefed9 (diff) | |
| download | rust-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.rs | 3 | ||||
| -rw-r--r-- | src/librustc/lint/context.rs | 43 | ||||
| -rw-r--r-- | src/librustc/lint/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_lint/lib.rs | 27 | ||||
| -rw-r--r-- | src/librustc_privacy/lib.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/_match.rs | 6 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/errors/mod.rs | 18 | ||||
| -rw-r--r-- | src/test/compile-fail/empty-struct-unit-pat.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/private-in-public-warn.rs | 36 | ||||
| -rw-r--r-- | src/test/compile-fail/private-variant-reexport.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/type-parameter-invalid-lint.rs | 2 |
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() {} |
