Skip to content

Commit c9bacb7

Browse files
committed
Auto merge of #66671 - matthewjasper:ast-address-of, r=Centril
Ast address-of This is the parts of #64588 that don't affect MIR. If an address-of expression makes it to MIR lowering we error and lower to the best currently expressible approximation to limit further errors. r? @Centril
2 parents 388ffd9 + f4efc5d commit c9bacb7

35 files changed

+678
-141
lines changed

src/librustc/hir/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
10241024
visitor.visit_expr(left_expression);
10251025
visitor.visit_expr(right_expression)
10261026
}
1027-
ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
1027+
ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
10281028
visitor.visit_expr(subexpression)
10291029
}
10301030
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {

src/librustc/hir/lowering/expr.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ impl LoweringContext<'_> {
6565
let expr = P(self.lower_expr(expr));
6666
hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
6767
}
68-
ExprKind::AddrOf(m, ref ohs) => {
68+
ExprKind::AddrOf(k, m, ref ohs) => {
6969
let ohs = P(self.lower_expr(ohs));
70-
hir::ExprKind::AddrOf(m, ohs)
70+
hir::ExprKind::AddrOf(k, m, ohs)
7171
}
7272
ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee),
7373
ExprKind::If(ref cond, ref then, ref else_opt) => {
@@ -1339,7 +1339,11 @@ impl LoweringContext<'_> {
13391339
}
13401340

13411341
fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
1342-
self.expr(span, hir::ExprKind::AddrOf(hir::Mutability::Mutable, e), ThinVec::new())
1342+
self.expr(
1343+
span,
1344+
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mutable, e),
1345+
ThinVec::new(),
1346+
)
13431347
}
13441348

13451349
fn expr_unit(&mut self, sp: Span) -> hir::Expr {

src/librustc/hir/mod.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
2121
use syntax::source_map::Spanned;
2222
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
2323
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
24-
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy, IsAuto, ImplPolarity};
24+
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
25+
pub use syntax::ast::{IsAuto, ImplPolarity, BorrowKind};
2526
use syntax::attr::{InlineAttr, OptimizeAttr};
2627
use syntax::symbol::{Symbol, kw};
2728
use syntax::tokenstream::TokenStream;
@@ -1493,8 +1494,20 @@ impl Expr {
14931494
}
14941495
}
14951496

1496-
pub fn is_place_expr(&self) -> bool {
1497-
match self.kind {
1497+
// Whether this looks like a place expr, without checking for deref
1498+
// adjustments.
1499+
// This will return `true` in some potentially surprising cases such as
1500+
// `CONSTANT.field`.
1501+
pub fn is_syntactic_place_expr(&self) -> bool {
1502+
self.is_place_expr(|_| true)
1503+
}
1504+
1505+
// Whether this is a place expression.
1506+
// `allow_projections_from` should return `true` if indexing a field or
1507+
// index expression based on the given expression should be considered a
1508+
// place expression.
1509+
pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
1510+
match self.kind {
14981511
ExprKind::Path(QPath::Resolved(_, ref path)) => {
14991512
match path.res {
15001513
Res::Local(..)
@@ -1504,14 +1517,19 @@ impl Expr {
15041517
}
15051518
}
15061519

1520+
// Type ascription inherits its place expression kind from its
1521+
// operand. See:
1522+
// https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
15071523
ExprKind::Type(ref e, _) => {
1508-
e.is_place_expr()
1524+
e.is_place_expr(allow_projections_from)
15091525
}
15101526

1511-
ExprKind::Unary(UnDeref, _) |
1512-
ExprKind::Field(..) |
1513-
ExprKind::Index(..) => {
1514-
true
1527+
ExprKind::Unary(UnDeref, _) => true,
1528+
1529+
ExprKind::Field(ref base, _) |
1530+
ExprKind::Index(ref base, _) => {
1531+
allow_projections_from(base)
1532+
|| base.is_place_expr(allow_projections_from)
15151533
}
15161534

15171535
// Partially qualified paths in expressions can only legally
@@ -1646,8 +1664,8 @@ pub enum ExprKind {
16461664
/// Path to a definition, possibly containing lifetime or type parameters.
16471665
Path(QPath),
16481666

1649-
/// A referencing operation (i.e., `&a` or `&mut a`).
1650-
AddrOf(Mutability, P<Expr>),
1667+
/// A referencing operation (i.e., `&a`, `&mut a`, `&raw const a`, or `&raw mut a`).
1668+
AddrOf(BorrowKind, Mutability, P<Expr>),
16511669
/// A `break`, with an optional label to break.
16521670
Break(Destination, Option<P<Expr>>),
16531671
/// A `continue`, with an optional label.

src/librustc/hir/print.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -294,16 +294,12 @@ impl<'a> State<'a> {
294294
}
295295
hir::TyKind::Ptr(ref mt) => {
296296
self.s.word("*");
297-
match mt.mutbl {
298-
hir::Mutability::Mutable => self.word_nbsp("mut"),
299-
hir::Mutability::Immutable => self.word_nbsp("const"),
300-
}
301-
self.print_type(&mt.ty);
297+
self.print_mt(mt, true);
302298
}
303299
hir::TyKind::Rptr(ref lifetime, ref mt) => {
304300
self.s.word("&");
305301
self.print_opt_lifetime(lifetime);
306-
self.print_mt(mt);
302+
self.print_mt(mt, false);
307303
}
308304
hir::TyKind::Never => {
309305
self.s.word("!");
@@ -1178,11 +1174,18 @@ impl<'a> State<'a> {
11781174
}
11791175

11801176
fn print_expr_addr_of(&mut self,
1177+
kind: hir::BorrowKind,
11811178
mutability: hir::Mutability,
11821179
expr: &hir::Expr)
1183-
{
1180+
{
11841181
self.s.word("&");
1185-
self.print_mutability(mutability);
1182+
match kind {
1183+
hir::BorrowKind::Ref => self.print_mutability(mutability, false),
1184+
hir::BorrowKind::Raw => {
1185+
self.word_nbsp("raw");
1186+
self.print_mutability(mutability, true);
1187+
}
1188+
}
11861189
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
11871190
}
11881191

@@ -1225,8 +1228,8 @@ impl<'a> State<'a> {
12251228
hir::ExprKind::Unary(op, ref expr) => {
12261229
self.print_expr_unary(op, &expr);
12271230
}
1228-
hir::ExprKind::AddrOf(m, ref expr) => {
1229-
self.print_expr_addr_of(m, &expr);
1231+
hir::ExprKind::AddrOf(k, m, ref expr) => {
1232+
self.print_expr_addr_of(k, m, &expr);
12301233
}
12311234
hir::ExprKind::Lit(ref lit) => {
12321235
self.print_literal(&lit);
@@ -1629,11 +1632,11 @@ impl<'a> State<'a> {
16291632
match binding_mode {
16301633
hir::BindingAnnotation::Ref => {
16311634
self.word_nbsp("ref");
1632-
self.print_mutability(hir::Mutability::Immutable);
1635+
self.print_mutability(hir::Mutability::Immutable, false);
16331636
}
16341637
hir::BindingAnnotation::RefMut => {
16351638
self.word_nbsp("ref");
1636-
self.print_mutability(hir::Mutability::Mutable);
1639+
self.print_mutability(hir::Mutability::Mutable, false);
16371640
}
16381641
hir::BindingAnnotation::Unannotated => {}
16391642
hir::BindingAnnotation::Mutable => {
@@ -2060,15 +2063,15 @@ impl<'a> State<'a> {
20602063
}
20612064
}
20622065

2063-
pub fn print_mutability(&mut self, mutbl: hir::Mutability) {
2066+
pub fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) {
20642067
match mutbl {
20652068
hir::Mutability::Mutable => self.word_nbsp("mut"),
2066-
hir::Mutability::Immutable => {},
2069+
hir::Mutability::Immutable => if print_const { self.word_nbsp("const") },
20672070
}
20682071
}
20692072

2070-
pub fn print_mt(&mut self, mt: &hir::MutTy) {
2071-
self.print_mutability(mt.mutbl);
2073+
pub fn print_mt(&mut self, mt: &hir::MutTy, print_const: bool) {
2074+
self.print_mutability(mt.mutbl, print_const);
20722075
self.print_type(&mt.ty)
20732076
}
20742077

src/librustc/middle/expr_use_visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
276276
self.consume_exprs(exprs);
277277
}
278278

279-
hir::ExprKind::AddrOf(m, ref base) => { // &base
279+
hir::ExprKind::AddrOf(_, m, ref base) => { // &base
280280
// make sure that the thing we are pointing out stays valid
281281
// for the lifetime `scope_r` of the resulting ptr:
282282
let bk = ty::BorrowKind::from_mutbl(m);

src/librustc/middle/region.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,7 @@ fn resolve_local<'tcx>(
12411241
blk_id: Option<Scope>,
12421242
) {
12431243
match expr.kind {
1244-
hir::ExprKind::AddrOf(_, ref subexpr) => {
1244+
hir::ExprKind::AddrOf(_, _, ref subexpr) => {
12451245
record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id);
12461246
record_rvalue_scope(visitor, &subexpr, blk_id);
12471247
}
@@ -1301,7 +1301,7 @@ fn resolve_local<'tcx>(
13011301
visitor.scope_tree.record_rvalue_scope(expr.hir_id.local_id, blk_scope);
13021302

13031303
match expr.kind {
1304-
hir::ExprKind::AddrOf(_, ref subexpr) |
1304+
hir::ExprKind::AddrOf(_, _, ref subexpr) |
13051305
hir::ExprKind::Unary(hir::UnDeref, ref subexpr) |
13061306
hir::ExprKind::Field(ref subexpr, _) |
13071307
hir::ExprKind::Index(ref subexpr, _) => {

src/librustc_error_codes/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ E0741: include_str!("./error_codes/E0741.md"),
409409
E0742: include_str!("./error_codes/E0742.md"),
410410
E0743: include_str!("./error_codes/E0743.md"),
411411
E0744: include_str!("./error_codes/E0744.md"),
412+
E0745: include_str!("./error_codes/E0745.md"),
412413
;
413414
// E0006, // merged with E0005
414415
// E0008, // cannot bind by-move into a pattern guard
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Cannot take address of temporary value.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0745
6+
# #![feature(raw_ref_op)]
7+
fn temp_address() {
8+
let ptr = &raw const 2; // ERROR
9+
}
10+
```
11+
12+
To avoid the error, first bind the temporary to a named local variable.
13+
14+
```ignore
15+
# #![feature(raw_ref_op)]
16+
fn temp_address() {
17+
let val = 2;
18+
let ptr = &raw const val;
19+
}
20+
```

0 commit comments

Comments
 (0)