}
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
+
+ // Default to forbidding the borrow and/or its promotion,
+ // due to the potential for direct or interior mutability,
+ // and only proceed by setting `forbidden_mut` to `false`.
+ let mut forbidden_mut = true;
+
if let BorrowKind::Mut { .. } = kind {
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
// is allowed right now, and only in functions.
- let allow = if self.mode == Mode::StaticMut {
+ if self.mode == Mode::StaticMut {
// Inside a `static mut`, &mut [...] is also allowed.
match ty.sty {
- ty::TyArray(..) | ty::TySlice(_) => true,
- _ => false
+ ty::TyArray(..) | ty::TySlice(_) => forbidden_mut = false,
+ _ => {}
}
} else if let ty::TyArray(_, len) = ty.sty {
- len.unwrap_usize(self.tcx) == 0 &&
- self.mode == Mode::Fn
- } else {
- false
- };
+ // FIXME(eddyb) the `self.mode == Mode::Fn` condition
+ // seems unnecessary, given that this is merely a ZST.
+ if len.unwrap_usize(self.tcx) == 0 && self.mode == Mode::Fn {
+ forbidden_mut = false;
+ }
+ }
- if !allow {
+ if forbidden_mut {
self.add(Qualif::NOT_CONST);
if self.mode != Mode::Fn {
let mut err = struct_span_err!(self.tcx.sess, self.span, E0017,
// it means that our "silent insertion of statics" could change
// initializer values (very bad).
if self.qualif.intersects(Qualif::MUTABLE_INTERIOR) {
- // Replace MUTABLE_INTERIOR with NOT_CONST to avoid
+ // A reference of a MUTABLE_INTERIOR place is instead
+ // NOT_CONST (see `if forbidden_mut` below), to avoid
// duplicate errors (from reborrowing, for example).
self.qualif = self.qualif - Qualif::MUTABLE_INTERIOR;
- self.add(Qualif::NOT_CONST);
if self.mode != Mode::Fn {
span_err!(self.tcx.sess, self.span, E0492,
"cannot borrow a constant which may contain \
interior mutability, create a static instead");
}
+ } else {
+ // We allow immutable borrows of frozen data.
+ forbidden_mut = false;
}
}
- // We might have a candidate for promotion.
- let candidate = Candidate::Ref(location);
- if self.can_promote() {
+ if forbidden_mut {
+ self.add(Qualif::NOT_CONST);
+ } else if self.can_promote() {
+ // We might have a candidate for promotion.
+ let candidate = Candidate::Ref(location);
// We can only promote interior borrows of non-drop temps.
let mut place = place;
while let Place::Projection(ref proj) = *place {