Skip to content

Commit a581c82

Browse files
committed
Auto merge of #33541 - eddyb:promote-only-temps, r=arielb1
mir: don't attempt to promote Unpromotable constant temps. Fixes #33537. This was a non-problem in regular functions, but we also promote in `const fn`s. There we always qualify temps so you can't depend on `Unpromotable` temps being `NOT_CONST`.
2 parents 709e5c5 + e5a91b7 commit a581c82

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

src/librustc_mir/transform/qualify_consts.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,18 @@ bitflags! {
6464
// pointer comparisons, ptr-to-int casts, etc.
6565
const NOT_CONST = 1 << 6,
6666

67+
// Refers to temporaries which cannot be promoted as
68+
// promote_consts decided they weren't simple enough.
69+
const NOT_PROMOTABLE = 1 << 7,
70+
6771
// Borrows of temporaries can be promoted only
6872
// if they have none of the above qualifications.
69-
const UNPROMOTABLE = !0,
73+
const NEVER_PROMOTE = !0,
7074

7175
// Const items can only have MUTABLE_INTERIOR
72-
// without producing an error.
73-
const CONST_ERROR = !Qualif::MUTABLE_INTERIOR.bits
76+
// and NOT_PROMOTABLE without producing an error.
77+
const CONST_ERROR = !Qualif::MUTABLE_INTERIOR.bits &
78+
!Qualif::NOT_PROMOTABLE.bits
7479
}
7580
}
7681

@@ -503,6 +508,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
503508
self.add(Qualif::NOT_CONST);
504509
}
505510
Lvalue::Temp(index) => {
511+
if !self.temp_promotion_state[index as usize].is_promotable() {
512+
self.add(Qualif::NOT_PROMOTABLE);
513+
}
514+
506515
if let Some(qualif) = self.temp_qualif[index as usize] {
507516
self.add(qualif);
508517
} else {
@@ -688,8 +697,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
688697
// We might have a candidate for promotion.
689698
let candidate = Candidate::Ref(self.location);
690699
if self.mode == Mode::Fn || self.mode == Mode::ConstFn {
691-
if !self.qualif.intersects(Qualif::UNPROMOTABLE) {
692-
self.promotion_candidates.push(candidate);
700+
if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
701+
// We can only promote direct borrows of temps.
702+
if let Lvalue::Temp(_) = *lvalue {
703+
self.promotion_candidates.push(candidate);
704+
}
693705
}
694706
}
695707
}
@@ -781,7 +793,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
781793
this.visit_operand(arg);
782794
if is_shuffle && i == 2 && this.mode == Mode::Fn {
783795
let candidate = Candidate::ShuffleIndices(bb);
784-
if !this.qualif.intersects(Qualif::UNPROMOTABLE) {
796+
if !this.qualif.intersects(Qualif::NEVER_PROMOTE) {
785797
this.promotion_candidates.push(candidate);
786798
} else {
787799
span_err!(this.tcx.sess, this.span, E0526,

src/test/run-pass/issue-33537.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(const_fn)]
12+
13+
const fn foo() -> *const i8 {
14+
b"foo" as *const _ as *const i8
15+
}
16+
17+
const fn bar() -> i32 {
18+
*&{(1, 2, 3).1}
19+
}
20+
21+
fn main() {
22+
assert_eq!(foo(), b"foo" as *const _ as *const i8);
23+
assert_eq!(bar(), 2);
24+
}

0 commit comments

Comments
 (0)