Skip to content

Commit f059461

Browse files
authored
Rollup merge of rust-lang#64588 - matthewjasper:mir-address-of, r=oli-obk
Add a raw "address of" operator * Parse and feature gate `&raw [const | mut] expr` (feature gate name is `raw_address_of`) * Add `mir::Rvalue::AddressOf` * Use the new `Rvalue` for: * the new syntax * reference to pointer casts * drop shims for slices and arrays * Stop using `mir::Rvalue::Cast` with a reference as the operand * Correctly evaluate `mir::Rvalue::{Ref, AddressOf}` in constant propagation cc @Centril @RalfJung @oli-obk @eddyb cc rust-lang#64490
2 parents 6b561b4 + a749116 commit f059461

File tree

69 files changed

+1159
-516
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1159
-516
lines changed

Diff for: src/librustc/mir/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,11 @@ pub enum Rvalue<'tcx> {
20602060
/// &x or &mut x
20612061
Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
20622062

2063+
/// Create a raw pointer to the given place
2064+
/// Can be generated by raw address of expressions (`&raw const x`),
2065+
/// or when casting a reference to a raw pointer.
2066+
AddressOf(Mutability, Place<'tcx>),
2067+
20632068
/// length of a [X] or [X;n] value
20642069
Len(Place<'tcx>),
20652070

@@ -2214,6 +2219,15 @@ impl<'tcx> Debug for Rvalue<'tcx> {
22142219
write!(fmt, "&{}{}{:?}", region, kind_str, place)
22152220
}
22162221

2222+
AddressOf(mutability, ref place) => {
2223+
let kind_str = match mutability {
2224+
Mutability::Mut => "mut",
2225+
Mutability::Not => "const",
2226+
};
2227+
2228+
write!(fmt, "&raw {} {:?}", kind_str, place)
2229+
}
2230+
22172231
Aggregate(ref kind, ref places) => {
22182232
fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
22192233
let mut tuple_fmt = fmt.debug_tuple("");
@@ -3085,6 +3099,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
30853099
Ref(region, bk, ref place) => {
30863100
Ref(region.fold_with(folder), bk, place.fold_with(folder))
30873101
}
3102+
AddressOf(mutability, ref place) => {
3103+
AddressOf(mutability, place.fold_with(folder))
3104+
}
30883105
Len(ref place) => Len(place.fold_with(folder)),
30893106
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
30903107
BinaryOp(op, ref rhs, ref lhs) => {
@@ -3125,6 +3142,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
31253142
Use(ref op) => op.visit_with(visitor),
31263143
Repeat(ref op, _) => op.visit_with(visitor),
31273144
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
3145+
AddressOf(_, ref place) => place.visit_with(visitor),
31283146
Len(ref place) => place.visit_with(visitor),
31293147
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
31303148
BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {

Diff for: src/librustc/mir/tcx.rs

+7
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ impl<'tcx> Rvalue<'tcx> {
172172
}
173173
)
174174
}
175+
Rvalue::AddressOf(mutability, ref place) => {
176+
let place_ty = place.ty(local_decls, tcx).ty;
177+
tcx.mk_ptr(ty::TypeAndMut {
178+
ty: place_ty,
179+
mutbl: mutability.into(),
180+
})
181+
}
175182
Rvalue::Len(..) => tcx.types.usize,
176183
Rvalue::Cast(.., ty) => ty,
177184
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {

Diff for: src/librustc/mir/visit.rs

+16
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,18 @@ macro_rules! make_mir_visitor {
570570
self.visit_place(path, ctx, location);
571571
}
572572

573+
Rvalue::AddressOf(m, path) => {
574+
let ctx = match m {
575+
Mutability::Mut => PlaceContext::MutatingUse(
576+
MutatingUseContext::AddressOf
577+
),
578+
Mutability::Not => PlaceContext::NonMutatingUse(
579+
NonMutatingUseContext::AddressOf
580+
),
581+
};
582+
self.visit_place(path, ctx, location);
583+
}
584+
573585
Rvalue::Len(path) => {
574586
self.visit_place(
575587
path,
@@ -1031,6 +1043,8 @@ pub enum NonMutatingUseContext {
10311043
ShallowBorrow,
10321044
/// Unique borrow.
10331045
UniqueBorrow,
1046+
/// AddressOf for *const pointer.
1047+
AddressOf,
10341048
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
10351049
/// For example, the projection `x.y` is not marked as a mutation in these cases:
10361050
///
@@ -1054,6 +1068,8 @@ pub enum MutatingUseContext {
10541068
Drop,
10551069
/// Mutable borrow.
10561070
Borrow,
1071+
/// AddressOf for *mut pointer.
1072+
AddressOf,
10571073
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
10581074
/// For example, the projection `x.y` is marked as a mutation in these cases:
10591075
///

Diff for: src/librustc/ty/cast.rs

-3
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ pub enum CastTy<'tcx> {
2828
FnPtr,
2929
/// Raw pointers
3030
Ptr(ty::TypeAndMut<'tcx>),
31-
/// References
32-
RPtr(ty::TypeAndMut<'tcx>),
3331
}
3432

3533
/// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
@@ -63,7 +61,6 @@ impl<'tcx> CastTy<'tcx> {
6361
ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() =>
6462
Some(CastTy::Int(IntTy::CEnum)),
6563
ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
66-
ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })),
6764
ty::FnPtr(..) => Some(CastTy::FnPtr),
6865
_ => None,
6966
}

Diff for: src/librustc_codegen_ssa/mir/analyze.rs

+2
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
340340
PlaceContext::MutatingUse(MutatingUseContext::Store) |
341341
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
342342
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
343+
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
343344
PlaceContext::MutatingUse(MutatingUseContext::Projection) |
344345
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
345346
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
346347
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
348+
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
347349
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
348350
self.not_ssa(local);
349351
}

Diff for: src/librustc_codegen_ssa/mir/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
448448
let cx = self.cx;
449449
let tcx = self.cx.tcx();
450450

451-
let result = match &place_ref {
451+
let result = match place_ref {
452452
mir::PlaceRef {
453453
base: mir::PlaceBase::Local(index),
454454
projection: [],

Diff for: src/librustc_codegen_ssa/mir/rvalue.rs

+38-20
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::MemFlags;
77
use crate::common::{self, RealPredicate, IntPredicate};
88
use crate::traits::*;
99

10-
use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance};
10+
use rustc::ty::{self, Ty, TyCtxt, adjustment::{PointerCast}, Instance};
1111
use rustc::ty::cast::{CastTy, IntTy};
1212
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
1313
use rustc::mir;
@@ -349,8 +349,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
349349
}
350350
}
351351
(CastTy::Ptr(_), CastTy::Ptr(_)) |
352-
(CastTy::FnPtr, CastTy::Ptr(_)) |
353-
(CastTy::RPtr(_), CastTy::Ptr(_)) =>
352+
(CastTy::FnPtr, CastTy::Ptr(_)) =>
354353
bx.pointercast(llval, ll_t_out),
355354
(CastTy::Ptr(_), CastTy::Int(_)) |
356355
(CastTy::FnPtr, CastTy::Int(_)) =>
@@ -375,24 +374,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
375374
}
376375

377376
mir::Rvalue::Ref(_, bk, ref place) => {
378-
let cg_place = self.codegen_place(&mut bx, &place.as_ref());
379-
380-
let ty = cg_place.layout.ty;
377+
let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ref(
378+
tcx.lifetimes.re_erased,
379+
ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
380+
);
381+
self.codegen_place_to_pointer(bx, place, mk_ref)
382+
}
381383

382-
// Note: places are indirect, so storing the `llval` into the
383-
// destination effectively creates a reference.
384-
let val = if !bx.cx().type_has_metadata(ty) {
385-
OperandValue::Immediate(cg_place.llval)
386-
} else {
387-
OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
388-
};
389-
(bx, OperandRef {
390-
val,
391-
layout: self.cx.layout_of(self.cx.tcx().mk_ref(
392-
self.cx.tcx().lifetimes.re_erased,
393-
ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() }
394-
)),
395-
})
384+
mir::Rvalue::AddressOf(mutability, ref place) => {
385+
let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ptr(
386+
ty::TypeAndMut { ty, mutbl: mutability.into() }
387+
);
388+
self.codegen_place_to_pointer(bx, place, mk_ptr)
396389
}
397390

398391
mir::Rvalue::Len(ref place) => {
@@ -548,6 +541,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
548541
cg_value.len(bx.cx())
549542
}
550543

544+
/// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref`
545+
fn codegen_place_to_pointer(
546+
&mut self,
547+
mut bx: Bx,
548+
place: &mir::Place<'tcx>,
549+
mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>,
550+
) -> (Bx, OperandRef<'tcx, Bx::Value>) {
551+
let cg_place = self.codegen_place(&mut bx, &place.as_ref());
552+
553+
let ty = cg_place.layout.ty;
554+
555+
// Note: places are indirect, so storing the `llval` into the
556+
// destination effectively creates a reference.
557+
let val = if !bx.cx().type_has_metadata(ty) {
558+
OperandValue::Immediate(cg_place.llval)
559+
} else {
560+
OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
561+
};
562+
(bx, OperandRef {
563+
val,
564+
layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)),
565+
})
566+
}
567+
551568
pub fn codegen_scalar_binop(
552569
&mut self,
553570
bx: &mut Bx,
@@ -704,6 +721,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
704721
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool {
705722
match *rvalue {
706723
mir::Rvalue::Ref(..) |
724+
mir::Rvalue::AddressOf(..) |
707725
mir::Rvalue::Len(..) |
708726
mir::Rvalue::Cast(..) | // (*)
709727
mir::Rvalue::BinaryOp(..) |

Diff for: src/librustc_error_codes/error_codes/E0745.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn temp_address() {
1111

1212
To avoid the error, first bind the temporary to a named local variable.
1313

14-
```ignore (not yet implemented)
14+
```
1515
# #![feature(raw_ref_op)]
1616
fn temp_address() {
1717
let val = 2;

Diff for: src/librustc_mir/borrow_check/invalidation.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc::mir::visit::Visitor;
33
use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue};
44
use rustc::mir::{Statement, StatementKind};
55
use rustc::mir::TerminatorKind;
6-
use rustc::mir::{Operand, BorrowKind};
6+
use rustc::mir::{Operand, BorrowKind, Mutability};
77
use rustc_data_structures::graph::dominators::Dominators;
88

99
use crate::dataflow::indexes::BorrowIndex;
@@ -337,6 +337,22 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
337337
);
338338
}
339339

340+
Rvalue::AddressOf(mutability, ref place) => {
341+
let access_kind = match mutability {
342+
Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
343+
allow_two_phase_borrow: false,
344+
}))),
345+
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
346+
};
347+
348+
self.access_place(
349+
location,
350+
place,
351+
access_kind,
352+
LocalMutationIsAllowed::No,
353+
);
354+
}
355+
340356
Rvalue::Use(ref operand)
341357
| Rvalue::Repeat(ref operand, _)
342358
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)

Diff for: src/librustc_mir/borrow_check/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12331233
);
12341234
}
12351235

1236+
1237+
Rvalue::AddressOf(mutability, ref place) => {
1238+
let access_kind = match mutability {
1239+
Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
1240+
allow_two_phase_borrow: false,
1241+
}))),
1242+
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
1243+
};
1244+
1245+
self.access_place(
1246+
location,
1247+
(place, span),
1248+
access_kind,
1249+
LocalMutationIsAllowed::No,
1250+
flow_state,
1251+
);
1252+
1253+
self.check_if_path_or_subpath_is_moved(
1254+
location,
1255+
InitializationRequiringAction::Borrow,
1256+
(place.as_ref(), span),
1257+
flow_state,
1258+
);
1259+
}
1260+
12361261
Rvalue::Use(ref operand)
12371262
| Rvalue::Repeat(ref operand, _)
12381263
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)

Diff for: src/librustc_mir/borrow_check/type_check/mod.rs

+12-37
Original file line numberDiff line numberDiff line change
@@ -2273,41 +2273,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22732273
let cast_ty_from = CastTy::from_ty(ty_from);
22742274
let cast_ty_to = CastTy::from_ty(ty);
22752275
match (cast_ty_from, cast_ty_to) {
2276-
(Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => {
2277-
if let hir::Mutability::Mutable = ptr_tm.mutbl {
2278-
if let Err(terr) = self.eq_types(
2279-
ref_tm.ty,
2280-
ptr_tm.ty,
2281-
location.to_locations(),
2282-
ConstraintCategory::Cast,
2283-
) {
2284-
span_mirbug!(
2285-
self,
2286-
rvalue,
2287-
"equating {:?} with {:?} yields {:?}",
2288-
ref_tm.ty,
2289-
ptr_tm.ty,
2290-
terr
2291-
)
2292-
}
2293-
} else {
2294-
if let Err(terr) = self.sub_types(
2295-
ref_tm.ty,
2296-
ptr_tm.ty,
2297-
location.to_locations(),
2298-
ConstraintCategory::Cast,
2299-
) {
2300-
span_mirbug!(
2301-
self,
2302-
rvalue,
2303-
"relating {:?} with {:?} yields {:?}",
2304-
ref_tm.ty,
2305-
ptr_tm.ty,
2306-
terr
2307-
)
2308-
}
2309-
}
2310-
},
23112276
(None, _)
23122277
| (_, None)
23132278
| (_, Some(CastTy::FnPtr))
@@ -2320,7 +2285,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23202285
ty_from,
23212286
ty,
23222287
),
2323-
_ => (),
2288+
(Some(CastTy::Int(_)), Some(CastTy::Int(_)))
2289+
| (Some(CastTy::Float), Some(CastTy::Int(_)))
2290+
| (Some(CastTy::Int(_)), Some(CastTy::Float))
2291+
| (Some(CastTy::Float), Some(CastTy::Float))
2292+
| (Some(CastTy::Ptr(_)), Some(CastTy::Int(_)))
2293+
| (Some(CastTy::FnPtr), Some(CastTy::Int(_)))
2294+
| (Some(CastTy::Int(_)), Some(CastTy::Ptr(_)))
2295+
| (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_)))
2296+
| (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
23242297
}
23252298
}
23262299
}
@@ -2371,7 +2344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23712344
}
23722345
}
23732346

2374-
Rvalue::Use(..)
2347+
Rvalue::AddressOf(..)
2348+
| Rvalue::Use(..)
23752349
| Rvalue::Len(..)
23762350
| Rvalue::BinaryOp(..)
23772351
| Rvalue::CheckedBinaryOp(..)
@@ -2388,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23882362
Rvalue::Use(_)
23892363
| Rvalue::Repeat(..)
23902364
| Rvalue::Ref(..)
2365+
| Rvalue::AddressOf(..)
23912366
| Rvalue::Len(..)
23922367
| Rvalue::Cast(..)
23932368
| Rvalue::BinaryOp(..)

Diff for: src/librustc_mir/build/expr/as_place.rs

+1
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 { .. }

Diff for: src/librustc_mir/build/expr/as_rvalue.rs

+1
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 { .. }

0 commit comments

Comments
 (0)