}
/// Check if a Local with the current qualifications is promotable.
- fn can_promote(&mut self) -> bool {
+ fn can_promote(&self, qualif: Qualif) -> 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()
+ (qualif - Qualif::STATIC_REF).is_empty()
} else {
- self.qualif.is_empty()
+ qualif.is_empty()
}
}
if forbidden_mut {
self.add(Qualif::NOT_CONST);
- } else if self.can_promote() {
+ } else {
// We might have a candidate for promotion.
let candidate = Candidate::Ref(location);
- // We can only promote interior borrows of non-drop temps.
+ // We can only promote interior borrows of promotable temps.
let mut place = place;
while let Place::Projection(ref proj) = *place {
if proj.elem == ProjectionElem::Deref {
if let Place::Local(local) = *place {
if self.mir.local_kind(local) == LocalKind::Temp {
if let Some(qualif) = self.temp_qualif[local] {
- if !qualif.intersects(Qualif::NEEDS_DROP) {
+ // `forbidden_mut` is false, so we can safely ignore
+ // `MUTABLE_INTERIOR` from the local's qualifications.
+ // This allows borrowing fields which don't have
+ // `MUTABLE_INTERIOR`, from a type that does, e.g.:
+ // `let _: &'static _ = &(Cell::new(1), 2).1;`
+ if self.can_promote(qualif - Qualif::MUTABLE_INTERIOR) {
self.promotion_candidates.push(candidate);
}
}
}
let candidate = Candidate::Argument { bb, index: i };
if is_shuffle && i == 2 {
- if this.can_promote() {
+ if this.can_promote(this.qualif) {
this.promotion_candidates.push(candidate);
} else {
span_err!(this.tcx.sess, this.span, E0526,
if !constant_arguments.contains(&i) {
return
}
- if this.can_promote() {
+ if this.can_promote(this.qualif) {
this.promotion_candidates.push(candidate);
} else {
this.tcx.sess.span_err(this.span,
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z borrowck=mir
+
+use std::cell::Cell;
+
+#[inline(never)]
+fn tuple_field() -> &'static u32 {
+ // This test is MIR-borrowck-only because the old borrowck
+ // doesn't agree that borrows of "frozen" (i.e. without any
+ // interior mutability) fields of non-frozen temporaries,
+ // should be promoted, while MIR promotion does promote them.
+ &(Cell::new(5), 42).1
+}
+
+fn main() {
+ assert_eq!(tuple_field().to_string(), "42");
+}