Skip to content

Commit

Permalink
Error if an unstable const eval feature is used in a stable const fn
Browse files Browse the repository at this point in the history
  • Loading branch information
ecstatic-morse committed Sep 16, 2020
1 parent e4edc16 commit 81b3b66
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 6 deletions.
26 changes: 24 additions & 2 deletions compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -1,6 +1,6 @@
//! Concrete error types for all operations which may be invalid in a certain const context.

use rustc_errors::struct_span_err;
use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_session::config::nightly_options;
Expand All @@ -16,7 +16,29 @@ pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) {

let gate = match op.status_in_item(ccx) {
Status::Allowed => return,
Status::Unstable(gate) if ccx.tcx.features().enabled(gate) => return,

Status::Unstable(gate) if ccx.tcx.features().enabled(gate) => {
let unstable_in_stable = ccx.const_kind() == hir::ConstContext::ConstFn
&& ccx.tcx.features().enabled(sym::staged_api)
&& !ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_const_unstable)
&& !super::allow_internal_unstable(ccx.tcx, ccx.def_id.to_def_id(), gate);

if unstable_in_stable {
ccx.tcx.sess
.struct_span_err(span, &format!("`#[feature({})]` cannot be depended on in a const-stable function", gate.as_str()))
.span_suggestion(
ccx.body.span,
"if it is not part of the public API, make this function unstably const",
concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
Applicability::HasPlaceholders,
)
.help("otherwise `#[allow_internal_unstable]` can be used to bypass stability checks")
.emit();
}

return;
}

Status::Unstable(gate) => Some(gate),
Status::Forbidden => None,
};
Expand Down
Expand Up @@ -2,7 +2,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
use rustc_span::{sym, Span};

use super::ops;
use super::qualifs::{NeedsDrop, Qualif};
Expand All @@ -11,7 +11,12 @@ use super::ConstCx;

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

tcx.features().const_precise_live_drops
}

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

if !checking_enabled(tcx) {
if !checking_enabled(tcx, def_id) {
return;
}

Expand Down
Expand Up @@ -551,7 +551,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
| TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
// If we are checking live drops after drop-elaboration, don't emit duplicate
// errors here.
if super::post_drop_elaboration::checking_enabled(self.tcx) {
if super::post_drop_elaboration::checking_enabled(self.tcx, self.def_id) {
return;
}

Expand Down

0 comments on commit 81b3b66

Please sign in to comment.