diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index a9dfc6ea651..118b23cf987 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -96,6 +96,7 @@ fn expr_as_lvalue(&mut self, ExprKind::LogicalOp { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } | + ExprKind::Use { .. } | ExprKind::NeverToAny { .. } | ExprKind::ReifyFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } | diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 2123235ddc1..9b7f3468c19 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -115,6 +115,10 @@ fn expr_as_rvalue(&mut self, let source = unpack!(block = this.as_operand(block, source)); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } + ExprKind::Use { source } => { + let source = unpack!(block = this.as_operand(block, source)); + block.and(Rvalue::Use(source)) + } ExprKind::ReifyFnPointer { source } => { let source = unpack!(block = this.as_operand(block, source)); block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty)) diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index c19ea0f445a..9671f80f48b 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -68,6 +68,7 @@ pub fn of<'tcx>(ek: &ExprKind<'tcx>) -> Option { ExprKind::Binary { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } | + ExprKind::Use { .. } | ExprKind::ReifyFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } | ExprKind::Unsize { .. } | diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index e5930f5a62d..58265b5b0d3 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -249,6 +249,7 @@ pub fn into_expr(&mut self, ExprKind::Binary { .. } | ExprKind::Box { .. } | ExprKind::Cast { .. } | + ExprKind::Use { .. } | ExprKind::ReifyFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } | ExprKind::Unsize { .. } | diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 2840538ae5b..00aab94ccdd 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -600,8 +600,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Check to see if this cast is a "coercion cast", where the cast is actually done // using a coercion (or is a no-op). if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) { - // Skip the actual cast itexpr, as it's now a no-op. - return source.make_mirror(cx); + // Convert the lexpr to a vexpr. + ExprKind::Use { source: source.to_ref() } } else { ExprKind::Cast { source: source.to_ref() } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 353f2433353..59137e2bcd7 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> { Cast { source: ExprRef<'tcx>, }, + Use { + source: ExprRef<'tcx>, + }, // Use a lexpr to get a vexpr. NeverToAny { source: ExprRef<'tcx>, }, diff --git a/src/test/run-pass/issue-36936.rs b/src/test/run-pass/issue-36936.rs new file mode 100644 index 00000000000..34a9c291668 --- /dev/null +++ b/src/test/run-pass/issue-36936.rs @@ -0,0 +1,35 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that casts are not being treated as lexprs. + +fn main() { + let mut a = 0i32; + let b = &(a as i32); + a = 1; + assert_ne!(&a as *const i32, b as *const i32); + assert_eq!(*b, 0); + + assert_eq!(issue_36936(), 1); +} + + +struct A(u32); + +impl Drop for A { + fn drop(&mut self) { + self.0 = 0; + } +} + +fn issue_36936() -> u32 { + let a = &(A(1) as A); + a.0 +}