about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-04-20 18:06:03 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2019-12-18 20:09:10 +0000
commit35919ace7084e10fce15cb9bb42a9404b63b849d (patch)
tree5f47e21ee65f14b8a542b554a7f6b3787f3f5c74
parent3a19fbf95d3b289f4c17aba910051cd9afd75887 (diff)
downloadrust-35919ace7084e10fce15cb9bb42a9404b63b849d.tar.gz
rust-35919ace7084e10fce15cb9bb42a9404b63b849d.zip
Start generating AddressOf rvalues in MIR
`hir::BorrowKind::Raw` borrows and casting a reference to a raw
pointer no longer do a reborrow followed by a cast. Instead we
dereference and take the address.
-rw-r--r--src/librustc_mir/build/expr/as_place.rs1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs1
-rw-r--r--src/librustc_mir/build/expr/category.rs1
-rw-r--r--src/librustc_mir/build/expr/into.rs18
-rw-r--r--src/librustc_mir/hair/cx/expr.rs84
-rw-r--r--src/librustc_mir/hair/mod.rs5
-rw-r--r--src/test/mir-opt/array-index-is-temporary.rs19
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs18
-rw-r--r--src/test/mir-opt/retag.rs10
-rw-r--r--src/test/ui/cast/cast-as-bool.rs2
-rw-r--r--src/test/ui/cast/cast-as-bool.stderr7
11 files changed, 61 insertions, 105 deletions
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index ddacda72e1e..15c7c92d7db 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::Pointer { .. }
             | ExprKind::Repeat { .. }
             | ExprKind::Borrow { .. }
+            | ExprKind::AddressOf { .. }
             | ExprKind::Match { .. }
             | ExprKind::Loop { .. }
             | ExprKind::Block { .. }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 37eb0cc9d96..24282a6617a 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::NeverToAny { .. }
             | ExprKind::Use { .. }
             | ExprKind::Borrow { .. }
+            | ExprKind::AddressOf { .. }
             | ExprKind::Adt { .. }
             | ExprKind::Loop { .. }
             | ExprKind::LogicalOp { .. }
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index 270a1a64474..4d0039b2e8c 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -49,6 +49,7 @@ impl Category {
             | ExprKind::Use { .. }
             | ExprKind::Adt { .. }
             | ExprKind::Borrow { .. }
+            | ExprKind::AddressOf { .. }
             | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
 
             ExprKind::Array { .. }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 07a44b190b2..6b33e8433f6 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -3,6 +3,7 @@
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::hair::*;
+use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation};
 use rustc_data_structures::fx::FxHashMap;
@@ -295,6 +296,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.push_assign(block, source_info, destination, borrow);
                 block.unit()
             }
+            ExprKind::AddressOf {
+                mutability,
+                arg,
+            } => {
+                let address_of = match mutability {
+                    hir::Mutability::Immutable => Rvalue::AddressOf(
+                        Mutability::Not,
+                        unpack!(block = this.as_read_only_place(block, arg)),
+                    ),
+                    hir::Mutability::Mutable => Rvalue::AddressOf(
+                        Mutability::Mut,
+                        unpack!(block = this.as_place(block, arg)),
+                    ),
+                };
+                this.cfg.push_assign(block, source_info, destination, address_of);
+                block.unit()
+            }
             ExprKind::Adt {
                 adt_def,
                 variant_index,
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 8c852854be1..6cbc25aa735 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>(
                 arg: expr.to_ref(),
             }
         }
-        Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => {
-            raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime)
+        Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
+            ExprKind::AddressOf {
+                mutability,
+                arg: expr.to_ref(),
+            }
         }
     };
 
@@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
             }
         }
 
-        hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => {
-            cx.tcx.sess
-                .struct_span_err(
-                    expr.span,
-                    "raw borrows are not yet implemented"
-                )
-                .note("for more information, see https://github.com/rust-lang/rust/issues/64490")
-                .emit();
-
-            // Lower to an approximation to avoid further errors.
-            raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime)
+        hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
+            ExprKind::AddressOf {
+                mutability,
+                arg: arg.to_ref(),
+            }
         }
 
         hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
@@ -1082,67 +1079,6 @@ fn convert_var(
 }
 
 
-/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf`
-/// exists in MIR.
-fn raw_ref_shim<'tcx>(
-    cx: &mut Cx<'_, 'tcx>,
-    arg: ExprRef<'tcx>,
-    ty: Ty<'tcx>,
-    mutbl: hir::Mutability,
-    span: Span,
-    temp_lifetime: Option<region::Scope>,
-) -> ExprKind<'tcx> {
-    let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind {
-        type_mutbl
-    } else {
-        bug!("raw_ref_shim called with non-raw pointer type");
-    };
-    // Convert this to a suitable `&foo` and
-    // then an unsafe coercion.
-    let borrow_expr = Expr {
-        temp_lifetime,
-        ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm),
-        span,
-        kind: ExprKind::Borrow {
-            borrow_kind: mutbl.to_borrow_kind(),
-            arg,
-        },
-    };
-    let cast_expr = Expr {
-        temp_lifetime,
-        ty,
-        span,
-        kind: ExprKind::Cast { source: borrow_expr.to_ref() }
-    };
-
-    // To ensure that both implicit and explicit coercions are
-    // handled the same way, we insert an extra layer of indirection here.
-    // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
-    // will be an ExprKind::Hair with the appropriate cast expression. Here,
-    // we make our Use source the generated Cast from the original coercion.
-    //
-    // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
-    // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
-    // Ordinary, this is identical to using the cast directly as an rvalue. However, if the
-    // source of the cast was previously borrowed as mutable, storing the cast in a
-    // temporary gives the source a chance to expire before the cast is used. For
-    // structs with a self-referential *mut ptr, this allows assignment to work as
-    // expected.
-    //
-    // For example, consider the type 'struct Foo { field: *mut Foo }',
-    // The method 'fn bar(&mut self) { self.field = self }'
-    // triggers a coercion from '&mut self' to '*mut self'. In order
-    // for the assignment to be valid, the implicit borrow
-    // of 'self' involved in the coercion needs to end before the local
-    // containing the '*mut T' is assigned to 'self.field' - otherwise,
-    // we end up trying to assign to 'self.field' while we have another mutable borrow
-    // active.
-    //
-    // We only need to worry about this kind of thing for coercions from refs to ptrs,
-    // since they get rid of a borrow implicitly.
-    ExprKind::Use { source: cast_expr.to_ref() }
-}
-
 fn bin_op(op: hir::BinOpKind) -> BinOp {
     match op {
         hir::BinOpKind::Add => BinOp::Add,
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 47644d9ba83..46e0d2a17b3 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> {
         borrow_kind: BorrowKind,
         arg: ExprRef<'tcx>,
     },
+    /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
+    AddressOf {
+        mutability: hir::Mutability,
+        arg: ExprRef<'tcx>,
+    },
     Break {
         label: region::Scope,
         value: Option<ExprRef<'tcx>>,
diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs
index 00a6b26d0cf..096f98bade2 100644
--- a/src/test/mir-opt/array-index-is-temporary.rs
+++ b/src/test/mir-opt/array-index-is-temporary.rs
@@ -18,24 +18,23 @@ fn main() {
 // START rustc.main.EraseRegions.after.mir
 //     bb0: {
 //         ...
-//         _5 = &mut _2;
-//         _4 = &mut (*_5);
-//         _3 = move _4 as *mut usize (Misc);
+//         _4 = &mut _2;
+//         _3 = &raw mut (*_4);
 //         ...
-//         _7 = _3;
-//         _6 = const foo(move _7) -> bb1;
+//         _6 = _3;
+//         _5 = const foo(move _6) -> bb1;
 //     }
 //
 //     bb1: {
 //         ...
-//         _8 = _2;
-//         _9 = Len(_1);
-//         _10 = Lt(_8, _9);
-//         assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2;
+//         _7 = _2;
+//         _8 = Len(_1);
+//         _9 = Lt(_7, _8);
+//         assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2;
 //     }
 //
 //     bb2: {
-//         _1[_8] = move _6;
+//         _1[_7] = move _5;
 //         ...
 //         return;
 //     }
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
index 3f82b81a47d..3c8c0ff4493 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
@@ -11,25 +11,21 @@ fn main() {
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _3 = _4;
-//      _2 = move _3 as *const i32 (Misc);
-//      ...
+//      _2 = &raw const (*_3);
 //      _1 = move _2 as usize (Misc);
 //      ...
-//      _6 = _1;
-//      _5 = const read(move _6) -> bb1;
+//      _5 = _1;
+//      _4 = const read(move _5) -> bb1;
 //  }
 // END rustc.main.ConstProp.before.mir
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _4 = const main::FOO;
-//      _3 = _4;
-//      _2 = move _3 as *const i32 (Misc);
-//      ...
+//      _3 = const main::FOO;
+//      _2 = &raw const (*_3);
 //      _1 = move _2 as usize (Misc);
 //      ...
-//      _6 = _1;
-//      _5 = const read(move _6) -> bb1;
+//      _5 = _1;
+//      _4 = const read(move _5) -> bb1;
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index 32995448a21..ccecaeac96b 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -82,18 +82,16 @@ fn main() {
 //         _10 = move _8;
 //         Retag(_10);
 //         ...
-//         _13 = &mut (*_10);
-//         Retag(_13);
-//         _12 = move _13 as *mut i32 (Misc);
+//         _12 = &raw mut (*_10);
 //         Retag([raw] _12);
 //         ...
-//         _16 = move _17(move _18) -> bb5;
+//         _15 = move _16(move _17) -> bb5;
 //     }
 //
 //     bb5: {
-//         Retag(_16);
+//         Retag(_15);
 //         ...
-//         _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7];
+//         _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7];
 //     }
 //
 //     ...
diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs
index 8130f4dedc9..1aed218aeb4 100644
--- a/src/test/ui/cast/cast-as-bool.rs
+++ b/src/test/ui/cast/cast-as-bool.rs
@@ -5,5 +5,5 @@ fn main() {
     let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
                              //~| HELP compare with zero instead
                              //~| SUGGESTION (1 + 2) != 0
-    let v = "hello" as bool; //~ ERROR cannot cast as `bool`
+    let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid
 }
diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr
index 30f8459c2e1..15d94ab69d8 100644
--- a/src/test/ui/cast/cast-as-bool.stderr
+++ b/src/test/ui/cast/cast-as-bool.stderr
@@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool`
 LL |     let t = (1 + 2) as bool;
    |             ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
 
-error[E0054]: cannot cast as `bool`
+error[E0606]: casting `&'static str` as `bool` is invalid
   --> $DIR/cast-as-bool.rs:8:13
    |
 LL |     let v = "hello" as bool;
-   |             ^^^^^^^^^^^^^^^ unsupported cast
+   |             ^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0054`.
+Some errors have detailed explanations: E0054, E0606.
+For more information about an error, try `rustc --explain E0054`.