diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 5688ea9d260f..29c3fb693396 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 b721120f74db..8fee74390cc6 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 601fe2d01f86..05a9079cdb1e 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 5708ac4e6b50..c05719ce95a6 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -391,7 +391,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | ExprKind::Adt { .. } | ExprKind::Closure { .. } | ExprKind::Literal { .. } - | ExprKind::Yield { .. } => { + | ExprKind::Yield { .. } + | ExprKind::PlaceTypeAscription { .. } + | ExprKind::ValueTypeAscription { .. } => { debug_assert!(match Category::of(&expr.kind).unwrap() { Category::Rvalue(RvalueFunc::Into) => false, _ => true, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 3183f0f47eac..f94f1a1a8c8f 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 d86aee543126..9258845ad06a 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>, base: Option> }, + 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 6d1f5be8470b..40af4b5f5aae 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4118,6 +4118,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) => {