From 80ad300b890c07d4c95fbf63c0f9cd3e397e545f Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Tue, 2 Oct 2018 09:31:46 -0700 Subject: [PATCH] Wrap cast expressions inside of ValueTypeAscription --- src/librustc_mir/hair/cx/expr.rs | 23 +++++++++++++++++-- src/librustc_typeck/check/mod.rs | 2 ++ .../user-annotations/cast_static_lifetime.rs | 17 ++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/nll/user-annotations/cast_static_lifetime.rs diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 04dd1aa3c88..796f6753e95 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -637,7 +637,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, name: Field::new(cx.tcx.field_index(expr.id, cx.tables)), } } - hir::ExprKind::Cast(ref source, _) => { + hir::ExprKind::Cast(ref source, ref ty) => { // Check to see if this cast is a "coercion cast", where the cast is actually done // using a coercion (or is a no-op). if let Some(&TyCastKind::CoercionCast) = cx.tables() @@ -714,7 +714,26 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } else { source.to_ref() }; - ExprKind::Cast { source } + + let cast = ExprKind::Cast { source }; + + if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) { + // NOTE: Creating a new Expr and wrapping a Cast inside of it may be + // inefficient, revisit this when performance becomes an issue. + let cast_expr = Expr { + temp_lifetime, + ty: expr_ty, + span: expr.span, + kind: cast, + }; + + ExprKind::ValueTypeAscription { + source: cast_expr.to_ref(), + user_ty: UserTypeAnnotation::Ty(*user_ty), + } + } else { + cast + } } } hir::ExprKind::Type(ref source, ref ty) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 14ce1bb4ccd..e6922d1c4c7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4166,6 +4166,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { Ok(cast_check) => { + let c_ty = self.infcx.canonicalize_response(&t_cast); + self.tables.borrow_mut().user_provided_tys_mut().insert(t.hir_id, c_ty); deferred_cast_checks.push(cast_check); t_cast } diff --git a/src/test/ui/nll/user-annotations/cast_static_lifetime.rs b/src/test/ui/nll/user-annotations/cast_static_lifetime.rs new file mode 100644 index 00000000000..aa2cf85dfd9 --- /dev/null +++ b/src/test/ui/nll/user-annotations/cast_static_lifetime.rs @@ -0,0 +1,17 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(warnings)] +#![feature(nll)] + +fn main() { + let x = 22_u32; + let y: &u32 = (&x) as &'static u32; +}