Skip to content

Commit d078728

Browse files
committed
Auto merge of #54447 - KiChjang:issue-54331, r=nikomatsakis
Lower type ascriptions to HAIR and MIR Fixes #54331. r? @nikomatsakis
2 parents 4bf883b + 8380b25 commit d078728

File tree

11 files changed

+176
-64
lines changed

11 files changed

+176
-64
lines changed

src/librustc/hir/mod.rs

+53
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,59 @@ impl Expr {
13581358
ExprKind::Yield(..) => ExprPrecedence::Yield,
13591359
}
13601360
}
1361+
1362+
pub fn is_place_expr(&self) -> bool {
1363+
match self.node {
1364+
ExprKind::Path(QPath::Resolved(_, ref path)) => {
1365+
match path.def {
1366+
Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
1367+
_ => false,
1368+
}
1369+
}
1370+
1371+
ExprKind::Type(ref e, _) => {
1372+
e.is_place_expr()
1373+
}
1374+
1375+
ExprKind::Unary(UnDeref, _) |
1376+
ExprKind::Field(..) |
1377+
ExprKind::Index(..) => {
1378+
true
1379+
}
1380+
1381+
// Partially qualified paths in expressions can only legally
1382+
// refer to associated items which are always rvalues.
1383+
ExprKind::Path(QPath::TypeRelative(..)) |
1384+
1385+
ExprKind::Call(..) |
1386+
ExprKind::MethodCall(..) |
1387+
ExprKind::Struct(..) |
1388+
ExprKind::Tup(..) |
1389+
ExprKind::If(..) |
1390+
ExprKind::Match(..) |
1391+
ExprKind::Closure(..) |
1392+
ExprKind::Block(..) |
1393+
ExprKind::Repeat(..) |
1394+
ExprKind::Array(..) |
1395+
ExprKind::Break(..) |
1396+
ExprKind::Continue(..) |
1397+
ExprKind::Ret(..) |
1398+
ExprKind::While(..) |
1399+
ExprKind::Loop(..) |
1400+
ExprKind::Assign(..) |
1401+
ExprKind::InlineAsm(..) |
1402+
ExprKind::AssignOp(..) |
1403+
ExprKind::Lit(_) |
1404+
ExprKind::Unary(..) |
1405+
ExprKind::Box(..) |
1406+
ExprKind::AddrOf(..) |
1407+
ExprKind::Binary(..) |
1408+
ExprKind::Yield(..) |
1409+
ExprKind::Cast(..) => {
1410+
false
1411+
}
1412+
}
1413+
}
13611414
}
13621415

13631416
impl fmt::Debug for Expr {

src/librustc_mir/build/expr/as_place.rs

+35
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use build::{BlockAnd, BlockAndExtension, Builder};
1616
use hair::*;
1717
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
1818
use rustc::mir::*;
19+
use rustc::ty::Variance;
1920

2021
use rustc_data_structures::indexed_vec::Idx;
2122

@@ -136,6 +137,40 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
136137
ty: expr.ty,
137138
}))),
138139

140+
ExprKind::PlaceTypeAscription { source, user_ty } => {
141+
let place = unpack!(block = this.as_place(block, source));
142+
this.cfg.push(
143+
block,
144+
Statement {
145+
source_info,
146+
kind: StatementKind::AscribeUserType(
147+
place.clone(),
148+
Variance::Invariant,
149+
user_ty,
150+
),
151+
},
152+
);
153+
block.and(place)
154+
}
155+
ExprKind::ValueTypeAscription { source, user_ty } => {
156+
let source = this.hir.mirror(source);
157+
let temp = unpack!(
158+
block = this.as_temp(block, source.temp_lifetime, source, mutability)
159+
);
160+
this.cfg.push(
161+
block,
162+
Statement {
163+
source_info,
164+
kind: StatementKind::AscribeUserType(
165+
Place::Local(temp.clone()),
166+
Variance::Invariant,
167+
user_ty,
168+
),
169+
},
170+
);
171+
block.and(Place::Local(temp))
172+
}
173+
139174
ExprKind::Array { .. }
140175
| ExprKind::Tuple { .. }
141176
| ExprKind::Adt { .. }

src/librustc_mir/build/expr/as_rvalue.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
386386
| ExprKind::Continue { .. }
387387
| ExprKind::Return { .. }
388388
| ExprKind::InlineAsm { .. }
389-
| ExprKind::StaticRef { .. } => {
389+
| ExprKind::StaticRef { .. }
390+
| ExprKind::PlaceTypeAscription { .. }
391+
| ExprKind::ValueTypeAscription { .. } => {
390392
// these do not have corresponding `Rvalue` variants,
391393
// so make an operand and then return that
392394
debug_assert!(match Category::of(&expr.kind) {

src/librustc_mir/build/expr/category.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ impl Category {
5050
| ExprKind::Index { .. }
5151
| ExprKind::SelfRef
5252
| ExprKind::VarRef { .. }
53-
| ExprKind::StaticRef { .. } => Some(Category::Place),
53+
| ExprKind::StaticRef { .. }
54+
| ExprKind::PlaceTypeAscription { .. }
55+
| ExprKind::ValueTypeAscription { .. } => Some(Category::Place),
5456

5557
ExprKind::LogicalOp { .. }
5658
| ExprKind::If { .. }

src/librustc_mir/build/expr/into.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
345345
}
346346

347347
// Avoid creating a temporary
348-
ExprKind::VarRef { .. } | ExprKind::SelfRef | ExprKind::StaticRef { .. } => {
348+
ExprKind::VarRef { .. } |
349+
ExprKind::SelfRef |
350+
ExprKind::StaticRef { .. } |
351+
ExprKind::PlaceTypeAscription { .. } |
352+
ExprKind::ValueTypeAscription { .. } => {
349353
debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
350354

351355
let place = unpack!(block = this.as_place(block, expr));
@@ -393,7 +397,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
393397
| ExprKind::Literal { .. }
394398
| ExprKind::Yield { .. } => {
395399
debug_assert!(match Category::of(&expr.kind).unwrap() {
400+
// should be handled above
396401
Category::Rvalue(RvalueFunc::Into) => false,
402+
403+
// must be handled above or else we get an
404+
// infinite loop in the builder; see
405+
// e.g. `ExprKind::VarRef` above
406+
Category::Place => false,
407+
397408
_ => true,
398409
});
399410

src/librustc_mir/hair/cx/expr.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,23 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
718718
ExprKind::Cast { source }
719719
}
720720
}
721-
hir::ExprKind::Type(ref source, _) => return source.make_mirror(cx),
721+
hir::ExprKind::Type(ref source, ref ty) => {
722+
let user_provided_tys = cx.tables.user_provided_tys();
723+
let user_ty = *user_provided_tys
724+
.get(ty.hir_id)
725+
.expect(&format!("{:?} not found in user_provided_tys, source: {:?}", ty, source));
726+
if source.is_place_expr() {
727+
ExprKind::PlaceTypeAscription {
728+
source: source.to_ref(),
729+
user_ty,
730+
}
731+
} else {
732+
ExprKind::ValueTypeAscription {
733+
source: source.to_ref(),
734+
user_ty,
735+
}
736+
}
737+
}
722738
hir::ExprKind::Box(ref value) => {
723739
ExprKind::Box {
724740
value: value.to_ref(),

src/librustc_mir/hair/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,16 @@ pub enum ExprKind<'tcx> {
268268
fields: Vec<FieldExprRef<'tcx>>,
269269
base: Option<FruInfo<'tcx>>
270270
},
271+
PlaceTypeAscription {
272+
source: ExprRef<'tcx>,
273+
/// Type that the user gave to this expression
274+
user_ty: CanonicalTy<'tcx>,
275+
},
276+
ValueTypeAscription {
277+
source: ExprRef<'tcx>,
278+
/// Type that the user gave to this expression
279+
user_ty: CanonicalTy<'tcx>,
280+
},
271281
Closure {
272282
closure_id: DefId,
273283
substs: UpvarSubsts<'tcx>,

src/librustc_typeck/check/mod.rs

+10-59
Original file line numberDiff line numberDiff line change
@@ -2469,59 +2469,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24692469
}
24702470
}
24712471

2472-
fn is_place_expr(&self, expr: &hir::Expr) -> bool {
2473-
match expr.node {
2474-
hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
2475-
match path.def {
2476-
Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
2477-
_ => false,
2478-
}
2479-
}
2480-
2481-
hir::ExprKind::Type(ref e, _) => {
2482-
self.is_place_expr(e)
2483-
}
2484-
2485-
hir::ExprKind::Unary(hir::UnDeref, _) |
2486-
hir::ExprKind::Field(..) |
2487-
hir::ExprKind::Index(..) => {
2488-
true
2489-
}
2490-
2491-
// Partially qualified paths in expressions can only legally
2492-
// refer to associated items which are always rvalues.
2493-
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) |
2494-
2495-
hir::ExprKind::Call(..) |
2496-
hir::ExprKind::MethodCall(..) |
2497-
hir::ExprKind::Struct(..) |
2498-
hir::ExprKind::Tup(..) |
2499-
hir::ExprKind::If(..) |
2500-
hir::ExprKind::Match(..) |
2501-
hir::ExprKind::Closure(..) |
2502-
hir::ExprKind::Block(..) |
2503-
hir::ExprKind::Repeat(..) |
2504-
hir::ExprKind::Array(..) |
2505-
hir::ExprKind::Break(..) |
2506-
hir::ExprKind::Continue(..) |
2507-
hir::ExprKind::Ret(..) |
2508-
hir::ExprKind::While(..) |
2509-
hir::ExprKind::Loop(..) |
2510-
hir::ExprKind::Assign(..) |
2511-
hir::ExprKind::InlineAsm(..) |
2512-
hir::ExprKind::AssignOp(..) |
2513-
hir::ExprKind::Lit(_) |
2514-
hir::ExprKind::Unary(..) |
2515-
hir::ExprKind::Box(..) |
2516-
hir::ExprKind::AddrOf(..) |
2517-
hir::ExprKind::Binary(..) |
2518-
hir::ExprKind::Yield(..) |
2519-
hir::ExprKind::Cast(..) => {
2520-
false
2521-
}
2522-
}
2523-
}
2524-
25252472
/// For the overloaded place expressions (`*x`, `x[3]`), the trait
25262473
/// returns a type of `&T`, but the actual type we assign to the
25272474
/// *expression* is `T`. So this function just peels off the return
@@ -3799,10 +3746,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
37993746
ty
38003747
}
38013748

3802-
fn check_expr_kind(&self,
3803-
expr: &'gcx hir::Expr,
3804-
expected: Expectation<'tcx>,
3805-
needs: Needs) -> Ty<'tcx> {
3749+
fn check_expr_kind(
3750+
&self,
3751+
expr: &'gcx hir::Expr,
3752+
expected: Expectation<'tcx>,
3753+
needs: Needs
3754+
) -> Ty<'tcx> {
38063755
let tcx = self.tcx;
38073756
let id = expr.id;
38083757
match expr.node {
@@ -3899,7 +3848,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
38993848
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
39003849
match ty.sty {
39013850
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
3902-
if self.is_place_expr(&oprnd) {
3851+
if oprnd.is_place_expr() {
39033852
// Places may legitimately have unsized types.
39043853
// For example, dereferences of a fat pointer and
39053854
// the last field of a struct can be unsized.
@@ -4075,7 +4024,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40754024
_ => {
40764025
// Only check this if not in an `if` condition, as the
40774026
// mistyped comparison help is more appropriate.
4078-
if !self.is_place_expr(&lhs) {
4027+
if !lhs.is_place_expr() {
40794028
struct_span_err!(self.tcx.sess, expr.span, E0070,
40804029
"invalid left-hand side expression")
40814030
.span_label(expr.span, "left-hand of expression not valid")
@@ -4203,6 +4152,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42034152
hir::ExprKind::Type(ref e, ref t) => {
42044153
let ty = self.to_ty(&t);
42054154
self.check_expr_eq_type(&e, ty);
4155+
let c_ty = self.infcx.canonicalize_response(&ty);
4156+
self.tables.borrow_mut().user_provided_tys_mut().insert(t.hir_id, c_ty);
42064157
ty
42074158
}
42084159
hir::ExprKind::Array(ref args) => {

src/librustc_typeck/check/op.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4040
return_ty
4141
};
4242

43-
if !self.is_place_expr(lhs_expr) {
43+
if !lhs_expr.is_place_expr() {
4444
struct_span_err!(
4545
self.tcx.sess, lhs_expr.span,
4646
E0067, "invalid left-hand side expression")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
#![allow(warnings)]
13+
#![feature(nll)]
14+
#![feature(type_ascription)]
15+
16+
fn main() {
17+
let x = 22_u32;
18+
let y: &u32 = &x: &'static u32; //~ ERROR E0597
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0597]: `x` does not live long enough
2+
--> $DIR/type_ascription_static_lifetime.rs:18:19
3+
|
4+
LL | let y: &u32 = &x: &'static u32; //~ ERROR E0597
5+
| ^^ borrowed value does not live long enough
6+
LL | }
7+
| - `x` dropped here while still borrowed
8+
|
9+
= note: borrowed value must be valid for the static lifetime...
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)