From 292c6ac57f6a805091ac4384c3e5ba410a3c5fa2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 6 Dec 2017 01:28:27 +0200 Subject: [PATCH] rustc_mir: promote references of statics from other statics. --- src/librustc_mir/transform/qualify_consts.rs | 23 ++++++++++++++------ src/test/run-pass/issue-44373.rs | 2 ++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b9b86dd6e840f..2b2323928efba 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -41,6 +41,9 @@ use transform::{MirPass, MirSource}; use super::promote_consts::{self, Candidate, TempState}; bitflags! { + // Borrows of temporaries can be promoted only if + // they have none of these qualifications, with + // the exception of `STATIC_REF` (in statics only). struct Qualif: u8 { // Constant containing interior mutability (UnsafeCell). const MUTABLE_INTERIOR = 1 << 0; @@ -65,10 +68,6 @@ bitflags! { // promote_consts decided they weren't simple enough. const NOT_PROMOTABLE = 1 << 6; - // Borrows of temporaries can be promoted only - // if they have none of the above qualifications. - const NEVER_PROMOTE = 0b111_1111; - // Const items can only have MUTABLE_INTERIOR // and NOT_PROMOTABLE without producing an error. const CONST_ERROR = !Qualif::MUTABLE_INTERIOR.bits & @@ -197,7 +196,17 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { self.add(original); } - /// Check if an Place with the current qualifications could + /// Check if a Local with the current qualifications is promotable. + fn can_promote(&mut self) -> bool { + // References to statics are allowed, but only in other statics. + if self.mode == Mode::Static || self.mode == Mode::StaticMut { + (self.qualif - Qualif::STATIC_REF).is_empty() + } else { + self.qualif.is_empty() + } + } + + /// Check if a Place with the current qualifications could /// be consumed, by either an operand or a Deref projection. fn try_consume(&mut self) -> bool { if self.qualif.intersects(Qualif::STATIC) && self.mode != Mode::Fn { @@ -633,7 +642,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // We might have a candidate for promotion. let candidate = Candidate::Ref(location); - if !self.qualif.intersects(Qualif::NEVER_PROMOTE) { + if self.can_promote() { // We can only promote direct borrows of temps. if let Place::Local(local) = *place { if self.mir.local_kind(local) == LocalKind::Temp { @@ -745,7 +754,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { this.visit_operand(arg, location); if is_shuffle && i == 2 && this.mode == Mode::Fn { let candidate = Candidate::ShuffleIndices(bb); - if !this.qualif.intersects(Qualif::NEVER_PROMOTE) { + if this.can_promote() { this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, diff --git a/src/test/run-pass/issue-44373.rs b/src/test/run-pass/issue-44373.rs index 06627e2ad9341..d0f8ed96f4cb3 100644 --- a/src/test/run-pass/issue-44373.rs +++ b/src/test/run-pass/issue-44373.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z borrowck=compare + struct Foo(bool); struct Container(&'static [&'static Foo]);