diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d4fa03b508566..297586f140e34 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1034,10 +1034,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprAssign(ref l, ref r) => { - // see comment on lvalues in - // propagate_through_lvalue_components() - let succ = self.write_lvalue(&l, succ, ACC_WRITE); - let succ = self.propagate_through_lvalue_components(&l, succ); + // see comment on places in + // propagate_through_place_components() + let succ = self.write_place(&l, succ, ACC_WRITE); + let succ = self.propagate_through_place_components(&l, succ); self.propagate_through_expr(&r, succ) } @@ -1047,11 +1047,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { - // see comment on lvalues in - // propagate_through_lvalue_components() - let succ = self.write_lvalue(&l, succ, ACC_WRITE|ACC_READ); + // see comment on places in + // propagate_through_place_components() + let succ = self.write_place(&l, succ, ACC_WRITE|ACC_READ); let succ = self.propagate_through_expr(&r, succ); - self.propagate_through_lvalue_components(&l, succ) + self.propagate_through_place_components(&l, succ) } } @@ -1121,14 +1121,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => { let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| { - // see comment on lvalues - // in propagate_through_lvalue_components() + // see comment on places + // in propagate_through_place_components() if o.is_indirect { self.propagate_through_expr(output, succ) } else { let acc = if o.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE }; - let succ = self.write_lvalue(output, succ, acc); - self.propagate_through_lvalue_components(output, succ) + let succ = self.write_place(output, succ, acc); + self.propagate_through_place_components(output, succ) } }); @@ -1146,11 +1146,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - fn propagate_through_lvalue_components(&mut self, + fn propagate_through_place_components(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode { - // # Lvalues + // # Places // // In general, the full flow graph structure for an // assignment/move/etc can be handled in one of two ways, @@ -1160,7 +1160,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // // The two kinds of graphs are: // - // Tracked lvalue Untracked lvalue + // Tracked place Untracked place // ----------------------++----------------------- // || // | || | @@ -1168,7 +1168,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // (rvalue) || (rvalue) // | || | // v || v - // (write of lvalue) || (lvalue components) + // (write of place) || (place components) // | || | // v || v // (succ) || (succ) @@ -1177,25 +1177,25 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // // I will cover the two cases in turn: // - // # Tracked lvalues + // # Tracked places // - // A tracked lvalue is a local variable/argument `x`. In + // A tracked place is a local variable/argument `x`. In // these cases, the link_node where the write occurs is linked - // to node id of `x`. The `write_lvalue()` routine generates + // to node id of `x`. The `write_place()` routine generates // the contents of this node. There are no subcomponents to // consider. // - // # Non-tracked lvalues + // # Non-tracked places // - // These are lvalues like `x[5]` or `x.f`. In that case, we + // These are places like `x[5]` or `x.f`. In that case, we // basically ignore the value which is written to but generate // reads for the components---`x` in these two examples. The // components reads are generated by - // `propagate_through_lvalue_components()` (this fn). + // `propagate_through_place_components()` (this fn). // - // # Illegal lvalues + // # Illegal places // - // It is still possible to observe assignments to non-lvalues; + // It is still possible to observe assignments to non-places; // these errors are detected in the later pass borrowck. We // just ignore such cases and treat them as reads. @@ -1207,17 +1207,17 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - // see comment on propagate_through_lvalue() - fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32) + // see comment on propagate_through_place() + fn write_place(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { match expr.node { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { self.access_path(expr.id, path, succ, acc) } - // We do not track other lvalues, so just propagate through + // We do not track other places, so just propagate through // to their subcomponents. Also, it may happen that - // non-lvalues occur here, because those are detected in the + // non-places occur here, because those are detected in the // later pass borrowck. _ => succ } @@ -1363,14 +1363,14 @@ fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) { fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { hir::ExprAssign(ref l, _) => { - this.check_lvalue(&l); + this.check_place(&l); intravisit::walk_expr(this, expr); } hir::ExprAssignOp(_, ref l, _) => { if !this.tables.is_method_call(expr) { - this.check_lvalue(&l); + this.check_place(&l); } intravisit::walk_expr(this, expr); @@ -1381,10 +1381,10 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { this.visit_expr(input); } - // Output operands must be lvalues + // Output operands must be places for (o, output) in ia.outputs.iter().zip(outputs) { if !o.is_indirect { - this.check_lvalue(output); + this.check_place(output); } this.visit_expr(output); } @@ -1409,7 +1409,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn check_lvalue(&mut self, expr: &'tcx Expr) { + fn check_place(&mut self, expr: &'tcx Expr) { match expr.node { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { if let Def::Local(nid) = path.def { @@ -1423,7 +1423,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } _ => { - // For other kinds of lvalues, no checks are required, + // For other kinds of places, no checks are required, // and any embedded expressions are actually rvalues intravisit::walk_expr(self, expr); } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index a8955723e3ae0..45b595adfe7b8 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -26,8 +26,8 @@ //! | E.comp // access to an interior component //! //! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an -//! address where the result is to be found. If Expr is an lvalue, then this -//! is the address of the lvalue. If Expr is an rvalue, this is the address of +//! address where the result is to be found. If Expr is a place, then this +//! is the address of the place. If Expr is an rvalue, this is the address of //! some temporary spot in memory where the result is stored. //! //! Now, cat_expr() classifies the expression Expr and the address A=ToAddr(Expr) @@ -182,7 +182,7 @@ pub struct cmt_<'tcx> { pub id: ast::NodeId, // id of expr/pat producing this value pub span: Span, // span of same expr/pat pub cat: Categorization<'tcx>, // categorization of expr - pub mutbl: MutabilityCategory, // mutability of expr as lvalue + pub mutbl: MutabilityCategory, // mutability of expr as place pub ty: Ty<'tcx>, // type of the expr (*see WARNING above*) pub note: Note, // Note about the provenance of this cmt } @@ -517,7 +517,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // a bind-by-ref means that the base_ty will be the type of the ident itself, // but what we want here is the type of the underlying value being borrowed. // So peel off one-level, turning the &T into T. - match base_ty.builtin_deref(false, ty::NoPreference) { + match base_ty.builtin_deref(false) { Some(t) => t.ty, None => { debug!("By-ref binding of non-derefable type {:?}", base_ty); @@ -603,7 +603,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { match expr.node { hir::ExprUnary(hir::UnDeref, ref e_base) => { if self.tables.is_method_call(expr) { - self.cat_overloaded_lvalue(expr, e_base, false) + self.cat_overloaded_place(expr, e_base, false) } else { let base_cmt = self.cat_expr(&e_base)?; self.cat_deref(expr, base_cmt, false) @@ -631,7 +631,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // The call to index() returns a `&T` value, which // is an rvalue. That is what we will be // dereferencing. - self.cat_overloaded_lvalue(expr, base, true) + self.cat_overloaded_place(expr, base, true) } else { let base_cmt = self.cat_expr(&base)?; self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index) @@ -983,27 +983,27 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ret } - fn cat_overloaded_lvalue(&self, + fn cat_overloaded_place(&self, expr: &hir::Expr, base: &hir::Expr, implicit: bool) -> McResult> { - debug!("cat_overloaded_lvalue: implicit={}", implicit); + debug!("cat_overloaded_place: implicit={}", implicit); // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. - let lvalue_ty = self.expr_ty(expr)?; + let place_ty = self.expr_ty(expr)?; let base_ty = self.expr_ty_adjusted(base)?; let (region, mutbl) = match base_ty.sty { ty::TyRef(region, mt) => (region, mt.mutbl), _ => { - span_bug!(expr.span, "cat_overloaded_lvalue: base is not a reference") + span_bug!(expr.span, "cat_overloaded_place: base is not a reference") } }; let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { - ty: lvalue_ty, + ty: place_ty, mutbl, }); @@ -1019,7 +1019,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("cat_deref: base_cmt={:?}", base_cmt); let base_cmt_ty = base_cmt.ty; - let deref_ty = match base_cmt_ty.builtin_deref(true, ty::NoPreference) { + let deref_ty = match base_cmt_ty.builtin_deref(true) { Some(mt) => mt.ty, None => { debug!("Explicit deref of non-derefable type: {:?}", @@ -1386,7 +1386,7 @@ impl<'tcx> cmt_<'tcx> { } } - /// Returns `FreelyAliasable(_)` if this lvalue represents a freely aliasable pointer type. + /// Returns `FreelyAliasable(_)` if this place represents a freely aliasable pointer type. pub fn freely_aliasable(&self) -> Aliasability { // Maybe non-obvious: copied upvars can only be considered // non-aliasable in once closures, since any other kind can be @@ -1453,7 +1453,7 @@ impl<'tcx> cmt_<'tcx> { "static item".to_string() } Categorization::Rvalue(..) => { - "non-lvalue".to_string() + "non-place".to_string() } Categorization::Local(vid) => { if tcx.hir.is_argument(vid) { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 66b3adb83c160..dad2d7a7c90fb 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -1112,7 +1112,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, // I mean that creating a binding into a ref-counted or managed value // would still count.) // - // 3. `ET`, which matches both rvalues like `foo()` as well as lvalues + // 3. `ET`, which matches both rvalues like `foo()` as well as places // based on rvalues like `foo().x[2].y`. // // A subexpression `` that appears in a let initializer @@ -1283,7 +1283,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, /// | (ET) /// | /// - /// Note: ET is intended to match "rvalues or lvalues based on rvalues". + /// Note: ET is intended to match "rvalues or places based on rvalues". fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &hir::Expr, blk_scope: Option) { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3aa94b3469942..3b644aa13f321 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -733,13 +733,13 @@ pub enum TerminatorKind<'tcx> { }, /// Drop the Place and assign the new value over it. This ensures - /// that the assignment to LV occurs *even if* the destructor for + /// that the assignment to `P` occurs *even if* the destructor for /// place unwinds. Its semantics are best explained by by the /// elaboration: /// /// ``` /// BB0 { - /// DropAndReplace(LV <- RV, goto BB1, unwind BB2) + /// DropAndReplace(P <- V, goto BB1, unwind BB2) /// } /// ``` /// @@ -747,15 +747,15 @@ pub enum TerminatorKind<'tcx> { /// /// ``` /// BB0 { - /// Drop(LV, goto BB1, unwind BB2) + /// Drop(P, goto BB1, unwind BB2) /// } /// BB1 { - /// // LV is now unitialized - /// LV <- RV + /// // P is now unitialized + /// P <- V /// } /// BB2 { - /// // LV is now unitialized -- its dtor panicked - /// LV <- RV + /// // P is now unitialized -- its dtor panicked + /// P <- V /// } /// ``` DropAndReplace { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 23f360d5c3922..53607764b3984 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { match *elem { ProjectionElem::Deref => { let ty = self.to_ty(tcx) - .builtin_deref(true, ty::LvaluePreference::NoPreference) + .builtin_deref(true) .unwrap_or_else(|| { bug!("deref projection of non-dereferencable ty {:?}", self) }) diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 6df6bb9df2320..96d69b4fba21a 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -77,7 +77,7 @@ pub enum Adjust<'tcx> { /// Go from a mut raw pointer to a const raw pointer. MutToConstPointer, - /// Dereference once, producing an lvalue. + /// Dereference once, producing a place. Deref(Option>), /// Take the address and produce either a `&` or `*` pointer. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 63df1179af228..f52f2ea0f9fc8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -12,7 +12,6 @@ pub use self::Variance::*; pub use self::AssociatedItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; -pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; use hir::{map as hir_map, FreevarMap, TraitMap}; @@ -2099,21 +2098,6 @@ impl<'tcx> TyS<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum LvaluePreference { - PreferMutLvalue, - NoPreference -} - -impl LvaluePreference { - pub fn from_mutbl(m: hir::Mutability) -> Self { - match m { - hir::MutMutable => PreferMutLvalue, - hir::MutImmutable => NoPreference, - } - } -} - impl BorrowKind { pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { match m { @@ -2193,60 +2177,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn expr_is_lval(self, expr: &hir::Expr) -> bool { - match expr.node { - hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { - match path.def { - Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true, - _ => false, - } - } - - hir::ExprType(ref e, _) => { - self.expr_is_lval(e) - } - - hir::ExprUnary(hir::UnDeref, _) | - hir::ExprField(..) | - hir::ExprTupField(..) | - hir::ExprIndex(..) => { - true - } - - // Partially qualified paths in expressions can only legally - // refer to associated items which are always rvalues. - hir::ExprPath(hir::QPath::TypeRelative(..)) | - - hir::ExprCall(..) | - hir::ExprMethodCall(..) | - hir::ExprStruct(..) | - hir::ExprTup(..) | - hir::ExprIf(..) | - hir::ExprMatch(..) | - hir::ExprClosure(..) | - hir::ExprBlock(..) | - hir::ExprRepeat(..) | - hir::ExprArray(..) | - hir::ExprBreak(..) | - hir::ExprAgain(..) | - hir::ExprRet(..) | - hir::ExprWhile(..) | - hir::ExprLoop(..) | - hir::ExprAssign(..) | - hir::ExprInlineAsm(..) | - hir::ExprAssignOp(..) | - hir::ExprLit(_) | - hir::ExprUnary(..) | - hir::ExprBox(..) | - hir::ExprAddrOf(..) | - hir::ExprBinary(..) | - hir::ExprYield(..) | - hir::ExprCast(..) => { - false - } - } - } - pub fn provided_trait_methods(self, id: DefId) -> Vec { self.associated_items(id) .filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value()) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index db7e4fe45ef76..0c1ebd1a2ba2f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1514,18 +1514,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// /// The parameter `explicit` indicates if this is an *explicit* dereference. /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. - pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference) - -> Option> - { + pub fn builtin_deref(&self, explicit: bool) -> Option> { match self.sty { TyAdt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), - mutbl: if pref == ty::PreferMutLvalue { - hir::MutMutable - } else { - hir::MutImmutable - }, + mutbl: hir::MutImmutable, }) }, TyRef(_, mt) => Some(mt), diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index b877c5a9cbcbc..da2b1ef0b1c02 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -43,14 +43,14 @@ it is safe with respect to the in-scope loans. # Formal model Throughout the docs we'll consider a simple subset of Rust in which -you can only borrow from lvalues, defined like so: +you can only borrow from places, defined like so: ```text -LV = x | LV.f | *LV +P = x | P.f | *P ``` -Here `x` represents some variable, `LV.f` is a field reference, -and `*LV` is a pointer dereference. There is no auto-deref or other +Here `x` represents some variable, `P.f` is a field reference, +and `*P` is a pointer dereference. There is no auto-deref or other niceties. This means that if you have a type like: ```rust @@ -58,7 +58,7 @@ struct S { f: i32 } ``` and a variable `a: Box`, then the rust expression `a.f` would correspond -to an `LV` of `(*a).f`. +to an `P` of `(*a).f`. Here is the formal grammar for the types we'll consider: @@ -99,7 +99,7 @@ this sort of thing. #### Loans and restrictions The way the borrow checker works is that it analyzes each borrow -expression (in our simple model, that's stuff like `&LV`, though in +expression (in our simple model, that's stuff like `&P`, though in real life there are a few other cases to consider). For each borrow expression, it computes a `Loan`, which is a data structure that records (1) the value being borrowed, (2) the mutability and scope of @@ -108,29 +108,29 @@ struct defined in `middle::borrowck`. Formally, we define `LOAN` as follows: ```text -LOAN = (LV, LT, MQ, RESTRICTION*) -RESTRICTION = (LV, ACTION*) +LOAN = (P, LT, MQ, RESTRICTION*) +RESTRICTION = (P, ACTION*) ACTION = MUTATE | CLAIM | FREEZE ``` -Here the `LOAN` tuple defines the lvalue `LV` being borrowed; the +Here the `LOAN` tuple defines the place `P` being borrowed; the lifetime `LT` of that borrow; the mutability `MQ` of the borrow; and a list of restrictions. The restrictions indicate actions which, if taken, could invalidate the loan and lead to type safety violations. -Each `RESTRICTION` is a pair of a restrictive lvalue `LV` (which will +Each `RESTRICTION` is a pair of a restrictive place `P` (which will either be the path that was borrowed or some prefix of the path that was borrowed) and a set of restricted actions. There are three kinds -of actions that may be restricted for the path `LV`: +of actions that may be restricted for the path `P`: -- `MUTATE` means that `LV` cannot be assigned to; -- `CLAIM` means that the `LV` cannot be borrowed mutably; -- `FREEZE` means that the `LV` cannot be borrowed immutably; +- `MUTATE` means that `P` cannot be assigned to; +- `CLAIM` means that the `P` cannot be borrowed mutably; +- `FREEZE` means that the `P` cannot be borrowed immutably; -Finally, it is never possible to move from an lvalue that appears in a -restriction. This implies that the "empty restriction" `(LV, [])`, +Finally, it is never possible to move from a place that appears in a +restriction. This implies that the "empty restriction" `(P, [])`, which contains an empty set of actions, still has a purpose---it -prevents moves from `LV`. I chose not to make `MOVE` a fourth kind of +prevents moves from `P`. I chose not to make `MOVE` a fourth kind of action because that would imply that sometimes moves are permitted from restricted values, which is not the case. @@ -239,22 +239,22 @@ live. (This is done via restrictions, read on.) We start with the `gather_loans` pass, which walks the AST looking for borrows. For each borrow, there are three bits of information: the -lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT` +place `P` being borrowed and the mutability `MQ` and lifetime `LT` of the resulting pointer. Given those, `gather_loans` applies four validity tests: -1. `MUTABILITY(LV, MQ)`: The mutability of the reference is -compatible with the mutability of `LV` (i.e., not borrowing immutable +1. `MUTABILITY(P, MQ)`: The mutability of the reference is +compatible with the mutability of `P` (i.e., not borrowing immutable data as mutable). -2. `ALIASABLE(LV, MQ)`: The aliasability of the reference is -compatible with the aliasability of `LV`. The goal is to prevent +2. `ALIASABLE(P, MQ)`: The aliasability of the reference is +compatible with the aliasability of `P`. The goal is to prevent `&mut` borrows of aliasability data. -3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed +3. `LIFETIME(P, LT, MQ)`: The lifetime of the borrow does not exceed the lifetime of the value being borrowed. -4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the +4. `RESTRICTIONS(P, LT, ACTIONS) = RS`: This pass checks and computes the restrictions to maintain memory safety. These are the restrictions that will go into the final loan. We'll discuss in more detail below. @@ -263,7 +263,7 @@ that will go into the final loan. We'll discuss in more detail below. Checking mutability is fairly straightforward. We just want to prevent immutable data from being borrowed as mutable. Note that it is ok to borrow mutable data as immutable, since that is simply a freeze. The judgement -`MUTABILITY(LV, MQ)` means the mutability of `LV` is compatible with a borrow +`MUTABILITY(P, MQ)` means the mutability of `P` is compatible with a borrow of mutability `MQ`. The Rust code corresponding to this predicate is the function `check_mutability` in `middle::borrowck::gather_loans`. @@ -288,15 +288,15 @@ MUTABILITY(X, imm) // M-Var-Imm Fields and boxes inherit their mutability from their base expressions, so both of their rules basically -delegate the check to the base expression `LV`: +delegate the check to the base expression `P`: ```text -MUTABILITY(LV.f, MQ) // M-Field - MUTABILITY(LV, MQ) +MUTABILITY(P.f, MQ) // M-Field + MUTABILITY(P, MQ) -MUTABILITY(*LV, MQ) // M-Deref-Unique - TYPE(LV) = Box - MUTABILITY(LV, MQ) +MUTABILITY(*P, MQ) // M-Deref-Unique + TYPE(P) = Box + MUTABILITY(P, MQ) ``` ### Checking mutability of immutable pointer types @@ -305,8 +305,8 @@ Immutable pointer types like `&T` can only be borrowed if MQ is immutable: ```text -MUTABILITY(*LV, imm) // M-Deref-Borrowed-Imm - TYPE(LV) = &Ty +MUTABILITY(*P, imm) // M-Deref-Borrowed-Imm + TYPE(P) = &Ty ``` ### Checking mutability of mutable pointer types @@ -314,15 +314,15 @@ MUTABILITY(*LV, imm) // M-Deref-Borrowed-Imm `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: ```text -MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut - TYPE(LV) = &mut Ty +MUTABILITY(*P, MQ) // M-Deref-Borrowed-Mut + TYPE(P) = &mut Ty ``` ## Checking aliasability The goal of the aliasability check is to ensure that we never permit `&mut` -borrows of aliasable data. The judgement `ALIASABLE(LV, MQ)` means the -aliasability of `LV` is compatible with a borrow of mutability `MQ`. The Rust +borrows of aliasable data. The judgement `ALIASABLE(P, MQ)` means the +aliasability of `P` is compatible with a borrow of mutability `MQ`. The Rust code corresponding to this predicate is the function `check_aliasability()` in `middle::borrowck::gather_loans`. @@ -340,11 +340,11 @@ the stack frame. Owned content is aliasable if it is found in an aliasable location: ```text -ALIASABLE(LV.f, MQ) // M-Field - ALIASABLE(LV, MQ) +ALIASABLE(P.f, MQ) // M-Field + ALIASABLE(P, MQ) -ALIASABLE(*LV, MQ) // M-Deref-Unique - ALIASABLE(LV, MQ) +ALIASABLE(*P, MQ) // M-Deref-Unique + ALIASABLE(P, MQ) ``` ### Checking aliasability of immutable pointer types @@ -353,8 +353,8 @@ Immutable pointer types like `&T` are aliasable, and hence can only be borrowed immutably: ```text -ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm - TYPE(LV) = &Ty +ALIASABLE(*P, imm) // M-Deref-Borrowed-Imm + TYPE(P) = &Ty ``` ### Checking aliasability of mutable pointer types @@ -362,16 +362,16 @@ ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: ```text -ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut - TYPE(LV) = &mut Ty +ALIASABLE(*P, MQ) // M-Deref-Borrowed-Mut + TYPE(P) = &mut Ty ``` ## Checking lifetime These rules aim to ensure that no data is borrowed for a scope that exceeds its lifetime. These two computations wind up being intimately related. -Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that -"the lvalue `LV` can be safely borrowed for the lifetime `LT` with mutability +Formally, we define a predicate `LIFETIME(P, LT, MQ)`, which states that +"the place `P` can be safely borrowed for the lifetime `LT` with mutability `MQ`". The Rust code corresponding to this predicate is the module `middle::borrowck::gather_loans::lifetime`. @@ -391,12 +391,12 @@ The lifetime of a field or box is the same as the lifetime of its owner: ```text -LIFETIME(LV.f, LT, MQ) // L-Field - LIFETIME(LV, LT, MQ) +LIFETIME(P.f, LT, MQ) // L-Field + LIFETIME(P, LT, MQ) -LIFETIME(*LV, LT, MQ) // L-Deref-Send - TYPE(LV) = Box - LIFETIME(LV, LT, MQ) +LIFETIME(*P, LT, MQ) // L-Deref-Send + TYPE(P) = Box + LIFETIME(P, LT, MQ) ``` ### Checking lifetime for derefs of references @@ -408,8 +408,8 @@ of the borrow is shorter than the lifetime `LT'` of the pointer itself: ```text -LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed - TYPE(LV) = <' Ty OR <' mut Ty +LIFETIME(*P, LT, MQ) // L-Deref-Borrowed + TYPE(P) = <' Ty OR <' mut Ty LT <= LT' ``` @@ -417,17 +417,17 @@ LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed The final rules govern the computation of *restrictions*, meaning that we compute the set of actions that will be illegal for the life of the -loan. The predicate is written `RESTRICTIONS(LV, LT, ACTIONS) = +loan. The predicate is written `RESTRICTIONS(P, LT, ACTIONS) = RESTRICTION*`, which can be read "in order to prevent `ACTIONS` from -occurring on `LV`, the restrictions `RESTRICTION*` must be respected +occurring on `P`, the restrictions `RESTRICTION*` must be respected for the lifetime of the loan". Note that there is an initial set of restrictions: these restrictions are computed based on the kind of borrow: ```text -&mut LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE) -&LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM) +&mut P => RESTRICTIONS(P, LT, MUTATE|CLAIM|FREEZE) +&P => RESTRICTIONS(P, LT, MUTATE|CLAIM) ``` The reasoning here is that a mutable borrow must be the only writer, @@ -451,8 +451,8 @@ Restricting a field is the same as restricting the owner of that field: ```text -RESTRICTIONS(LV.f, LT, ACTIONS) = RS, (LV.f, ACTIONS) // R-Field - RESTRICTIONS(LV, LT, ACTIONS) = RS +RESTRICTIONS(P.f, LT, ACTIONS) = RS, (P.f, ACTIONS) // R-Field + RESTRICTIONS(P, LT, ACTIONS) = RS ``` The reasoning here is as follows. If the field must not be mutated, @@ -467,16 +467,16 @@ origin of inherited mutability. Because the mutability of owned referents is inherited, restricting an owned referent is similar to restricting a field, in that it implies restrictions on the pointer. However, boxes have an important -twist: if the owner `LV` is mutated, that causes the owned referent -`*LV` to be freed! So whenever an owned referent `*LV` is borrowed, we -must prevent the box `LV` from being mutated, which means +twist: if the owner `P` is mutated, that causes the owned referent +`*P` to be freed! So whenever an owned referent `*P` is borrowed, we +must prevent the box `P` from being mutated, which means that we always add `MUTATE` and `CLAIM` to the restriction set imposed -on `LV`: +on `P`: ```text -RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer - TYPE(LV) = Box - RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS +RESTRICTIONS(*P, LT, ACTIONS) = RS, (*P, ACTIONS) // R-Deref-Send-Pointer + TYPE(P) = Box + RESTRICTIONS(P, LT, ACTIONS|MUTATE|CLAIM) = RS ``` ### Restrictions for loans of immutable borrowed referents @@ -484,15 +484,15 @@ RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer Immutable borrowed referents are freely aliasable, meaning that the compiler does not prevent you from copying the pointer. This implies that issuing restrictions is useless. We might prevent the -user from acting on `*LV` itself, but there could be another path -`*LV1` that refers to the exact same memory, and we would not be +user from acting on `*P` itself, but there could be another path +`*P1` that refers to the exact same memory, and we would not be restricting that path. Therefore, the rule for `&Ty` pointers always returns an empty set of restrictions, and it only permits restricting `MUTATE` and `CLAIM` actions: ```text -RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed - TYPE(LV) = <' Ty +RESTRICTIONS(*P, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed + TYPE(P) = <' Ty LT <= LT' // (1) ACTIONS subset of [MUTATE, CLAIM] ``` @@ -546,7 +546,7 @@ This function is legal. The reason for this is that the inner pointer (`*point : &'b Point`) is enough to guarantee the memory is immutable and valid for the lifetime `'b`. This is reflected in `RESTRICTIONS()` by the fact that we do not recurse (i.e., we impose -no restrictions on `LV`, which in this particular case is the pointer +no restrictions on `P`, which in this particular case is the pointer `point : &'a &'b Point`). #### Why both `LIFETIME()` and `RESTRICTIONS()`? @@ -612,10 +612,10 @@ while the new claimant is live. The rule for mutable borrowed pointers is as follows: ```text -RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Mut-Borrowed - TYPE(LV) = <' mut Ty +RESTRICTIONS(*P, LT, ACTIONS) = RS, (*P, ACTIONS) // R-Deref-Mut-Borrowed + TYPE(P) = <' mut Ty LT <= LT' // (1) - RESTRICTIONS(LV, LT, ACTIONS) = RS // (2) + RESTRICTIONS(P, LT, ACTIONS) = RS // (2) ``` Let's examine the two numbered clauses: @@ -670,7 +670,7 @@ fn foo(t0: &mut i32) { Remember that `&mut` pointers are linear, and hence `let t1 = t0` is a move of `t0` -- or would be, if it were legal. Instead, we get an -error, because clause (2) imposes restrictions on `LV` (`t0`, here), +error, because clause (2) imposes restrictions on `P` (`t0`, here), and any restrictions on a path make it impossible to move from that path. @@ -906,7 +906,7 @@ results of a dataflow computation. The `MovePath` tree tracks every path that is moved or assigned to. These paths have the same form as the `LoanPath` data structure, which -in turn is the "real world version of the lvalues `LV` that we +in turn is the "real world version of the places `P` that we introduced earlier. The difference between a `MovePath` and a `LoanPath` is that move paths are: @@ -1132,7 +1132,7 @@ is implied by the relevant moves. While writing up these docs, I encountered some rules I believe to be stricter than necessary: -- I think restricting the `&mut` LV against moves and `ALIAS` is sufficient, +- I think restricting the `&mut` P against moves and `ALIAS` is sufficient, `MUTATE` and `CLAIM` are overkill. `MUTATE` was necessary when swap was a built-in operator, but as it is not, it is implied by `CLAIM`, and `CLAIM` is implied by `ALIAS`. The only net effect of this is an diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 66aaafb77f757..97fa94b5e5cf9 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { fn scope(&self, cmt: &mc::cmt<'tcx>) -> ty::Region<'tcx> { //! Returns the maximal region scope for the which the - //! lvalue `cmt` is guaranteed to be valid without any + //! place `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. match cmt.cat { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index b35e8c6b41953..84ca2a9318ab3 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -170,7 +170,7 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc if !force_analysis && move_data.is_empty() && all_loans.is_empty() { // large arrays of data inserted as constants can take a lot of // time and memory to borrow-check - see issue #36799. However, - // they don't have lvalues, so no borrow-check is actually needed. + // they don't have places, so no borrow-check is actually needed. // Recognize that case and skip borrow-checking. debug!("skipping loan propagation for {:?} because of no loans", body_id); return None; @@ -384,9 +384,9 @@ impl ToInteriorKind for mc::InteriorKind { } // This can be: -// - a pointer dereference (`*LV` in README.md) +// - a pointer dereference (`*P` in README.md) // - a field reference, with an optional definition of the containing -// enum variant (`LV.f` in README.md) +// enum variant (`P.f` in README.md) // `DefId` is present when the field is part of struct that is in // a variant of an enum. For instance in: // `enum E { X { foo: u32 }, Y { foo: u32 }}` diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 98de394ae3967..a90dcd1072f95 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -153,7 +153,7 @@ pub struct Assignment { /// span of node where assignment occurs pub span: Span, - /// id for l-value expression on lhs of assignment + /// id for place expression on lhs of assignment pub assignee_id: hir::ItemLocalId, } diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 61d6c14d62730..ba966c9d4e316 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -15,8 +15,8 @@ use rustc::mir::{BasicBlock, Location}; -use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use dataflow::{EverInitializedLvals, MovingOutStatements}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{ActiveBorrows, FlowAtLocation, FlowsAtLocation}; use dataflow::move_paths::HasMoveData; use std::fmt; @@ -24,19 +24,19 @@ use std::fmt; // (forced to be `pub` due to its use as an associated type below.) pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { pub borrows: FlowAtLocation>, - pub inits: FlowAtLocation>, - pub uninits: FlowAtLocation>, + pub inits: FlowAtLocation>, + pub uninits: FlowAtLocation>, pub move_outs: FlowAtLocation>, - pub ever_inits: FlowAtLocation>, + pub ever_inits: FlowAtLocation>, } impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { pub fn new( borrows: FlowAtLocation>, - inits: FlowAtLocation>, - uninits: FlowAtLocation>, + inits: FlowAtLocation>, + uninits: FlowAtLocation>, move_outs: FlowAtLocation>, - ever_inits: FlowAtLocation>, + ever_inits: FlowAtLocation>, ) -> Self { Flows { borrows, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f69236516630d..9a6d83b8eb759 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -35,8 +35,8 @@ use dataflow::{do_dataflow, DebugFormatted}; use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; use dataflow::{DataflowAnalysis, DataflowResultsConsumer}; -use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; -use dataflow::{EverInitializedLvals, MovingOutStatements}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex}; use dataflow::{ActiveBorrows, Reservations}; use dataflow::indexes::BorrowIndex; @@ -160,7 +160,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &mdpe), + MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_uninits = FlowAtLocation::new(do_dataflow( @@ -169,7 +169,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), + MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_move_outs = FlowAtLocation::new(do_dataflow( @@ -187,7 +187,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - EverInitializedLvals::new(tcx, mir, &mdpe), + EverInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); @@ -607,7 +607,7 @@ enum ArtificialField { #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ShallowOrDeep { /// From the RFC: "A *shallow* access means that the immediate - /// fields reached at LV are accessed, but references or pointers + /// fields reached at P are accessed, but references or pointers /// found within are not dereferenced. Right now, the only access /// that is shallow is an assignment like `x = ...;`, which would /// be a *shallow write* of `x`." diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index f96e107efa38f..66ca74b0139a3 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -19,7 +19,7 @@ use std::io; use transform::MirSource; use util::liveness::{LivenessResults, LocalSet}; use dataflow::FlowAtLocation; -use dataflow::MaybeInitializedLvals; +use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::MoveData; use util as mir_util; @@ -71,7 +71,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, param_env: ty::ParamEnv<'gcx>, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) -> ( RegionInferenceContext<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 8a0578ae4d45c..6c2037810d326 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -10,7 +10,7 @@ use dataflow::{FlowAtLocation, FlowsAtLocation}; use borrow_check::nll::region_infer::Cause; -use dataflow::MaybeInitializedLvals; +use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::{HasMoveData, MoveData}; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::mir::Local; @@ -34,7 +34,7 @@ pub(super) fn generate<'gcx, 'tcx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, liveness: &LivenessResults, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { let tcx = cx.tcx(); @@ -63,7 +63,7 @@ where tcx: TyCtxt<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, liveness: &'gen LivenessResults, - flow_inits: &'gen mut FlowAtLocation>, + flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 9dcd4435580ab..015eb8a3b6643 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -15,7 +15,7 @@ use borrow_check::nll::region_infer::Cause; use borrow_check::nll::region_infer::ClosureRegionRequirementsExt; use borrow_check::nll::universal_regions::UniversalRegions; use dataflow::FlowAtLocation; -use dataflow::MaybeInitializedLvals; +use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::MoveData; use rustc::hir::def_id::DefId; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; @@ -100,7 +100,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( mir_def_id: DefId, universal_regions: &UniversalRegions<'tcx>, liveness: &LivenessResults, - flow_inits: &mut FlowAtLocation>, + flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) -> MirTypeckRegionConstraints<'tcx> { let body_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap(); @@ -397,7 +397,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { let base_ty = base.to_ty(tcx); match *pi { ProjectionElem::Deref => { - let deref_ty = base_ty.builtin_deref(true, ty::LvaluePreference::NoPreference); + let deref_ty = base_ty.builtin_deref(true); PlaceTy::Ty { ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| { span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index d7cd8830adb00..632bb5b34284d 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -575,10 +575,10 @@ impl<'a, 'b, 'tcx> FindPlaceUses<'a, 'b, 'tcx> { /// has a reservation at the time). fn is_potential_use(context: PlaceContext) -> bool { match context { - // storage effects on an place do not activate it + // storage effects on a place do not activate it PlaceContext::StorageLive | PlaceContext::StorageDead => false, - // validation effects do not activate an place + // validation effects do not activate a place // // FIXME: Should they? Is it just another read? Or can we // guarantee it won't dereference the stored address? How @@ -589,11 +589,11 @@ impl<'a, 'b, 'tcx> FindPlaceUses<'a, 'b, 'tcx> { // AsmOutput existed, but it's not necessarily a pure overwrite. // so it's possible this should activate the place. PlaceContext::AsmOutput | - // pure overwrites of an place do not activate it. (note + // pure overwrites of a place do not activate it. (note // PlaceContext::Call is solely about dest place) PlaceContext::Store | PlaceContext::Call => false, - // reads of an place *do* activate it + // reads of a place *do* activate it PlaceContext::Move | PlaceContext::Copy | PlaceContext::Drop | diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 106a88e703c79..e7c15625cbe2b 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -36,7 +36,7 @@ pub use self::storage_liveness::*; #[allow(dead_code)] pub(super) mod borrows; -/// `MaybeInitializedLvals` tracks all l-values that might be +/// `MaybeInitializedPlaces` tracks all places that might be /// initialized upon reaching a particular point in the control flow /// for a function. /// @@ -63,35 +63,35 @@ pub(super) mod borrows; /// } /// ``` /// -/// To determine whether an l-value *must* be initialized at a +/// To determine whether a place *must* be initialized at a /// particular control-flow point, one can take the set-difference -/// between this data and the data from `MaybeUninitializedLvals` at the +/// between this data and the data from `MaybeUninitializedPlaces` at the /// corresponding control-flow point. /// /// Similarly, at a given `drop` statement, the set-intersection -/// between this data and `MaybeUninitializedLvals` yields the set of -/// l-values that would require a dynamic drop-flag at that statement. -pub struct MaybeInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +/// between this data and `MaybeUninitializedPlaces` yields the set of +/// places that would require a dynamic drop-flag at that statement. +pub struct MaybeInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + MaybeInitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `MaybeUninitializedLvals` tracks all l-values that might be +/// `MaybeUninitializedPlaces` tracks all places that might be /// uninitialized upon reaching a particular point in the control flow /// for a function. /// @@ -118,42 +118,42 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'gcx, 'tcx> /// } /// ``` /// -/// To determine whether an l-value *must* be uninitialized at a +/// To determine whether a place *must* be uninitialized at a /// particular control-flow point, one can take the set-difference -/// between this data and the data from `MaybeInitializedLvals` at the +/// between this data and the data from `MaybeInitializedPlaces` at the /// corresponding control-flow point. /// /// Similarly, at a given `drop` statement, the set-intersection -/// between this data and `MaybeInitializedLvals` yields the set of -/// l-values that would require a dynamic drop-flag at that statement. -pub struct MaybeUninitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +/// between this data and `MaybeInitializedPlaces` yields the set of +/// places that would require a dynamic drop-flag at that statement. +pub struct MaybeUninitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + MaybeUninitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `DefinitelyInitializedLvals` tracks all l-values that are definitely +/// `DefinitelyInitializedPlaces` tracks all places that are definitely /// initialized upon reaching a particular point in the control flow /// for a function. /// /// FIXME: Note that once flow-analysis is complete, this should be -/// the set-complement of MaybeUninitializedLvals; thus we can get rid +/// the set-complement of MaybeUninitializedPlaces; thus we can get rid /// of one or the other of these two. I'm inclined to get rid of -/// MaybeUninitializedLvals, simply because the sets will tend to be +/// MaybeUninitializedPlaces, simply because the sets will tend to be /// smaller in this analysis and thus easier for humans to process /// when debugging. /// @@ -180,43 +180,43 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'gcx, 'tc /// } /// ``` /// -/// To determine whether an l-value *may* be uninitialized at a +/// To determine whether a place *may* be uninitialized at a /// particular control-flow point, one can take the set-complement /// of this data. /// /// Similarly, at a given `drop` statement, the set-difference between -/// this data and `MaybeInitializedLvals` yields the set of l-values +/// this data and `MaybeInitializedPlaces` yields the set of places /// that would require a dynamic drop-flag at that statement. -pub struct DefinitelyInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +pub struct DefinitelyInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + DefinitelyInitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } /// `MovingOutStatements` tracks the statements that perform moves out -/// of particular l-values. More precisely, it tracks whether the +/// of particular places. More precisely, it tracks whether the /// *effect* of such moves (namely, the uninitialization of the -/// l-value in question) can reach some point in the control-flow of +/// place in question) can reach some point in the control-flow of /// the function, or if that effect is "killed" by some intervening -/// operation reinitializing that l-value. +/// operation reinitializing that place. /// /// The resulting dataflow is a more enriched version of -/// `MaybeUninitializedLvals`. Both structures on their own only tell -/// you if an l-value *might* be uninitialized at a given point in the +/// `MaybeUninitializedPlaces`. Both structures on their own only tell +/// you if a place *might* be uninitialized at a given point in the /// control flow. But `MovingOutStatements` also includes the added /// data of *which* particular statement causing the deinitialization /// that the borrow checker's error message may need to report. @@ -241,7 +241,7 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `EverInitializedLvals` tracks all l-values that might have ever been +/// `EverInitializedPlaces` tracks all places that might have ever been /// initialized upon reaching a particular point in the control flow /// for a function, without an intervening `Storage Dead`. /// @@ -270,28 +270,28 @@ impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> { /// c = S; // {a, b, c, d } /// } /// ``` -pub struct EverInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> { +pub struct EverInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, } -impl<'a, 'gcx: 'tcx, 'tcx: 'a> EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx: 'tcx, 'tcx: 'a> EverInitializedPlaces<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) -> Self { - EverInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } + EverInitializedPlaces { tcx: tcx, mir: mir, mdpe: mdpe } } } -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -impl<'a, 'gcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> { fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { @@ -302,7 +302,7 @@ impl<'a, 'gcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { @@ -313,7 +313,7 @@ impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { fn update_bits(sets: &mut BlockSets, path: MovePathIndex, state: DropFlagState) { @@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "maybe_init" } fn bits_per_block(&self) -> usize { @@ -375,7 +375,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "maybe_uninit" } fn bits_per_block(&self) -> usize { @@ -430,7 +430,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = MovePathIndex; fn name() -> &'static str { "definite_init" } fn bits_per_block(&self) -> usize { @@ -561,7 +561,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = InitIndex; fn name() -> &'static str { "ever_init" } fn bits_per_block(&self) -> usize { @@ -657,21 +657,21 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // "maybe" means we union effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // "maybe" means we union effects of both preds } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 & pred2 // "definitely" means we intersect effects of both preds @@ -685,7 +685,7 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // inits from both preds are in scope @@ -702,21 +702,21 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedLvals<'a, 'gcx, 'tcx> { // propagating, or you start at all-ones and then use Intersect as // your merge when propagating. -impl<'a, 'gcx, 'tcx> InitialFlow for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = uninitialized } } -impl<'a, 'gcx, 'tcx> InitialFlow for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = initialized (start_block_effect counters this at outset) } } -impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { true // bottom = initialized (start_block_effect counters this at outset) @@ -730,7 +730,7 @@ impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = no initialized variables by default diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index b18fb7c7b9cce..bd63198ecd0d2 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -26,9 +26,9 @@ use std::path::PathBuf; use std::usize; pub use self::impls::{MaybeStorageLive}; -pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; -pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; -pub use self::impls::EverInitializedLvals; +pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; +pub use self::impls::EverInitializedPlaces; pub use self::impls::borrows::{Borrows, BorrowData}; pub(crate) use self::impls::borrows::{ActiveBorrows, Reservations, ReserveOrActivateIndex}; pub use self::at_location::{FlowAtLocation, FlowsAtLocation}; diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index bcf4662211e8b..7b6ebc6fba872 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -86,7 +86,7 @@ impl MoveOutIndex { /// It follows a tree structure. /// /// Given `struct X { m: M, n: N }` and `x: X`, moves like `drop x.m;` -/// move *out* of the l-value `x.m`. +/// move *out* of the place `x.m`. /// /// The MovePaths representing `x.m` and `x.n` are siblings (that is, /// one of them will link to the other via the `next_sibling` field, @@ -222,7 +222,7 @@ impl fmt::Debug for Init { } } -/// Tables mapping from an l-value to its MovePathIndex. +/// Tables mapping from a place to its MovePathIndex. #[derive(Debug)] pub struct MovePathLookup<'tcx> { locals: IndexVec, @@ -247,7 +247,7 @@ pub enum LookupResult { impl<'tcx> MovePathLookup<'tcx> { // Unlike the builder `fn move_path_for` below, this lookup // alternative will *not* create a MovePath on the fly for an - // unknown l-value, but will rather return the nearest available + // unknown place, but will rather return the nearest available // parent. pub fn find(&self, place: &Place<'tcx>) -> LookupResult { match *place { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index c2c6b23c083a2..701b7a07ac988 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,9 +9,9 @@ use interpret::memory::HasMemory; #[derive(Copy, Clone, Debug)] pub enum Place { - /// An place referring to a value allocated in the `Memory` system. + /// A place referring to a value allocated in the `Memory` system. Ptr { - /// An place may have an invalid (integral or undef) pointer, + /// A place may have an invalid (integral or undef) pointer, /// since it might be turned back into a reference /// before ever being dereferenced. ptr: Pointer, @@ -19,7 +19,7 @@ pub enum Place { extra: PlaceExtra, }, - /// An place referring to a value on the stack. Represented by a stack frame index paired with + /// A place referring to a value on the stack. Represented by a stack frame index paired with /// a Mir local index. Local { frame: usize, local: mir::Local }, } @@ -33,7 +33,7 @@ pub enum PlaceExtra { } impl<'tcx> Place { - /// Produces an Place that will error if attempted to be read from + /// Produces a Place that will error if attempted to be read from pub fn undef() -> Self { Self::from_primval_ptr(PrimVal::Undef.into(), Align::from_bytes(1, 1).unwrap()) } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 106bc39d0fc5b..9eca343cb5edc 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -9,7 +9,7 @@ // except according to those terms. use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; -use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::{DataflowResults}; use dataflow::{on_all_children_bits, on_all_drop_children_bits}; use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; @@ -60,11 +60,11 @@ impl MirPass for ElaborateDrops { let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); let flow_inits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), + MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); let flow_uninits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &env), + MaybeUninitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); ElaborateDropsCtxt { @@ -97,7 +97,7 @@ fn find_dead_unwinds<'a, 'tcx>( let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &env), + MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { let location = match bb_data.terminator().kind { @@ -300,8 +300,8 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, env: &'a MoveDataParamEnv<'tcx, 'tcx>, - flow_inits: DataflowResults>, - flow_uninits: DataflowResults>, + flow_inits: DataflowResults>, + flow_uninits: DataflowResults>, drop_flags: FxHashMap, patch: MirPatch<'tcx>, } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index b6153ea1fdbad..76283edac7284 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -22,7 +22,7 @@ use dataflow::{do_dataflow, DebugFormatted}; use dataflow::MoveDataParamEnv; use dataflow::BitDenotation; use dataflow::DataflowResults; -use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::move_paths::{MovePathIndex, LookupResult}; use dataflow::move_paths::{HasMoveData, MoveData}; use dataflow; @@ -50,15 +50,15 @@ impl MirPass for SanityCheck { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, - MaybeInitializedLvals::new(tcx, mir, &mdpe), + MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, - MaybeUninitializedLvals::new(tcx, mir, &mdpe), + MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_def_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, - DefinitelyInitializedLvals::new(tcx, mir, &mdpe), + DefinitelyInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 3331bc9e59e0b..6577106801499 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -560,7 +560,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> /// ptr = cur /// cur = cur.offset(1) /// } else { - /// ptr = &mut LV[cur] + /// ptr = &mut P[cur] /// cur = cur + 1 /// } /// drop(ptr) @@ -731,7 +731,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::Local(self.new_temp(tmp_ty)); - // tmp = &LV; + // tmp = &P; // cur = tmp as *mut T; // end = Offset(cur, len); drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref( diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 9cabd9356e9bf..12698964d2e65 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -545,7 +545,7 @@ impl<'a, 'tcx> ArgType<'tcx> { self.mode == PassMode::Ignore } - /// Get the LLVM type for an place of the original Rust type of + /// Get the LLVM type for a place of the original Rust type of /// this argument/return, i.e. the result of `type_of::type_of`. pub fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { self.layout.llvm_type(cx) @@ -674,7 +674,7 @@ impl<'a, 'tcx> FnType<'tcx> { _ => bug!("FnType::new_vtable: non-pair self {:?}", self_arg) } - let pointee = self_arg.layout.ty.builtin_deref(true, ty::NoPreference) + let pointee = self_arg.layout.ty.builtin_deref(true) .unwrap_or_else(|| { bug!("FnType::new_vtable: non-pointer self {:?}", self_arg) }).ty; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 71ce0aa3da96b..416e3639bc180 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -209,7 +209,7 @@ enum Base { Static(ValueRef) } -/// An place as seen from a constant. +/// A place as seen from a constant. #[derive(Copy, Clone)] struct ConstPlace<'tcx> { base: Base, @@ -740,7 +740,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { operand.llval } mir::CastKind::Unsize => { - let pointee_ty = operand.ty.builtin_deref(true, ty::NoPreference) + let pointee_ty = operand.ty.builtin_deref(true) .expect("consts: unsizing got non-pointer type").ty; let (base, old_info) = if !self.cx.type_is_sized(pointee_ty) { // Normally, the source is a thin pointer and we are @@ -755,7 +755,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { (operand.llval, None) }; - let unsized_ty = cast_ty.builtin_deref(true, ty::NoPreference) + let unsized_ty = cast_ty.builtin_deref(true) .expect("consts: unsizing got non-pointer target type").ty; let ptr_ty = self.cx.layout_of(unsized_ty).llvm_type(self.cx).ptr_to(); let base = consts::ptrcast(base, ptr_ty); diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 25db9f9b4c8a8..e1b906646aa43 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -9,7 +9,6 @@ // except according to those terms. use llvm::ValueRef; -use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; @@ -100,7 +99,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { } pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> { - let projected_ty = self.layout.ty.builtin_deref(true, ty::NoPreference) + let projected_ty = self.layout.ty.builtin_deref(true) .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty; let (llptr, llextra) = match self.val { OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d5e4aa69c5b4e..1a285cd869aec 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -14,8 +14,8 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::infer; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::ObligationCauseCode; -use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference}; -use check::{FnCtxt, Expectation, Diverges}; +use rustc::ty::{self, Ty, TypeFoldable}; +use check::{FnCtxt, Expectation, Diverges, Needs}; use check::coercion::CoerceMany; use util::nodemap::FxHashMap; @@ -500,7 +500,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { if let PatKind::Binding(..) = inner.node { - if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) { + if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { if let ty::TyDynamic(..) = mt.ty.sty { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. @@ -584,7 +584,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }); let discrim_ty; if let Some(m) = contains_ref_bindings { - discrim_ty = self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m)); + discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m)); } else { // ...but otherwise we want to use any supertype of the // discriminant. This is sort of a workaround, see note (*) in diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 169959d12b5d5..1d7c533178f07 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -10,7 +10,7 @@ use astconv::AstConv; -use super::{FnCtxt, LvalueOp}; +use super::{FnCtxt, PlaceOp, Needs}; use super::method::MethodCallee; use rustc::infer::InferOk; @@ -18,7 +18,6 @@ use rustc::session::DiagnosticMessageId; use rustc::traits; use rustc::ty::{self, Ty, TraitRef}; use rustc::ty::{ToPredicate, TypeFoldable}; -use rustc::ty::{LvaluePreference, NoPreference}; use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use syntax_pos::Span; @@ -85,7 +84,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { // Otherwise, deref if type is derefable: let (kind, new_ty) = - if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers, NoPreference) { + if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers) { (AutoderefKind::Builtin, mt.ty) } else { let ty = self.overloaded_deref_ty(self.cur_ty)?; @@ -163,19 +162,19 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { } /// Returns the adjustment steps. - pub fn adjust_steps(&self, pref: LvaluePreference) + pub fn adjust_steps(&self, needs: Needs) -> Vec> { - self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(pref)) + self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(needs)) } - pub fn adjust_steps_as_infer_ok(&self, pref: LvaluePreference) + pub fn adjust_steps_as_infer_ok(&self, needs: Needs) -> InferOk<'tcx, Vec>> { let mut obligations = vec![]; let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty) .chain(iter::once(self.cur_ty)); let steps: Vec<_> = self.steps.iter().map(|&(source, kind)| { if let AutoderefKind::Overloaded = kind { - self.fcx.try_overloaded_deref(self.span, source, pref) + self.fcx.try_overloaded_deref(self.span, source, needs) .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::TyRef(region, mt) = method.sig.output().sty { @@ -238,8 +237,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn try_overloaded_deref(&self, span: Span, base_ty: Ty<'tcx>, - pref: LvaluePreference) + needs: Needs) -> Option>> { - self.try_overloaded_lvalue_op(span, base_ty, &[], pref, LvalueOp::Deref) + self.try_overloaded_place_op(span, base_ty, &[], needs, PlaceOp::Deref) } } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 5c5e5f2735b71..76df9be48386d 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Expectation, FnCtxt, TupleArgumentsFlag}; +use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; use super::autoderef::Autoderef; use super::method::MethodCallee; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; -use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty}; +use rustc::ty::{self, TyCtxt, TypeFoldable, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use syntax::abi; use syntax::symbol::Symbol; @@ -96,7 +96,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { ty::TyFnDef(..) | ty::TyFnPtr(_) => { - let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let adjustments = autoderef.adjust_steps(Needs::None); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); } @@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { infer::FnCall, &closure_ty) .0; - let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let adjustments = autoderef.adjust_steps(Needs::None); self.record_deferred_call_resolution(def_id, DeferredCallResolution { call_expr, callee_expr, @@ -143,7 +143,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let mut adjustments = autoderef.adjust_steps(Needs::None); adjustments.extend(autoref); self.apply_adjustments(callee_expr, adjustments); CallStep::Overloaded(method) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index edda557c98c37..d0280bf0b30be 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -60,7 +60,7 @@ //! sort of a minor point so I've opted to leave it for later---after all //! we may want to adjust precisely when coercions occur. -use check::{Diverges, FnCtxt}; +use check::{Diverges, FnCtxt, Needs}; use rustc::hir; use rustc::hir::def_id::DefId; @@ -69,8 +69,7 @@ use rustc::infer::type_variable::TypeVariableOrigin; use rustc::lint; use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; -use rustc::ty::{self, LvaluePreference, TypeAndMut, - Ty, ClosureSubsts}; +use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; @@ -410,9 +409,9 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { return success(vec![], ty, obligations); } - let pref = LvaluePreference::from_mutbl(mt_b.mutbl); + let needs = Needs::maybe_mut_place(mt_b.mutbl); let InferOk { value: mut adjustments, obligations: o } - = autoderef.adjust_steps_as_infer_ok(pref); + = autoderef.adjust_steps_as_infer_ok(needs); obligations.extend(o); obligations.extend(autoderef.into_obligations()); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 3a9c4e1901d27..7f5b353f79ef7 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -11,11 +11,11 @@ use super::{probe, MethodCallee}; use astconv::AstConv; -use check::{FnCtxt, LvalueOp, callee}; +use check::{FnCtxt, PlaceOp, callee, Needs}; use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; -use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; +use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, OverloadedDeref}; use rustc::ty::fold::TypeFoldable; @@ -136,7 +136,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { }; if let Some(hir::MutMutable) = pick.autoref { - self.convert_lvalue_derefs_to_mutable(); + self.convert_place_derefs_to_mutable(); } ConfirmResult { callee, illegal_sized_bound } @@ -155,7 +155,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); assert_eq!(n, pick.autoderefs); - let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference); + let mut adjustments = autoderef.adjust_steps(Needs::None); let mut target = autoderef.unambiguous_final_ty(); @@ -416,7 +416,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { /// When we select a method with a mutable autoref, we have to go convert any /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut` /// respectively. - fn convert_lvalue_derefs_to_mutable(&self) { + fn convert_place_derefs_to_mutable(&self) { // Gather up expressions we want to munge. let mut exprs = Vec::new(); exprs.push(self.self_expr); @@ -431,14 +431,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } } - debug!("convert_lvalue_derefs_to_mutable: exprs={:?}", exprs); + debug!("convert_place_derefs_to_mutable: exprs={:?}", exprs); // Fix up autoderefs and derefs. for (i, &expr) in exprs.iter().rev().enumerate() { - debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr); + debug!("convert_place_derefs_to_mutable: i={} expr={:?}", i, expr); // Fix up the autoderefs. Autorefs can only occur immediately preceding - // overloaded lvalue ops, and will be fixed by them in order to get + // overloaded place ops, and will be fixed by them in order to get // the correct region. let mut source = self.node_ty(expr.hir_id); // Do not mutate adjustments in place, but rather take them, @@ -449,10 +449,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .adjustments_mut() .remove(expr.hir_id); if let Some(mut adjustments) = previous_adjustments { - let pref = LvaluePreference::PreferMutLvalue; + let needs = Needs::MutPlace; for adjustment in &mut adjustments { if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind { - if let Some(ok) = self.try_overloaded_deref(expr.span, source, pref) { + if let Some(ok) = self.try_overloaded_deref(expr.span, source, needs) { let method = self.register_infer_ok_obligations(ok); if let ty::TyRef(region, mt) = method.sig.output().sty { *deref = OverloadedDeref { @@ -470,28 +470,28 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { match expr.node { hir::ExprIndex(ref base_expr, ref index_expr) => { let index_expr_ty = self.node_ty(index_expr.hir_id); - self.convert_lvalue_op_to_mutable( - LvalueOp::Index, expr, base_expr, &[index_expr_ty]); + self.convert_place_op_to_mutable( + PlaceOp::Index, expr, base_expr, &[index_expr_ty]); } hir::ExprUnary(hir::UnDeref, ref base_expr) => { - self.convert_lvalue_op_to_mutable( - LvalueOp::Deref, expr, base_expr, &[]); + self.convert_place_op_to_mutable( + PlaceOp::Deref, expr, base_expr, &[]); } _ => {} } } } - fn convert_lvalue_op_to_mutable(&self, - op: LvalueOp, + fn convert_place_op_to_mutable(&self, + op: PlaceOp, expr: &hir::Expr, base_expr: &hir::Expr, arg_tys: &[Ty<'tcx>]) { - debug!("convert_lvalue_op_to_mutable({:?}, {:?}, {:?}, {:?})", + debug!("convert_place_op_to_mutable({:?}, {:?}, {:?}, {:?})", op, expr, base_expr, arg_tys); if !self.tables.borrow().is_method_call(expr) { - debug!("convert_lvalue_op_to_mutable - builtin, nothing to do"); + debug!("convert_place_op_to_mutable - builtin, nothing to do"); return } @@ -499,24 +499,24 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .map_or_else(|| self.node_ty(expr.hir_id), |adj| adj.target); let base_ty = self.resolve_type_vars_if_possible(&base_ty); - // Need to deref because overloaded lvalue ops take self by-reference. - let base_ty = base_ty.builtin_deref(false, NoPreference) - .expect("lvalue op takes something that is not a ref") + // Need to deref because overloaded place ops take self by-reference. + let base_ty = base_ty.builtin_deref(false) + .expect("place op takes something that is not a ref") .ty; - let method = self.try_overloaded_lvalue_op( - expr.span, base_ty, arg_tys, PreferMutLvalue, op); + let method = self.try_overloaded_place_op( + expr.span, base_ty, arg_tys, Needs::MutPlace, op); let method = match method { Some(ok) => self.register_infer_ok_obligations(ok), None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed") }; - debug!("convert_lvalue_op_to_mutable: method={:?}", method); + debug!("convert_place_op_to_mutable: method={:?}", method); self.write_method_call(expr.hir_id, method); let (region, mutbl) = if let ty::TyRef(r, mt) = method.sig.inputs()[0].sty { (r, mt.mutbl) } else { - span_bug!(expr.span, "input to lvalue op is not a ref?"); + span_bug!(expr.span, "input to place op is not a ref?"); }; // Convert the autoref in the base expr to mutable with the correct @@ -529,7 +529,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let mut source = base_expr_ty; for adjustment in &mut adjustments[..] { if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind { - debug!("convert_lvalue_op_to_mutable: converting autoref {:?}", adjustment); + debug!("convert_place_op_to_mutable: converting autoref {:?}", adjustment); adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(region, mutbl)); adjustment.target = self.tcx.mk_ref(region, ty::TypeAndMut { ty: source, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9b24c09036bce..483dd345286d4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,7 +95,6 @@ use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; -use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate}; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc::ty::fold::TypeFoldable; @@ -368,6 +367,21 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Needs { + MutPlace, + None +} + +impl Needs { + fn maybe_mut_place(m: hir::Mutability) -> Self { + match m { + hir::MutMutable => Needs::MutPlace, + hir::MutImmutable => Needs::None, + } + } +} + #[derive(Copy, Clone)] pub struct UnsafetyState { pub def: ast::NodeId, @@ -410,7 +424,7 @@ impl UnsafetyState { } #[derive(Debug, Copy, Clone)] -pub enum LvalueOp { +pub enum PlaceOp { Deref, Index } @@ -543,7 +557,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// foo();}` or `{return; 22}`, where we would warn on the /// `foo()` or `22`. /// - /// - To permit assignment into a local variable or other lvalue + /// - To permit assignment into a local variable or other place /// (including the "return slot") of type `!`. This is allowed /// if **either** the type of value being assigned is `!`, which /// means the current code is dead, **or** the expression's @@ -2207,11 +2221,65 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait + fn is_place_expr(&self, expr: &hir::Expr) -> bool { + match expr.node { + hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { + match path.def { + Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true, + _ => false, + } + } + + hir::ExprType(ref e, _) => { + self.is_place_expr(e) + } + + hir::ExprUnary(hir::UnDeref, _) | + hir::ExprField(..) | + hir::ExprTupField(..) | + hir::ExprIndex(..) => { + true + } + + // Partially qualified paths in expressions can only legally + // refer to associated items which are always rvalues. + hir::ExprPath(hir::QPath::TypeRelative(..)) | + + hir::ExprCall(..) | + hir::ExprMethodCall(..) | + hir::ExprStruct(..) | + hir::ExprTup(..) | + hir::ExprIf(..) | + hir::ExprMatch(..) | + hir::ExprClosure(..) | + hir::ExprBlock(..) | + hir::ExprRepeat(..) | + hir::ExprArray(..) | + hir::ExprBreak(..) | + hir::ExprAgain(..) | + hir::ExprRet(..) | + hir::ExprWhile(..) | + hir::ExprLoop(..) | + hir::ExprAssign(..) | + hir::ExprInlineAsm(..) | + hir::ExprAssignOp(..) | + hir::ExprLit(_) | + hir::ExprUnary(..) | + hir::ExprBox(..) | + hir::ExprAddrOf(..) | + hir::ExprBinary(..) | + hir::ExprYield(..) | + hir::ExprCast(..) => { + false + } + } + } + + /// For the overloaded place expressions (`*x`, `x[3]`), the trait /// returns a type of `&T`, but the actual type we assign to the /// *expression* is `T`. So this function just peels off the return /// type by one layer to yield `T`. - fn make_overloaded_lvalue_return_type(&self, + fn make_overloaded_place_return_type(&self, method: MethodCallee<'tcx>) -> ty::TypeAndMut<'tcx> { @@ -2219,7 +2287,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ret_ty = method.sig.output(); // method returns &T, but the type as visible to user is T, so deref - ret_ty.builtin_deref(true, NoPreference).unwrap() + ret_ty.builtin_deref(true).unwrap() } fn lookup_indexing(&self, @@ -2227,7 +2295,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { base_expr: &'gcx hir::Expr, base_ty: Ty<'tcx>, idx_ty: Ty<'tcx>, - lvalue_pref: LvaluePreference) + needs: Needs) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { // FIXME(#18741) -- this is almost but not quite the same as the @@ -2237,7 +2305,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut autoderef = self.autoderef(base_expr.span, base_ty); let mut result = None; while result.is_none() && autoderef.next().is_some() { - result = self.try_index_step(expr, base_expr, &autoderef, lvalue_pref, idx_ty); + result = self.try_index_step(expr, base_expr, &autoderef, needs, idx_ty); } autoderef.finalize(); result @@ -2252,7 +2320,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &hir::Expr, base_expr: &hir::Expr, autoderef: &Autoderef<'a, 'gcx, 'tcx>, - lvalue_pref: LvaluePreference, + needs: Needs, index_ty: Ty<'tcx>) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { @@ -2279,14 +2347,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type from the method signature. // If some lookup succeeded, install method in table let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span)); - let method = self.try_overloaded_lvalue_op( - expr.span, self_ty, &[input_ty], lvalue_pref, LvalueOp::Index); + let method = self.try_overloaded_place_op( + expr.span, self_ty, &[input_ty], needs, PlaceOp::Index); let result = method.map(|ok| { debug!("try_index_step: success, using overloaded indexing"); let method = self.register_infer_ok_obligations(ok); - let mut adjustments = autoderef.adjust_steps(lvalue_pref); + let mut adjustments = autoderef.adjust_steps(needs); if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { adjustments.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)), @@ -2305,7 +2373,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.apply_adjustments(base_expr, adjustments); self.write_method_call(expr.hir_id, method); - (input_ty, self.make_overloaded_lvalue_return_type(method).ty) + (input_ty, self.make_overloaded_place_return_type(method).ty) }); if result.is_some() { return result; @@ -2315,45 +2383,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } - fn resolve_lvalue_op(&self, op: LvalueOp, is_mut: bool) -> (Option, Symbol) { + fn resolve_place_op(&self, op: PlaceOp, is_mut: bool) -> (Option, Symbol) { let (tr, name) = match (op, is_mut) { - (LvalueOp::Deref, false) => + (PlaceOp::Deref, false) => (self.tcx.lang_items().deref_trait(), "deref"), - (LvalueOp::Deref, true) => + (PlaceOp::Deref, true) => (self.tcx.lang_items().deref_mut_trait(), "deref_mut"), - (LvalueOp::Index, false) => + (PlaceOp::Index, false) => (self.tcx.lang_items().index_trait(), "index"), - (LvalueOp::Index, true) => + (PlaceOp::Index, true) => (self.tcx.lang_items().index_mut_trait(), "index_mut"), }; (tr, Symbol::intern(name)) } - fn try_overloaded_lvalue_op(&self, + fn try_overloaded_place_op(&self, span: Span, base_ty: Ty<'tcx>, arg_tys: &[Ty<'tcx>], - lvalue_pref: LvaluePreference, - op: LvalueOp) + needs: Needs, + op: PlaceOp) -> Option>> { - debug!("try_overloaded_lvalue_op({:?},{:?},{:?},{:?})", + debug!("try_overloaded_place_op({:?},{:?},{:?},{:?})", span, base_ty, - lvalue_pref, + needs, op); - // Try Mut first, if preferred. - let (mut_tr, mut_op) = self.resolve_lvalue_op(op, true); - let method = match (lvalue_pref, mut_tr) { - (PreferMutLvalue, Some(trait_did)) => { + // Try Mut first, if needed. + let (mut_tr, mut_op) = self.resolve_place_op(op, true); + let method = match (needs, mut_tr) { + (Needs::MutPlace, Some(trait_did)) => { self.lookup_method_in_trait(span, mut_op, trait_did, base_ty, Some(arg_tys)) } _ => None, }; // Otherwise, fall back to the immutable version. - let (imm_tr, imm_op) = self.resolve_lvalue_op(op, false); + let (imm_tr, imm_op) = self.resolve_place_op(op, false); let method = match (method, imm_tr) { (None, Some(trait_did)) => { self.lookup_method_in_trait(span, imm_op, trait_did, base_ty, Some(arg_tys)) @@ -2738,18 +2806,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_coercable_to_type(&self, expr: &'gcx hir::Expr, expected: Ty<'tcx>) -> Ty<'tcx> { - self.check_expr_coercable_to_type_with_lvalue_pref(expr, expected, NoPreference) + self.check_expr_coercable_to_type_with_needs(expr, expected, Needs::None) } - fn check_expr_coercable_to_type_with_lvalue_pref(&self, - expr: &'gcx hir::Expr, - expected: Ty<'tcx>, - lvalue_pref: LvaluePreference) - -> Ty<'tcx> { - let ty = self.check_expr_with_expectation_and_lvalue_pref( + fn check_expr_coercable_to_type_with_needs(&self, + expr: &'gcx hir::Expr, + expected: Ty<'tcx>, + needs: Needs) + -> Ty<'tcx> { + let ty = self.check_expr_with_expectation_and_needs( expr, ExpectHasType(expected), - lvalue_pref); + needs); self.demand_coerce(expr, ty, expected) } @@ -2761,16 +2829,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_with_expectation(&self, expr: &'gcx hir::Expr, expected: Expectation<'tcx>) -> Ty<'tcx> { - self.check_expr_with_expectation_and_lvalue_pref(expr, expected, NoPreference) + self.check_expr_with_expectation_and_needs(expr, expected, Needs::None) } fn check_expr(&self, expr: &'gcx hir::Expr) -> Ty<'tcx> { self.check_expr_with_expectation(expr, NoExpectation) } - fn check_expr_with_lvalue_pref(&self, expr: &'gcx hir::Expr, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { - self.check_expr_with_expectation_and_lvalue_pref(expr, NoExpectation, lvalue_pref) + fn check_expr_with_needs(&self, expr: &'gcx hir::Expr, needs: Needs) -> Ty<'tcx> { + self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs) } // determine the `self` type, using fresh variables for all variables @@ -2853,9 +2920,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, args: &'gcx [hir::Expr], expected: Expectation<'tcx>, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { + needs: Needs) -> Ty<'tcx> { let rcvr = &args[0]; - let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref); + let rcvr_t = self.check_expr_with_needs(&rcvr, needs); // no need to check for bot/err -- callee does that let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t); @@ -2965,10 +3032,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check field access expressions fn check_field(&self, expr: &'gcx hir::Expr, - lvalue_pref: LvaluePreference, + needs: Needs, base: &'gcx hir::Expr, field: &Spanned) -> Ty<'tcx> { - let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref); + let expr_t = self.check_expr_with_needs(base, needs); let expr_t = self.structurally_resolved_type(expr.span, expr_t); let mut private_candidate = None; @@ -2983,7 +3050,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { let field_ty = self.field_ty(expr.span, field, substs); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = autoderef.adjust_steps(lvalue_pref); + let adjustments = autoderef.adjust_steps(needs); self.apply_adjustments(base, adjustments); autoderef.finalize(); @@ -3102,10 +3169,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check tuple index expressions fn check_tup_field(&self, expr: &'gcx hir::Expr, - lvalue_pref: LvaluePreference, + needs: Needs, base: &'gcx hir::Expr, idx: codemap::Spanned) -> Ty<'tcx> { - let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref); + let expr_t = self.check_expr_with_needs(base, needs); let expr_t = self.structurally_resolved_type(expr.span, expr_t); let mut private_candidate = None; @@ -3146,7 +3213,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some(field_ty) = field { - let adjustments = autoderef.adjust_steps(lvalue_pref); + let adjustments = autoderef.adjust_steps(needs); self.apply_adjustments(base, adjustments); autoderef.finalize(); return field_ty; @@ -3476,10 +3543,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Note that inspecting a type's structure *directly* may expose the fact /// that there are actually multiple representations for `TyError`, so avoid /// that when err needs to be handled differently. - fn check_expr_with_expectation_and_lvalue_pref(&self, + fn check_expr_with_expectation_and_needs(&self, expr: &'gcx hir::Expr, expected: Expectation<'tcx>, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { + needs: Needs) -> Ty<'tcx> { debug!(">> typechecking: expr={:?} expected={:?}", expr, expected); @@ -3492,7 +3559,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(Diverges::Maybe); self.has_errors.set(false); - let ty = self.check_expr_kind(expr, expected, lvalue_pref); + let ty = self.check_expr_kind(expr, expected, needs); // Warn for non-block expressions with diverging children. match expr.node { @@ -3526,7 +3593,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_kind(&self, expr: &'gcx hir::Expr, expected: Expectation<'tcx>, - lvalue_pref: LvaluePreference) -> Ty<'tcx> { + needs: Needs) -> Ty<'tcx> { let tcx = self.tcx; let id = expr.id; match expr.node { @@ -3560,22 +3627,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { NoExpectation } }; - let lvalue_pref = match unop { - hir::UnDeref => lvalue_pref, - _ => NoPreference + let needs = match unop { + hir::UnDeref => needs, + _ => Needs::None }; - let mut oprnd_t = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, + let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd, expected_inner, - lvalue_pref); + needs); if !oprnd_t.references_error() { oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); match unop { hir::UnDeref => { - if let Some(mt) = oprnd_t.builtin_deref(true, NoPreference) { + if let Some(mt) = oprnd_t.builtin_deref(true) { oprnd_t = mt.ty; } else if let Some(ok) = self.try_overloaded_deref( - expr.span, oprnd_t, lvalue_pref) { + expr.span, oprnd_t, needs) { let method = self.register_infer_ok_obligations(ok); if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty { self.apply_adjustments(oprnd, vec![Adjustment { @@ -3583,7 +3650,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { target: method.sig.inputs()[0] }]); } - oprnd_t = self.make_overloaded_lvalue_return_type(method).ty; + oprnd_t = self.make_overloaded_place_return_type(method).ty; self.write_method_call(expr.hir_id, method); } else { type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, @@ -3614,8 +3681,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { match ty.sty { ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => { - if self.tcx.expr_is_lval(&oprnd) { - // Lvalues may legitimately have unsized types. + if self.is_place_expr(&oprnd) { + // Places may legitimately have unsized types. // For example, dereferences of a fat pointer and // the last field of a struct can be unsized. ExpectHasType(mt.ty) @@ -3626,8 +3693,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => NoExpectation } }); - let lvalue_pref = LvaluePreference::from_mutbl(mutbl); - let ty = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, hint, lvalue_pref); + let needs = Needs::maybe_mut_place(mutbl); + let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs); let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl }; if tm.ty.references_error() { @@ -3771,7 +3838,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.never } hir::ExprAssign(ref lhs, ref rhs) => { - let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); + let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); @@ -3783,7 +3850,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => { // Only check this if not in an `if` condition, as the // mistyped comparison help is more appropriate. - if !self.tcx.expr_is_lval(&lhs) { + if !self.is_place_expr(&lhs) { struct_span_err!(self.tcx.sess, expr.span, E0070, "invalid left-hand side expression") .span_label(expr.span, "left-hand of expression not valid") @@ -3872,7 +3939,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_call(expr, &callee, args, expected) } hir::ExprMethodCall(ref segment, span, ref args) => { - self.check_method_call(expr, segment, span, args, expected, lvalue_pref) + self.check_method_call(expr, segment, span, args, expected, needs) } hir::ExprCast(ref e, ref t) => { // Find the type of `e`. Supply hints based on the type we are casting to, @@ -4015,13 +4082,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_struct(expr, expected, qpath, fields, base_expr) } hir::ExprField(ref base, ref field) => { - self.check_field(expr, lvalue_pref, &base, field) + self.check_field(expr, needs, &base, field) } hir::ExprTupField(ref base, idx) => { - self.check_tup_field(expr, lvalue_pref, &base, idx) + self.check_tup_field(expr, needs, &base, idx) } hir::ExprIndex(ref base, ref idx) => { - let base_t = self.check_expr_with_lvalue_pref(&base, lvalue_pref); + let base_t = self.check_expr_with_needs(&base, needs); let idx_t = self.check_expr(&idx); if base_t.references_error() { @@ -4030,7 +4097,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { idx_t } else { let base_t = self.structurally_resolved_type(expr.span, base_t); - match self.lookup_indexing(expr, base, base_t, idx_t, lvalue_pref) { + match self.lookup_indexing(expr, base, base_t, idx_t, needs) { Some((index_ty, element_ty)) => { self.demand_coerce(idx, idx_t, index_ty); element_ty @@ -4178,9 +4245,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // ref mut, for soundness (issue #23116). In particular, in // the latter case, we need to be clear that the type of the // referent for the reference that results is *equal to* the - // type of the lvalue it is referencing, and not some + // type of the place it is referencing, and not some // supertype thereof. - let init_ty = self.check_expr_with_lvalue_pref(init, LvaluePreference::from_mutbl(m)); + let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m)); self.demand_eqtype(init.span, local_ty, init_ty); init_ty } else { @@ -5023,7 +5090,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let lifetime_count = generics.lifetimes().count(); for leaf_ty in ty.walk() { - if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty { + if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty { debug!("Found use of ty param num {}", idx); tps_used[idx as usize - lifetime_count] = true; } else if let ty::TyError = leaf_ty.sty { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index e099d1c0c2531..0698e3ecb6edd 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -10,9 +10,9 @@ //! Code related to processing overloaded binary and unary operators. -use super::FnCtxt; +use super::{FnCtxt, Needs}; use super::method::MethodCallee; -use rustc::ty::{self, Ty, TypeFoldable, NoPreference, PreferMutLvalue, TypeVariants}; +use rustc::ty::{self, Ty, TypeFoldable, TypeVariants}; use rustc::ty::TypeVariants::{TyStr, TyRef}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::infer::type_variable::TypeVariableOrigin; @@ -40,10 +40,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return_ty }; - let tcx = self.tcx; - if !tcx.expr_is_lval(lhs_expr) { + if !self.is_place_expr(lhs_expr) { struct_span_err!( - tcx.sess, lhs_expr.span, + self.tcx.sess, lhs_expr.span, E0067, "invalid left-hand side expression") .span_label( lhs_expr.span, @@ -166,18 +165,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { op, is_assign); - let lhs_pref = match is_assign { - IsAssign::Yes => PreferMutLvalue, - IsAssign::No => NoPreference + let lhs_needs = match is_assign { + IsAssign::Yes => Needs::MutPlace, + IsAssign::No => Needs::None }; // Find a suitable supertype of the LHS expression's type, by coercing to // a type variable, to pass as the `Self` to the trait, avoiding invariant // trait matching creating lifetime constraints that are too strict. // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. - let lhs_ty = self.check_expr_coercable_to_type_with_lvalue_pref(lhs_expr, + let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr, self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)), - lhs_pref); + lhs_needs); let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); // NB: As we have not yet type-checked the RHS, we don't have the diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 18d573bd581eb..ac7f54250d32b 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -732,8 +732,8 @@ and [RFC 809] for more details. "##, E0067: r##" -The left-hand side of a compound assignment expression must be an lvalue -expression. An lvalue expression represents a memory location and includes +The left-hand side of a compound assignment expression must be a place +expression. A place expression represents a memory location and includes item paths (ie, namespaced variables), dereferences, indexing expressions, and field references. @@ -742,7 +742,7 @@ Let's start with some erroneous code examples: ```compile_fail,E0067 use std::collections::LinkedList; -// Bad: assignment to non-lvalue expression +// Bad: assignment to non-place expression LinkedList::new() += 1; // ... @@ -783,14 +783,14 @@ function's return type and the value being returned. "##, E0070: r##" -The left-hand side of an assignment operator must be an lvalue expression. An -lvalue expression represents a memory location and can be a variable (with +The left-hand side of an assignment operator must be a place expression. An +place expression represents a memory location and can be a variable (with optional namespacing), a dereference, an indexing expression or a field reference. More details can be found in the [Expressions] section of the Reference. -[Expressions]: https://doc.rust-lang.org/reference/expressions.html#lvalues-rvalues-and-temporaries +[Expressions]: https://doc.rust-lang.org/reference/expressions.html#places-rvalues-and-temporaries Now, we can go further. Here are some erroneous code examples: @@ -806,7 +806,7 @@ fn some_other_func() {} fn some_function() { SOME_CONST = 14; // error : a constant value cannot be changed! - 1 = 3; // error : 1 isn't a valid lvalue! + 1 = 3; // error : 1 isn't a valid place! some_other_func() = 4; // error : we can't assign value to a function! SomeStruct.x = 12; // error : SomeStruct a structure name but it is used // like a variable! diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 3660d2fe46a92..0dfe9cb970efb 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1439,7 +1439,7 @@ impl<'a> MethodDef<'a> { &catch_all_substructure); // Final wrinkle: the self_args are expressions that deref - // down to desired l-values, but we cannot actually deref + // down to desired places, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. @@ -1516,7 +1516,7 @@ impl<'a> MethodDef<'a> { } else { // Final wrinkle: the self_args are expressions that deref - // down to desired l-values, but we cannot actually deref + // down to desired places, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. diff --git a/src/test/compile-fail/regions-adjusted-lvalue-op.rs b/src/test/compile-fail/regions-adjusted-lvalue-op.rs index 167c863070752..bb02d6d8bba8a 100644 --- a/src/test/compile-fail/regions-adjusted-lvalue-op.rs +++ b/src/test/compile-fail/regions-adjusted-lvalue-op.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// check that we link regions in mutable lvalue ops correctly - issue #41774 +// check that we link regions in mutable place ops correctly - issue #41774 struct Data(i32); diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 85f6ef60c5dc0..466690e7ca12b 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -404,9 +404,9 @@ pub fn value_cast(a: u32) -> i32 { -// Change l-value in assignment ------------------------------------------------ +// Change place in assignment -------------------------------------------------- #[cfg(cfail1)] -pub fn lvalue() -> i32 { +pub fn place() -> i32 { let mut x = 10; let mut y = 11; x = 9; @@ -416,7 +416,7 @@ pub fn lvalue() -> i32 { #[cfg(not(cfail1))] #[rustc_clean(except="HirBody,MirOptimized,MirValidated", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -pub fn lvalue() -> i32 { +pub fn place() -> i32 { let mut x = 10; let mut y = 11; y = 9; diff --git a/src/test/run-pass/issue-18514.rs b/src/test/run-pass/issue-18514.rs index 88bf95f036b86..2a1e55d867f72 100644 --- a/src/test/run-pass/issue-18514.rs +++ b/src/test/run-pass/issue-18514.rs @@ -10,7 +10,7 @@ // Test that we don't ICE when translating a generic impl method from // an extern crate that contains a match expression on a local -// variable lvalue where one of the match case bodies contains an +// variable place where one of the match case bodies contains an // expression that autoderefs through an overloaded generic deref // impl. diff --git a/src/test/run-pass/issue-18845.rs b/src/test/run-pass/issue-18845.rs index 3d8e0556a560e..241408ddef135 100644 --- a/src/test/run-pass/issue-18845.rs +++ b/src/test/run-pass/issue-18845.rs @@ -11,7 +11,7 @@ // This used to generate invalid IR in that even if we took the // `false` branch we'd still try to free the Box from the other // arm. This was due to treating `*Box::new(9)` as an rvalue datum -// instead of as an lvalue. +// instead of as a place. fn test(foo: bool) -> u8 { match foo { diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index c729f736115a9..4de8f6a719415 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that an `&mut self` method, when invoked on an lvalue whose -// type is `&mut [u8]`, passes in a pointer to the lvalue and not a +// Test that an `&mut self` method, when invoked on a place whose +// type is `&mut [u8]`, passes in a pointer to the place and not a // temporary. Issue #19147. use std::slice; diff --git a/src/test/run-pass/mir_drop_order.rs b/src/test/run-pass/mir_drop_order.rs index 41cb458c0b8b4..7ab133bbab4e1 100644 --- a/src/test/run-pass/mir_drop_order.rs +++ b/src/test/run-pass/mir_drop_order.rs @@ -41,7 +41,7 @@ fn main() { // all borrows are extended - nothing has been dropped yet assert_eq!(get(), vec![]); } - // in a let-statement, extended lvalues are dropped + // in a let-statement, extended places are dropped // *after* the let result (tho they have the same scope // as far as scope-based borrowck goes). assert_eq!(get(), vec![0, 2, 3, 1]); diff --git a/src/test/run-pass/type-ascription.rs b/src/test/run-pass/type-ascription.rs index bca384c64712f..18fb8e2e408f1 100644 --- a/src/test/run-pass/type-ascription.rs +++ b/src/test/run-pass/type-ascription.rs @@ -40,6 +40,6 @@ fn main() { assert_eq!(b, 1: u16); let mut v = Vec::new(); - v: Vec = vec![1, 2, 3]; // Lvalue type ascription + v: Vec = vec![1, 2, 3]; // Place expression type ascription assert_eq!(v, [1u8, 2, 3]); } diff --git a/src/test/ui/issue-26093.rs b/src/test/ui/issue-26093.rs index 3489a2ca9be15..22751c4a37cdd 100644 --- a/src/test/ui/issue-26093.rs +++ b/src/test/ui/issue-26093.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! not_an_lvalue { +macro_rules! not_a_place { ($thing:expr) => { $thing = 42; //~^ ERROR invalid left-hand side expression @@ -16,5 +16,5 @@ macro_rules! not_an_lvalue { } fn main() { - not_an_lvalue!(99); + not_a_place!(99); } diff --git a/src/test/ui/issue-26093.stderr b/src/test/ui/issue-26093.stderr index c2b81b2ce43fd..b850852623fd8 100644 --- a/src/test/ui/issue-26093.stderr +++ b/src/test/ui/issue-26093.stderr @@ -4,8 +4,8 @@ error[E0070]: invalid left-hand side expression 13 | $thing = 42; | ^^^^^^^^^^^ left-hand of expression not valid ... -19 | not_an_lvalue!(99); - | ------------------- in this macro invocation +19 | not_a_place!(99); + | ----------------- in this macro invocation error: aborting due to previous error