Add -Z allow_features=... flag
This commit is contained in:
@@ -1440,6 +1440,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||||||
merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
|
merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
|
||||||
"control the operation of the MergeFunctions LLVM pass, taking
|
"control the operation of the MergeFunctions LLVM pass, taking
|
||||||
the same values as the target option of the same name"),
|
the same values as the target option of the same name"),
|
||||||
|
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
|
||||||
|
"only allow the listed language features to be enabled in code (space separated)"),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_lib_output() -> CrateType {
|
pub fn default_lib_output() -> CrateType {
|
||||||
@@ -3286,6 +3288,10 @@ mod tests {
|
|||||||
opts = reference.clone();
|
opts = reference.clone();
|
||||||
opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled);
|
opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled);
|
||||||
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
||||||
|
|
||||||
|
opts = reference.clone();
|
||||||
|
opts.debugging_opts.allow_features = Some(vec![String::from("lang_items")]);
|
||||||
|
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ pub fn register_plugins<'a>(
|
|||||||
krate,
|
krate,
|
||||||
&sess.parse_sess,
|
&sess.parse_sess,
|
||||||
sess.edition(),
|
sess.edition(),
|
||||||
|
&sess.opts.debugging_opts.allow_features,
|
||||||
);
|
);
|
||||||
// these need to be set "early" so that expansion sees `quote` if enabled.
|
// these need to be set "early" so that expansion sees `quote` if enabled.
|
||||||
sess.init_features(features);
|
sess.init_features(features);
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ pub struct StripUnconfigured<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `cfg_attr`-process the crate's attributes and compute the crate's features.
|
// `cfg_attr`-process the crate's attributes and compute the crate's features.
|
||||||
pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
|
pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition,
|
||||||
-> (ast::Crate, Features) {
|
allow_features: &Option<Vec<String>>) -> (ast::Crate, Features) {
|
||||||
let features;
|
let features;
|
||||||
{
|
{
|
||||||
let mut strip_unconfigured = StripUnconfigured {
|
let mut strip_unconfigured = StripUnconfigured {
|
||||||
@@ -43,7 +43,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
|
|||||||
return (krate, Features::new());
|
return (krate, Features::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
features = get_features(&sess.span_diagnostic, &krate.attrs, edition);
|
features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
|
||||||
|
|
||||||
// Avoid reconfiguring malformed `cfg_attr`s
|
// Avoid reconfiguring malformed `cfg_attr`s
|
||||||
if err_count == sess.span_diagnostic.err_count() {
|
if err_count == sess.span_diagnostic.err_count() {
|
||||||
|
|||||||
@@ -378,6 +378,21 @@ Erroneous code example:
|
|||||||
|
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0725: r##"
|
||||||
|
A feature attribute named a feature that was disallowed in the compiler
|
||||||
|
command line flags.
|
||||||
|
|
||||||
|
Erroneous code example:
|
||||||
|
|
||||||
|
```ignore (can't specify compiler flags from doctests)
|
||||||
|
#![feature(never_type)] // error: the feature `never_type` is not in
|
||||||
|
// the list of allowed features
|
||||||
|
```
|
||||||
|
|
||||||
|
Delete the offending feature attribute, or add it to the list of allowed
|
||||||
|
features in the `-Z allow_features` flag.
|
||||||
|
"##,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
register_diagnostics! {
|
register_diagnostics! {
|
||||||
|
|||||||
@@ -2008,7 +2008,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||||
crate_edition: Edition) -> Features {
|
crate_edition: Edition, allow_features: &Option<Vec<String>>) -> Features {
|
||||||
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
|
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
|
||||||
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
|
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
|
||||||
if let Some(reason) = reason {
|
if let Some(reason) = reason {
|
||||||
@@ -2127,6 +2127,15 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
|
if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
|
||||||
|
if let Some(allowed) = allow_features.as_ref() {
|
||||||
|
if allowed.iter().find(|f| *f == name.as_str()).is_none() {
|
||||||
|
span_err!(span_handler, mi.span, E0725,
|
||||||
|
"the feature `{}` is not in the list of allowed features",
|
||||||
|
name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
set(&mut features, mi.span);
|
set(&mut features, mi.span);
|
||||||
features.declared_lang_features.push((name, mi.span, None));
|
features.declared_lang_features.push((name, mi.span, None));
|
||||||
continue
|
continue
|
||||||
|
|||||||
10
src/test/ui/feature-gate/allow-features-empty.rs
Normal file
10
src/test/ui/feature-gate/allow-features-empty.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// compile-flags: -Z allow_features=
|
||||||
|
// Note: This test uses rustc internal flags because they will never stabilize.
|
||||||
|
|
||||||
|
#![feature(rustc_diagnostic_macros)] //~ ERROR
|
||||||
|
|
||||||
|
#![feature(rustc_const_unstable)] //~ ERROR
|
||||||
|
|
||||||
|
#![feature(lang_items)] //~ ERROR
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
21
src/test/ui/feature-gate/allow-features-empty.stderr
Normal file
21
src/test/ui/feature-gate/allow-features-empty.stderr
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features
|
||||||
|
--> $DIR/allow-features-empty.rs:4:12
|
||||||
|
|
|
||||||
|
LL | #![feature(rustc_diagnostic_macros)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
|
||||||
|
--> $DIR/allow-features-empty.rs:6:12
|
||||||
|
|
|
||||||
|
LL | #![feature(rustc_const_unstable)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0725]: the feature `lang_items` is not in the list of allowed features
|
||||||
|
--> $DIR/allow-features-empty.rs:8:12
|
||||||
|
|
|
||||||
|
LL | #![feature(lang_items)]
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0725`.
|
||||||
10
src/test/ui/feature-gate/allow-features.rs
Normal file
10
src/test/ui/feature-gate/allow-features.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items
|
||||||
|
// Note: This test uses rustc internal flags because they will never stabilize.
|
||||||
|
|
||||||
|
#![feature(rustc_diagnostic_macros)]
|
||||||
|
|
||||||
|
#![feature(rustc_const_unstable)] //~ ERROR
|
||||||
|
|
||||||
|
#![feature(lang_items)]
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
9
src/test/ui/feature-gate/allow-features.stderr
Normal file
9
src/test/ui/feature-gate/allow-features.stderr
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
|
||||||
|
--> $DIR/allow-features.rs:6:12
|
||||||
|
|
|
||||||
|
LL | #![feature(rustc_const_unstable)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0725`.
|
||||||
Reference in New Issue
Block a user