mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-22 11:53:44 +00:00
Prevent promotion of const fn calls in inline consts
This commit is contained in:
parent
44e199bf30
commit
9c762b58ba
@ -580,7 +580,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
|
||||
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
|
||||
let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
|
||||
if self.mir_def.to_def_id() == typeck_root_def_id {
|
||||
let args =
|
||||
|
@ -167,7 +167,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
|
||||
false
|
||||
}
|
||||
|
||||
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
|
||||
hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => {
|
||||
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
|
||||
.into_engine(ccx.tcx, &ccx.body)
|
||||
.iterate_to_fixpoint()
|
||||
|
@ -644,7 +644,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
// Everywhere else, we require `#[rustc_promotable]` on the callee.
|
||||
let promote_all_const_fn = matches!(
|
||||
self.const_kind,
|
||||
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const)
|
||||
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { inline: false })
|
||||
);
|
||||
if !promote_all_const_fn {
|
||||
if let ty::FnDef(def_id, _) = *fn_ty.kind() {
|
||||
|
@ -161,7 +161,7 @@ impl IntoDiagnosticArg for hir::ConstContext {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed(match self {
|
||||
hir::ConstContext::ConstFn => "const_fn",
|
||||
hir::ConstContext::Static(_) => "static",
|
||||
hir::ConstContext::Const => "const",
|
||||
hir::ConstContext::Const { .. } => "const",
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -1581,8 +1581,8 @@ pub enum BodyOwnerKind {
|
||||
/// Closures
|
||||
Closure,
|
||||
|
||||
/// Constants and associated constants.
|
||||
Const,
|
||||
/// Constants and associated constants, also including inline constants.
|
||||
Const { inline: bool },
|
||||
|
||||
/// Initializer of a `static` item.
|
||||
Static(Mutability),
|
||||
@ -1592,7 +1592,7 @@ impl BodyOwnerKind {
|
||||
pub fn is_fn_or_closure(self) -> bool {
|
||||
match self {
|
||||
BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
|
||||
BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
|
||||
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1615,7 +1615,7 @@ pub enum ConstContext {
|
||||
///
|
||||
/// For the most part, other contexts are treated just like a regular `const`, so they are
|
||||
/// lumped into the same category.
|
||||
Const,
|
||||
Const { inline: bool },
|
||||
}
|
||||
|
||||
impl ConstContext {
|
||||
@ -1624,7 +1624,7 @@ impl ConstContext {
|
||||
/// E.g. `const` or `static mut`.
|
||||
pub fn keyword_name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Const => "const",
|
||||
Self::Const { .. } => "const",
|
||||
Self::Static(Mutability::Not) => "static",
|
||||
Self::Static(Mutability::Mut) => "static mut",
|
||||
Self::ConstFn => "const fn",
|
||||
@ -1637,7 +1637,7 @@ impl ConstContext {
|
||||
impl fmt::Display for ConstContext {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Self::Const => write!(f, "constant"),
|
||||
Self::Const { .. } => write!(f, "constant"),
|
||||
Self::Static(_) => write!(f, "static"),
|
||||
Self::ConstFn => write!(f, "constant function"),
|
||||
}
|
||||
|
@ -788,7 +788,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let effect = match const_context {
|
||||
_ if host_always_on => tcx.consts.true_,
|
||||
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_,
|
||||
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
|
||||
tcx.consts.false_
|
||||
}
|
||||
Some(hir::ConstContext::ConstFn) => {
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, context);
|
||||
args.host_effect_param().expect("ConstContext::Maybe must have host effect param")
|
||||
|
@ -46,7 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
// Type only exists for constants and statics, not functions.
|
||||
match self.tcx.hir().body_owner_kind(item_def_id) {
|
||||
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
|
||||
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => {
|
||||
let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id);
|
||||
wbcx.visit_node_id(body.value.span, item_hir_id);
|
||||
}
|
||||
|
@ -442,9 +442,10 @@ impl<'hir> Map<'hir> {
|
||||
/// Panics if `LocalDefId` does not have an associated body.
|
||||
pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind {
|
||||
match self.tcx.def_kind(def_id) {
|
||||
DefKind::Const | DefKind::AssocConst | DefKind::InlineConst | DefKind::AnonConst => {
|
||||
BodyOwnerKind::Const
|
||||
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
|
||||
BodyOwnerKind::Const { inline: false }
|
||||
}
|
||||
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
||||
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
||||
DefKind::Closure | DefKind::Generator => BodyOwnerKind::Closure,
|
||||
DefKind::Static(mt) => BodyOwnerKind::Static(mt),
|
||||
@ -461,7 +462,7 @@ impl<'hir> Map<'hir> {
|
||||
/// just that it has to be checked as if it were.
|
||||
pub fn body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
|
||||
let ccx = match self.body_owner_kind(def_id) {
|
||||
BodyOwnerKind::Const => ConstContext::Const,
|
||||
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
|
||||
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
|
||||
|
||||
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None,
|
||||
|
@ -633,7 +633,7 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
|
||||
_ => bug!("expected closure or generator, found {ty:?}"),
|
||||
}
|
||||
}
|
||||
hir::BodyOwnerKind::Const => 0,
|
||||
hir::BodyOwnerKind::Const { .. } => 0,
|
||||
hir::BodyOwnerKind::Static(_) => 0,
|
||||
};
|
||||
let mut cfg = CFG { basic_blocks: IndexVec::new() };
|
||||
@ -700,7 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// Constants always need overflow checks.
|
||||
check_overflow |= matches!(
|
||||
tcx.hir().body_owner_kind(def),
|
||||
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_)
|
||||
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_)
|
||||
);
|
||||
|
||||
let lint_level = LintLevel::Explicit(hir_id);
|
||||
|
@ -343,7 +343,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
|
||||
let body = match tcx.hir().body_const_context(def) {
|
||||
// consts and statics do not have `optimized_mir`, so we can steal the body instead of
|
||||
// cloning it.
|
||||
Some(hir::ConstContext::Const | hir::ConstContext::Static(_)) => body.steal(),
|
||||
Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => body.steal(),
|
||||
Some(hir::ConstContext::ConstFn) => body.borrow().clone(),
|
||||
None => bug!("`mir_for_ctfe` called on non-const {def:?}"),
|
||||
};
|
||||
|
@ -193,12 +193,12 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
|
||||
let kind = Some(hir::ConstContext::Const);
|
||||
let kind = Some(hir::ConstContext::Const { inline: false });
|
||||
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
|
||||
}
|
||||
|
||||
fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) {
|
||||
let kind = Some(hir::ConstContext::Const);
|
||||
let kind = Some(hir::ConstContext::Const { inline: true });
|
||||
self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block));
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
|
||||
let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
|
||||
|
||||
let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
|
||||
if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind {
|
||||
if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind {
|
||||
let body_span = cx.tcx.hir().span_with_body(body_owner);
|
||||
if let Some(span) = self.const_span && span.contains(body_span) {
|
||||
return;
|
||||
|
@ -72,7 +72,7 @@ impl Context {
|
||||
let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
|
||||
|
||||
match cx.tcx.hir().body_owner_kind(body_owner_def_id) {
|
||||
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
|
||||
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => {
|
||||
let body_span = cx.tcx.hir().span_with_body(body_owner);
|
||||
|
||||
if let Some(span) = self.const_span {
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![feature(inline_const)]
|
||||
#![allow(arithmetic_overflow, unconditional_panic)]
|
||||
// check-pass
|
||||
|
||||
// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
|
||||
// Make sure that in a `const` block, we do not promote such calls.
|
||||
const fn div_by_zero() -> i32 {
|
||||
1 / 0
|
||||
}
|
||||
@ -15,6 +15,7 @@ fn main() {
|
||||
let v = const {
|
||||
if mk_false() {
|
||||
let _x: &'static i32 = &div_by_zero();
|
||||
//~^ ERROR: temporary value dropped while borrowed
|
||||
}
|
||||
42
|
||||
};
|
||||
|
14
tests/ui/inline-const/promotion.stderr
Normal file
14
tests/ui/inline-const/promotion.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:17:37
|
||||
|
|
||||
LL | let _x: &'static i32 = &div_by_zero();
|
||||
| ------------ ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL |
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0716`.
|
Loading…
Reference in New Issue
Block a user