提交 25937942 编写于 作者: N Niko Matsakis

Revamp the "future incompatible" section to clarify the situation

better
上级 7cffc9b1
......@@ -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,
......
......@@ -75,10 +75,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
......@@ -123,6 +135,7 @@ pub fn new() -> LintStore {
late_passes: Some(vec!()),
by_name: FnvHashMap(),
levels: FnvHashMap(),
future_incompatible: FnvHashMap(),
lint_groups: FnvHashMap(),
lint_cap: None,
}
......@@ -182,6 +195,20 @@ fn push_pass<P: LintPass + ?Sized + 'static>(&mut self,
}
}
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>) {
......@@ -417,14 +444,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, \
and 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.span_warn(sp, &explanation);
err.span_note(sp, &citation);
} else {
err.note(msg);
err.warn(&explanation);
err.note(&citation);
}
}
......
......@@ -41,7 +41,7 @@
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)]
......
......@@ -54,6 +54,7 @@
use session::Session;
use lint::LintId;
use lint::FutureIncompatibleInfo;
mod bad_style;
mod builtin;
......@@ -144,9 +145,28 @@ 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);
......
......@@ -1528,7 +1528,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
lint::builtin::PRIVATE_IN_PUBLIC,
node_id,
ty.span,
"private type in public interface (error E0446)".to_string()
format!("private type in public interface"),
);
}
}
......
......@@ -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);
}
......
......@@ -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`"));
}
}
......
......@@ -160,6 +160,17 @@ pub fn span_note(&mut self ,
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册