stop promoting union field accesses in 'const'
This commit is contained in:
parent
0d37dca25a
commit
d727f642b9
3 changed files with 30 additions and 21 deletions
|
|
@ -294,17 +294,6 @@ impl std::ops::Deref for Validator<'a, 'tcx> {
|
|||
struct Unpromotable;
|
||||
|
||||
impl<'tcx> Validator<'_, 'tcx> {
|
||||
/// Determines if this code could be executed at runtime and thus is subject to codegen.
|
||||
/// That means even unused constants need to be evaluated.
|
||||
///
|
||||
/// `const_kind` should not be used in this file other than through this method!
|
||||
fn maybe_runtime(&self) -> bool {
|
||||
match self.const_kind {
|
||||
None | Some(hir::ConstContext::ConstFn) => true,
|
||||
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
|
||||
match candidate {
|
||||
Candidate::Ref(loc) => {
|
||||
|
|
@ -555,14 +544,12 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
}
|
||||
|
||||
ProjectionElem::Field(..) => {
|
||||
if self.maybe_runtime() {
|
||||
let base_ty =
|
||||
Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
// No promotion of union field accesses.
|
||||
if def.is_union() {
|
||||
return Err(Unpromotable);
|
||||
}
|
||||
let base_ty =
|
||||
Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
// No promotion of union field accesses.
|
||||
if def.is_union() {
|
||||
return Err(Unpromotable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -744,7 +731,14 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
) -> Result<(), Unpromotable> {
|
||||
let fn_ty = callee.ty(self.body, self.tcx);
|
||||
|
||||
if !self.explicit && self.maybe_runtime() {
|
||||
// When doing explicit promotion and inside const/static items, we promote all (eligible) function calls.
|
||||
// Everywhere else, we require `#[rustc_promotable]` on the callee.
|
||||
let promote_all_const_fn = self.explicit
|
||||
|| matches!(
|
||||
self.const_kind,
|
||||
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const)
|
||||
);
|
||||
if !promote_all_const_fn {
|
||||
if let ty::FnDef(def_id, _) = *fn_ty.kind() {
|
||||
// Never promote runtime `const fn` calls of
|
||||
// functions without `#[rustc_promotable]`.
|
||||
|
|
|
|||
|
|
@ -27,4 +27,9 @@ pub const fn promote_union() {
|
|||
let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed
|
||||
}
|
||||
|
||||
// We do not promote union field accesses in `const`, either.
|
||||
const TEST_UNION: () = {
|
||||
let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed
|
||||
};
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,16 @@ LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x };
|
|||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promote-not.rs:32:29
|
||||
|
|
||||
LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x };
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL | };
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0716`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue