Support unstable moves via stable in unstable items

This commit is contained in:
Jane Lusby 2022-04-11 18:12:26 -07:00 committed by Jane Losare-Lusby
parent 052495d001
commit e7fe5456c5
20 changed files with 200 additions and 18 deletions

View File

@ -471,13 +471,15 @@ impl<'tcx> TyCtxt<'tcx> {
/// ///
/// This function will also check if the item is deprecated. /// This function will also check if the item is deprecated.
/// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted. /// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted.
///
/// Returns `true` if item is allowed aka, stable or unstable under an enabled feature.
pub fn check_stability( pub fn check_stability(
self, self,
def_id: DefId, def_id: DefId,
id: Option<HirId>, id: Option<HirId>,
span: Span, span: Span,
method_span: Option<Span>, method_span: Option<Span>,
) { ) -> bool {
self.check_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No) self.check_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No)
} }
@ -497,7 +499,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Span, span: Span,
method_span: Option<Span>, method_span: Option<Span>,
allow_unstable: AllowUnstable, allow_unstable: AllowUnstable,
) { ) -> bool {
self.check_optional_stability( self.check_optional_stability(
def_id, def_id,
id, id,
@ -516,6 +518,8 @@ impl<'tcx> TyCtxt<'tcx> {
/// missing stability attributes (not necessarily just emit a `bug!`). This is necessary /// missing stability attributes (not necessarily just emit a `bug!`). This is necessary
/// for default generic parameters, which only have stability attributes if they were /// for default generic parameters, which only have stability attributes if they were
/// added after the type on which they're defined. /// added after the type on which they're defined.
///
/// Returns `true` if item is allowed aka, stable or unstable under an enabled feature.
pub fn check_optional_stability( pub fn check_optional_stability(
self, self,
def_id: DefId, def_id: DefId,
@ -524,13 +528,16 @@ impl<'tcx> TyCtxt<'tcx> {
method_span: Option<Span>, method_span: Option<Span>,
allow_unstable: AllowUnstable, allow_unstable: AllowUnstable,
unmarked: impl FnOnce(Span, DefId), unmarked: impl FnOnce(Span, DefId),
) { ) -> bool {
let soft_handler = |lint, span, msg: &_| { let soft_handler = |lint, span, msg: &_| {
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| { self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
lint.build(msg).emit(); lint.build(msg).emit();
}) })
}; };
match self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable) { let eval_result =
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
let is_allowed = matches!(eval_result, EvalResult::Allow);
match eval_result {
EvalResult::Allow => {} EvalResult::Allow => {}
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable( EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable(
self.sess, self.sess,
@ -544,6 +551,8 @@ impl<'tcx> TyCtxt<'tcx> {
), ),
EvalResult::Unmarked => unmarked(span, def_id), EvalResult::Unmarked => unmarked(span, def_id),
} }
is_allowed
} }
pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> { pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {

View File

@ -807,7 +807,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) { fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
if let Some(def_id) = path.res.opt_def_id() { if let Some(def_id) = path.res.opt_def_id() {
let method_span = path.segments.last().map(|s| s.ident.span); let method_span = path.segments.last().map(|s| s.ident.span);
self.tcx.check_stability_allow_unstable( let item_is_allowed = self.tcx.check_stability_allow_unstable(
def_id, def_id,
Some(id), Some(id),
path.span, path.span,
@ -817,8 +817,33 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
} else { } else {
AllowUnstable::No AllowUnstable::No
}, },
) );
if item_is_allowed {
// Check parent modules stability as well
//
// We check here rather than in `visit_path_segment` to prevent visiting the last
// path segment twice
let parents = path.segments.iter().rev().skip(1);
for path_segment in parents {
if let Some(def_id) = path_segment.res.as_ref().and_then(Res::opt_def_id) {
// use `None` for id to prevent deprecation check
self.tcx.check_stability_allow_unstable(
def_id,
None,
path.span,
None,
if is_unstable_reexport(self.tcx, id) {
AllowUnstable::Yes
} else {
AllowUnstable::No
},
)
}
}
}
} }
intravisit::walk_path(self, path) intravisit::walk_path(self, path)
} }
} }

View File

@ -439,7 +439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// as the rest of the type. As such, we ignore missing // as the rest of the type. As such, we ignore missing
// stability attributes. // stability attributes.
}, },
) );
} }
if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) { if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
self.inferred_params.push(ty.span); self.inferred_params.push(ty.span);

View File

@ -2649,6 +2649,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
/// Here is an example of how this could cause a problem: /// Here is an example of how this could cause a problem:
/// ```no_run /// ```no_run
/// #![feature(const_eval_select)] /// #![feature(const_eval_select)]
/// #![feature(core_intrinsics)]
/// use std::hint::unreachable_unchecked; /// use std::hint::unreachable_unchecked;
/// use std::intrinsics::const_eval_select; /// use std::intrinsics::const_eval_select;
/// ///

View File

@ -1,7 +1,9 @@
#![unstable(feature = "unicode_internals", issue = "none")] #![stable(feature = "unicode_version", since = "1.45.0")]
#![allow(missing_docs)] #![allow(missing_docs)]
#[unstable(feature = "unicode_internals", issue = "none")]
pub(crate) mod printable; pub(crate) mod printable;
#[unstable(feature = "unicode_internals", issue = "none")]
mod unicode_data; mod unicode_data;
/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
@ -18,6 +20,7 @@ mod unicode_data;
pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION;
// For use in liballoc, not re-exported in libstd. // For use in liballoc, not re-exported in libstd.
#[unstable(feature = "unicode_internals", issue = "none")]
pub use unicode_data::{ pub use unicode_data::{
case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions, case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions,
}; };

View File

@ -214,7 +214,7 @@
#![cfg_attr(not(bootstrap), deny(ffi_unwind_calls))] #![cfg_attr(not(bootstrap), deny(ffi_unwind_calls))]
// std may use features in a platform-specific way // std may use features in a platform-specific way
#![allow(unused_features)] #![allow(unused_features)]
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))]
#![cfg_attr( #![cfg_attr(
all(target_vendor = "fortanix", target_env = "sgx"), all(target_vendor = "fortanix", target_env = "sgx"),
feature(slice_index_methods, coerce_unsized, sgx_platform) feature(slice_index_methods, coerce_unsized, sgx_platform)
@ -297,6 +297,7 @@
// Library features (alloc): // Library features (alloc):
#![feature(alloc_layout_extra)] #![feature(alloc_layout_extra)]
#![feature(alloc_c_string)] #![feature(alloc_c_string)]
#![feature(alloc_ffi)]
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(get_mut_unchecked)] #![feature(get_mut_unchecked)]
#![feature(map_try_insert)] #![feature(map_try_insert)]

View File

@ -11,7 +11,7 @@ use crate::thread::Result;
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)] #[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic, rt)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")] #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
#[rustc_macro_transparency = "semitransparent"] #[rustc_macro_transparency = "semitransparent"]
pub macro panic_2015 { pub macro panic_2015 {

View File

@ -2,6 +2,7 @@
#![crate_type = "lib"] #![crate_type = "lib"]
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(core_intrinsics)]
use std::intrinsics::const_eval_select; use std::intrinsics::const_eval_select;

View File

@ -1,4 +1,5 @@
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(core_intrinsics)]
use std::intrinsics::const_eval_select; use std::intrinsics::const_eval_select;

View File

@ -1,3 +1,4 @@
<<<<<<< HEAD
error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]: ~const FnOnce<()>` is not satisfied error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]: ~const FnOnce<()>` is not satisfied
--> $DIR/const-eval-select-bad.rs:6:27 --> $DIR/const-eval-select-bad.rs:6:27
| |
@ -13,6 +14,23 @@ note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select
LL | const_eval_select((), || {}, || {}); LL | const_eval_select((), || {}, || {});
| ^^^^^ | ^^^^^
= note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]` in a closure with no arguments: `|| { /* code */ }` = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]` in a closure with no arguments: `|| { /* code */ }`
=======
error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]: ~const FnOnce<()>` is not satisfied
--> $DIR/const-eval-select-bad.rs:7:27
|
LL | const_eval_select((), || {}, || {});
| ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]`
| |
| required by a bound introduced by this call
|
= help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]`
note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]`, but that implementation is not `const`
--> $DIR/const-eval-select-bad.rs:7:27
|
LL | const_eval_select((), || {}, || {});
| ^^^^^
= note: wrap the `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]` in a closure with no arguments: `|| { /* code */ }`
>>>>>>> c1798b7c60e... Support unstable moves via stable in unstable items
note: required by a bound in `const_eval_select` note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
| |
@ -20,7 +38,7 @@ LL | F: ~const FnOnce<ARG, Output = RET>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0277]: the trait bound `{integer}: ~const FnOnce<()>` is not satisfied error[E0277]: the trait bound `{integer}: ~const FnOnce<()>` is not satisfied
--> $DIR/const-eval-select-bad.rs:8:27 --> $DIR/const-eval-select-bad.rs:9:27
| |
LL | const_eval_select((), 42, 0xDEADBEEF); LL | const_eval_select((), 42, 0xDEADBEEF);
| ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}` | ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}`
@ -36,7 +54,7 @@ LL | F: ~const FnOnce<ARG, Output = RET>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
--> $DIR/const-eval-select-bad.rs:8:31 --> $DIR/const-eval-select-bad.rs:9:31
| |
LL | const_eval_select((), 42, 0xDEADBEEF); LL | const_eval_select((), 42, 0xDEADBEEF);
| ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}` | ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
@ -52,7 +70,7 @@ LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32` error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32`
--> $DIR/const-eval-select-bad.rs:28:5 --> $DIR/const-eval-select-bad.rs:29:5
| |
LL | const_eval_select((1,), foo, bar); LL | const_eval_select((1,), foo, bar);
| ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool` | ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool`
@ -64,7 +82,7 @@ LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
| ^^^^^^^^^^^^ required by this bound in `const_eval_select` | ^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0631]: type mismatch in function arguments error[E0631]: type mismatch in function arguments
--> $DIR/const-eval-select-bad.rs:33:32 --> $DIR/const-eval-select-bad.rs:34:32
| |
LL | const fn foo(n: i32) -> i32 { LL | const fn foo(n: i32) -> i32 {
| --------------------------- found signature of `fn(i32) -> _` | --------------------------- found signature of `fn(i32) -> _`

View File

@ -1,5 +1,6 @@
#![feature(staged_api)] #![feature(staged_api)]
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(core_intrinsics)]
#![stable(since = "1.0", feature = "ui_test")] #![stable(since = "1.0", feature = "ui_test")]
use std::intrinsics::const_eval_select; use std::intrinsics::const_eval_select;

View File

@ -1,5 +1,5 @@
error: `const_eval_select` is not yet stable as a const fn error: `const_eval_select` is not yet stable as a const fn
--> $DIR/const-eval-select-stability.rs:16:5 --> $DIR/const-eval-select-stability.rs:17:5
| |
LL | const_eval_select((), nothing, log); LL | const_eval_select((), nothing, log);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -2,6 +2,7 @@
// only-x86_64 // only-x86_64
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(core_intrinsics)]
use std::intrinsics::const_eval_select; use std::intrinsics::const_eval_select;
use std::arch::x86_64::*; use std::arch::x86_64::*;
use std::mem::transmute; use std::mem::transmute;

View File

@ -1,6 +1,7 @@
// run-pass // run-pass
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(core_intrinsics)]
use std::intrinsics::const_eval_select; use std::intrinsics::const_eval_select;

View File

@ -191,11 +191,11 @@ mod inheritance {
stable_mod::unstable(); //~ ERROR use of unstable library feature stable_mod::unstable(); //~ ERROR use of unstable library feature
stable_mod::stable(); stable_mod::stable();
unstable_mod::deprecated(); unstable_mod::deprecated(); //~ ERROR use of unstable library feature
unstable_mod::unstable(); //~ ERROR use of unstable library feature unstable_mod::unstable(); //~ ERROR use of unstable library feature
let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature
let _ = Unstable::StableVariant; let _ = Unstable::StableVariant; //~ ERROR use of unstable library feature
let x: usize = 0; let x: usize = 0;
x.stable(); x.stable();

View File

@ -294,6 +294,14 @@ LL | stable_mod::unstable();
| |
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/lint-stability.rs:194:9
|
LL | unstable_mod::deprecated();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature' error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/lint-stability.rs:195:9 --> $DIR/lint-stability.rs:195:9
| |
@ -310,6 +318,14 @@ LL | let _ = Unstable::UnstableVariant;
| |
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/lint-stability.rs:198:17
|
LL | let _ = Unstable::StableVariant;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature' error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/lint-stability.rs:88:48 --> $DIR/lint-stability.rs:88:48
| |
@ -326,6 +342,6 @@ LL | TypeUnstable = u8,
| |
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error: aborting due to 41 previous errors error: aborting due to 43 previous errors
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,8 @@
#![feature(staged_api)]
#![stable(feature = "stable_test_feature", since = "1.2.0")]
#[unstable(feature = "unstable_test_feature", issue = "1")]
pub mod new_unstable_module {
#[stable(feature = "stable_test_feature", since = "1.2.0")]
pub trait OldTrait {}
}

View File

@ -0,0 +1,11 @@
#![feature(staged_api)]
#![feature(unstable_test_feature)]
#![stable(feature = "stable_test_feature", since = "1.2.0")]
extern crate stable_in_unstable_core;
#[stable(feature = "stable_test_feature", since = "1.2.0")]
pub mod old_stable_module {
#[stable(feature = "stable_test_feature", since = "1.2.0")]
pub use stable_in_unstable_core::new_unstable_module::OldTrait;
}

View File

@ -0,0 +1,46 @@
// This test is meant to test that we can have a stable item in an unstable module, and that
// calling that item through the unstable module is unstable, but that re-exporting it from another
// crate in a stable module is fine.
//
// This is necessary to support moving items from `std` into `core` or `alloc` unstably while still
// exporting the original stable interface in `std`, such as moving `Error` into `core`.
//
// aux-build:stable-in-unstable-core.rs
// aux-build:stable-in-unstable-std.rs
#![crate_type = "lib"]
extern crate stable_in_unstable_core;
extern crate stable_in_unstable_std;
mod isolated1 {
use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature 'unstable_test_feature'
use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature'
}
mod isolated2 {
use stable_in_unstable_std::old_stable_module::OldTrait;
struct LocalType;
impl OldTrait for LocalType {}
}
mod isolated3 {
use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature'
struct LocalType;
impl OldTrait for LocalType {}
}
mod isolated4 {
struct LocalType;
impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature 'unstable_test_feature'
}
mod isolated5 {
struct LocalType;
impl stable_in_unstable_std::old_stable_module::OldTrait for LocalType {}
}

View File

@ -0,0 +1,39 @@
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/stable-in-unstable.rs:16:9
|
LL | use stable_in_unstable_core::new_unstable_module;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/stable-in-unstable.rs:17:9
|
LL | use stable_in_unstable_core::new_unstable_module::OldTrait;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/stable-in-unstable.rs:29:9
|
LL | use stable_in_unstable_core::new_unstable_module::OldTrait;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/stable-in-unstable.rs:39:10
|
LL | impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.