mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #54447 - KiChjang:issue-54331, r=nikomatsakis
Lower type ascriptions to HAIR and MIR Fixes #54331. r? @nikomatsakis
This commit is contained in:
commit
d0787284da
@ -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 {
|
||||
|
@ -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 { .. }
|
||||
|
@ -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) {
|
||||
|
@ -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 { .. }
|
||||
|
@ -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,
|
||||
});
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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>,
|
||||
|
@ -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) => {
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user