Skip to content

Commit 9c762b5

Browse files
committed
Prevent promotion of const fn calls in inline consts
1 parent 44e199b commit 9c762b5

File tree

15 files changed

+41
-23
lines changed

15 files changed

+41
-23
lines changed

compiler/rustc_borrowck/src/universal_regions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
580580
}
581581
}
582582

583-
BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
583+
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
584584
let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
585585
if self.mir_def.to_def_id() == typeck_root_def_id {
586586
let args =

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
167167
false
168168
}
169169

170-
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
170+
hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => {
171171
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
172172
.into_engine(ccx.tcx, &ccx.body)
173173
.iterate_to_fixpoint()

compiler/rustc_const_eval/src/transform/promote_consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ impl<'tcx> Validator<'_, 'tcx> {
644644
// Everywhere else, we require `#[rustc_promotable]` on the callee.
645645
let promote_all_const_fn = matches!(
646646
self.const_kind,
647-
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const)
647+
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { inline: false })
648648
);
649649
if !promote_all_const_fn {
650650
if let ty::FnDef(def_id, _) = *fn_ty.kind() {

compiler/rustc_errors/src/diagnostic_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl IntoDiagnosticArg for hir::ConstContext {
161161
DiagnosticArgValue::Str(Cow::Borrowed(match self {
162162
hir::ConstContext::ConstFn => "const_fn",
163163
hir::ConstContext::Static(_) => "static",
164-
hir::ConstContext::Const => "const",
164+
hir::ConstContext::Const { .. } => "const",
165165
}))
166166
}
167167
}

compiler/rustc_hir/src/hir.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1581,8 +1581,8 @@ pub enum BodyOwnerKind {
15811581
/// Closures
15821582
Closure,
15831583

1584-
/// Constants and associated constants.
1585-
Const,
1584+
/// Constants and associated constants, also including inline constants.
1585+
Const { inline: bool },
15861586

15871587
/// Initializer of a `static` item.
15881588
Static(Mutability),
@@ -1592,7 +1592,7 @@ impl BodyOwnerKind {
15921592
pub fn is_fn_or_closure(self) -> bool {
15931593
match self {
15941594
BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
1595-
BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
1595+
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
15961596
}
15971597
}
15981598
}
@@ -1615,7 +1615,7 @@ pub enum ConstContext {
16151615
///
16161616
/// For the most part, other contexts are treated just like a regular `const`, so they are
16171617
/// lumped into the same category.
1618-
Const,
1618+
Const { inline: bool },
16191619
}
16201620

16211621
impl ConstContext {
@@ -1624,7 +1624,7 @@ impl ConstContext {
16241624
/// E.g. `const` or `static mut`.
16251625
pub fn keyword_name(self) -> &'static str {
16261626
match self {
1627-
Self::Const => "const",
1627+
Self::Const { .. } => "const",
16281628
Self::Static(Mutability::Not) => "static",
16291629
Self::Static(Mutability::Mut) => "static mut",
16301630
Self::ConstFn => "const fn",
@@ -1637,7 +1637,7 @@ impl ConstContext {
16371637
impl fmt::Display for ConstContext {
16381638
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16391639
match *self {
1640-
Self::Const => write!(f, "constant"),
1640+
Self::Const { .. } => write!(f, "constant"),
16411641
Self::Static(_) => write!(f, "static"),
16421642
Self::ConstFn => write!(f, "constant function"),
16431643
}

compiler/rustc_hir_typeck/src/callee.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
788788

789789
let effect = match const_context {
790790
_ if host_always_on => tcx.consts.true_,
791-
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_,
791+
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
792+
tcx.consts.false_
793+
}
792794
Some(hir::ConstContext::ConstFn) => {
793795
let args = ty::GenericArgs::identity_for_item(tcx, context);
794796
args.host_effect_param().expect("ConstContext::Maybe must have host effect param")

compiler/rustc_hir_typeck/src/writeback.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4646
}
4747
// Type only exists for constants and statics, not functions.
4848
match self.tcx.hir().body_owner_kind(item_def_id) {
49-
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
49+
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => {
5050
let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id);
5151
wbcx.visit_node_id(body.value.span, item_hir_id);
5252
}

compiler/rustc_middle/src/hir/map/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -442,9 +442,10 @@ impl<'hir> Map<'hir> {
442442
/// Panics if `LocalDefId` does not have an associated body.
443443
pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind {
444444
match self.tcx.def_kind(def_id) {
445-
DefKind::Const | DefKind::AssocConst | DefKind::InlineConst | DefKind::AnonConst => {
446-
BodyOwnerKind::Const
445+
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
446+
BodyOwnerKind::Const { inline: false }
447447
}
448+
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
448449
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
449450
DefKind::Closure | DefKind::Generator => BodyOwnerKind::Closure,
450451
DefKind::Static(mt) => BodyOwnerKind::Static(mt),
@@ -461,7 +462,7 @@ impl<'hir> Map<'hir> {
461462
/// just that it has to be checked as if it were.
462463
pub fn body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
463464
let ccx = match self.body_owner_kind(def_id) {
464-
BodyOwnerKind::Const => ConstContext::Const,
465+
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
465466
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
466467

467468
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None,

compiler/rustc_mir_build/src/build/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
633633
_ => bug!("expected closure or generator, found {ty:?}"),
634634
}
635635
}
636-
hir::BodyOwnerKind::Const => 0,
636+
hir::BodyOwnerKind::Const { .. } => 0,
637637
hir::BodyOwnerKind::Static(_) => 0,
638638
};
639639
let mut cfg = CFG { basic_blocks: IndexVec::new() };
@@ -700,7 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
700700
// Constants always need overflow checks.
701701
check_overflow |= matches!(
702702
tcx.hir().body_owner_kind(def),
703-
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_)
703+
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_)
704704
);
705705

706706
let lint_level = LintLevel::Explicit(hir_id);

compiler/rustc_mir_transform/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
343343
let body = match tcx.hir().body_const_context(def) {
344344
// consts and statics do not have `optimized_mir`, so we can steal the body instead of
345345
// cloning it.
346-
Some(hir::ConstContext::Const | hir::ConstContext::Static(_)) => body.steal(),
346+
Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => body.steal(),
347347
Some(hir::ConstContext::ConstFn) => body.borrow().clone(),
348348
None => bug!("`mir_for_ctfe` called on non-const {def:?}"),
349349
};

compiler/rustc_passes/src/check_const.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,12 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
193193
}
194194

195195
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
196-
let kind = Some(hir::ConstContext::Const);
196+
let kind = Some(hir::ConstContext::Const { inline: false });
197197
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
198198
}
199199

200200
fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) {
201-
let kind = Some(hir::ConstContext::Const);
201+
let kind = Some(hir::ConstContext::Const { inline: true });
202202
self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block));
203203
}
204204

src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
315315
let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
316316

317317
let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
318-
if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind {
318+
if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind {
319319
let body_span = cx.tcx.hir().span_with_body(body_owner);
320320
if let Some(span) = self.const_span && span.contains(body_span) {
321321
return;

src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl Context {
7272
let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
7373

7474
match cx.tcx.hir().body_owner_kind(body_owner_def_id) {
75-
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
75+
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => {
7676
let body_span = cx.tcx.hir().span_with_body(body_owner);
7777

7878
if let Some(span) = self.const_span {

tests/ui/inline-const/promotion.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![feature(inline_const)]
22
#![allow(arithmetic_overflow, unconditional_panic)]
3-
// check-pass
43

54
// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
5+
// Make sure that in a `const` block, we do not promote such calls.
66
const fn div_by_zero() -> i32 {
77
1 / 0
88
}
@@ -15,6 +15,7 @@ fn main() {
1515
let v = const {
1616
if mk_false() {
1717
let _x: &'static i32 = &div_by_zero();
18+
//~^ ERROR: temporary value dropped while borrowed
1819
}
1920
42
2021
};
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/promotion.rs:17:37
3+
|
4+
LL | let _x: &'static i32 = &div_by_zero();
5+
| ------------ ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
6+
| |
7+
| type annotation requires that borrow lasts for `'static`
8+
LL |
9+
LL | }
10+
| - temporary value is freed at the end of this statement
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0716`.

0 commit comments

Comments
 (0)