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::Pointer { .. }
|
||||||
| ExprKind::Repeat { .. }
|
| ExprKind::Repeat { .. }
|
||||||
| ExprKind::Borrow { .. }
|
| ExprKind::Borrow { .. }
|
||||||
|
| ExprKind::AddressOf { .. }
|
||||||
| ExprKind::Match { .. }
|
| ExprKind::Match { .. }
|
||||||
| ExprKind::Loop { .. }
|
| ExprKind::Loop { .. }
|
||||||
| ExprKind::Block { .. }
|
| ExprKind::Block { .. }
|
||||||
|
@ -276,6 +276,7 @@ fn expr_as_rvalue(
|
|||||||
| ExprKind::NeverToAny { .. }
|
| ExprKind::NeverToAny { .. }
|
||||||
| ExprKind::Use { .. }
|
| ExprKind::Use { .. }
|
||||||
| ExprKind::Borrow { .. }
|
| ExprKind::Borrow { .. }
|
||||||
|
| ExprKind::AddressOf { .. }
|
||||||
| ExprKind::Adt { .. }
|
| ExprKind::Adt { .. }
|
||||||
| ExprKind::Loop { .. }
|
| ExprKind::Loop { .. }
|
||||||
| ExprKind::LogicalOp { .. }
|
| ExprKind::LogicalOp { .. }
|
||||||
|
@ -49,6 +49,7 @@ pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
|
|||||||
| ExprKind::Use { .. }
|
| ExprKind::Use { .. }
|
||||||
| ExprKind::Adt { .. }
|
| ExprKind::Adt { .. }
|
||||||
| ExprKind::Borrow { .. }
|
| ExprKind::Borrow { .. }
|
||||||
|
| ExprKind::AddressOf { .. }
|
||||||
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||||
|
|
||||||
ExprKind::Array { .. }
|
ExprKind::Array { .. }
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use crate::build::expr::category::{Category, RvalueFunc};
|
use crate::build::expr::category::{Category, RvalueFunc};
|
||||||
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
|
||||||
use crate::hair::*;
|
use crate::hair::*;
|
||||||
|
use rustc::hir;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::ty::{self, CanonicalUserTypeAnnotation};
|
use rustc::ty::{self, CanonicalUserTypeAnnotation};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
@ -295,6 +296,23 @@ pub fn into_expr(
|
|||||||
this.cfg.push_assign(block, source_info, destination, borrow);
|
this.cfg.push_assign(block, source_info, destination, borrow);
|
||||||
block.unit()
|
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 {
|
ExprKind::Adt {
|
||||||
adt_def,
|
adt_def,
|
||||||
variant_index,
|
variant_index,
|
||||||
|
@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>(
|
|||||||
arg: expr.to_ref(),
|
arg: expr.to_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => {
|
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
||||||
raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime)
|
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) => {
|
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
|
||||||
cx.tcx.sess
|
ExprKind::AddressOf {
|
||||||
.struct_span_err(
|
mutability,
|
||||||
expr.span,
|
arg: arg.to_ref(),
|
||||||
"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::Block(ref blk, _) => ExprKind::Block { body: &blk },
|
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 {
|
fn bin_op(op: hir::BinOpKind) -> BinOp {
|
||||||
match op {
|
match op {
|
||||||
hir::BinOpKind::Add => BinOp::Add,
|
hir::BinOpKind::Add => BinOp::Add,
|
||||||
|
@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> {
|
|||||||
borrow_kind: BorrowKind,
|
borrow_kind: BorrowKind,
|
||||||
arg: ExprRef<'tcx>,
|
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 {
|
Break {
|
||||||
label: region::Scope,
|
label: region::Scope,
|
||||||
value: Option<ExprRef<'tcx>>,
|
value: Option<ExprRef<'tcx>>,
|
||||||
|
@ -18,24 +18,23 @@ fn main() {
|
|||||||
// START rustc.main.EraseRegions.after.mir
|
// START rustc.main.EraseRegions.after.mir
|
||||||
// bb0: {
|
// bb0: {
|
||||||
// ...
|
// ...
|
||||||
// _5 = &mut _2;
|
// _4 = &mut _2;
|
||||||
// _4 = &mut (*_5);
|
// _3 = &raw mut (*_4);
|
||||||
// _3 = move _4 as *mut usize (Misc);
|
|
||||||
// ...
|
// ...
|
||||||
// _7 = _3;
|
// _6 = _3;
|
||||||
// _6 = const foo(move _7) -> bb1;
|
// _5 = const foo(move _6) -> bb1;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb1: {
|
// bb1: {
|
||||||
// ...
|
// ...
|
||||||
// _8 = _2;
|
// _7 = _2;
|
||||||
// _9 = Len(_1);
|
// _8 = Len(_1);
|
||||||
// _10 = Lt(_8, _9);
|
// _9 = Lt(_7, _8);
|
||||||
// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2;
|
// assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb2: {
|
// bb2: {
|
||||||
// _1[_8] = move _6;
|
// _1[_7] = move _5;
|
||||||
// ...
|
// ...
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
@ -11,25 +11,21 @@ fn main() {
|
|||||||
// START rustc.main.ConstProp.before.mir
|
// START rustc.main.ConstProp.before.mir
|
||||||
// bb0: {
|
// bb0: {
|
||||||
// ...
|
// ...
|
||||||
// _3 = _4;
|
// _2 = &raw const (*_3);
|
||||||
// _2 = move _3 as *const i32 (Misc);
|
|
||||||
// ...
|
|
||||||
// _1 = move _2 as usize (Misc);
|
// _1 = move _2 as usize (Misc);
|
||||||
// ...
|
// ...
|
||||||
// _6 = _1;
|
// _5 = _1;
|
||||||
// _5 = const read(move _6) -> bb1;
|
// _4 = const read(move _5) -> bb1;
|
||||||
// }
|
// }
|
||||||
// END rustc.main.ConstProp.before.mir
|
// END rustc.main.ConstProp.before.mir
|
||||||
// START rustc.main.ConstProp.after.mir
|
// START rustc.main.ConstProp.after.mir
|
||||||
// bb0: {
|
// bb0: {
|
||||||
// ...
|
// ...
|
||||||
// _4 = const main::FOO;
|
// _3 = const main::FOO;
|
||||||
// _3 = _4;
|
// _2 = &raw const (*_3);
|
||||||
// _2 = move _3 as *const i32 (Misc);
|
|
||||||
// ...
|
|
||||||
// _1 = move _2 as usize (Misc);
|
// _1 = move _2 as usize (Misc);
|
||||||
// ...
|
// ...
|
||||||
// _6 = _1;
|
// _5 = _1;
|
||||||
// _5 = const read(move _6) -> bb1;
|
// _4 = const read(move _5) -> bb1;
|
||||||
// }
|
// }
|
||||||
// END rustc.main.ConstProp.after.mir
|
// END rustc.main.ConstProp.after.mir
|
||||||
|
@ -82,18 +82,16 @@ fn main() {
|
|||||||
// _10 = move _8;
|
// _10 = move _8;
|
||||||
// Retag(_10);
|
// Retag(_10);
|
||||||
// ...
|
// ...
|
||||||
// _13 = &mut (*_10);
|
// _12 = &raw mut (*_10);
|
||||||
// Retag(_13);
|
|
||||||
// _12 = move _13 as *mut i32 (Misc);
|
|
||||||
// Retag([raw] _12);
|
// Retag([raw] _12);
|
||||||
// ...
|
// ...
|
||||||
// _16 = move _17(move _18) -> bb5;
|
// _15 = move _16(move _17) -> bb5;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// 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`
|
let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
|
||||||
//~| HELP compare with zero instead
|
//~| HELP compare with zero instead
|
||||||
//~| SUGGESTION (1 + 2) != 0
|
//~| 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;
|
LL | let t = (1 + 2) as bool;
|
||||||
| ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
|
| ^^^^^^^^^^^^^^^ 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
|
--> $DIR/cast-as-bool.rs:8:13
|
||||||
|
|
|
|
||||||
LL | let v = "hello" as bool;
|
LL | let v = "hello" as bool;
|
||||||
| ^^^^^^^^^^^^^^^ unsupported cast
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
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