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 gating feature flags on epochs ; rejigger epoch lints #48801

Merged
merged 9 commits into from
Mar 9, 2018
6 changes: 2 additions & 4 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use errors::DiagnosticBuilder;
use lint::{LintPass, LateLintPass, LintArray};
use session::Session;
use session::config::Epoch;
use syntax::codemap::Span;

declare_lint! {
Expand Down Expand Up @@ -264,9 +263,8 @@ declare_lint! {

declare_lint! {
pub BARE_TRAIT_OBJECT,
Warn,
"suggest using `dyn Trait` for trait objects",
Epoch::Epoch2018
Allow,
"suggest using `dyn Trait` for trait objects"
}

declare_lint! {
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use util::nodemap::FxHashMap;
use std::default::Default as StdDefault;
use std::cell::{Ref, RefCell};
use syntax::ast;
use syntax::epoch;
use syntax_pos::{MultiSpan, Span};
use errors::DiagnosticBuilder;
use hir;
Expand Down Expand Up @@ -105,7 +106,7 @@ pub struct FutureIncompatibleInfo {
pub reference: &'static str,
/// If this is an epoch fixing lint, the epoch in which
/// this lint becomes obsolete
pub epoch: Option<config::Epoch>,
pub epoch: Option<epoch::Epoch>,
}

/// The target of the `by_name` map, which accounts for renaming/deprecation.
Expand Down Expand Up @@ -201,7 +202,7 @@ impl LintStore {
sess: Option<&Session>,
lints: Vec<FutureIncompatibleInfo>) {

for epoch in config::ALL_EPOCHS {
for epoch in epoch::ALL_EPOCHS {
let lints = lints.iter().filter(|f| f.epoch == Some(*epoch)).map(|f| f.id)
.collect::<Vec<_>>();
if !lints.is_empty() {
Expand Down
12 changes: 9 additions & 3 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ use hir::def_id::{CrateNum, LOCAL_CRATE};
use hir::intravisit::{self, FnKind};
use hir;
use lint::builtin::BuiltinLintDiagnostics;
use session::{config, Session, DiagnosticMessageId};
use session::{Session, DiagnosticMessageId};
use std::hash;
use syntax::ast;
use syntax::codemap::MultiSpan;
use syntax::epoch::Epoch;
use syntax::symbol::Symbol;
use syntax::visit as ast_visit;
use syntax_pos::Span;
Expand Down Expand Up @@ -77,7 +78,7 @@ pub struct Lint {
pub desc: &'static str,

/// Deny lint after this epoch
pub epoch_deny: Option<config::Epoch>,
pub epoch_deny: Option<Epoch>,
}

impl Lint {
Expand Down Expand Up @@ -492,9 +493,14 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
// Check for future incompatibility lints and issue a stronger warning.
let lints = sess.lint_store.borrow();
if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
let future = if let Some(epoch) = future_incompatible.epoch {
format!("the {} epoch", epoch)
} else {
"a future release".to_owned()
};
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!");
it will become a hard error in {}!", future);
let citation = format!("for more information, see {}",
future_incompatible.reference);
err.warn(&explanation);
Expand Down
57 changes: 3 additions & 54 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use middle::cstore;

use syntax::ast::{self, IntTy, UintTy};
use syntax::codemap::{FileName, FilePathMapping};
use syntax::epoch::Epoch;
use syntax::parse::token;
use syntax::parse;
use syntax::symbol::Symbol;
Expand Down Expand Up @@ -111,59 +112,6 @@ pub enum OutputType {
DepInfo,
}

/// The epoch of the compiler (RFC 2052)
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
#[non_exhaustive]
pub enum Epoch {
// epochs must be kept in order, newest to oldest
/// The 2015 epoch
Epoch2015,
/// The 2018 epoch
Epoch2018,
// when adding new epochs, be sure to update:
//
// - the list in the `parse_epoch` static
// - the match in the `parse_epoch` function
// - add a `rust_####()` function to the session
// - update the enum in Cargo's sources as well
//
// When -Zepoch becomes --epoch, there will
// also be a check for the epoch being nightly-only
// somewhere. That will need to be updated
// whenever we're stabilizing/introducing a new epoch
// as well as changing the default Cargo template.
}

pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018];

impl ToString for Epoch {
fn to_string(&self) -> String {
match *self {
Epoch::Epoch2015 => "2015".into(),
Epoch::Epoch2018 => "2018".into(),
}
}
}

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, ()> {
match s {
"2015" => Ok(Epoch::Epoch2015),
"2018" => Ok(Epoch::Epoch2018),
_ => Err(()),
}
}
}

impl_stable_hash_for!(enum self::OutputType {
Bitcode,
Expand Down Expand Up @@ -829,9 +777,10 @@ macro_rules! options {

#[allow(dead_code)]
mod $mod_set {
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, Epoch};
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
use std::path::PathBuf;
use syntax::epoch::Epoch;

$(
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics;
use middle::allocator::AllocatorKind;
use middle::dependency_format;
use session::search_paths::PathKind;
use session::config::{DebugInfoLevel, Epoch, OutputType};
use session::config::{DebugInfoLevel, OutputType};
use ty::tls;
use util::nodemap::{FxHashMap, FxHashSet};
use util::common::{duration_to_secs_str, ErrorReported};
Expand All @@ -30,6 +30,7 @@ use rustc_data_structures::sync::Lrc;
use syntax::ast::NodeId;
use errors::{self, DiagnosticBuilder, DiagnosticId};
use errors::emitter::{Emitter, EmitterWriter};
use syntax::epoch::Epoch;
use syntax::json::JsonEmitter;
use syntax::feature_gate;
use syntax::symbol::Symbol;
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
{
let time_passes = sess.time_passes();

let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test);
let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess,
sess.opts.test,
sess.opts.debugging_opts.epoch);
// these need to be set "early" so that expansion sees `quote` if enabled.
sess.init_features(features);

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
pub struct UnreachablePub;

declare_lint! {
UNREACHABLE_PUB,
pub UNREACHABLE_PUB,
Allow,
"`pub` items not reachable from crate root"
}
Expand Down
16 changes: 9 additions & 7 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ extern crate rustc_mir;
extern crate syntax_pos;

use rustc::lint;
use rustc::lint::builtin::BARE_TRAIT_OBJECT;
use rustc::session;
use rustc::util;

use session::Session;
use syntax::epoch::Epoch;
use lint::LintId;
use lint::FutureIncompatibleInfo;

Expand Down Expand Up @@ -176,6 +178,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UNUSED_FEATURES,
UNUSED_PARENS);

add_lint_group!(sess,
"rust_2018_idioms",
BARE_TRAIT_OBJECT,
UNREACHABLE_PUB);

// Guidelines for creating a future incompatibility lint:
//
// - Create a lint defaulting to warn as normal, with ideally the same error
Expand Down Expand Up @@ -274,13 +281,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
FutureIncompatibleInfo {
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(lint::builtin::BARE_TRAIT_OBJECT),
reference: "issue #48457 <https://github.com/rust-lang/rust/issues/48457>",
epoch: Some(session::config::Epoch::Epoch2018),
}
epoch: Some(Epoch::Epoch2018),
}
]);

// Register renamed and removed lints
Expand Down
5 changes: 3 additions & 2 deletions src/libsyntax/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features
use {fold, attr};
use ast;
use codemap::Spanned;
use epoch::Epoch;
use parse::{token, ParseSess};

use ptr::P;
Expand All @@ -26,7 +27,7 @@ pub struct StripUnconfigured<'a> {
}

// `cfg_attr`-process the crate's attributes and compute the crate's features.
pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool)
pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, epoch: Epoch)
-> (ast::Crate, Features) {
let features;
{
Expand All @@ -46,7 +47,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool)
return (krate, Features::new());
}

features = get_features(&sess.span_diagnostic, &krate.attrs);
features = get_features(&sess.span_diagnostic, &krate.attrs, epoch);

// Avoid reconfiguring malformed `cfg_attr`s
if err_count == sess.span_diagnostic.err_count() {
Expand Down
69 changes: 69 additions & 0 deletions src/libsyntax/epoch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::str::FromStr;

/// The epoch of the compiler (RFC 2052)
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
#[non_exhaustive]
pub enum Epoch {
// epochs must be kept in order, newest to oldest

/// The 2015 epoch
Epoch2015,
/// The 2018 epoch
Epoch2018,

// when adding new epochs, be sure to update:
//
// - the list in the `parse_epoch` static in librustc::session::config
// - add a `rust_####()` function to the session
// - update the enum in Cargo's sources as well
//
// When -Zepoch becomes --epoch, there will
// also be a check for the epoch being nightly-only
// somewhere. That will need to be updated
// whenever we're stabilizing/introducing a new epoch
// as well as changing the default Cargo template.
}

// must be in order from oldest to newest
pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018];

impl fmt::Display for Epoch {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Epoch::Epoch2015 => "2015",
Epoch::Epoch2018 => "2018",
};
write!(f, "{}", s)
}
}

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

impl FromStr for Epoch {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
match s {
"2015" => Ok(Epoch::Epoch2015),
"2018" => Ok(Epoch::Epoch2018),
_ => Err(())
}
}
}
Loading