Skip to content

Commit 81b3b66

Browse files
Error if an unstable const eval feature is used in a stable const fn
1 parent e4edc16 commit 81b3b66

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

compiler/rustc_mir/src/transform/check_consts/ops.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
3-
use rustc_errors::struct_span_err;
3+
use rustc_errors::{struct_span_err, Applicability};
44
use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
66
use rustc_session::config::nightly_options;
@@ -16,7 +16,29 @@ pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) {
1616

1717
let gate = match op.status_in_item(ccx) {
1818
Status::Allowed => return,
19-
Status::Unstable(gate) if ccx.tcx.features().enabled(gate) => return,
19+
20+
Status::Unstable(gate) if ccx.tcx.features().enabled(gate) => {
21+
let unstable_in_stable = ccx.const_kind() == hir::ConstContext::ConstFn
22+
&& ccx.tcx.features().enabled(sym::staged_api)
23+
&& !ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_const_unstable)
24+
&& !super::allow_internal_unstable(ccx.tcx, ccx.def_id.to_def_id(), gate);
25+
26+
if unstable_in_stable {
27+
ccx.tcx.sess
28+
.struct_span_err(span, &format!("`#[feature({})]` cannot be depended on in a const-stable function", gate.as_str()))
29+
.span_suggestion(
30+
ccx.body.span,
31+
"if it is not part of the public API, make this function unstably const",
32+
concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
33+
Applicability::HasPlaceholders,
34+
)
35+
.help("otherwise `#[allow_internal_unstable]` can be used to bypass stability checks")
36+
.emit();
37+
}
38+
39+
return;
40+
}
41+
2042
Status::Unstable(gate) => Some(gate),
2143
Status::Forbidden => None,
2244
};

compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_hir::def_id::LocalDefId;
22
use rustc_middle::mir::visit::Visitor;
33
use rustc_middle::mir::{self, BasicBlock, Location};
44
use rustc_middle::ty::TyCtxt;
5-
use rustc_span::Span;
5+
use rustc_span::{sym, Span};
66

77
use super::ops;
88
use super::qualifs::{NeedsDrop, Qualif};
@@ -11,7 +11,12 @@ use super::ConstCx;
1111

1212
/// Returns `true` if we should use the more precise live drop checker that runs after drop
1313
/// elaboration.
14-
pub fn checking_enabled(tcx: TyCtxt<'tcx>) -> bool {
14+
pub fn checking_enabled(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
15+
// Const-stable functions must always use the stable live drop checker.
16+
if tcx.features().staged_api && !tcx.has_attr(def_id.to_def_id(), sym::rustc_const_unstable) {
17+
return false;
18+
}
19+
1520
tcx.features().const_precise_live_drops
1621
}
1722

@@ -25,7 +30,7 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<
2530
return;
2631
}
2732

28-
if !checking_enabled(tcx) {
33+
if !checking_enabled(tcx, def_id) {
2934
return;
3035
}
3136

compiler/rustc_mir/src/transform/check_consts/validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
551551
| TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
552552
// If we are checking live drops after drop-elaboration, don't emit duplicate
553553
// errors here.
554-
if super::post_drop_elaboration::checking_enabled(self.tcx) {
554+
if super::post_drop_elaboration::checking_enabled(self.tcx, self.def_id) {
555555
return;
556556
}
557557

0 commit comments

Comments
 (0)