about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/diagnostics.rs55
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs123
-rw-r--r--src/test/compile-fail/issue-16538.rs1
-rw-r--r--src/test/run-pass/issue-17718-borrow-interior.rs (renamed from src/test/compile-fail/issue-17718-borrow-interior.rs)6
-rw-r--r--src/test/ui/error-codes/E0394.rs18
-rw-r--r--src/test/ui/error-codes/E0394.stderr11
-rw-r--r--src/test/ui/error-codes/E0494.rs19
-rw-r--r--src/test/ui/error-codes/E0494.stderr9
8 files changed, 27 insertions, 215 deletions
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index c2da1bee395..3c751d52b06 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -1145,33 +1145,6 @@ fn main() {
 ```
 "##,
 
-E0394: r##"
-A static was referred to by value by another static.
-
-Erroneous code examples:
-
-```compile_fail,E0394
-static A: u32 = 0;
-static B: u32 = A; // error: cannot refer to other statics by value, use the
-                   //        address-of operator or a constant instead
-```
-
-A static cannot be referred by value. To fix this issue, either use a
-constant:
-
-```
-const A: u32 = 0; // `A` is now a constant
-static B: u32 = A; // ok!
-```
-
-Or refer to `A` by reference:
-
-```
-static A: u32 = 0;
-static B: &'static u32 = &A; // ok!
-```
-"##,
-
 E0395: r##"
 The value assigned to a constant scalar must be known at compile time,
 which is not the case when comparing raw pointers.
@@ -1333,34 +1306,6 @@ Remember this solution is unsafe! You will have to ensure that accesses to the
 cell are synchronized.
 "##,
 
-E0494: r##"
-A reference of an interior static was assigned to another const/static.
-Erroneous code example:
-
-```compile_fail,E0494
-struct Foo {
-    a: u32
-}
-
-static S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a;
-// error: cannot refer to the interior of another static, use a
-//        constant instead
-```
-
-The "base" variable has to be a const if you want another static/const variable
-to refer to one of its fields. Example:
-
-```
-struct Foo {
-    a: u32
-}
-
-const S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a; // ok!
-```
-"##,
-
 E0499: r##"
 A variable was borrowed as mutable more than once. Erroneous code example:
 
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 144ebce76e1..66106c7eca1 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -56,19 +56,13 @@ bitflags! {
         // Function argument.
         const FN_ARGUMENT       = 1 << 2;
 
-        // Static place or move from a static.
-        const STATIC            = 1 << 3;
-
-        // Reference to a static.
-        const STATIC_REF        = 1 << 4;
-
         // Not constant at all - non-`const fn` calls, asm!,
         // pointer comparisons, ptr-to-int casts, etc.
-        const NOT_CONST         = 1 << 5;
+        const NOT_CONST         = 1 << 3;
 
         // Refers to temporaries which cannot be promoted as
         // promote_consts decided they weren't simple enough.
-        const NOT_PROMOTABLE    = 1 << 6;
+        const NOT_PROMOTABLE    = 1 << 4;
 
         // Const items can only have MUTABLE_INTERIOR
         // and NOT_PROMOTABLE without producing an error.
@@ -226,42 +220,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
         self.add(original);
     }
 
-    /// Check if a Local with the current qualifications is promotable.
-    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 {
-            (qualif - Qualif::STATIC_REF).is_empty()
-        } else {
-            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 {
-            let msg = if self.mode == Mode::Static ||
-                         self.mode == Mode::StaticMut {
-                "cannot refer to other statics by value, use the \
-                 address-of operator or a constant instead"
-            } else {
-                "cannot refer to statics by value, use a constant instead"
-            };
-            struct_span_err!(self.tcx.sess, self.span, E0394, "{}", msg)
-                .span_label(self.span, "referring to another static by value")
-                .note("use the address-of operator or a constant instead")
-                .emit();
-
-            // Replace STATIC with NOT_CONST to avoid further errors.
-            self.qualif = self.qualif - Qualif::STATIC;
-            self.add(Qualif::NOT_CONST);
-
-            false
-        } else {
-            true
-        }
-    }
-
     /// Assign the current qualification to the given destination.
     fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
         trace!("assign: {:?}", dest);
@@ -305,7 +263,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
             }) if self.mir.local_kind(index) == LocalKind::Temp
                && self.mir.local_decls[index].ty.is_box()
                && self.local_qualif[index].map_or(false, |qualif| {
-                    qualif.intersects(Qualif::NOT_CONST)
+                    qualif.contains(Qualif::NOT_CONST)
                }) => {
                 // Part of `box expr`, we should've errored
                 // already for the Box allocation Rvalue.
@@ -492,17 +450,21 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
         match *place {
             Place::Local(ref local) => self.visit_local(local, context, location),
             Place::Static(ref global) => {
-                self.add(Qualif::STATIC);
+                // Only allow statics (not consts) to refer to other statics.
+                if !(self.mode == Mode::Static || self.mode == Mode::StaticMut) {
+                    self.add(Qualif::NOT_CONST);
+                }
 
                 if self.mode != Mode::Fn {
-                    for attr in &self.tcx.get_attrs(global.def_id)[..] {
-                        if attr.check_name("thread_local") {
-                            span_err!(self.tcx.sess, self.span, E0625,
-                                      "thread-local statics cannot be \
-                                       accessed at compile-time");
-                            self.add(Qualif::NOT_CONST);
-                            return;
-                        }
+                    if self.tcx
+                           .get_attrs(global.def_id)
+                           .iter()
+                           .any(|attr| attr.check_name("thread_local")) {
+                        span_err!(self.tcx.sess, self.span, E0625,
+                                    "thread-local statics cannot be \
+                                    accessed at compile-time");
+                        self.add(Qualif::NOT_CONST);
+                        return;
                     }
                 }
 
@@ -527,15 +489,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     this.super_place(place, context, location);
                     match proj.elem {
                         ProjectionElem::Deref => {
-                            if !this.try_consume() {
-                                return;
-                            }
-
-                            if this.qualif.intersects(Qualif::STATIC_REF) {
-                                this.qualif = this.qualif - Qualif::STATIC_REF;
-                                this.add(Qualif::STATIC);
-                            }
-
                             this.add(Qualif::NOT_CONST);
 
                             let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
@@ -573,11 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                                         this.not_const();
                                     }
                                 }
-                            } else if this.qualif.intersects(Qualif::STATIC) {
-                                span_err!(this.tcx.sess, this.span, E0494,
-                                          "cannot refer to the interior of another \
-                                           static, use a constant instead");
                             }
+
                             let ty = place.ty(this.mir, this.tcx).to_ty(this.tcx);
                             this.qualif.restrict(ty, this.tcx, this.param_env);
                         }
@@ -599,7 +549,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             Operand::Move(_) => {
                 self.nest(|this| {
                     this.super_operand(operand, location);
-                    this.try_consume();
                 });
 
                 // Mark the consumed locals to indicate later drops are noops.
@@ -651,14 +600,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                         region,
                         kind
                     }, location);
-                    if !this.try_consume() {
-                        return;
-                    }
-
-                    if this.qualif.intersects(Qualif::STATIC_REF) {
-                        this.qualif = this.qualif - Qualif::STATIC_REF;
-                        this.add(Qualif::STATIC);
-                    }
                 });
             } else {
                 self.super_rvalue(rvalue, location);
@@ -678,22 +619,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
             Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
             Rvalue::Cast(CastKind::Unsize, ..) |
-            Rvalue::Discriminant(..) => {}
-
-            Rvalue::Len(_) => {
-                // Static places in consts would have errored already,
-                // don't treat length checks as reads from statics.
-                self.qualif = self.qualif - Qualif::STATIC;
-            }
+            Rvalue::Discriminant(..) |
+            Rvalue::Len(_) => {}
 
             Rvalue::Ref(_, kind, ref place) => {
-                // Static places in consts would have errored already,
-                // only keep track of references to them here.
-                if self.qualif.intersects(Qualif::STATIC) {
-                    self.qualif = self.qualif - Qualif::STATIC;
-                    self.add(Qualif::STATIC_REF);
-                }
-
                 let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
 
                 // Default to forbidding the borrow and/or its promotion,
@@ -744,7 +673,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     // Constants cannot be borrowed if they contain interior mutability as
                     // it means that our "silent insertion of statics" could change
                     // initializer values (very bad).
-                    if self.qualif.intersects(Qualif::MUTABLE_INTERIOR) {
+                    if self.qualif.contains(Qualif::MUTABLE_INTERIOR) {
                         // A reference of a MUTABLE_INTERIOR place is instead
                         // NOT_CONST (see `if forbidden_mut` below), to avoid
                         // duplicate errors (from reborrowing, for example).
@@ -781,7 +710,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                                 // 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) {
+                                if (qualif - Qualif::MUTABLE_INTERIOR).is_empty() {
                                     self.promotion_candidates.push(candidate);
                                 }
                             }
@@ -889,7 +818,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     if Some(def.did) == self.tcx.lang_items().unsafe_cell_type() {
                         let ty = rvalue.ty(self.mir, self.tcx);
                         self.add_type(ty);
-                        assert!(self.qualif.intersects(Qualif::MUTABLE_INTERIOR));
+                        assert!(self.qualif.contains(Qualif::MUTABLE_INTERIOR));
                     }
                 }
             }
@@ -949,7 +878,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     }
                     let candidate = Candidate::Argument { bb, index: i };
                     if is_shuffle && i == 2 {
-                        if this.can_promote(this.qualif) {
+                        if this.qualif.is_empty() {
                             this.promotion_candidates.push(candidate);
                         } else {
                             span_err!(this.tcx.sess, this.span, E0526,
@@ -965,7 +894,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     if !constant_arguments.contains(&i) {
                         return
                     }
-                    if this.can_promote(this.qualif) {
+                    if this.qualif.is_empty() {
                         this.promotion_candidates.push(candidate);
                     } else {
                         this.tcx.sess.span_err(this.span,
@@ -1059,7 +988,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                 // HACK(eddyb) Emulate a bit of dataflow analysis,
                 // conservatively, that drop elaboration will do.
                 let needs_drop = if let Place::Local(local) = *place {
-                    if self.local_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
+                    if self.local_qualif[local].map_or(true, |q| q.contains(Qualif::NEEDS_DROP)) {
                         Some(self.mir.local_decls[local].source_info.span)
                     } else {
                         None
@@ -1111,7 +1040,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                 }
 
                 // Avoid a generic error for other uses of arguments.
-                if self.qualif.intersects(Qualif::FN_ARGUMENT) {
+                if self.qualif.contains(Qualif::FN_ARGUMENT) {
                     let decl = &self.mir.local_decls[index];
                     let mut err = feature_err(
                         &self.tcx.sess.parse_sess,
diff --git a/src/test/compile-fail/issue-16538.rs b/src/test/compile-fail/issue-16538.rs
index 7df445c676c..cc652119377 100644
--- a/src/test/compile-fail/issue-16538.rs
+++ b/src/test/compile-fail/issue-16538.rs
@@ -22,7 +22,6 @@ mod Y {
 
 static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
 //~^ ERROR `*const usize` cannot be shared between threads safely [E0277]
-//~| ERROR cannot refer to other statics by value, use the address-of operator or a constant instead
 //~| ERROR E0015
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-17718-borrow-interior.rs b/src/test/run-pass/issue-17718-borrow-interior.rs
index 31352c57f1b..77df168c257 100644
--- a/src/test/compile-fail/issue-17718-borrow-interior.rs
+++ b/src/test/run-pass/issue-17718-borrow-interior.rs
@@ -9,17 +9,13 @@
 // except according to those terms.
 
 struct S { a: usize }
+
 static A: S  = S { a: 3 };
 static B: &'static usize = &A.a;
-//~^ ERROR: cannot refer to the interior of another static
 static C: &'static usize = &(A.a);
-//~^ ERROR: cannot refer to the interior of another static
 
 static D: [usize; 1] = [1];
 static E: usize = D[0];
-//~^ ERROR: cannot refer to the interior of another static
-//~^^ ERROR: cannot refer to other statics by value
 static F: &'static usize = &D[0];
-//~^ ERROR: cannot refer to the interior of another static
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0394.rs b/src/test/ui/error-codes/E0394.rs
deleted file mode 100644
index dae8e14c5ef..00000000000
--- a/src/test/ui/error-codes/E0394.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 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.
-
-#![allow(warnings)]
-
-static A: u32 = 0;
-static B: u32 = A;
-//~^ ERROR E0394
-
-fn main() {
-}
diff --git a/src/test/ui/error-codes/E0394.stderr b/src/test/ui/error-codes/E0394.stderr
deleted file mode 100644
index 6c89957de07..00000000000
--- a/src/test/ui/error-codes/E0394.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0394]: cannot refer to other statics by value, use the address-of operator or a constant instead
-  --> $DIR/E0394.rs:14:17
-   |
-LL | static B: u32 = A;
-   |                 ^ referring to another static by value
-   |
-   = note: use the address-of operator or a constant instead
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0394`.
diff --git a/src/test/ui/error-codes/E0494.rs b/src/test/ui/error-codes/E0494.rs
deleted file mode 100644
index 5f8632ac1c2..00000000000
--- a/src/test/ui/error-codes/E0494.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 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.
-
-struct Foo {
-    a: u32
-}
-
-static S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a; //~ ERROR E0494
-
-fn main() {
-}
diff --git a/src/test/ui/error-codes/E0494.stderr b/src/test/ui/error-codes/E0494.stderr
deleted file mode 100644
index 65e6b1fe670..00000000000
--- a/src/test/ui/error-codes/E0494.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0494]: cannot refer to the interior of another static, use a constant instead
-  --> $DIR/E0494.rs:16:27
-   |
-LL | static A : &'static u32 = &S.a; //~ ERROR E0494
-   |                           ^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0494`.