Skip to content

Commit 56cae9f

Browse files
committed
Rollup merge of rust-lang#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 <rust-lang#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 rust-lang#30746
2 parents 8637da8 + 0704279 commit 56cae9f

File tree

12 files changed

+127
-22
lines changed

12 files changed

+127
-22
lines changed

src/librustc/lint/builtin.rs

-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
1717
use lint::{LintPass, LateLintPass, LintArray};
1818

19-
// name of the future-incompatible group
20-
pub const FUTURE_INCOMPATIBLE: &'static str = "future_incompatible";
21-
2219
declare_lint! {
2320
pub CONST_ERR,
2421
Warn,

src/librustc/lint/context.rs

+37-6
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,22 @@ pub struct LintStore {
7676
/// is true if the lint group was added by a plugin.
7777
lint_groups: FnvHashMap<&'static str, (Vec<LintId>, bool)>,
7878

79+
/// Extra info for future incompatibility lints, descibing the
80+
/// issue or RFC that caused the incompatibility.
81+
future_incompatible: FnvHashMap<LintId, FutureIncompatibleInfo>,
82+
7983
/// Maximum level a lint can be
8084
lint_cap: Option<Level>,
8185
}
8286

87+
/// Extra information for a future incompatibility lint. See the call
88+
/// to `register_future_incompatible` in `librustc_lint/lib.rs` for
89+
/// guidelines.
90+
pub struct FutureIncompatibleInfo {
91+
pub id: LintId,
92+
pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code
93+
}
94+
8395
/// The targed of the `by_name` map, which accounts for renaming/deprecation.
8496
enum TargetLint {
8597
/// A direct lint target
@@ -124,6 +136,7 @@ impl LintStore {
124136
late_passes: Some(vec!()),
125137
by_name: FnvHashMap(),
126138
levels: FnvHashMap(),
139+
future_incompatible: FnvHashMap(),
127140
lint_groups: FnvHashMap(),
128141
lint_cap: None,
129142
}
@@ -183,6 +196,20 @@ impl LintStore {
183196
}
184197
}
185198

199+
pub fn register_future_incompatible(&mut self,
200+
sess: Option<&Session>,
201+
lints: Vec<FutureIncompatibleInfo>) {
202+
let ids = lints.iter().map(|f| f.id).collect();
203+
self.register_group(sess, false, "future_incompatible", ids);
204+
for info in lints {
205+
self.future_incompatible.insert(info.id, info);
206+
}
207+
}
208+
209+
pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
210+
self.future_incompatible.get(&id)
211+
}
212+
186213
pub fn register_group(&mut self, sess: Option<&Session>,
187214
from_plugin: bool, name: &'static str,
188215
to: Vec<LintId>) {
@@ -418,14 +445,18 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
418445
};
419446

420447
// Check for future incompatibility lints and issue a stronger warning.
421-
let future_incompat_lints = &lints.lint_groups[builtin::FUTURE_INCOMPATIBLE];
422-
let this_id = LintId::of(lint);
423-
if future_incompat_lints.0.iter().any(|&id| id == this_id) {
424-
let msg = "this lint will become a HARD ERROR in a future release!";
448+
if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
449+
let explanation = format!("this was previously accepted by the compiler \
450+
but is being phased out; \
451+
it will become a hard error in a future release!");
452+
let citation = format!("for more information, see {}",
453+
future_incompatible.reference);
425454
if let Some(sp) = span {
426-
err.span_note(sp, msg);
455+
err.fileline_warn(sp, &explanation);
456+
err.fileline_note(sp, &citation);
427457
} else {
428-
err.note(msg);
458+
err.warn(&explanation);
459+
err.note(&citation);
429460
}
430461
}
431462

src/librustc/lint/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use rustc_front::hir;
4141

4242
pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
4343
raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
44-
raw_struct_lint, GatherNodeLevels};
44+
raw_struct_lint, GatherNodeLevels, FutureIncompatibleInfo};
4545

4646
/// Specification of a single lint.
4747
#[derive(Copy, Clone, Debug)]

src/librustc_lint/lib.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub use rustc::util as util;
5454

5555
use session::Session;
5656
use lint::LintId;
57+
use lint::FutureIncompatibleInfo;
5758

5859
mod bad_style;
5960
mod builtin;
@@ -144,9 +145,29 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
144145
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
145146
UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
146147

147-
add_lint_group!(sess, FUTURE_INCOMPATIBLE,
148-
PRIVATE_IN_PUBLIC, INVALID_TYPE_PARAM_DEFAULT,
149-
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT);
148+
// Guidelines for creating a future incompatibility lint:
149+
//
150+
// - Create a lint defaulting to warn as normal, with ideally the same error
151+
// message you would normally give
152+
// - Add a suitable reference, typically an RFC or tracking issue. Go ahead
153+
// and include the full URL.
154+
// - Later, change lint to error
155+
// - Eventually, remove lint
156+
store.register_future_incompatible(sess, vec![
157+
FutureIncompatibleInfo {
158+
id: LintId::of(PRIVATE_IN_PUBLIC),
159+
reference: "the explanation for E0446 (`--explain E0446`)",
160+
},
161+
FutureIncompatibleInfo {
162+
id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
163+
reference: "PR 30742 <https://github.com/rust-lang/rust/pull/30724>",
164+
},
165+
FutureIncompatibleInfo {
166+
id: LintId::of(MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT),
167+
reference: "RFC 218 <https://github.com/rust-lang/rfcs/blob/\
168+
master/text/0218-empty-struct-with-braces.md>",
169+
},
170+
]);
150171

151172
// We have one lint pass defined specially
152173
store.register_late_pass(sess, false, box lint::GatherNodeLevels);

src/librustc_privacy/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,7 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
15281528
lint::builtin::PRIVATE_IN_PUBLIC,
15291529
node_id,
15301530
ty.span,
1531-
"private type in public interface (error E0446)".to_string()
1531+
format!("private type in public interface"),
15321532
);
15331533
}
15341534
}

src/librustc_typeck/check/_match.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -595,14 +595,10 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
595595
let name = pprust::path_to_string(path);
596596
let msg = format!("`{}` does not name a tuple variant or a tuple struct", name);
597597
if lint {
598-
let expanded_msg =
599-
format!("{}; RFC 218 disallowed matching of unit variants or unit structs via {}(..)",
600-
msg,
601-
name);
602598
sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
603599
pat.id,
604600
pat.span,
605-
expanded_msg);
601+
msg);
606602
} else {
607603
span_err!(sess, pat.span, E0164, "{}", msg);
608604
}

src/librustc_typeck/collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1917,8 +1917,8 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
19171917
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
19181918
param.id,
19191919
param.span,
1920-
format!("defaults for type parameters are only allowed \
1921-
on `struct` or `enum` definitions (see issue #27336)"));
1920+
format!("defaults for type parameters are only allowed on type definitions, \
1921+
like `struct` or `enum`"));
19221922
}
19231923
}
19241924

src/libsyntax/errors/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,17 @@ impl<'a> DiagnosticBuilder<'a> {
161161
self.sub(Level::Note, msg, Some(sp), None);
162162
self
163163
}
164+
pub fn warn(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
165+
self.sub(Level::Warning, msg, None, None);
166+
self
167+
}
168+
pub fn span_warn(&mut self,
169+
sp: Span,
170+
msg: &str)
171+
-> &mut DiagnosticBuilder<'a> {
172+
self.sub(Level::Warning, msg, Some(sp), None);
173+
self
174+
}
164175
pub fn help(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> {
165176
self.sub(Level::Help, msg, None, None);
166177
self
@@ -190,6 +201,13 @@ impl<'a> DiagnosticBuilder<'a> {
190201
self.sub(Level::Note, msg, Some(sp), Some(EndSpan(sp)));
191202
self
192203
}
204+
pub fn fileline_warn(&mut self ,
205+
sp: Span,
206+
msg: &str)
207+
-> &mut DiagnosticBuilder<'a> {
208+
self.sub(Level::Warning, msg, Some(sp), Some(FileLine(sp)));
209+
self
210+
}
193211
pub fn fileline_note(&mut self ,
194212
sp: Span,
195213
msg: &str)

src/test/compile-fail/empty-struct-unit-pat.rs

+2
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@ fn main() { //~ ERROR: compilation successful
3232
// }
3333
match e1 {
3434
Empty1(..) => () //~ WARN `Empty1` does not name a tuple variant or a tuple struct
35+
//~^ WARN hard error
3536
}
3637
// Rejected by parser as yet
3738
// match e2 {
3839
// E::Empty2() => () // ERROR `E::Empty2` does not name a tuple variant or a tuple struct
3940
// }
4041
match e2 {
4142
E::Empty2(..) => () //~ WARN `E::Empty2` does not name a tuple variant or a tuple struct
43+
//~^ WARN hard error
4244
}
4345
}

src/test/compile-fail/private-in-public-warn.rs

+36
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,34 @@ mod types {
2626
}
2727

2828
pub type Alias = Priv; //~ WARN private type in public interface
29+
//~^ WARNING hard error
2930
pub enum E {
3031
V1(Priv), //~ WARN private type in public interface
32+
//~^ WARNING hard error
3133
V2 { field: Priv }, //~ WARN private type in public interface
34+
//~^ WARNING hard error
3235
}
3336
pub trait Tr {
3437
const C: Priv = Priv; //~ WARN private type in public interface
38+
//~^ WARNING hard error
3539
type Alias = Priv; //~ WARN private type in public interface
40+
//~^ WARNING hard error
3641
fn f1(arg: Priv) {} //~ WARN private type in public interface
42+
//~^ WARNING hard error
3743
fn f2() -> Priv { panic!() } //~ WARN private type in public interface
44+
//~^ WARNING hard error
3845
}
3946
extern {
4047
pub static ES: Priv; //~ WARN private type in public interface
48+
//~^ WARNING hard error
4149
pub fn ef1(arg: Priv); //~ WARN private type in public interface
50+
//~^ WARNING hard error
4251
pub fn ef2() -> Priv; //~ WARN private type in public interface
52+
//~^ WARNING hard error
4353
}
4454
impl PubTr for Pub {
4555
type Alias = Priv; //~ WARN private type in public interface
56+
//~^ WARNING hard error
4657
}
4758
}
4859

@@ -53,14 +64,21 @@ mod traits {
5364

5465
pub type Alias<T: PrivTr> = T; //~ WARN private trait in public interface
5566
//~^ WARN trait bounds are not (yet) enforced in type definitions
67+
//~| WARNING hard error
5668
pub trait Tr1: PrivTr {} //~ WARN private trait in public interface
69+
//~^ WARNING hard error
5770
pub trait Tr2<T: PrivTr> {} //~ WARN private trait in public interface
71+
//~^ WARNING hard error
5872
pub trait Tr3 {
5973
type Alias: PrivTr; //~ WARN private trait in public interface
74+
//~^ WARNING hard error
6075
fn f<T: PrivTr>(arg: T) {} //~ WARN private trait in public interface
76+
//~^ WARNING hard error
6177
}
6278
impl<T: PrivTr> Pub<T> {} //~ WARN private trait in public interface
79+
//~^ WARNING hard error
6380
impl<T: PrivTr> PubTr for Pub<T> {} //~ WARN private trait in public interface
81+
//~^ WARNING hard error
6482
}
6583

6684
mod traits_where {
@@ -69,12 +87,17 @@ mod traits_where {
6987
pub trait PubTr {}
7088

7189
pub type Alias<T> where T: PrivTr = T; //~ WARN private trait in public interface
90+
//~^ WARNING hard error
7291
pub trait Tr2<T> where T: PrivTr {} //~ WARN private trait in public interface
92+
//~^ WARNING hard error
7393
pub trait Tr3 {
7494
fn f<T>(arg: T) where T: PrivTr {} //~ WARN private trait in public interface
95+
//~^ WARNING hard error
7596
}
7697
impl<T> Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
98+
//~^ WARNING hard error
7799
impl<T> PubTr for Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
100+
//~^ WARNING hard error
78101
}
79102

80103
mod generics {
@@ -84,9 +107,13 @@ mod generics {
84107
pub trait PubTr<T> {}
85108

86109
pub trait Tr1: PrivTr<Pub> {} //~ WARN private trait in public interface
110+
//~^ WARNING hard error
87111
pub trait Tr2: PubTr<Priv> {} //~ WARN private type in public interface
112+
//~^ WARNING hard error
88113
pub trait Tr3: PubTr<[Priv; 1]> {} //~ WARN private type in public interface
114+
//~^ WARNING hard error
89115
pub trait Tr4: PubTr<Pub<Priv>> {} //~ WARN private type in public interface
116+
//~^ WARNING hard error
90117
}
91118

92119
mod impls {
@@ -113,6 +140,7 @@ mod impls {
113140
}
114141
impl PubTr for Pub {
115142
type Alias = Priv; //~ WARN private type in public interface
143+
//~^ WARNING hard error
116144
}
117145
}
118146

@@ -179,22 +207,27 @@ mod aliases_pub {
179207
pub trait Tr1: PrivUseAliasTr {} // OK
180208
// This should be OK, if type aliases are substituted
181209
pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private type in public interface
210+
//~^ WARNING hard error
182211

183212
impl PrivAlias {
184213
pub fn f(arg: Priv) {} //~ WARN private type in public interface
214+
//~^ WARNING hard error
185215
}
186216
// This doesn't even parse
187217
// impl <Priv as PrivTr>::AssocAlias {
188218
// pub fn f(arg: Priv) {} // WARN private type in public interface
189219
// }
190220
impl PrivUseAliasTr for PrivUseAlias {
191221
type Check = Priv; //~ WARN private type in public interface
222+
//~^ WARNING hard error
192223
}
193224
impl PrivUseAliasTr for PrivAlias {
194225
type Check = Priv; //~ WARN private type in public interface
226+
//~^ WARNING hard error
195227
}
196228
impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
197229
type Check = Priv; //~ WARN private type in public interface
230+
//~^ WARNING hard error
198231
}
199232
}
200233

@@ -217,8 +250,11 @@ mod aliases_priv {
217250
impl PrivTr for Priv {}
218251

219252
pub trait Tr1: PrivUseAliasTr {} //~ WARN private trait in public interface
253+
//~^ WARNING hard error
220254
pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private trait in public interface
221255
//~^ WARN private type in public interface
256+
//~| WARNING hard error
257+
//~| WARNING hard error
222258

223259
impl PrivUseAlias {
224260
pub fn f(arg: Priv) {} // OK

src/test/compile-fail/private-variant-reexport.rs

+4
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@
1313

1414
mod m1 {
1515
pub use ::E::V; //~ WARN variant `V` is private, and cannot be reexported
16+
//~^ WARNING hard error
1617
}
1718

1819
mod m2 {
1920
pub use ::E::{V}; //~ WARN variant `V` is private, and cannot be reexported
21+
//~^ WARNING hard error
2022
}
2123

2224
mod m3 {
2325
pub use ::E::V::{self}; //~ WARN variant `V` is private, and cannot be reexported
26+
//~^ WARNING hard error
2427
}
2528

2629
mod m4 {
2730
pub use ::E::*; //~ WARN variant `V` is private, and cannot be reexported
31+
//~^ WARNING hard error
2832
}
2933

3034
enum E { V }

src/test/compile-fail/type-parameter-invalid-lint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313

1414
fn avg<T=i32>(_: T) {}
1515
//~^ ERROR defaults for type parameters are only allowed
16-
//~| NOTE HARD ERROR
16+
//~| WARNING hard error
1717
fn main() {}

0 commit comments

Comments
 (0)