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.
This commit is contained in:
parent
3a19fbf95d
commit
35919ace70
@ -276,6 +276,7 @@ fn expr_as_place(
|
||||
| ExprKind::Pointer { .. }
|
||||
| ExprKind::Repeat { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::Match { .. }
|
||||
| ExprKind::Loop { .. }
|
||||
| ExprKind::Block { .. }
|
||||
|
@ -276,6 +276,7 @@ fn expr_as_rvalue(
|
||||
| ExprKind::NeverToAny { .. }
|
||||
| ExprKind::Use { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Loop { .. }
|
||||
| ExprKind::LogicalOp { .. }
|
||||
|
@ -49,6 +49,7 @@ pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
|
||||
| ExprKind::Use { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||
|
||||
ExprKind::Array { .. }
|
||||
|
@ -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 @@ pub fn into_expr(
|
||||
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,
|
||||
|
@ -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,
|
||||
|
@ -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>>,
|
||||
|
@ -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;
|
||||
// }
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
// }
|
||||
//
|
||||
// ...
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user