diff --git a/COMPILER_TESTS.md b/COMPILER_TESTS.md index 91975c1f9ed9a..58df1aae6d3f0 100644 --- a/COMPILER_TESTS.md +++ b/COMPILER_TESTS.md @@ -45,6 +45,10 @@ whole, instead of just a few lines inside the test. * `should-fail` indicates that the test should fail; used for "meta testing", where we test the compiletest program itself to check that it will generate errors in appropriate scenarios. This header is ignored for pretty-printer tests. +* `gate-test-X` where `X` is a feature marks the test as "gate test" for feature X. + Such tests are supposed to ensure that the compiler errors when usage of a gated + feature is attempted without the proper `#![feature(X)]` tag. + Each unstable lang feature is required to have a gate test. ## Revisions diff --git a/src/test/compile-fail/asm-gated.rs b/src/test/compile-fail/asm-gated.rs index 8d053bdae789b..cd9cc22370149 100644 --- a/src/test/compile-fail/asm-gated.rs +++ b/src/test/compile-fail/asm-gated.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-asm + fn main() { unsafe { asm!(""); //~ ERROR inline assembly is not stable enough diff --git a/src/test/compile-fail/asm-gated2.rs b/src/test/compile-fail/asm-gated2.rs index d2ee01109f8d8..222190de9fe9c 100644 --- a/src/test/compile-fail/asm-gated2.rs +++ b/src/test/compile-fail/asm-gated2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-asm + fn main() { unsafe { println!("{}", asm!("")); //~ ERROR inline assembly is not stable diff --git a/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs b/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs index 944802f450a6d..b341f7c78257a 100644 --- a/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs +++ b/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs @@ -16,6 +16,8 @@ // using `rustc_attrs` feature. There is a separate compile-fail/ test // ensuring that the attribute feature-gating works in this context.) +// gate-test-generic_param_attrs + #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/compile-fail/check-static-values-constraints.rs b/src/test/compile-fail/check-static-values-constraints.rs index df22e2ea4de13..f65968e0e1192 100644 --- a/src/test/compile-fail/check-static-values-constraints.rs +++ b/src/test/compile-fail/check-static-values-constraints.rs @@ -10,6 +10,8 @@ // Verifies all possible restrictions for statics values. +// gate-test-drop_types_in_const + #![feature(box_syntax)] use std::marker; diff --git a/src/test/compile-fail/concat_idents-gate.rs b/src/test/compile-fail/concat_idents-gate.rs index f4d97445725cd..5b125d0e51c08 100644 --- a/src/test/compile-fail/concat_idents-gate.rs +++ b/src/test/compile-fail/concat_idents-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-concat_idents + const XY_1: i32 = 10; fn main() { diff --git a/src/test/compile-fail/concat_idents-gate2.rs b/src/test/compile-fail/concat_idents-gate2.rs index d8f8f803edcc8..5a9ffe98c93ca 100644 --- a/src/test/compile-fail/concat_idents-gate2.rs +++ b/src/test/compile-fail/concat_idents-gate2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-concat_idents + const XY_1: i32 = 10; fn main() { diff --git a/src/test/compile-fail/const-fn-stability.rs b/src/test/compile-fail/const-fn-stability.rs index 9913c2fa12c4a..436244525e1c2 100644 --- a/src/test/compile-fail/const-fn-stability.rs +++ b/src/test/compile-fail/const-fn-stability.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-const_fn + // Test use of const fn without feature gate. const fn foo() -> usize { 0 } //~ ERROR const fn is unstable diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/compile-fail/feature-gate-abi.rs index 0c01f955c063b..c0fb94e8c42c9 100644 --- a/src/test/compile-fail/feature-gate-abi.rs +++ b/src/test/compile-fail/feature-gate-abi.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-intrinsics +// gate-test-platform_intrinsics +// gate-test-abi_vectorcall + // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental diff --git a/src/test/compile-fail/feature-gate-advanced-slice-features.rs b/src/test/compile-fail/feature-gate-advanced-slice-features.rs index 1daca371b3409..dc9b4e634ab72 100644 --- a/src/test/compile-fail/feature-gate-advanced-slice-features.rs +++ b/src/test/compile-fail/feature-gate-advanced-slice-features.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-advanced_slice_patterns + #![feature(slice_patterns)] fn main() { diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs b/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs index 9ebf8a9b74a6c..1aabe6b87dff5 100644 --- a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs +++ b/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-allow_internal_unstable + macro_rules! bar { () => { // more layers don't help: diff --git a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs b/src/test/compile-fail/feature-gate-assoc-type-defaults.rs index fc4871a712dff..de3521eb0f20b 100644 --- a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs +++ b/src/test/compile-fail/feature-gate-assoc-type-defaults.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-associated_type_defaults + trait Foo { type Bar = u8; //~ ERROR associated type defaults are unstable } diff --git a/src/test/compile-fail/feature-gate-box-expr.rs b/src/test/compile-fail/feature-gate-box-expr.rs index f1bb5c0dea21d..65d437d0c0d31 100644 --- a/src/test/compile-fail/feature-gate-box-expr.rs +++ b/src/test/compile-fail/feature-gate-box-expr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-box_syntax + // Check that `box EXPR` is feature-gated. // // See also feature-gate-placement-expr.rs diff --git a/src/test/compile-fail/feature-gate-box-pat.rs b/src/test/compile-fail/feature-gate-box-pat.rs index e64081823e74c..c30f3952dbfbe 100644 --- a/src/test/compile-fail/feature-gate-box-pat.rs +++ b/src/test/compile-fail/feature-gate-box-pat.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-box_patterns + fn main() { let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental println!("x: {}", x); diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs index aa479a987a35b..7c290b3c9c262 100644 --- a/src/test/compile-fail/feature-gate-dropck-ugeh.rs +++ b/src/test/compile-fail/feature-gate-dropck-ugeh.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-dropck_parametricity + // Ensure that attempts to use the unsafe attribute are feature-gated. // Example adapted from RFC 1238 text (just left out the feature gate). diff --git a/src/test/compile-fail/feature-gate-may-dangle.rs b/src/test/compile-fail/feature-gate-may-dangle.rs index 23f8ead0ca9dc..0bf1e93d9aace 100644 --- a/src/test/compile-fail/feature-gate-may-dangle.rs +++ b/src/test/compile-fail/feature-gate-may-dangle.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-dropck_eyepatch + // Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent. #![feature(generic_param_attrs)] diff --git a/src/test/compile-fail/feature-gate-placement-expr.rs b/src/test/compile-fail/feature-gate-placement-expr.rs index 080364c08554f..e3478876763b4 100644 --- a/src/test/compile-fail/feature-gate-placement-expr.rs +++ b/src/test/compile-fail/feature-gate-placement-expr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-placement_in_syntax + // Check that `in PLACE { EXPR }` is feature-gated. // // See also feature-gate-box-expr.rs diff --git a/src/test/compile-fail/gated-associated_consts.rs b/src/test/compile-fail/gated-associated_consts.rs index cfa75ff9763e9..ee4422faf3a24 100644 --- a/src/test/compile-fail/gated-associated_consts.rs +++ b/src/test/compile-fail/gated-associated_consts.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-associated_consts + trait MyTrait { const C: bool; //~^ associated constants are experimental diff --git a/src/test/compile-fail/gated-attr-literals.rs b/src/test/compile-fail/gated-attr-literals.rs index f3132d5593e62..04abc44caecd7 100644 --- a/src/test/compile-fail/gated-attr-literals.rs +++ b/src/test/compile-fail/gated-attr-literals.rs @@ -10,6 +10,8 @@ // Check that literals in attributes don't parse without the feature gate. +// gate-test-attr_literals + #![feature(rustc_attrs)] #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/compile-fail/gated-box-syntax.rs index a2643fe02b8f7..9a68ddb305960 100644 --- a/src/test/compile-fail/gated-box-syntax.rs +++ b/src/test/compile-fail/gated-box-syntax.rs @@ -10,6 +10,8 @@ // Test that the use of the box syntax is gated by `box_syntax` feature gate. +// gate-test-box_syntax + fn main() { let x = box 3; //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead. diff --git a/src/test/compile-fail/gated-concat_idents.rs b/src/test/compile-fail/gated-concat_idents.rs index 054e70f382268..af288a9790440 100644 --- a/src/test/compile-fail/gated-concat_idents.rs +++ b/src/test/compile-fail/gated-concat_idents.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-concat_idents + fn main() { concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough } diff --git a/src/test/compile-fail/gated-link-args.rs b/src/test/compile-fail/gated-link-args.rs index 7b1405c913f6b..d34057e290eba 100644 --- a/src/test/compile-fail/gated-link-args.rs +++ b/src/test/compile-fail/gated-link-args.rs @@ -11,6 +11,8 @@ // Test that `#[link_args]` attribute is gated by `link_args` // feature gate. +// gate-test-link_args + #[link_args = "aFdEfSeVEEE"] extern {} //~^ ERROR the `link_args` attribute is not portable across platforms diff --git a/src/test/compile-fail/gated-link-llvm-intrinsics.rs b/src/test/compile-fail/gated-link-llvm-intrinsics.rs index 92a1b071437e6..681824ae71dd0 100644 --- a/src/test/compile-fail/gated-link-llvm-intrinsics.rs +++ b/src/test/compile-fail/gated-link-llvm-intrinsics.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-link_llvm_intrinsics + extern { #[link_name = "llvm.sqrt.f32"] fn sqrt(x: f32) -> f32; diff --git a/src/test/compile-fail/gated-naked_functions.rs b/src/test/compile-fail/gated-naked_functions.rs index ceb475e119217..5eb4118102768 100644 --- a/src/test/compile-fail/gated-naked_functions.rs +++ b/src/test/compile-fail/gated-naked_functions.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-naked_functions + #[naked] //~^ the `#[naked]` attribute is an experimental feature fn naked() {} diff --git a/src/test/compile-fail/gated-no-core.rs b/src/test/compile-fail/gated-no-core.rs index 0a55a8a78ce5a..66b9c2e56705f 100644 --- a/src/test/compile-fail/gated-no-core.rs +++ b/src/test/compile-fail/gated-no-core.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-no_core + #![no_core] //~ ERROR no_core is experimental fn main() {} diff --git a/src/test/compile-fail/gated-non-ascii-idents.rs b/src/test/compile-fail/gated-non-ascii-idents.rs index 9e042c3a7d50e..1dff22839ad87 100644 --- a/src/test/compile-fail/gated-non-ascii-idents.rs +++ b/src/test/compile-fail/gated-non-ascii-idents.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-non_ascii_idents + extern crate core as bäz; //~ ERROR non-ascii idents use föö::bar; //~ ERROR non-ascii idents diff --git a/src/test/compile-fail/gated-plugin_registrar.rs b/src/test/compile-fail/gated-plugin_registrar.rs index 9cdebde7b7b98..8d185d183b419 100644 --- a/src/test/compile-fail/gated-plugin_registrar.rs +++ b/src/test/compile-fail/gated-plugin_registrar.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-plugin_registrar + // Test that `#[plugin_registrar]` attribute is gated by `plugin_registrar` // feature gate. diff --git a/src/test/compile-fail/gated-target_feature.rs b/src/test/compile-fail/gated-target_feature.rs index da2e41a0f5e42..02db8a71d5340 100644 --- a/src/test/compile-fail/gated-target_feature.rs +++ b/src/test/compile-fail/gated-target_feature.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-target_feature + #[target_feature = "+sse2"] //~^ the `#[target_feature]` attribute is an experimental feature fn foo() {} diff --git a/src/test/compile-fail/gated-thread-local.rs b/src/test/compile-fail/gated-thread-local.rs index f355c6562c8b0..b02ce9b7ecb81 100644 --- a/src/test/compile-fail/gated-thread-local.rs +++ b/src/test/compile-fail/gated-thread-local.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-thread_local + // Test that `#[thread_local]` attribute is gated by `thread_local` // feature gate. // diff --git a/src/test/compile-fail/gated-trace_macros.rs b/src/test/compile-fail/gated-trace_macros.rs index 19b08ce655c06..0b85b19f176d7 100644 --- a/src/test/compile-fail/gated-trace_macros.rs +++ b/src/test/compile-fail/gated-trace_macros.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-trace_macros fn main() { trace_macros!(true); //~ ERROR: `trace_macros` is not stable diff --git a/src/test/compile-fail/i128-feature-2.rs b/src/test/compile-fail/i128-feature-2.rs index 4a76d39921842..d3bd810ceb2b4 100644 --- a/src/test/compile-fail/i128-feature-2.rs +++ b/src/test/compile-fail/i128-feature-2.rs @@ -7,6 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +// gate-test-i128_type + fn test1() -> i128 { //~ ERROR 128-bit type is unstable 0 } diff --git a/src/test/compile-fail/i128-feature.rs b/src/test/compile-fail/i128-feature.rs index 87dda469f9390..e94fd14a42163 100644 --- a/src/test/compile-fail/i128-feature.rs +++ b/src/test/compile-fail/i128-feature.rs @@ -7,6 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +// gate-test-i128_type + fn test2() { 0i128; //~ ERROR 128-bit integers are not stable } diff --git a/src/test/compile-fail/impl-trait/feature-gate.rs b/src/test/compile-fail/impl-trait/feature-gate.rs index 8239b06f2b4a3..f171b6becc4b7 100644 --- a/src/test/compile-fail/impl-trait/feature-gate.rs +++ b/src/test/compile-fail/impl-trait/feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-conservative_impl_trait + fn foo() -> impl Fn() { || {} } //~^ ERROR `impl Trait` is experimental diff --git a/src/test/compile-fail/link-cfg-gated.rs b/src/test/compile-fail/link-cfg-gated.rs index 27918a27caf50..bb6fb9e356352 100644 --- a/src/test/compile-fail/link-cfg-gated.rs +++ b/src/test/compile-fail/link-cfg-gated.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-link_cfg + #[link(name = "foo", cfg(foo))] //~^ ERROR: is feature gated extern {} diff --git a/src/test/compile-fail/linkage1.rs b/src/test/compile-fail/linkage1.rs index 555cc2b9a7aad..1cf208f021588 100644 --- a/src/test/compile-fail/linkage1.rs +++ b/src/test/compile-fail/linkage1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-linkage + extern { #[linkage = "extern_weak"] static foo: isize; //~^ ERROR: the `linkage` attribute is experimental and not portable diff --git a/src/test/compile-fail/log-syntax-gate.rs b/src/test/compile-fail/log-syntax-gate.rs index 63c66e53c5ee8..b9688af35dc90 100644 --- a/src/test/compile-fail/log-syntax-gate.rs +++ b/src/test/compile-fail/log-syntax-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-log_syntax + fn main() { log_syntax!() //~ ERROR `log_syntax!` is not stable enough } diff --git a/src/test/compile-fail/log-syntax-gate2.rs b/src/test/compile-fail/log-syntax-gate2.rs index bb19e97ab0fa8..dcbe7eefee52c 100644 --- a/src/test/compile-fail/log-syntax-gate2.rs +++ b/src/test/compile-fail/log-syntax-gate2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-log_syntax + fn main() { println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable } diff --git a/src/test/compile-fail/never-disabled.rs b/src/test/compile-fail/never-disabled.rs index 11b9f412957eb..fb6b34fcbb676 100644 --- a/src/test/compile-fail/never-disabled.rs +++ b/src/test/compile-fail/never-disabled.rs @@ -10,6 +10,8 @@ // Test that ! errors when used in illegal positions with feature(never_type) disabled +// gate-test-never_type + trait Foo { type Wub; } diff --git a/src/test/compile-fail/no-core-gated.rs b/src/test/compile-fail/no-core-gated.rs index dbaa4177e1429..27f8fda98ab34 100644 --- a/src/test/compile-fail/no-core-gated.rs +++ b/src/test/compile-fail/no-core-gated.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-no_core + #![no_core] //~ ERROR no_core is experimental fn main() {} diff --git a/src/test/compile-fail/numeric-fields-feature-gate.rs b/src/test/compile-fail/numeric-fields-feature-gate.rs index 3ce85813a9b51..bd8ec16ef8826 100644 --- a/src/test/compile-fail/numeric-fields-feature-gate.rs +++ b/src/test/compile-fail/numeric-fields-feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-relaxed_adts + struct S(u8); fn main() { diff --git a/src/test/compile-fail/panic-runtime/needs-gate.rs b/src/test/compile-fail/panic-runtime/needs-gate.rs index 02f3da58f1da8..1b3b978c40811 100644 --- a/src/test/compile-fail/panic-runtime/needs-gate.rs +++ b/src/test/compile-fail/panic-runtime/needs-gate.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-needs_panic_runtime +// gate-test-panic_runtime + #![panic_runtime] //~ ERROR: is an experimental feature #![needs_panic_runtime] //~ ERROR: is an experimental feature diff --git a/src/test/compile-fail/privacy/restricted/feature-gate.rs b/src/test/compile-fail/privacy/restricted/feature-gate.rs index 53ae439867f98..e81e1e30d1750 100644 --- a/src/test/compile-fail/privacy/restricted/feature-gate.rs +++ b/src/test/compile-fail/privacy/restricted/feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-pub_restricted + pub(crate) //~ ERROR experimental mod foo {} diff --git a/src/test/compile-fail/rfc1445/feature-gate.rs b/src/test/compile-fail/rfc1445/feature-gate.rs index 1f2d7819e26d8..b51ee3d8b5ed8 100644 --- a/src/test/compile-fail/rfc1445/feature-gate.rs +++ b/src/test/compile-fail/rfc1445/feature-gate.rs @@ -14,6 +14,8 @@ // revisions: with_gate no_gate +// gate-test-structural_match + #![allow(dead_code)] #![deny(future_incompatible)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/single-derive-attr.rs b/src/test/compile-fail/single-derive-attr.rs index 0b1b3141f5bf7..cd37611aceda9 100644 --- a/src/test/compile-fail/single-derive-attr.rs +++ b/src/test/compile-fail/single-derive-attr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-custom_derive + #[derive_Clone] //~^ ERROR attributes of the form `#[derive_*]` are reserved struct Test; diff --git a/src/test/compile-fail/specialization/specialization-feature-gate-default.rs b/src/test/compile-fail/specialization/specialization-feature-gate-default.rs index e7c194ce84df9..3a01ecdf9db6f 100644 --- a/src/test/compile-fail/specialization/specialization-feature-gate-default.rs +++ b/src/test/compile-fail/specialization/specialization-feature-gate-default.rs @@ -10,6 +10,8 @@ // Check that specialization must be ungated to use the `default` keyword +// gate-test-specialization + trait Foo { fn foo(&self); } diff --git a/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs b/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs index d11ab56ff7e87..5eb48eab15e52 100644 --- a/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs +++ b/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs @@ -10,6 +10,8 @@ // Check that writing an overlapping impl is not allow unless specialization is ungated. +// gate-test-specialization + trait Foo { fn foo(&self); } diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs index 9b83c42609aa5..7c37abf765769 100644 --- a/src/test/compile-fail/static-mut-not-constant.rs +++ b/src/test/compile-fail/static-mut-not-constant.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-drop_types_in_const + #![feature(box_syntax)] static mut a: Box = box 3; diff --git a/src/test/compile-fail/struct-field-attr-feature-gate.rs b/src/test/compile-fail/struct-field-attr-feature-gate.rs index 665c3fd67f48f..47495be4ad2c9 100644 --- a/src/test/compile-fail/struct-field-attr-feature-gate.rs +++ b/src/test/compile-fail/struct-field-attr-feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-struct_field_attributes + struct Foo { present: (), } diff --git a/src/test/compile-fail/type-ascription-feature-gate.rs b/src/test/compile-fail/type-ascription-feature-gate.rs index d3c07d653f40c..bf4ca03069c57 100644 --- a/src/test/compile-fail/type-ascription-feature-gate.rs +++ b/src/test/compile-fail/type-ascription-feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-type_ascription + // Type ascription is feature gated fn main() { diff --git a/src/test/compile-fail/unadjusted-unstable.rs b/src/test/compile-fail/unadjusted-unstable.rs index 501f4451ed8d5..2c23050085d88 100644 --- a/src/test/compile-fail/unadjusted-unstable.rs +++ b/src/test/compile-fail/unadjusted-unstable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-abi_unadjusted + extern "unadjusted" fn foo() { //~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable } diff --git a/src/test/compile-fail/union/union-feature-gate.rs b/src/test/compile-fail/union/union-feature-gate.rs index abfc4d909218b..0c2165871f6db 100644 --- a/src/test/compile-fail/union/union-feature-gate.rs +++ b/src/test/compile-fail/union/union-feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-untagged_unions + union U { //~ ERROR unions are unstable and possibly buggy a: u8, } diff --git a/src/test/compile-fail/windows-subsystem-gated.rs b/src/test/compile-fail/windows-subsystem-gated.rs index 4b563e78e55c8..63f891a2af7bf 100644 --- a/src/test/compile-fail/windows-subsystem-gated.rs +++ b/src/test/compile-fail/windows-subsystem-gated.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// gate-test-windows_subsystem + #![windows_subsystem = "console"] //~^ ERROR: the windows subsystem attribute is currently unstable diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index ac5dff0980c08..b0da6647eb900 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -16,6 +16,7 @@ //! * The set of library features is disjoint from the set of language features //! * Library features have at most one stability level //! * Library features have at most one `since` value +//! * All unstable lang features have tests to ensure they are actually unstable use std::collections::HashMap; use std::fmt; @@ -26,6 +27,7 @@ use std::path::Path; #[derive(PartialEq)] enum Status { Stable, + Removed, Unstable, } @@ -34,27 +36,22 @@ impl fmt::Display for Status { let as_str = match *self { Status::Stable => "stable", Status::Unstable => "unstable", + Status::Removed => "removed", }; fmt::Display::fmt(as_str, f) } } - struct Feature { - name: String, - level: Status, - since: String, -} - -struct LibFeature { level: Status, since: String, + has_gate_test: bool, } pub fn check(path: &Path, bad: &mut bool) { - let features = collect_lang_features(&path.join("libsyntax/feature_gate.rs")); + let mut features = collect_lang_features(&path.join("libsyntax/feature_gate.rs")); assert!(!features.is_empty()); - let mut lib_features = HashMap::::new(); + let mut lib_features = HashMap::::new(); let mut contents = String::new(); super::walk(path, @@ -97,7 +94,7 @@ pub fn check(path: &Path, bad: &mut bool) { None => "None", }; - if features.iter().any(|f| f.name == feature_name) { + if features.contains_key(feature_name) { err("duplicating a lang feature"); } if let Some(ref s) = lib_features.get(feature_name) { @@ -110,21 +107,105 @@ pub fn check(path: &Path, bad: &mut bool) { continue; } lib_features.insert(feature_name.to_owned(), - LibFeature { + Feature { level: level, since: since.to_owned(), + has_gate_test: false, }); } }); + super::walk(&path.join("test/compile-fail"), + &mut |path| super::filter_dirs(path), + &mut |file| { + let filename = file.file_name().unwrap().to_string_lossy(); + if !filename.ends_with(".rs") || filename == "features.rs" || + filename == "diagnostic_list.rs" { + return; + } + + let filen_underscore = filename.replace("-","_").replace(".rs",""); + test_filen_gate(&filen_underscore, &mut features); + + contents.truncate(0); + t!(t!(File::open(&file), &file).read_to_string(&mut contents)); + + for (i, line) in contents.lines().enumerate() { + let mut err = |msg: &str| { + println!("{}:{}: {}", file.display(), i + 1, msg); + *bad = true; + }; + + let gate_test_str = "gate-test-"; + + if !line.contains(gate_test_str) { + continue; + } + + let feature_name = match line.find(gate_test_str) { + Some(i) => { + &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())] + }, + None => continue, + }; + let found_feature = features.get_mut(feature_name) + .map(|v| { v.has_gate_test = true; () }) + .is_some(); + + let found_lib_feature = features.get_mut(feature_name) + .map(|v| { v.has_gate_test = true; () }) + .is_some(); + + if !(found_feature || found_lib_feature) { + err(&format!("gate-test test found referencing a nonexistent feature '{}'", + feature_name)); + } + } + }); + + // FIXME get this whitelist empty. + let whitelist = vec![ + "abi_ptx", "simd", "safe_suggestion", "macro_reexport", + "more_struct_aliases", "static_recursion", "reflect", + "quote", "cfg_target_has_atomic", "custom_attribute", + "default_type_parameter_fallback", "pushpop_unsafe", + "use_extern_macros", "staged_api", "const_indexing", + "unboxed_closures", "stmt_expr_attributes", + "cfg_target_thread_local", "unwind_attributes", + "inclusive_range_syntax" + ]; + + // Only check the number of lang features. + // Obligatory testing for library features is dumb. + let gate_untested = features.iter() + .filter(|&(_, f)| f.level == Status::Unstable) + .filter(|&(_, f)| !f.has_gate_test) + .filter(|&(n, _)| !whitelist.contains(&n.as_str())) + .collect::>(); + + for &(name, _) in gate_untested.iter() { + println!("Expected a gate test for the feature '{}'.", name); + println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\ + \n test suite, with its failures due to missing usage of\ + \n #![feature({})].", name, name); + println!("Hint: If you already have such a test and don't want to rename it,\ + \n you can also add a // gate-test-{} line to the test file.", + name); + } + + if gate_untested.len() > 0 { + println!("Found {} features without a gate test.", gate_untested.len()); + *bad = true; + } + if *bad { return; } let mut lines = Vec::new(); - for feature in features { + for (name, feature) in features.iter() { lines.push(format!("{:<32} {:<8} {:<12} {:<8}", - feature.name, + name, "lang", feature.level, feature.since)); @@ -150,7 +231,20 @@ fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> { .map(|(i, j)| &line[i..j]) } -fn collect_lang_features(path: &Path) -> Vec { +fn test_filen_gate(filen_underscore: &str, + features: &mut HashMap) -> bool { + if filen_underscore.starts_with("feature_gate") { + for (n, f) in features.iter_mut() { + if filen_underscore == format!("feature_gate_{}", n) { + f.has_gate_test = true; + return true; + } + } + } + return false; +} + +fn collect_lang_features(path: &Path) -> HashMap { let mut contents = String::new(); t!(t!(File::open(path)).read_to_string(&mut contents)); @@ -159,17 +253,18 @@ fn collect_lang_features(path: &Path) -> Vec { let mut parts = line.trim().split(","); let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) { Some("active") => Status::Unstable, - Some("removed") => Status::Unstable, + Some("removed") => Status::Removed, Some("accepted") => Status::Stable, _ => return None, }; let name = parts.next().unwrap().trim(); let since = parts.next().unwrap().trim().trim_matches('"'); - Some(Feature { - name: name.to_owned(), - level: level, - since: since.to_owned(), - }) + Some((name.to_owned(), + Feature { + level: level, + since: since.to_owned(), + has_gate_test: false, + })) }) .collect() }