]> git.lizzy.rs Git - rust.git/commitdiff
Do not promote union field accesses
authorOliver Schneider <github35764891676564198441@oli-obk.de>
Sun, 3 Jun 2018 17:00:22 +0000 (19:00 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Sun, 3 Jun 2018 17:06:31 +0000 (19:06 +0200)
src/librustc_mir/transform/qualify_consts.rs
src/librustc_passes/rvalue_promotion.rs
src/test/ui/const-eval/union_promotion.rs [new file with mode: 0644]
src/test/ui/const-eval/union_promotion.stderr [new file with mode: 0644]

index 03ca85faafff6b6af56c96eb14d1154c375d89c9..f3fba5b47be14080d99de722ae123fc29a3ba1b8 100644 (file)
@@ -566,8 +566,14 @@ fn visit_place(&mut self,
 
                         ProjectionElem::Field(..) |
                         ProjectionElem::Index(_) => {
-                            if this.mode != Mode::Fn &&
-                               this.qualif.intersects(Qualif::STATIC) {
+                            if this.mode == Mode::Fn {
+                                let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
+                                if let Some(def) = base_ty.ty_adt_def() {
+                                    if def.is_union() {
+                                        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");
index 74b9315f0c1eed1a043313a99d23e964b9dc8bf9..82ac112b534e9f5dd317633a0209cf903de0866a 100644 (file)
@@ -445,9 +445,16 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             }
         }
 
+        hir::ExprField(ref expr, _) => {
+            if let Some(def) = v.tables.expr_ty(expr).ty_adt_def() {
+                if def.is_union() {
+                    v.promotable = false
+                }
+            }
+        }
+
         hir::ExprBlock(..) |
         hir::ExprIndex(..) |
-        hir::ExprField(..) |
         hir::ExprArray(_) |
         hir::ExprType(..) |
         hir::ExprTup(..) => {}
diff --git a/src/test/ui/const-eval/union_promotion.rs b/src/test/ui/const-eval/union_promotion.rs
new file mode 100644 (file)
index 0000000..714d7a4
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+#![allow(const_err)]
+
+union Foo {
+    a: &'static u32,
+    b: usize,
+}
+
+fn main() {
+    let x: &'static bool = &unsafe { //~ borrowed value does not live long enough
+        Foo { a: &1 }.b == Foo { a: &2 }.b
+    };
+}
diff --git a/src/test/ui/const-eval/union_promotion.stderr b/src/test/ui/const-eval/union_promotion.stderr
new file mode 100644 (file)
index 0000000..b4aa91f
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/union_promotion.rs:19:29
+   |
+LL |       let x: &'static bool = &unsafe { //~ borrowed value does not live long enough
+   |  _____________________________^
+LL | |         Foo { a: &1 }.b == Foo { a: &2 }.b
+LL | |     };
+   | |_____^ temporary value does not live long enough
+LL |   }
+   |   - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.