Skip to content

Commit 35919ac

Browse files
committed
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.
1 parent 3a19fbf commit 35919ac

File tree

11 files changed

+61
-105
lines changed

11 files changed

+61
-105
lines changed

src/librustc_mir/build/expr/as_place.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
276276
| ExprKind::Pointer { .. }
277277
| ExprKind::Repeat { .. }
278278
| ExprKind::Borrow { .. }
279+
| ExprKind::AddressOf { .. }
279280
| ExprKind::Match { .. }
280281
| ExprKind::Loop { .. }
281282
| ExprKind::Block { .. }

src/librustc_mir/build/expr/as_rvalue.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
276276
| ExprKind::NeverToAny { .. }
277277
| ExprKind::Use { .. }
278278
| ExprKind::Borrow { .. }
279+
| ExprKind::AddressOf { .. }
279280
| ExprKind::Adt { .. }
280281
| ExprKind::Loop { .. }
281282
| ExprKind::LogicalOp { .. }

src/librustc_mir/build/expr/category.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ impl Category {
4949
| ExprKind::Use { .. }
5050
| ExprKind::Adt { .. }
5151
| ExprKind::Borrow { .. }
52+
| ExprKind::AddressOf { .. }
5253
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
5354

5455
ExprKind::Array { .. }

src/librustc_mir/build/expr/into.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::build::expr::category::{Category, RvalueFunc};
44
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
55
use crate::hair::*;
6+
use rustc::hir;
67
use rustc::mir::*;
78
use rustc::ty::{self, CanonicalUserTypeAnnotation};
89
use rustc_data_structures::fx::FxHashMap;
@@ -295,6 +296,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
295296
this.cfg.push_assign(block, source_info, destination, borrow);
296297
block.unit()
297298
}
299+
ExprKind::AddressOf {
300+
mutability,
301+
arg,
302+
} => {
303+
let address_of = match mutability {
304+
hir::Mutability::Immutable => Rvalue::AddressOf(
305+
Mutability::Not,
306+
unpack!(block = this.as_read_only_place(block, arg)),
307+
),
308+
hir::Mutability::Mutable => Rvalue::AddressOf(
309+
Mutability::Mut,
310+
unpack!(block = this.as_place(block, arg)),
311+
),
312+
};
313+
this.cfg.push_assign(block, source_info, destination, address_of);
314+
block.unit()
315+
}
298316
ExprKind::Adt {
299317
adt_def,
300318
variant_index,

src/librustc_mir/hair/cx/expr.rs

Lines changed: 10 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>(
137137
arg: expr.to_ref(),
138138
}
139139
}
140-
Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => {
141-
raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime)
140+
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
141+
ExprKind::AddressOf {
142+
mutability,
143+
arg: expr.to_ref(),
144+
}
142145
}
143146
};
144147

@@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
262265
}
263266
}
264267

265-
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => {
266-
cx.tcx.sess
267-
.struct_span_err(
268-
expr.span,
269-
"raw borrows are not yet implemented"
270-
)
271-
.note("for more information, see https://github.com/rust-lang/rust/issues/64490")
272-
.emit();
273-
274-
// Lower to an approximation to avoid further errors.
275-
raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime)
268+
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
269+
ExprKind::AddressOf {
270+
mutability,
271+
arg: arg.to_ref(),
272+
}
276273
}
277274

278275
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
@@ -1082,67 +1079,6 @@ fn convert_var(
10821079
}
10831080

10841081

1085-
/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf`
1086-
/// exists in MIR.
1087-
fn raw_ref_shim<'tcx>(
1088-
cx: &mut Cx<'_, 'tcx>,
1089-
arg: ExprRef<'tcx>,
1090-
ty: Ty<'tcx>,
1091-
mutbl: hir::Mutability,
1092-
span: Span,
1093-
temp_lifetime: Option<region::Scope>,
1094-
) -> ExprKind<'tcx> {
1095-
let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind {
1096-
type_mutbl
1097-
} else {
1098-
bug!("raw_ref_shim called with non-raw pointer type");
1099-
};
1100-
// Convert this to a suitable `&foo` and
1101-
// then an unsafe coercion.
1102-
let borrow_expr = Expr {
1103-
temp_lifetime,
1104-
ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm),
1105-
span,
1106-
kind: ExprKind::Borrow {
1107-
borrow_kind: mutbl.to_borrow_kind(),
1108-
arg,
1109-
},
1110-
};
1111-
let cast_expr = Expr {
1112-
temp_lifetime,
1113-
ty,
1114-
span,
1115-
kind: ExprKind::Cast { source: borrow_expr.to_ref() }
1116-
};
1117-
1118-
// To ensure that both implicit and explicit coercions are
1119-
// handled the same way, we insert an extra layer of indirection here.
1120-
// For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
1121-
// will be an ExprKind::Hair with the appropriate cast expression. Here,
1122-
// we make our Use source the generated Cast from the original coercion.
1123-
//
1124-
// In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
1125-
// as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
1126-
// Ordinary, this is identical to using the cast directly as an rvalue. However, if the
1127-
// source of the cast was previously borrowed as mutable, storing the cast in a
1128-
// temporary gives the source a chance to expire before the cast is used. For
1129-
// structs with a self-referential *mut ptr, this allows assignment to work as
1130-
// expected.
1131-
//
1132-
// For example, consider the type 'struct Foo { field: *mut Foo }',
1133-
// The method 'fn bar(&mut self) { self.field = self }'
1134-
// triggers a coercion from '&mut self' to '*mut self'. In order
1135-
// for the assignment to be valid, the implicit borrow
1136-
// of 'self' involved in the coercion needs to end before the local
1137-
// containing the '*mut T' is assigned to 'self.field' - otherwise,
1138-
// we end up trying to assign to 'self.field' while we have another mutable borrow
1139-
// active.
1140-
//
1141-
// We only need to worry about this kind of thing for coercions from refs to ptrs,
1142-
// since they get rid of a borrow implicitly.
1143-
ExprKind::Use { source: cast_expr.to_ref() }
1144-
}
1145-
11461082
fn bin_op(op: hir::BinOpKind) -> BinOp {
11471083
match op {
11481084
hir::BinOpKind::Add => BinOp::Add,

src/librustc_mir/hair/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> {
212212
borrow_kind: BorrowKind,
213213
arg: ExprRef<'tcx>,
214214
},
215+
/// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
216+
AddressOf {
217+
mutability: hir::Mutability,
218+
arg: ExprRef<'tcx>,
219+
},
215220
Break {
216221
label: region::Scope,
217222
value: Option<ExprRef<'tcx>>,

src/test/mir-opt/array-index-is-temporary.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,23 @@ fn main() {
1818
// START rustc.main.EraseRegions.after.mir
1919
// bb0: {
2020
// ...
21-
// _5 = &mut _2;
22-
// _4 = &mut (*_5);
23-
// _3 = move _4 as *mut usize (Misc);
21+
// _4 = &mut _2;
22+
// _3 = &raw mut (*_4);
2423
// ...
25-
// _7 = _3;
26-
// _6 = const foo(move _7) -> bb1;
24+
// _6 = _3;
25+
// _5 = const foo(move _6) -> bb1;
2726
// }
2827
//
2928
// bb1: {
3029
// ...
31-
// _8 = _2;
32-
// _9 = Len(_1);
33-
// _10 = Lt(_8, _9);
34-
// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2;
30+
// _7 = _2;
31+
// _8 = Len(_1);
32+
// _9 = Lt(_7, _8);
33+
// assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2;
3534
// }
3635
//
3736
// bb2: {
38-
// _1[_8] = move _6;
37+
// _1[_7] = move _5;
3938
// ...
4039
// return;
4140
// }

src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,21 @@ fn main() {
1111
// START rustc.main.ConstProp.before.mir
1212
// bb0: {
1313
// ...
14-
// _3 = _4;
15-
// _2 = move _3 as *const i32 (Misc);
16-
// ...
14+
// _2 = &raw const (*_3);
1715
// _1 = move _2 as usize (Misc);
1816
// ...
19-
// _6 = _1;
20-
// _5 = const read(move _6) -> bb1;
17+
// _5 = _1;
18+
// _4 = const read(move _5) -> bb1;
2119
// }
2220
// END rustc.main.ConstProp.before.mir
2321
// START rustc.main.ConstProp.after.mir
2422
// bb0: {
2523
// ...
26-
// _4 = const main::FOO;
27-
// _3 = _4;
28-
// _2 = move _3 as *const i32 (Misc);
29-
// ...
24+
// _3 = const main::FOO;
25+
// _2 = &raw const (*_3);
3026
// _1 = move _2 as usize (Misc);
3127
// ...
32-
// _6 = _1;
33-
// _5 = const read(move _6) -> bb1;
28+
// _5 = _1;
29+
// _4 = const read(move _5) -> bb1;
3430
// }
3531
// END rustc.main.ConstProp.after.mir

src/test/mir-opt/retag.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,16 @@ fn main() {
8282
// _10 = move _8;
8383
// Retag(_10);
8484
// ...
85-
// _13 = &mut (*_10);
86-
// Retag(_13);
87-
// _12 = move _13 as *mut i32 (Misc);
85+
// _12 = &raw mut (*_10);
8886
// Retag([raw] _12);
8987
// ...
90-
// _16 = move _17(move _18) -> bb5;
88+
// _15 = move _16(move _17) -> bb5;
9189
// }
9290
//
9391
// bb5: {
94-
// Retag(_16);
92+
// Retag(_15);
9593
// ...
96-
// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7];
94+
// _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7];
9795
// }
9896
//
9997
// ...

src/test/ui/cast/cast-as-bool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ fn main() {
55
let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
66
//~| HELP compare with zero instead
77
//~| SUGGESTION (1 + 2) != 0
8-
let v = "hello" as bool; //~ ERROR cannot cast as `bool`
8+
let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid
99
}

src/test/ui/cast/cast-as-bool.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool`
1010
LL | let t = (1 + 2) as bool;
1111
| ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
1212

13-
error[E0054]: cannot cast as `bool`
13+
error[E0606]: casting `&'static str` as `bool` is invalid
1414
--> $DIR/cast-as-bool.rs:8:13
1515
|
1616
LL | let v = "hello" as bool;
17-
| ^^^^^^^^^^^^^^^ unsupported cast
17+
| ^^^^^^^^^^^^^^^
1818

1919
error: aborting due to 3 previous errors
2020

21-
For more information about this error, try `rustc --explain E0054`.
21+
Some errors have detailed explanations: E0054, E0606.
22+
For more information about an error, try `rustc --explain E0054`.

0 commit comments

Comments
 (0)