Skip to content

Commit

Permalink
Auto merge of rust-lang#66671 - matthewjasper:ast-address-of, r=Centril
Browse files Browse the repository at this point in the history
Ast address-of

This is the parts of rust-lang#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
  • Loading branch information
bors committed Nov 25, 2019
2 parents 388ffd9 + f4efc5d commit c9bacb7
Show file tree
Hide file tree
Showing 35 changed files with 678 additions and 141 deletions.
2 changes: 1 addition & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(left_expression);
visitor.visit_expr(right_expression)
}
ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
visitor.visit_expr(subexpression)
}
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/hir/lowering/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ impl LoweringContext<'_> {
let expr = P(self.lower_expr(expr));
hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
}
ExprKind::AddrOf(m, ref ohs) => {
ExprKind::AddrOf(k, m, ref ohs) => {
let ohs = P(self.lower_expr(ohs));
hir::ExprKind::AddrOf(m, ohs)
hir::ExprKind::AddrOf(k, m, ohs)
}
ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee),
ExprKind::If(ref cond, ref then, ref else_opt) => {
Expand Down Expand Up @@ -1339,7 +1339,11 @@ impl LoweringContext<'_> {
}

fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
self.expr(span, hir::ExprKind::AddrOf(hir::Mutability::Mutable, e), ThinVec::new())
self.expr(
span,
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mutable, e),
ThinVec::new(),
)
}

fn expr_unit(&mut self, sp: Span) -> hir::Expr {
Expand Down
38 changes: 28 additions & 10 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use syntax::source_map::Spanned;
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy, IsAuto, ImplPolarity};
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
pub use syntax::ast::{IsAuto, ImplPolarity, BorrowKind};
use syntax::attr::{InlineAttr, OptimizeAttr};
use syntax::symbol::{Symbol, kw};
use syntax::tokenstream::TokenStream;
Expand Down Expand Up @@ -1493,8 +1494,20 @@ impl Expr {
}
}

pub fn is_place_expr(&self) -> bool {
match self.kind {
// Whether this looks like a place expr, without checking for deref
// adjustments.
// This will return `true` in some potentially surprising cases such as
// `CONSTANT.field`.
pub fn is_syntactic_place_expr(&self) -> bool {
self.is_place_expr(|_| true)
}

// Whether this is a place expression.
// `allow_projections_from` should return `true` if indexing a field or
// index expression based on the given expression should be considered a
// place expression.
pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
match self.kind {
ExprKind::Path(QPath::Resolved(_, ref path)) => {
match path.res {
Res::Local(..)
Expand All @@ -1504,14 +1517,19 @@ impl Expr {
}
}

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

ExprKind::Unary(UnDeref, _) |
ExprKind::Field(..) |
ExprKind::Index(..) => {
true
ExprKind::Unary(UnDeref, _) => true,

ExprKind::Field(ref base, _) |
ExprKind::Index(ref base, _) => {
allow_projections_from(base)
|| base.is_place_expr(allow_projections_from)
}

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

/// A referencing operation (i.e., `&a` or `&mut a`).
AddrOf(Mutability, P<Expr>),
/// A referencing operation (i.e., `&a`, `&mut a`, `&raw const a`, or `&raw mut a`).
AddrOf(BorrowKind, Mutability, P<Expr>),
/// A `break`, with an optional label to break.
Break(Destination, Option<P<Expr>>),
/// A `continue`, with an optional label.
Expand Down
35 changes: 19 additions & 16 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,16 +294,12 @@ impl<'a> State<'a> {
}
hir::TyKind::Ptr(ref mt) => {
self.s.word("*");
match mt.mutbl {
hir::Mutability::Mutable => self.word_nbsp("mut"),
hir::Mutability::Immutable => self.word_nbsp("const"),
}
self.print_type(&mt.ty);
self.print_mt(mt, true);
}
hir::TyKind::Rptr(ref lifetime, ref mt) => {
self.s.word("&");
self.print_opt_lifetime(lifetime);
self.print_mt(mt);
self.print_mt(mt, false);
}
hir::TyKind::Never => {
self.s.word("!");
Expand Down Expand Up @@ -1178,11 +1174,18 @@ impl<'a> State<'a> {
}

fn print_expr_addr_of(&mut self,
kind: hir::BorrowKind,
mutability: hir::Mutability,
expr: &hir::Expr)
{
{
self.s.word("&");
self.print_mutability(mutability);
match kind {
hir::BorrowKind::Ref => self.print_mutability(mutability, false),
hir::BorrowKind::Raw => {
self.word_nbsp("raw");
self.print_mutability(mutability, true);
}
}
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
}

Expand Down Expand Up @@ -1225,8 +1228,8 @@ impl<'a> State<'a> {
hir::ExprKind::Unary(op, ref expr) => {
self.print_expr_unary(op, &expr);
}
hir::ExprKind::AddrOf(m, ref expr) => {
self.print_expr_addr_of(m, &expr);
hir::ExprKind::AddrOf(k, m, ref expr) => {
self.print_expr_addr_of(k, m, &expr);
}
hir::ExprKind::Lit(ref lit) => {
self.print_literal(&lit);
Expand Down Expand Up @@ -1629,11 +1632,11 @@ impl<'a> State<'a> {
match binding_mode {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Immutable);
self.print_mutability(hir::Mutability::Immutable, false);
}
hir::BindingAnnotation::RefMut => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Mutable);
self.print_mutability(hir::Mutability::Mutable, false);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
Expand Down Expand Up @@ -2060,15 +2063,15 @@ impl<'a> State<'a> {
}
}

pub fn print_mutability(&mut self, mutbl: hir::Mutability) {
pub fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) {
match mutbl {
hir::Mutability::Mutable => self.word_nbsp("mut"),
hir::Mutability::Immutable => {},
hir::Mutability::Immutable => if print_const { self.word_nbsp("const") },
}
}

pub fn print_mt(&mut self, mt: &hir::MutTy) {
self.print_mutability(mt.mutbl);
pub fn print_mt(&mut self, mt: &hir::MutTy, print_const: bool) {
self.print_mutability(mt.mutbl, print_const);
self.print_type(&mt.ty)
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.consume_exprs(exprs);
}

hir::ExprKind::AddrOf(m, ref base) => { // &base
hir::ExprKind::AddrOf(_, m, ref base) => { // &base
// make sure that the thing we are pointing out stays valid
// for the lifetime `scope_r` of the resulting ptr:
let bk = ty::BorrowKind::from_mutbl(m);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ fn resolve_local<'tcx>(
blk_id: Option<Scope>,
) {
match expr.kind {
hir::ExprKind::AddrOf(_, ref subexpr) => {
hir::ExprKind::AddrOf(_, _, ref subexpr) => {
record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id);
record_rvalue_scope(visitor, &subexpr, blk_id);
}
Expand Down Expand Up @@ -1301,7 +1301,7 @@ fn resolve_local<'tcx>(
visitor.scope_tree.record_rvalue_scope(expr.hir_id.local_id, blk_scope);

match expr.kind {
hir::ExprKind::AddrOf(_, ref subexpr) |
hir::ExprKind::AddrOf(_, _, ref subexpr) |
hir::ExprKind::Unary(hir::UnDeref, ref subexpr) |
hir::ExprKind::Field(ref subexpr, _) |
hir::ExprKind::Index(ref subexpr, _) => {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_error_codes/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ E0741: include_str!("./error_codes/E0741.md"),
E0742: include_str!("./error_codes/E0742.md"),
E0743: include_str!("./error_codes/E0743.md"),
E0744: include_str!("./error_codes/E0744.md"),
E0745: include_str!("./error_codes/E0745.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
Expand Down
20 changes: 20 additions & 0 deletions src/librustc_error_codes/error_codes/E0745.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Cannot take address of temporary value.

Erroneous code example:

```compile_fail,E0745
# #![feature(raw_ref_op)]
fn temp_address() {
let ptr = &raw const 2; // ERROR
}
```

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

```ignore
# #![feature(raw_ref_op)]
fn temp_address() {
let val = 2;
let ptr = &raw const val;
}
```
Loading

0 comments on commit c9bacb7

Please sign in to comment.