From e7fe5456c53a8cc620a10f6284c366d6de0b7df0 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 11 Apr 2022 18:12:26 -0700 Subject: [PATCH] Support unstable moves via stable in unstable items --- compiler/rustc_middle/src/middle/stability.rs | 17 +++++-- compiler/rustc_passes/src/stability.rs | 29 +++++++++++- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- library/core/src/intrinsics.rs | 1 + library/core/src/unicode/mod.rs | 5 +- library/std/src/lib.rs | 3 +- library/std/src/panic.rs | 2 +- .../codegen/intrinsics/const_eval_select.rs | 1 + .../ui/intrinsics/const-eval-select-bad.rs | 1 + .../intrinsics/const-eval-select-bad.stderr | 26 +++++++++-- .../intrinsics/const-eval-select-stability.rs | 1 + .../const-eval-select-stability.stderr | 2 +- .../ui/intrinsics/const-eval-select-x86_64.rs | 1 + src/test/ui/intrinsics/const-eval-select.rs | 1 + src/test/ui/lint/lint-stability.rs | 4 +- src/test/ui/lint/lint-stability.stderr | 18 +++++++- .../auxiliary/stable-in-unstable-core.rs | 8 ++++ .../auxiliary/stable-in-unstable-std.rs | 11 +++++ .../stability-attribute/stable-in-unstable.rs | 46 +++++++++++++++++++ .../stable-in-unstable.stderr | 39 ++++++++++++++++ 20 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs create mode 100644 src/test/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs create mode 100644 src/test/ui/stability-attribute/stable-in-unstable.rs create mode 100644 src/test/ui/stability-attribute/stable-in-unstable.stderr diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 802b7852bac..9f00c6ac112 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -471,13 +471,15 @@ impl<'tcx> TyCtxt<'tcx> { /// /// 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. + /// + /// Returns `true` if item is allowed aka, stable or unstable under an enabled feature. pub fn check_stability( self, def_id: DefId, id: Option, span: Span, method_span: Option, - ) { + ) -> bool { self.check_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No) } @@ -497,7 +499,7 @@ impl<'tcx> TyCtxt<'tcx> { span: Span, method_span: Option, allow_unstable: AllowUnstable, - ) { + ) -> bool { self.check_optional_stability( def_id, id, @@ -516,6 +518,8 @@ impl<'tcx> TyCtxt<'tcx> { /// missing stability attributes (not necessarily just emit a `bug!`). This is necessary /// for default generic parameters, which only have stability attributes if they were /// 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( self, def_id: DefId, @@ -524,13 +528,16 @@ impl<'tcx> TyCtxt<'tcx> { method_span: Option, allow_unstable: AllowUnstable, unmarked: impl FnOnce(Span, DefId), - ) { + ) -> bool { let soft_handler = |lint, span, msg: &_| { self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| { 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::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable( self.sess, @@ -544,6 +551,8 @@ impl<'tcx> TyCtxt<'tcx> { ), EvalResult::Unmarked => unmarked(span, def_id), } + + is_allowed } pub fn lookup_deprecation(self, id: DefId) -> Option { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 12050dceb60..df6051bb59a 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -807,7 +807,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { 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, Some(id), path.span, @@ -817,8 +817,33 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } else { 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) } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 0a2b54eec47..b5b90b389d9 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -439,7 +439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // as the rest of the type. As such, we ignore missing // stability attributes. }, - ) + ); } if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) { self.inferred_params.push(ty.span); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 2895c923adc..cb6f42f1cc0 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2649,6 +2649,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { /// Here is an example of how this could cause a problem: /// ```no_run /// #![feature(const_eval_select)] +/// #![feature(core_intrinsics)] /// use std::hint::unreachable_unchecked; /// use std::intrinsics::const_eval_select; /// diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 72fa059b787..e8b888c9507 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -1,7 +1,9 @@ -#![unstable(feature = "unicode_internals", issue = "none")] +#![stable(feature = "unicode_version", since = "1.45.0")] #![allow(missing_docs)] +#[unstable(feature = "unicode_internals", issue = "none")] pub(crate) mod printable; +#[unstable(feature = "unicode_internals", issue = "none")] mod unicode_data; /// 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; // For use in liballoc, not re-exported in libstd. +#[unstable(feature = "unicode_internals", issue = "none")] pub use unicode_data::{ case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions, }; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 298321f41e4..8bd597d49aa 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -214,7 +214,7 @@ #![cfg_attr(not(bootstrap), deny(ffi_unwind_calls))] // std may use features in a platform-specific way #![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( all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) @@ -297,6 +297,7 @@ // Library features (alloc): #![feature(alloc_layout_extra)] #![feature(alloc_c_string)] +#![feature(alloc_ffi)] #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(map_try_insert)] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index ac16f476143..45bc56efb3b 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -11,7 +11,7 @@ use crate::thread::Result; #[doc(hidden)] #[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")] #[rustc_macro_transparency = "semitransparent"] pub macro panic_2015 { diff --git a/src/test/codegen/intrinsics/const_eval_select.rs b/src/test/codegen/intrinsics/const_eval_select.rs index 34e653b4b9d..db8a04763d3 100644 --- a/src/test/codegen/intrinsics/const_eval_select.rs +++ b/src/test/codegen/intrinsics/const_eval_select.rs @@ -2,6 +2,7 @@ #![crate_type = "lib"] #![feature(const_eval_select)] +#![feature(core_intrinsics)] use std::intrinsics::const_eval_select; diff --git a/src/test/ui/intrinsics/const-eval-select-bad.rs b/src/test/ui/intrinsics/const-eval-select-bad.rs index 7d924e2b7f3..52f4e594f1a 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.rs +++ b/src/test/ui/intrinsics/const-eval-select-bad.rs @@ -1,4 +1,5 @@ #![feature(const_eval_select)] +#![feature(core_intrinsics)] use std::intrinsics::const_eval_select; diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 1d3bff3a724..bdd5b700a92 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -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 --> $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((), || {}, || {}); | ^^^^^ = 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` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | @@ -20,7 +38,7 @@ LL | F: ~const FnOnce, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` 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); | ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}` @@ -36,7 +54,7 @@ LL | F: ~const FnOnce, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` 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); | ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}` @@ -52,7 +70,7 @@ LL | G: FnOnce + ~const Destruct, | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0271]: type mismatch resolving ` 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); | ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool` @@ -64,7 +82,7 @@ LL | G: FnOnce + ~const Destruct, | ^^^^^^^^^^^^ required by this bound in `const_eval_select` 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 { | --------------------------- found signature of `fn(i32) -> _` diff --git a/src/test/ui/intrinsics/const-eval-select-stability.rs b/src/test/ui/intrinsics/const-eval-select-stability.rs index db2462aee59..f9554decec1 100644 --- a/src/test/ui/intrinsics/const-eval-select-stability.rs +++ b/src/test/ui/intrinsics/const-eval-select-stability.rs @@ -1,5 +1,6 @@ #![feature(staged_api)] #![feature(const_eval_select)] +#![feature(core_intrinsics)] #![stable(since = "1.0", feature = "ui_test")] use std::intrinsics::const_eval_select; diff --git a/src/test/ui/intrinsics/const-eval-select-stability.stderr b/src/test/ui/intrinsics/const-eval-select-stability.stderr index 79641bbb46a..65b507b887b 100644 --- a/src/test/ui/intrinsics/const-eval-select-stability.stderr +++ b/src/test/ui/intrinsics/const-eval-select-stability.stderr @@ -1,5 +1,5 @@ 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); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/intrinsics/const-eval-select-x86_64.rs b/src/test/ui/intrinsics/const-eval-select-x86_64.rs index afec8e054bb..f3924acf0fa 100644 --- a/src/test/ui/intrinsics/const-eval-select-x86_64.rs +++ b/src/test/ui/intrinsics/const-eval-select-x86_64.rs @@ -2,6 +2,7 @@ // only-x86_64 #![feature(const_eval_select)] +#![feature(core_intrinsics)] use std::intrinsics::const_eval_select; use std::arch::x86_64::*; use std::mem::transmute; diff --git a/src/test/ui/intrinsics/const-eval-select.rs b/src/test/ui/intrinsics/const-eval-select.rs index 744db2f15b0..9ff20d3fbdd 100644 --- a/src/test/ui/intrinsics/const-eval-select.rs +++ b/src/test/ui/intrinsics/const-eval-select.rs @@ -1,6 +1,7 @@ // run-pass #![feature(const_eval_select)] +#![feature(core_intrinsics)] use std::intrinsics::const_eval_select; diff --git a/src/test/ui/lint/lint-stability.rs b/src/test/ui/lint/lint-stability.rs index 464b32c5f43..d0f0e9f8071 100644 --- a/src/test/ui/lint/lint-stability.rs +++ b/src/test/ui/lint/lint-stability.rs @@ -191,11 +191,11 @@ mod inheritance { stable_mod::unstable(); //~ ERROR use of unstable library feature stable_mod::stable(); - unstable_mod::deprecated(); + unstable_mod::deprecated(); //~ 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::StableVariant; + let _ = Unstable::StableVariant; //~ ERROR use of unstable library feature let x: usize = 0; x.stable(); diff --git a/src/test/ui/lint/lint-stability.stderr b/src/test/ui/lint/lint-stability.stderr index 167140ef92b..bd1a57dc4cc 100644 --- a/src/test/ui/lint/lint-stability.stderr +++ b/src/test/ui/lint/lint-stability.stderr @@ -294,6 +294,14 @@ LL | stable_mod::unstable(); | = 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' --> $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 +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' --> $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 -error: aborting due to 41 previous errors +error: aborting due to 43 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs b/src/test/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs new file mode 100644 index 00000000000..e45b00f994a --- /dev/null +++ b/src/test/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs @@ -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 {} +} diff --git a/src/test/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs b/src/test/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs new file mode 100644 index 00000000000..28ad8c28da1 --- /dev/null +++ b/src/test/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs @@ -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; +} diff --git a/src/test/ui/stability-attribute/stable-in-unstable.rs b/src/test/ui/stability-attribute/stable-in-unstable.rs new file mode 100644 index 00000000000..272a1a97234 --- /dev/null +++ b/src/test/ui/stability-attribute/stable-in-unstable.rs @@ -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 {} +} diff --git a/src/test/ui/stability-attribute/stable-in-unstable.stderr b/src/test/ui/stability-attribute/stable-in-unstable.stderr new file mode 100644 index 00000000000..e123d83584c --- /dev/null +++ b/src/test/ui/stability-attribute/stable-in-unstable.stderr @@ -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 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 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 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 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`.