Skip to content

Commit e7fe545

Browse files
committed
Support unstable moves via stable in unstable items
1 parent 052495d commit e7fe545

File tree

20 files changed

+200
-18
lines changed

20 files changed

+200
-18
lines changed

compiler/rustc_middle/src/middle/stability.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,13 +471,15 @@ impl<'tcx> TyCtxt<'tcx> {
471471
///
472472
/// This function will also check if the item is deprecated.
473473
/// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted.
474+
///
475+
/// Returns `true` if item is allowed aka, stable or unstable under an enabled feature.
474476
pub fn check_stability(
475477
self,
476478
def_id: DefId,
477479
id: Option<HirId>,
478480
span: Span,
479481
method_span: Option<Span>,
480-
) {
482+
) -> bool {
481483
self.check_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No)
482484
}
483485

@@ -497,7 +499,7 @@ impl<'tcx> TyCtxt<'tcx> {
497499
span: Span,
498500
method_span: Option<Span>,
499501
allow_unstable: AllowUnstable,
500-
) {
502+
) -> bool {
501503
self.check_optional_stability(
502504
def_id,
503505
id,
@@ -516,6 +518,8 @@ impl<'tcx> TyCtxt<'tcx> {
516518
/// missing stability attributes (not necessarily just emit a `bug!`). This is necessary
517519
/// for default generic parameters, which only have stability attributes if they were
518520
/// added after the type on which they're defined.
521+
///
522+
/// Returns `true` if item is allowed aka, stable or unstable under an enabled feature.
519523
pub fn check_optional_stability(
520524
self,
521525
def_id: DefId,
@@ -524,13 +528,16 @@ impl<'tcx> TyCtxt<'tcx> {
524528
method_span: Option<Span>,
525529
allow_unstable: AllowUnstable,
526530
unmarked: impl FnOnce(Span, DefId),
527-
) {
531+
) -> bool {
528532
let soft_handler = |lint, span, msg: &_| {
529533
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
530534
lint.build(msg).emit();
531535
})
532536
};
533-
match self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable) {
537+
let eval_result =
538+
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
539+
let is_allowed = matches!(eval_result, EvalResult::Allow);
540+
match eval_result {
534541
EvalResult::Allow => {}
535542
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable(
536543
self.sess,
@@ -544,6 +551,8 @@ impl<'tcx> TyCtxt<'tcx> {
544551
),
545552
EvalResult::Unmarked => unmarked(span, def_id),
546553
}
554+
555+
is_allowed
547556
}
548557

549558
pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {

compiler/rustc_passes/src/stability.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
807807
fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
808808
if let Some(def_id) = path.res.opt_def_id() {
809809
let method_span = path.segments.last().map(|s| s.ident.span);
810-
self.tcx.check_stability_allow_unstable(
810+
let item_is_allowed = self.tcx.check_stability_allow_unstable(
811811
def_id,
812812
Some(id),
813813
path.span,
@@ -817,8 +817,33 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
817817
} else {
818818
AllowUnstable::No
819819
},
820-
)
820+
);
821+
822+
if item_is_allowed {
823+
// Check parent modules stability as well
824+
//
825+
// We check here rather than in `visit_path_segment` to prevent visiting the last
826+
// path segment twice
827+
let parents = path.segments.iter().rev().skip(1);
828+
for path_segment in parents {
829+
if let Some(def_id) = path_segment.res.as_ref().and_then(Res::opt_def_id) {
830+
// use `None` for id to prevent deprecation check
831+
self.tcx.check_stability_allow_unstable(
832+
def_id,
833+
None,
834+
path.span,
835+
None,
836+
if is_unstable_reexport(self.tcx, id) {
837+
AllowUnstable::Yes
838+
} else {
839+
AllowUnstable::No
840+
},
841+
)
842+
}
843+
}
844+
}
821845
}
846+
822847
intravisit::walk_path(self, path)
823848
}
824849
}

compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
439439
// as the rest of the type. As such, we ignore missing
440440
// stability attributes.
441441
},
442-
)
442+
);
443443
}
444444
if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
445445
self.inferred_params.push(ty.span);

library/core/src/intrinsics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,6 +2649,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
26492649
/// Here is an example of how this could cause a problem:
26502650
/// ```no_run
26512651
/// #![feature(const_eval_select)]
2652+
/// #![feature(core_intrinsics)]
26522653
/// use std::hint::unreachable_unchecked;
26532654
/// use std::intrinsics::const_eval_select;
26542655
///

library/core/src/unicode/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
#![unstable(feature = "unicode_internals", issue = "none")]
1+
#![stable(feature = "unicode_version", since = "1.45.0")]
22
#![allow(missing_docs)]
33

4+
#[unstable(feature = "unicode_internals", issue = "none")]
45
pub(crate) mod printable;
6+
#[unstable(feature = "unicode_internals", issue = "none")]
57
mod unicode_data;
68

79
/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of
@@ -18,6 +20,7 @@ mod unicode_data;
1820
pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION;
1921

2022
// For use in liballoc, not re-exported in libstd.
23+
#[unstable(feature = "unicode_internals", issue = "none")]
2124
pub use unicode_data::{
2225
case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions,
2326
};

library/std/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@
214214
#![cfg_attr(not(bootstrap), deny(ffi_unwind_calls))]
215215
// std may use features in a platform-specific way
216216
#![allow(unused_features)]
217-
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))]
217+
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))]
218218
#![cfg_attr(
219219
all(target_vendor = "fortanix", target_env = "sgx"),
220220
feature(slice_index_methods, coerce_unsized, sgx_platform)
@@ -297,6 +297,7 @@
297297
// Library features (alloc):
298298
#![feature(alloc_layout_extra)]
299299
#![feature(alloc_c_string)]
300+
#![feature(alloc_ffi)]
300301
#![feature(allocator_api)]
301302
#![feature(get_mut_unchecked)]
302303
#![feature(map_try_insert)]

library/std/src/panic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::thread::Result;
1111

1212
#[doc(hidden)]
1313
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
14-
#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)]
14+
#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic, rt)]
1515
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
1616
#[rustc_macro_transparency = "semitransparent"]
1717
pub macro panic_2015 {

src/test/codegen/intrinsics/const_eval_select.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![crate_type = "lib"]
44
#![feature(const_eval_select)]
5+
#![feature(core_intrinsics)]
56

67
use std::intrinsics::const_eval_select;
78

src/test/ui/intrinsics/const-eval-select-bad.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![feature(const_eval_select)]
2+
#![feature(core_intrinsics)]
23

34
use std::intrinsics::const_eval_select;
45

src/test/ui/intrinsics/const-eval-select-bad.stderr

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<<<<<<< HEAD
12
error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]: ~const FnOnce<()>` is not satisfied
23
--> $DIR/const-eval-select-bad.rs:6:27
34
|
@@ -13,14 +14,31 @@ note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select
1314
LL | const_eval_select((), || {}, || {});
1415
| ^^^^^
1516
= note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:29]` in a closure with no arguments: `|| { /* code */ }`
17+
=======
18+
error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]: ~const FnOnce<()>` is not satisfied
19+
--> $DIR/const-eval-select-bad.rs:7:27
20+
|
21+
LL | const_eval_select((), || {}, || {});
22+
| ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]`
23+
| |
24+
| required by a bound introduced by this call
25+
|
26+
= help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]`
27+
note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]`, but that implementation is not `const`
28+
--> $DIR/const-eval-select-bad.rs:7:27
29+
|
30+
LL | const_eval_select((), || {}, || {});
31+
| ^^^^^
32+
= note: wrap the `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:32]` in a closure with no arguments: `|| { /* code */ }`
33+
>>>>>>> c1798b7c60e... Support unstable moves via stable in unstable items
1634
note: required by a bound in `const_eval_select`
1735
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
1836
|
1937
LL | F: ~const FnOnce<ARG, Output = RET>,
2038
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
2139

2240
error[E0277]: the trait bound `{integer}: ~const FnOnce<()>` is not satisfied
23-
--> $DIR/const-eval-select-bad.rs:8:27
41+
--> $DIR/const-eval-select-bad.rs:9:27
2442
|
2543
LL | const_eval_select((), 42, 0xDEADBEEF);
2644
| ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}`
@@ -36,7 +54,7 @@ LL | F: ~const FnOnce<ARG, Output = RET>,
3654
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
3755

3856
error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
39-
--> $DIR/const-eval-select-bad.rs:8:31
57+
--> $DIR/const-eval-select-bad.rs:9:31
4058
|
4159
LL | const_eval_select((), 42, 0xDEADBEEF);
4260
| ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
@@ -52,7 +70,7 @@ LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
5270
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
5371

5472
error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32`
55-
--> $DIR/const-eval-select-bad.rs:28:5
73+
--> $DIR/const-eval-select-bad.rs:29:5
5674
|
5775
LL | const_eval_select((1,), foo, bar);
5876
| ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool`
@@ -64,7 +82,7 @@ LL | G: FnOnce<ARG, Output = RET> + ~const Destruct,
6482
| ^^^^^^^^^^^^ required by this bound in `const_eval_select`
6583

6684
error[E0631]: type mismatch in function arguments
67-
--> $DIR/const-eval-select-bad.rs:33:32
85+
--> $DIR/const-eval-select-bad.rs:34:32
6886
|
6987
LL | const fn foo(n: i32) -> i32 {
7088
| --------------------------- found signature of `fn(i32) -> _`

src/test/ui/intrinsics/const-eval-select-stability.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(staged_api)]
22
#![feature(const_eval_select)]
3+
#![feature(core_intrinsics)]
34
#![stable(since = "1.0", feature = "ui_test")]
45

56
use std::intrinsics::const_eval_select;

src/test/ui/intrinsics/const-eval-select-stability.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: `const_eval_select` is not yet stable as a const fn
2-
--> $DIR/const-eval-select-stability.rs:16:5
2+
--> $DIR/const-eval-select-stability.rs:17:5
33
|
44
LL | const_eval_select((), nothing, log);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/test/ui/intrinsics/const-eval-select-x86_64.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// only-x86_64
33

44
#![feature(const_eval_select)]
5+
#![feature(core_intrinsics)]
56
use std::intrinsics::const_eval_select;
67
use std::arch::x86_64::*;
78
use std::mem::transmute;

src/test/ui/intrinsics/const-eval-select.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// run-pass
22

33
#![feature(const_eval_select)]
4+
#![feature(core_intrinsics)]
45

56
use std::intrinsics::const_eval_select;
67

src/test/ui/lint/lint-stability.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ mod inheritance {
191191
stable_mod::unstable(); //~ ERROR use of unstable library feature
192192
stable_mod::stable();
193193

194-
unstable_mod::deprecated();
194+
unstable_mod::deprecated(); //~ ERROR use of unstable library feature
195195
unstable_mod::unstable(); //~ ERROR use of unstable library feature
196196

197197
let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature
198-
let _ = Unstable::StableVariant;
198+
let _ = Unstable::StableVariant; //~ ERROR use of unstable library feature
199199

200200
let x: usize = 0;
201201
x.stable();

src/test/ui/lint/lint-stability.stderr

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@ LL | stable_mod::unstable();
294294
|
295295
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
296296

297+
error[E0658]: use of unstable library feature 'unstable_test_feature'
298+
--> $DIR/lint-stability.rs:194:9
299+
|
300+
LL | unstable_mod::deprecated();
301+
| ^^^^^^^^^^^^^^^^^^^^^^^^
302+
|
303+
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
304+
297305
error[E0658]: use of unstable library feature 'unstable_test_feature'
298306
--> $DIR/lint-stability.rs:195:9
299307
|
@@ -310,6 +318,14 @@ LL | let _ = Unstable::UnstableVariant;
310318
|
311319
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
312320

321+
error[E0658]: use of unstable library feature 'unstable_test_feature'
322+
--> $DIR/lint-stability.rs:198:17
323+
|
324+
LL | let _ = Unstable::StableVariant;
325+
| ^^^^^^^^^^^^^^^^^^^^^^^
326+
|
327+
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
328+
313329
error[E0658]: use of unstable library feature 'unstable_test_feature'
314330
--> $DIR/lint-stability.rs:88:48
315331
|
@@ -326,6 +342,6 @@ LL | TypeUnstable = u8,
326342
|
327343
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
328344

329-
error: aborting due to 41 previous errors
345+
error: aborting due to 43 previous errors
330346

331347
For more information about this error, try `rustc --explain E0658`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(staged_api)]
2+
#![stable(feature = "stable_test_feature", since = "1.2.0")]
3+
4+
#[unstable(feature = "unstable_test_feature", issue = "1")]
5+
pub mod new_unstable_module {
6+
#[stable(feature = "stable_test_feature", since = "1.2.0")]
7+
pub trait OldTrait {}
8+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(staged_api)]
2+
#![feature(unstable_test_feature)]
3+
#![stable(feature = "stable_test_feature", since = "1.2.0")]
4+
5+
extern crate stable_in_unstable_core;
6+
7+
#[stable(feature = "stable_test_feature", since = "1.2.0")]
8+
pub mod old_stable_module {
9+
#[stable(feature = "stable_test_feature", since = "1.2.0")]
10+
pub use stable_in_unstable_core::new_unstable_module::OldTrait;
11+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// This test is meant to test that we can have a stable item in an unstable module, and that
2+
// calling that item through the unstable module is unstable, but that re-exporting it from another
3+
// crate in a stable module is fine.
4+
//
5+
// This is necessary to support moving items from `std` into `core` or `alloc` unstably while still
6+
// exporting the original stable interface in `std`, such as moving `Error` into `core`.
7+
//
8+
// aux-build:stable-in-unstable-core.rs
9+
// aux-build:stable-in-unstable-std.rs
10+
#![crate_type = "lib"]
11+
12+
extern crate stable_in_unstable_core;
13+
extern crate stable_in_unstable_std;
14+
15+
mod isolated1 {
16+
use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature 'unstable_test_feature'
17+
use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature'
18+
}
19+
20+
mod isolated2 {
21+
use stable_in_unstable_std::old_stable_module::OldTrait;
22+
23+
struct LocalType;
24+
25+
impl OldTrait for LocalType {}
26+
}
27+
28+
mod isolated3 {
29+
use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature'
30+
31+
struct LocalType;
32+
33+
impl OldTrait for LocalType {}
34+
}
35+
36+
mod isolated4 {
37+
struct LocalType;
38+
39+
impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature 'unstable_test_feature'
40+
}
41+
42+
mod isolated5 {
43+
struct LocalType;
44+
45+
impl stable_in_unstable_std::old_stable_module::OldTrait for LocalType {}
46+
}

0 commit comments

Comments
 (0)