Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functionality for epoch lints; add epoch lint for dyn-trait #48461

Merged
merged 8 commits into from
Mar 1, 2018
27 changes: 22 additions & 5 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ pub struct BufferedEarlyLint {
/// guidelines.
pub struct FutureIncompatibleInfo {
pub id: LintId,
pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code
/// e.g., a URL for an issue/PR/RFC or error code
pub reference: &'static str,
/// If this is an epoch fixing lint, the epoch in which
/// this lint becomes obsolete
pub epoch: Option<config::Epoch>,
}

/// The target of the `by_name` map, which accounts for renaming/deprecation.
Expand Down Expand Up @@ -194,11 +198,24 @@ 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);

for epoch in config::ALL_EPOCHS {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment plz


"Create a lint group for each epoch corresponding to the future compatibility warnings targeting that epoch"


(Do you think that this ought to include the lints for "all previous epochs", since they are additive?)

(Also, are these lint groups insta-stable?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could. I think having them separate is cleaner, Rust doesn't do well with overlapping lint groups.

Rust lint stability is a very low bar, you just need to not remove the lint (aside from register_removed_lint() or whatever it's called). I think it's fine to insta-stable lint groups.

let lints = lints.iter().filter(|f| f.epoch == Some(*epoch)).map(|f| f.id)
.collect::<Vec<_>>();
if !lints.is_empty() {
self.register_group(sess, false, epoch.lint_name(), lints)
}
}

let mut future_incompatible = vec![];
for lint in lints {
future_incompatible.push(lint.id);
self.future_incompatible.insert(lint.id, lint);
}

self.register_group(sess, false, "future_incompatible", future_incompatible);


}

pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
Expand Down
17 changes: 10 additions & 7 deletions src/librustc/lint/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@ impl LintLevelSets {
fn get_lint_level(&self,
lint: &'static Lint,
idx: u32,
aux: Option<&FxHashMap<LintId, (Level, LintSource)>>)
aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
sess: &Session)
-> (Level, LintSource)
{
let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);

// If `level` is none then we actually assume the default level for this
// lint.
let mut level = level.unwrap_or(lint.default_level);
let mut level = level.unwrap_or(lint.default_level(sess));

// If we're about to issue a warning, check at the last minute for any
// directives against the warnings "lint". If, for example, there's an
Expand Down Expand Up @@ -235,7 +236,8 @@ impl<'a> LintLevelsBuilder<'a> {
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
let (level, src) = self.sets.get_lint_level(lint,
self.cur,
Some(&specs));
Some(&specs),
&sess);
lint::struct_lint_level(self.sess,
lint,
level,
Expand All @@ -248,7 +250,8 @@ impl<'a> LintLevelsBuilder<'a> {
let lint = builtin::UNKNOWN_LINTS;
let (level, src) = self.sets.get_lint_level(lint,
self.cur,
Some(&specs));
Some(&specs),
self.sess);
let msg = format!("unknown lint: `{}`", name);
let mut db = lint::struct_lint_level(self.sess,
lint,
Expand Down Expand Up @@ -342,7 +345,7 @@ impl<'a> LintLevelsBuilder<'a> {
msg: &str)
-> DiagnosticBuilder<'a>
{
let (level, src) = self.sets.get_lint_level(lint, self.cur, None);
let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess);
lint::struct_lint_level(self.sess, lint, level, src, span, msg)
}

Expand Down Expand Up @@ -377,11 +380,11 @@ impl LintLevelMap {
/// If the `id` was not previously registered, returns `None`. If `None` is
/// returned then the parent of `id` should be acquired and this function
/// should be called again.
pub fn level_and_source(&self, lint: &'static Lint, id: HirId)
pub fn level_and_source(&self, lint: &'static Lint, id: HirId, session: &Session)
-> Option<(Level, LintSource)>
{
self.id_to_set.get(&id).map(|idx| {
self.sets.get_lint_level(lint, *idx, None)
self.sets.get_lint_level(lint, *idx, None, session)
})
}

Expand Down
29 changes: 25 additions & 4 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use errors::{DiagnosticBuilder, DiagnosticId};
use hir::def_id::{CrateNum, LOCAL_CRATE};
use hir::intravisit::{self, FnKind};
use hir;
use session::{Session, DiagnosticMessageId};
use session::{config, Session, DiagnosticMessageId};
use std::hash;
use syntax::ast;
use syntax::codemap::MultiSpan;
Expand Down Expand Up @@ -74,25 +74,46 @@ pub struct Lint {
///
/// e.g. "imports that are never used"
pub desc: &'static str,

/// Deny lint after this epoch
pub epoch_deny: Option<config::Epoch>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further down you state that the lint should be removed after the epoch, here it seems to suggest it should be deny.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this? It used to say this, but that changed.

This specific lint becomes Deny in Rust2018. Other lints may wish to disappear entirely because they are no longer lints.

}

impl Lint {
/// Get the lint's name, with ASCII letters converted to lowercase.
pub fn name_lower(&self) -> String {
self.name.to_ascii_lowercase()
}

pub fn default_level(&self, session: &Session) -> Level {
if let Some(epoch_deny) = self.epoch_deny {
if session.epoch() >= epoch_deny {
return Level::Deny
}
}
self.default_level
}
}

/// Declare a static item of type `&'static Lint`.
#[macro_export]
macro_rules! declare_lint {
($vis: vis $NAME: ident, $Level: ident, $desc: expr, $epoch: expr) => (
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: stringify!($NAME),
default_level: $crate::lint::$Level,
desc: $desc,
epoch_deny: Some($epoch)
};
);
($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: stringify!($NAME),
default_level: $crate::lint::$Level,
desc: $desc
desc: $desc,
epoch_deny: None,
};
)
);
}

/// Declare a static `LintArray` and return it as an expression.
Expand Down Expand Up @@ -304,7 +325,7 @@ impl LintId {
/// Setting for how to handle a lint.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum Level {
Allow, Warn, Deny, Forbid
Allow, Warn, Deny, Forbid,
}

impl_stable_hash_for!(enum self::Level {
Expand Down
11 changes: 10 additions & 1 deletion src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub enum OutputType {
}

/// The epoch of the compiler (RFC 2052)
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)]
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
#[non_exhaustive]
pub enum Epoch {
// epochs must be kept in order, newest to oldest
Expand Down Expand Up @@ -148,6 +148,15 @@ impl ToString for Epoch {
}
}

impl Epoch {
pub fn lint_name(&self) -> &'static str {
match *self {
Epoch::Epoch2015 => "epoch_2015",
Epoch::Epoch2018 => "epoch_2018",
}
}
}

impl str::FromStr for Epoch {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,10 @@ impl Session {
pub fn rust_2018(&self) -> bool {
self.opts.debugging_opts.epoch >= Epoch::Epoch2018
}

pub fn epoch(&self) -> Epoch {
self.opts.debugging_opts.epoch
}
}

pub fn build_session(sopts: config::Options,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2234,7 +2234,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let sets = self.lint_levels(LOCAL_CRATE);
loop {
let hir_id = self.hir.definitions().node_to_hir_id(id);
if let Some(pair) = sets.level_and_source(lint, hir_id) {
if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) {
return pair
}
let next = self.hir.get_parent_node(id);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,

// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
super::describe_lints(&sess.lint_store.borrow(), true);
super::describe_lints(&sess, &sess.lint_store.borrow(), true);
return Err(CompileIncomplete::Stopped);
}

Expand Down
20 changes: 10 additions & 10 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,15 +774,15 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
-> Option<(Input, Option<PathBuf>)> {
match matches.free.len() {
0 => {
let mut sess = build_session(sopts.clone(),
None,
descriptions.clone());
if sopts.describe_lints {
let mut ls = lint::LintStore::new();
rustc_lint::register_builtins(&mut ls, None);
describe_lints(&ls, false);
rustc_lint::register_builtins(&mut ls, Some(&sess));
describe_lints(&sess, &ls, false);
return None;
}
let mut sess = build_session(sopts.clone(),
None,
descriptions.clone());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg.clone());
let trans = get_trans(&sess);
Expand Down Expand Up @@ -1121,7 +1121,7 @@ fn usage(verbose: bool, include_unstable_options: bool) {
verbose_help);
}

fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) {
fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) {
println!("
Available lint options:
-W <foo> Warn about <foo>
Expand All @@ -1133,10 +1133,10 @@ Available lint options:

");

fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
lints.sort_by(|x: &&Lint, y: &&Lint| {
match x.default_level.cmp(&y.default_level) {
match x.default_level(sess).cmp(&y.default_level(sess)) {
// The sort doesn't case-fold but it's doubtful we care.
Equal => x.name.cmp(y.name),
r => r,
Expand All @@ -1159,8 +1159,8 @@ Available lint options:
.iter()
.cloned()
.partition(|&(_, p)| p);
let plugin = sort_lints(plugin);
let builtin = sort_lints(builtin);
let plugin = sort_lints(sess, plugin);
let builtin = sort_lints(sess, builtin);

let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups()
.iter()
Expand Down
18 changes: 18 additions & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,74 +185,92 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
FutureIncompatibleInfo {
id: LintId::of(PRIVATE_IN_PUBLIC),
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(SAFE_EXTERN_STATICS),
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(LEGACY_IMPORTS),
reference: "issue #38260 <https://github.com/rust-lang/rust/issues/38260>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(ANONYMOUS_PARAMETERS),
reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(SAFE_PACKED_BORROWS),
reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS),
reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(COERCE_NEVER),
reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
epoch: None,
},
]);

Expand Down