Skip to content

Commit e89e935

Browse files
Remove non_const_op helper
Most of the extra logic was unused in the post-drop-elaboration checker.
1 parent e900f1f commit e89e935

File tree

3 files changed

+70
-57
lines changed

3 files changed

+70
-57
lines changed

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

+1-44
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, Applicability};
3+
use rustc_errors::struct_span_err;
44
use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
66
use rustc_session::config::nightly_options;
@@ -10,49 +10,6 @@ use rustc_span::{Span, Symbol};
1010

1111
use super::ConstCx;
1212

13-
/// Emits an error and returns `true` if `op` is not allowed in the given const context.
14-
pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) -> bool {
15-
debug!("illegal_op: op={:?}", op);
16-
17-
let gate = match op.status_in_item(ccx) {
18-
Status::Allowed => return false,
19-
20-
Status::Unstable(gate) if ccx.tcx.features().enabled(gate) => {
21-
let unstable_in_stable = ccx.is_const_stable_const_fn()
22-
&& !super::allow_internal_unstable(ccx.tcx, ccx.def_id.to_def_id(), gate);
23-
24-
if unstable_in_stable {
25-
ccx.tcx.sess
26-
.struct_span_err(
27-
span,
28-
&format!("const-stable function cannot use `#[feature({})]`", gate.as_str()),
29-
)
30-
.span_suggestion(
31-
ccx.body.span,
32-
"if it is not part of the public API, make this function unstably const",
33-
concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
34-
Applicability::HasPlaceholders,
35-
)
36-
.note("otherwise `#[allow_internal_unstable]` can be used to bypass stability checks")
37-
.emit();
38-
}
39-
40-
return unstable_in_stable;
41-
}
42-
43-
Status::Unstable(gate) => Some(gate),
44-
Status::Forbidden => None,
45-
};
46-
47-
if ccx.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
48-
ccx.tcx.sess.miri_unleashed_feature(span, gate);
49-
return false;
50-
}
51-
52-
op.emit_error(ccx, span);
53-
true
54-
}
55-
5613
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5714
pub enum Status {
5815
Allowed,

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_middle::mir::{self, BasicBlock, Location};
44
use rustc_middle::ty::TyCtxt;
55
use rustc_span::Span;
66

7-
use super::ops;
7+
use super::ops::{self, NonConstOp};
88
use super::qualifs::{NeedsDrop, Qualif};
99
use super::validation::Qualifs;
1010
use super::ConstCx;
@@ -56,7 +56,7 @@ impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
5656

5757
impl CheckLiveDrops<'mir, 'tcx> {
5858
fn check_live_drop(&self, span: Span) {
59-
ops::non_const(self.ccx, ops::LiveDrop { dropped_at: None }, span);
59+
ops::LiveDrop { dropped_at: None }.emit_error(self.ccx, span)
6060
}
6161
}
6262

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

+67-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
22
3-
use rustc_errors::struct_span_err;
3+
use rustc_errors::{Applicability, struct_span_err};
44
use rustc_hir::{self as hir, LangItem};
55
use rustc_hir::{def_id::DefId, HirId};
66
use rustc_infer::infer::TyCtxtInferExt;
@@ -11,13 +11,13 @@ use rustc_middle::ty::subst::GenericArgKind;
1111
use rustc_middle::ty::{
1212
self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt, TypeAndMut,
1313
};
14-
use rustc_span::{sym, Span};
14+
use rustc_span::{sym, Span, Symbol};
1515
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
1616
use rustc_trait_selection::traits::{self, TraitEngine};
1717

1818
use std::ops::Deref;
1919

20-
use super::ops::{self, NonConstOp};
20+
use super::ops::{self, NonConstOp, Status};
2121
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
2222
use super::resolver::FlowSensitiveAnalysis;
2323
use super::{is_lang_panic_fn, ConstCx, Qualif};
@@ -179,7 +179,12 @@ pub struct Validator<'mir, 'tcx> {
179179
/// The span of the current statement.
180180
span: Span,
181181

182-
const_checking_stopped: bool,
182+
/// True if we shouldn't emit errors when we find them.
183+
///
184+
/// This allows items to be speculatively const-checked.
185+
silence_errors: bool,
186+
187+
passes_checks_without_unstable_features: bool,
183188
}
184189

185190
impl Deref for Validator<'mir, 'tcx> {
@@ -196,7 +201,8 @@ impl Validator<'mir, 'tcx> {
196201
span: ccx.body.span,
197202
ccx,
198203
qualifs: Default::default(),
199-
const_checking_stopped: false,
204+
passes_checks_without_unstable_features: true,
205+
silence_errors: false,
200206
}
201207
}
202208

@@ -266,15 +272,48 @@ impl Validator<'mir, 'tcx> {
266272
/// Emits an error at the given `span` if an expression cannot be evaluated in the current
267273
/// context.
268274
pub fn check_op_spanned<O: NonConstOp>(&mut self, op: O, span: Span) {
269-
// HACK: This is for strict equivalence with the old `qualify_min_const_fn` pass, which
270-
// only emitted one error per function. It should be removed and the test output updated.
271-
if self.const_checking_stopped {
275+
debug!("illegal_op: op={:?}", op);
276+
277+
let ccx = self.ccx;
278+
279+
let gate = match op.status_in_item(ccx) {
280+
Status::Allowed => return,
281+
Status::Unstable(gate) => Some(gate),
282+
Status::Forbidden => None,
283+
};
284+
285+
self.passes_checks_without_unstable_features = false;
286+
287+
if self.silence_errors {
272288
return;
273289
}
274290

275-
let err_emitted = ops::non_const(self.ccx, op, span);
276-
if err_emitted && O::STOPS_CONST_CHECKING {
277-
self.const_checking_stopped = true;
291+
// Unless we are const-checking a const-stable function, return before emitting an error if
292+
// the user has enabled the requisite feature gate.
293+
if let Some(gate) = gate {
294+
if ccx.tcx.features().enabled(gate) {
295+
let unstable_in_stable = ccx.is_const_stable_const_fn()
296+
&& !super::allow_internal_unstable(ccx.tcx, ccx.def_id.to_def_id(), gate);
297+
298+
if unstable_in_stable {
299+
error_unstable_in_stable(ccx, gate, span);
300+
}
301+
302+
return;
303+
}
304+
}
305+
306+
if ccx.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
307+
ccx.tcx.sess.miri_unleashed_feature(span, gate);
308+
return;
309+
}
310+
311+
op.emit_error(ccx, span);
312+
313+
// HACK: This is for strict equivalence with the old `qualify_min_const_fn` pass, which
314+
// only emitted one error per function. It should be removed and the test output updated.
315+
if O::STOPS_CONST_CHECKING {
316+
self.silence_errors = true;
278317
}
279318
}
280319

@@ -866,3 +905,20 @@ fn place_as_reborrow(
866905
}
867906
})
868907
}
908+
909+
fn error_unstable_in_stable(ccx: &ConstCx<'_, '_>, gate: Symbol, span: Span) {
910+
ccx.tcx
911+
.sess
912+
.struct_span_err(
913+
span,
914+
&format!("const-stable function cannot use `#[feature({})]`", gate.as_str()),
915+
)
916+
.span_suggestion(
917+
ccx.body.span,
918+
"if it is not part of the public API, make this function unstably const",
919+
concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
920+
Applicability::HasPlaceholders,
921+
)
922+
.note("otherwise `#[allow_internal_unstable]` can be used to bypass stability checks")
923+
.emit();
924+
}

0 commit comments

Comments
 (0)