Skip to content

Commit d727f64

Browse files
committed
stop promoting union field accesses in 'const'
1 parent 0d37dca commit d727f64

File tree

3 files changed

+30
-21
lines changed

3 files changed

+30
-21
lines changed

compiler/rustc_mir/src/transform/promote_consts.rs

+14-20
Original file line numberDiff line numberDiff line change
@@ -294,17 +294,6 @@ impl std::ops::Deref for Validator<'a, 'tcx> {
294294
struct Unpromotable;
295295

296296
impl<'tcx> Validator<'_, 'tcx> {
297-
/// Determines if this code could be executed at runtime and thus is subject to codegen.
298-
/// That means even unused constants need to be evaluated.
299-
///
300-
/// `const_kind` should not be used in this file other than through this method!
301-
fn maybe_runtime(&self) -> bool {
302-
match self.const_kind {
303-
None | Some(hir::ConstContext::ConstFn) => true,
304-
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => false,
305-
}
306-
}
307-
308297
fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
309298
match candidate {
310299
Candidate::Ref(loc) => {
@@ -555,14 +544,12 @@ impl<'tcx> Validator<'_, 'tcx> {
555544
}
556545

557546
ProjectionElem::Field(..) => {
558-
if self.maybe_runtime() {
559-
let base_ty =
560-
Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
561-
if let Some(def) = base_ty.ty_adt_def() {
562-
// No promotion of union field accesses.
563-
if def.is_union() {
564-
return Err(Unpromotable);
565-
}
547+
let base_ty =
548+
Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
549+
if let Some(def) = base_ty.ty_adt_def() {
550+
// No promotion of union field accesses.
551+
if def.is_union() {
552+
return Err(Unpromotable);
566553
}
567554
}
568555
}
@@ -744,7 +731,14 @@ impl<'tcx> Validator<'_, 'tcx> {
744731
) -> Result<(), Unpromotable> {
745732
let fn_ty = callee.ty(self.body, self.tcx);
746733

747-
if !self.explicit && self.maybe_runtime() {
734+
// When doing explicit promotion and inside const/static items, we promote all (eligible) function calls.
735+
// Everywhere else, we require `#[rustc_promotable]` on the callee.
736+
let promote_all_const_fn = self.explicit
737+
|| matches!(
738+
self.const_kind,
739+
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const)
740+
);
741+
if !promote_all_const_fn {
748742
if let ty::FnDef(def_id, _) = *fn_ty.kind() {
749743
// Never promote runtime `const fn` calls of
750744
// functions without `#[rustc_promotable]`.

src/test/ui/consts/promote-not.rs

+5
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,9 @@ pub const fn promote_union() {
2727
let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed
2828
}
2929

30+
// We do not promote union field accesses in `const`, either.
31+
const TEST_UNION: () = {
32+
let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed
33+
};
34+
3035
fn main() {}

src/test/ui/consts/promote-not.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x };
3838
LL | }
3939
| - temporary value is freed at the end of this statement
4040

41-
error: aborting due to 4 previous errors
41+
error[E0716]: temporary value dropped while borrowed
42+
--> $DIR/promote-not.rs:32:29
43+
|
44+
LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x };
45+
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
46+
| |
47+
| type annotation requires that borrow lasts for `'static`
48+
LL | };
49+
| - temporary value is freed at the end of this statement
50+
51+
error: aborting due to 5 previous errors
4252

4353
For more information about this error, try `rustc --explain E0716`.

0 commit comments

Comments
 (0)