diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c9cf3f3b81f..f020f86b686 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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); diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index aa360ed1bf5..6013c20daf2 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -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; @@ -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; { @@ -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() { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c53fa2bd9a6..ec9a15d9f2b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -30,7 +30,7 @@ use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax}; use attr; use epoch::Epoch; use codemap::Spanned; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; use errors::{DiagnosticBuilder, Handler, FatalError}; use visit::{self, FnKind, Visitor}; use parse::ParseSess; @@ -59,7 +59,8 @@ macro_rules! declare_features { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. const ACTIVE_FEATURES: - &'static [(&'static str, &'static str, Option, Option, fn(&mut Features, Span))] = + &'static [(&'static str, &'static str, Option, + Option, fn(&mut Features, Span))] = &[$((stringify!($feature), $ver, $issue, $epoch, set!($feature))),+]; /// A set of features to be used by later passes. @@ -408,7 +409,7 @@ declare_features! ( (active, match_default_bindings, "1.22.0", Some(42640), None), // Trait object syntax with `dyn` prefix - (active, dyn_trait, "1.22.0", Some(44662), None), + (active, dyn_trait, "1.22.0", Some(44662), Some(Epoch::Epoch2018)), // `crate` as visibility modifier, synonymous to `pub(crate)` (active, crate_visibility_modifier, "1.23.0", Some(45388), None), @@ -1794,11 +1795,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } -pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features { +pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], + epoch: Epoch) -> Features { let mut features = Features::new(); let mut feature_checker = FeatureChecker::default(); + for &(.., f_epoch, set) in ACTIVE_FEATURES.iter() { + if let Some(f_epoch) = f_epoch { + if epoch >= f_epoch { + // FIXME(Manishearth) there is currently no way to set + // lang features by epoch + set(&mut features, DUMMY_SP); + } + } + } + for attr in krate_attrs { if !attr.check_name("feature") { continue