about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-10-04 00:26:00 +0000
committerbors <bors@rust-lang.org>2018-10-04 00:26:00 +0000
commitd0787284da6e25a018f2f94fcd3779d33d6150fc (patch)
tree016ba2eb4a57c74afa52a30593746117d0ca5390
parent4bf883b5e76f3a59770b891cb8b1b0576dfe359e (diff)
parent8380b25d13eeeb387efd6442c4e3638198b06412 (diff)
downloadrust-d0787284da6e25a018f2f94fcd3779d33d6150fc.tar.gz
rust-d0787284da6e25a018f2f94fcd3779d33d6150fc.zip
Auto merge of #54447 - KiChjang:issue-54331, r=nikomatsakis
Lower type ascriptions to HAIR and MIR

Fixes #54331.

r? @nikomatsakis
-rw-r--r--src/librustc/hir/mod.rs53
-rw-r--r--src/librustc_mir/build/expr/as_place.rs35
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs4
-rw-r--r--src/librustc_mir/build/expr/category.rs4
-rw-r--r--src/librustc_mir/build/expr/into.rs13
-rw-r--r--src/librustc_mir/hair/cx/expr.rs18
-rw-r--r--src/librustc_mir/hair/mod.rs10
-rw-r--r--src/librustc_typeck/check/mod.rs69
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs19
-rw-r--r--src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr13
11 files changed, 176 insertions, 64 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f06a09e706f..e2a9fd078a5 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1358,6 +1358,59 @@ impl Expr {
             ExprKind::Yield(..) => ExprPrecedence::Yield,
         }
     }
+
+    pub fn is_place_expr(&self) -> bool {
+         match self.node {
+            ExprKind::Path(QPath::Resolved(_, ref path)) => {
+                match path.def {
+                    Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
+                    _ => false,
+                }
+            }
+
+            ExprKind::Type(ref e, _) => {
+                e.is_place_expr()
+            }
+
+            ExprKind::Unary(UnDeref, _) |
+            ExprKind::Field(..) |
+            ExprKind::Index(..) => {
+                true
+            }
+
+            // Partially qualified paths in expressions can only legally
+            // refer to associated items which are always rvalues.
+            ExprKind::Path(QPath::TypeRelative(..)) |
+
+            ExprKind::Call(..) |
+            ExprKind::MethodCall(..) |
+            ExprKind::Struct(..) |
+            ExprKind::Tup(..) |
+            ExprKind::If(..) |
+            ExprKind::Match(..) |
+            ExprKind::Closure(..) |
+            ExprKind::Block(..) |
+            ExprKind::Repeat(..) |
+            ExprKind::Array(..) |
+            ExprKind::Break(..) |
+            ExprKind::Continue(..) |
+            ExprKind::Ret(..) |
+            ExprKind::While(..) |
+            ExprKind::Loop(..) |
+            ExprKind::Assign(..) |
+            ExprKind::InlineAsm(..) |
+            ExprKind::AssignOp(..) |
+            ExprKind::Lit(_) |
+            ExprKind::Unary(..) |
+            ExprKind::Box(..) |
+            ExprKind::AddrOf(..) |
+            ExprKind::Binary(..) |
+            ExprKind::Yield(..) |
+            ExprKind::Cast(..) => {
+                false
+            }
+        }
+    }
 }
 
 impl fmt::Debug for Expr {
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index 5688ea9d260..29c3fb69339 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -16,6 +16,7 @@ use build::{BlockAnd, BlockAndExtension, Builder};
 use hair::*;
 use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::*;
+use rustc::ty::Variance;
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -136,6 +137,40 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 ty: expr.ty,
             }))),
 
+            ExprKind::PlaceTypeAscription { source, user_ty } => {
+                let place = unpack!(block = this.as_place(block, source));
+                this.cfg.push(
+                    block,
+                    Statement {
+                        source_info,
+                        kind: StatementKind::AscribeUserType(
+                            place.clone(),
+                            Variance::Invariant,
+                            user_ty,
+                        ),
+                    },
+                );
+                block.and(place)
+            }
+            ExprKind::ValueTypeAscription { source, user_ty } => {
+                let source = this.hir.mirror(source);
+                let temp = unpack!(
+                    block = this.as_temp(block, source.temp_lifetime, source, mutability)
+                );
+                this.cfg.push(
+                    block,
+                    Statement {
+                        source_info,
+                        kind: StatementKind::AscribeUserType(
+                            Place::Local(temp.clone()),
+                            Variance::Invariant,
+                            user_ty,
+                        ),
+                    },
+                );
+                block.and(Place::Local(temp))
+            }
+
             ExprKind::Array { .. }
             | ExprKind::Tuple { .. }
             | ExprKind::Adt { .. }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index b721120f74d..8fee74390cc 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -386,7 +386,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             | ExprKind::Continue { .. }
             | ExprKind::Return { .. }
             | ExprKind::InlineAsm { .. }
-            | ExprKind::StaticRef { .. } => {
+            | ExprKind::StaticRef { .. }
+            | ExprKind::PlaceTypeAscription { .. }
+            | ExprKind::ValueTypeAscription { .. } => {
                 // these do not have corresponding `Rvalue` variants,
                 // so make an operand and then return that
                 debug_assert!(match Category::of(&expr.kind) {
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index 601fe2d01f8..05a9079cdb1 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -50,7 +50,9 @@ impl Category {
             | ExprKind::Index { .. }
             | ExprKind::SelfRef
             | ExprKind::VarRef { .. }
-            | ExprKind::StaticRef { .. } => Some(Category::Place),
+            | ExprKind::StaticRef { .. }
+            | ExprKind::PlaceTypeAscription { .. }
+            | ExprKind::ValueTypeAscription { .. } => Some(Category::Place),
 
             ExprKind::LogicalOp { .. }
             | ExprKind::If { .. }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 5708ac4e6b5..9ea3805fdc6 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -345,7 +345,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             }
 
             // Avoid creating a temporary
-            ExprKind::VarRef { .. } | ExprKind::SelfRef | ExprKind::StaticRef { .. } => {
+            ExprKind::VarRef { .. } |
+            ExprKind::SelfRef |
+            ExprKind::StaticRef { .. } |
+            ExprKind::PlaceTypeAscription { .. } |
+            ExprKind::ValueTypeAscription { .. } => {
                 debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
 
                 let place = unpack!(block = this.as_place(block, expr));
@@ -393,7 +397,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             | ExprKind::Literal { .. }
             | ExprKind::Yield { .. } => {
                 debug_assert!(match Category::of(&expr.kind).unwrap() {
+                    // should be handled above
                     Category::Rvalue(RvalueFunc::Into) => false,
+
+                    // must be handled above or else we get an
+                    // infinite loop in the builder; see
+                    // e.g. `ExprKind::VarRef` above
+                    Category::Place => false,
+
                     _ => true,
                 });
 
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 3183f0f47ea..f94f1a1a8c8 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -718,7 +718,23 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ExprKind::Cast { source }
             }
         }
-        hir::ExprKind::Type(ref source, _) => return source.make_mirror(cx),
+        hir::ExprKind::Type(ref source, ref ty) => {
+            let user_provided_tys = cx.tables.user_provided_tys();
+            let user_ty = *user_provided_tys
+                .get(ty.hir_id)
+                .expect(&format!("{:?} not found in user_provided_tys, source: {:?}", ty, source));
+            if source.is_place_expr() {
+                ExprKind::PlaceTypeAscription {
+                    source: source.to_ref(),
+                    user_ty,
+                }
+            } else {
+                ExprKind::ValueTypeAscription {
+                    source: source.to_ref(),
+                    user_ty,
+                }
+            }
+        }
         hir::ExprKind::Box(ref value) => {
             ExprKind::Box {
                 value: value.to_ref(),
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index d86aee54312..9258845ad06 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -268,6 +268,16 @@ pub enum ExprKind<'tcx> {
         fields: Vec<FieldExprRef<'tcx>>,
         base: Option<FruInfo<'tcx>>
     },
+    PlaceTypeAscription {
+        source: ExprRef<'tcx>,
+        /// Type that the user gave to this expression
+        user_ty: CanonicalTy<'tcx>,
+    },
+    ValueTypeAscription {
+        source: ExprRef<'tcx>,
+        /// Type that the user gave to this expression
+        user_ty: CanonicalTy<'tcx>,
+    },
     Closure {
         closure_id: DefId,
         substs: UpvarSubsts<'tcx>,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a9354e12deb..529f1e6161b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2469,59 +2469,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn is_place_expr(&self, expr: &hir::Expr) -> bool {
-         match expr.node {
-            hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
-                match path.def {
-                    Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
-                    _ => false,
-                }
-            }
-
-            hir::ExprKind::Type(ref e, _) => {
-                self.is_place_expr(e)
-            }
-
-            hir::ExprKind::Unary(hir::UnDeref, _) |
-            hir::ExprKind::Field(..) |
-            hir::ExprKind::Index(..) => {
-                true
-            }
-
-            // Partially qualified paths in expressions can only legally
-            // refer to associated items which are always rvalues.
-            hir::ExprKind::Path(hir::QPath::TypeRelative(..)) |
-
-            hir::ExprKind::Call(..) |
-            hir::ExprKind::MethodCall(..) |
-            hir::ExprKind::Struct(..) |
-            hir::ExprKind::Tup(..) |
-            hir::ExprKind::If(..) |
-            hir::ExprKind::Match(..) |
-            hir::ExprKind::Closure(..) |
-            hir::ExprKind::Block(..) |
-            hir::ExprKind::Repeat(..) |
-            hir::ExprKind::Array(..) |
-            hir::ExprKind::Break(..) |
-            hir::ExprKind::Continue(..) |
-            hir::ExprKind::Ret(..) |
-            hir::ExprKind::While(..) |
-            hir::ExprKind::Loop(..) |
-            hir::ExprKind::Assign(..) |
-            hir::ExprKind::InlineAsm(..) |
-            hir::ExprKind::AssignOp(..) |
-            hir::ExprKind::Lit(_) |
-            hir::ExprKind::Unary(..) |
-            hir::ExprKind::Box(..) |
-            hir::ExprKind::AddrOf(..) |
-            hir::ExprKind::Binary(..) |
-            hir::ExprKind::Yield(..) |
-            hir::ExprKind::Cast(..) => {
-                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
@@ -3799,10 +3746,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         ty
     }
 
-    fn check_expr_kind(&self,
-                       expr: &'gcx hir::Expr,
-                       expected: Expectation<'tcx>,
-                       needs: Needs) -> Ty<'tcx> {
+    fn check_expr_kind(
+        &self,
+        expr: &'gcx hir::Expr,
+        expected: Expectation<'tcx>,
+        needs: Needs
+    ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let id = expr.id;
         match expr.node {
@@ -3899,7 +3848,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
                     match ty.sty {
                         ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
-                            if self.is_place_expr(&oprnd) {
+                            if oprnd.is_place_expr() {
                                 // Places may legitimately have unsized types.
                                 // For example, dereferences of a fat pointer and
                                 // the last field of a struct can be unsized.
@@ -4075,7 +4024,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.is_place_expr(&lhs) {
+                        if !lhs.is_place_expr() {
                             struct_span_err!(self.tcx.sess, expr.span, E0070,
                                                 "invalid left-hand side expression")
                                 .span_label(expr.span, "left-hand of expression not valid")
@@ -4203,6 +4152,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hir::ExprKind::Type(ref e, ref t) => {
                 let ty = self.to_ty(&t);
                 self.check_expr_eq_type(&e, ty);
+                let c_ty = self.infcx.canonicalize_response(&ty);
+                self.tables.borrow_mut().user_provided_tys_mut().insert(t.hir_id, c_ty);
                 ty
             }
             hir::ExprKind::Array(ref args) => {
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 89ed689b5d4..54f4406b4af 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             return_ty
         };
 
-        if !self.is_place_expr(lhs_expr) {
+        if !lhs_expr.is_place_expr() {
             struct_span_err!(
                 self.tcx.sess, lhs_expr.span,
                 E0067, "invalid left-hand side expression")
diff --git a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs
new file mode 100644
index 00000000000..2785f71ebcf
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs
@@ -0,0 +1,19 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![allow(warnings)]
+#![feature(nll)]
+#![feature(type_ascription)]
+
+fn main() {
+    let x = 22_u32;
+    let y: &u32 = &x: &'static u32; //~ ERROR E0597
+}
diff --git a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
new file mode 100644
index 00000000000..2303ed64db9
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/type_ascription_static_lifetime.rs:18:19
+   |
+LL |     let y: &u32 = &x: &'static u32; //~ ERROR E0597
+   |                   ^^ borrowed value does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.