diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 03ca85faaff..f3fba5b47be 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -566,8 +566,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { 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"); diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 74b9315f0c1..82ac112b534 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -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 index 00000000000..714d7a4fc8b --- /dev/null +++ b/src/test/ui/const-eval/union_promotion.rs @@ -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 or the MIT license +// , 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 index 00000000000..b4aa91f2de7 --- /dev/null +++ b/src/test/ui/const-eval/union_promotion.stderr @@ -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`.