Skip to content

Commit b8157cc

Browse files
eddybpetrochenkov
authored andcommitted
Implement type ascription.
1 parent ce7bc51 commit b8157cc

File tree

20 files changed

+112
-12
lines changed

20 files changed

+112
-12
lines changed

src/librustc/middle/cfg/construct.rs

+1
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
352352
hir::ExprBox(ref e) |
353353
hir::ExprAddrOf(_, ref e) |
354354
hir::ExprCast(ref e, _) |
355+
hir::ExprType(ref e, _) |
355356
hir::ExprUnary(_, ref e) |
356357
hir::ExprField(ref e, _) |
357358
hir::ExprTupField(ref e, _) => {

src/librustc/middle/check_const.rs

+1
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
784784
hir::ExprField(..) |
785785
hir::ExprTupField(..) |
786786
hir::ExprVec(_) |
787+
hir::ExprType(..) |
787788
hir::ExprTup(..) => {}
788789

789790
// Conditional control flow (possible to implement).

src/librustc/middle/const_eval.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
11261126
None => unreachable!(),
11271127
}
11281128
}
1129+
hir::ExprType(ref e, _) => try!(eval_const_expr_partial(tcx, &**e, ety)),
11291130
hir::ExprTup(_) => Tuple(e.id),
11301131
hir::ExprStruct(..) => Struct(e.id),
11311132
hir::ExprIndex(ref arr, ref idx) => {

src/librustc/middle/expr_use_visitor.rs

+4
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
373373
match expr.node {
374374
hir::ExprPath(..) => { }
375375

376+
hir::ExprType(ref subexpr, _) => {
377+
self.walk_expr(&**subexpr)
378+
}
379+
376380
hir::ExprUnary(hir::UnDeref, ref base) => { // *base
377381
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
378382
self.select_from_expr(&**base);

src/librustc/middle/liveness.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
496496
hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
497497
hir::ExprStruct(..) | hir::ExprRepeat(..) |
498498
hir::ExprInlineAsm(..) | hir::ExprBox(..) |
499-
hir::ExprRange(..) => {
499+
hir::ExprRange(..) | hir::ExprType(..) => {
500500
intravisit::walk_expr(ir, expr);
501501
}
502502
}
@@ -1160,6 +1160,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
11601160
hir::ExprBox(ref e) |
11611161
hir::ExprAddrOf(_, ref e) |
11621162
hir::ExprCast(ref e, _) |
1163+
hir::ExprType(ref e, _) |
11631164
hir::ExprUnary(_, ref e) => {
11641165
self.propagate_through_expr(&**e, succ)
11651166
}
@@ -1443,7 +1444,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
14431444
hir::ExprBlock(..) | hir::ExprAddrOf(..) |
14441445
hir::ExprStruct(..) | hir::ExprRepeat(..) |
14451446
hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
1446-
hir::ExprRange(..) => {
1447+
hir::ExprRange(..) | hir::ExprType(..) => {
14471448
intravisit::walk_expr(this, expr);
14481449
}
14491450
}

src/librustc/middle/mem_categorization.rs

+4
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,10 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
518518
self.cat_def(expr.id, expr.span, expr_ty, def)
519519
}
520520

521+
hir::ExprType(ref e, _) => {
522+
self.cat_expr(&**e)
523+
}
524+
521525
hir::ExprAddrOf(..) | hir::ExprCall(..) |
522526
hir::ExprAssign(..) | hir::ExprAssignOp(..) |
523527
hir::ExprClosure(..) | hir::ExprRet(..) |

src/librustc_back/svh.rs

+2
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ mod svh_visitor {
234234
SawExprUnary(hir::UnOp),
235235
SawExprLit(ast::Lit_),
236236
SawExprCast,
237+
SawExprType,
237238
SawExprIf,
238239
SawExprWhile,
239240
SawExprMatch,
@@ -262,6 +263,7 @@ mod svh_visitor {
262263
ExprUnary(op, _) => SawExprUnary(op),
263264
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
264265
ExprCast(..) => SawExprCast,
266+
ExprType(..) => SawExprType,
265267
ExprIf(..) => SawExprIf,
266268
ExprWhile(..) => SawExprWhile,
267269
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.name.as_str())),

src/librustc_trans/trans/consts.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
10041004
try!(const_fn_call(cx, MethodCallKey(method_call),
10051005
method_did, &arg_vals, param_substs, trueconst))
10061006
},
1007+
hir::ExprType(ref e, _) => const_expr(cx, &**e, param_substs).0,
10071008
hir::ExprBlock(ref block) => {
10081009
match block.expr {
10091010
Some(ref expr) => try!(const_expr(

src/librustc_trans/trans/expr.rs

+9
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,9 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
656656
let _icx = push_ctxt("trans_datum_unadjusted");
657657

658658
match expr.node {
659+
hir::ExprType(ref e, _) => {
660+
trans(bcx, &**e)
661+
}
659662
hir::ExprPath(..) => {
660663
trans_def(bcx, expr, bcx.def(expr.id))
661664
}
@@ -941,6 +944,9 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
941944
hir::ExprBreak(label_opt) => {
942945
controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node.name))
943946
}
947+
hir::ExprType(ref e, _) => {
948+
trans_into(bcx, &**e, Ignore)
949+
}
944950
hir::ExprAgain(label_opt) => {
945951
controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node.name))
946952
}
@@ -1064,6 +1070,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
10641070
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
10651071

10661072
match expr.node {
1073+
hir::ExprType(ref e, _) => {
1074+
trans_into(bcx, &**e, dest)
1075+
}
10671076
hir::ExprPath(..) => {
10681077
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
10691078
}

src/librustc_typeck/check/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3525,6 +3525,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
35253525
deferred_cast_checks.push(cast_check);
35263526
}
35273527
}
3528+
hir::ExprType(ref e, ref t) => {
3529+
let typ = fcx.to_ty(&**t);
3530+
check_expr_coercable_to_type(fcx, &**e, typ);
3531+
fcx.write_ty(id, typ);
3532+
}
35283533
hir::ExprVec(ref args) => {
35293534
let uty = expected.to_option(fcx).and_then(|uty| {
35303535
match uty.sty {

src/libsyntax/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ pub enum Expr_ {
943943
ExprLit(P<Lit>),
944944
/// A cast (`foo as f64`)
945945
ExprCast(P<Expr>, P<Ty>),
946+
ExprType(P<Expr>, P<Ty>),
946947
/// An `if` block, with an optional else block
947948
///
948949
/// `if expr { block } else { expr }`

src/libsyntax/fold.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,9 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
12031203
ExprCast(expr, ty) => {
12041204
ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
12051205
}
1206+
ExprType(expr, ty) => {
1207+
ExprType(folder.fold_expr(expr), folder.fold_ty(ty))
1208+
}
12061209
ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
12071210
ExprIf(cond, tr, fl) => {
12081211
ExprIf(folder.fold_expr(cond),

src/libsyntax/parse/parser.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use ast::{ExprBreak, ExprCall, ExprCast, ExprInPlace};
2626
use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
2727
use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
2828
use ast::{ExprMethodCall, ExprParen, ExprPath};
29-
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
29+
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprType, ExprUnary};
3030
use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
3131
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
3232
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
@@ -2811,7 +2811,6 @@ impl<'a> Parser<'a> {
28112811
break
28122812
}
28132813

2814-
28152814
let rhs = try!(match op.fixity() {
28162815
Fixity::Right => self.with_res(restrictions, |this|{
28172816
this.parse_assoc_expr_with(op.precedence(), LhsExpr::NotYetParsed)

src/libsyntax/print/pprust.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
445445
ast::ExprAssign(..) | ast::ExprBinary(..) |
446446
ast::ExprClosure(..) |
447447
ast::ExprAssignOp(..) | ast::ExprCast(..) |
448-
ast::ExprInPlace(..) => true,
448+
ast::ExprInPlace(..) | ast::ExprType(..) => true,
449449
_ => false,
450450
}
451451
}
@@ -2036,6 +2036,11 @@ impl<'a> State<'a> {
20362036
try!(self.word_space("as"));
20372037
try!(self.print_type(&**ty));
20382038
}
2039+
ast::ExprType(ref expr, ref ty) => {
2040+
try!(self.print_expr(&**expr));
2041+
try!(self.word_space(":"));
2042+
try!(self.print_type(&**ty));
2043+
}
20392044
ast::ExprIf(ref test, ref blk, ref elseopt) => {
20402045
try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
20412046
}

src/libsyntax/visit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
697697
visitor.visit_expr(subexpression);
698698
visitor.visit_ty(typ)
699699
}
700+
ExprType(ref subexpression, ref typ) => {
701+
visitor.visit_expr(&**subexpression);
702+
visitor.visit_ty(&**typ)
703+
}
700704
ExprIf(ref head_expression, ref if_block, ref optional_else) => {
701705
visitor.visit_expr(head_expression);
702706
visitor.visit_block(if_block);

src/libsyntax_ext/asm.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use syntax::ext::base;
2020
use syntax::ext::base::*;
2121
use syntax::feature_gate;
2222
use syntax::parse::token::{intern, InternedString};
23-
use syntax::parse::token;
23+
use syntax::parse::{self, token};
2424
use syntax::ptr::P;
2525
use syntax::ast::AsmDialect;
2626

@@ -58,8 +58,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
5858
return DummyResult::expr(sp);
5959
}
6060

61-
let mut p = cx.new_parser_from_tts(tts);
62-
let mut asm = InternedString::new("");
61+
// Split the tts before the first colon, to avoid `asm!("x": y)` being
62+
// parsed as `asm!(z)` with `z = "x": y` which is type ascription.
63+
let first_colon = tts.iter().position(|tt| {
64+
match *tt {
65+
ast::TtToken(_, token::Colon) |
66+
ast::TtToken(_, token::ModSep) => true,
67+
_ => false
68+
}
69+
}).unwrap_or(tts.len());
70+
let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
71+
let mut asm = token::InternedString::new("");
6372
let mut asm_str_style = None;
6473
let mut outputs = Vec::new();
6574
let mut inputs = Vec::new();
@@ -79,12 +88,22 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
7988
cx.span_err(sp, "malformed inline assembly");
8089
return DummyResult::expr(sp);
8190
}
82-
let (s, style) = match expr_to_string(cx, panictry!(p.parse_expr()),
91+
// Nested parser, stop before the first colon (see above).
92+
let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
93+
let (s, style) = match expr_to_string(cx, panictry!(p2.parse_expr()),
8394
"inline assembly must be a string literal") {
8495
Some((s, st)) => (s, st),
8596
// let compilation continue
8697
None => return DummyResult::expr(sp),
8798
};
99+
100+
// This is most likely malformed.
101+
if p2.token != token::Eof {
102+
let mut extra_tts = p2.parse_all_token_trees();
103+
extra_tts.extend(tts[first_colon..].iter().cloned());
104+
p = parse::tts_to_parser(cx.parse_sess, extra_tts, cx.cfg());
105+
}
106+
88107
asm = s;
89108
asm_str_style = Some(style);
90109
}

src/test/parse-fail/struct-literal-in-for.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl Foo {
2222

2323
fn main() {
2424
for x in Foo {
25-
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
25+
x: 3 //~ ERROR expected type, found `3`
2626
}.hi() {
2727
println!("yo");
2828
}

src/test/parse-fail/struct-literal-in-if.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl Foo {
2222

2323
fn main() {
2424
if Foo {
25-
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
25+
x: 3 //~ ERROR expected type, found `3`
2626
}.hi() {
2727
println!("yo");
2828
}

src/test/parse-fail/struct-literal-in-while.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl Foo {
2222

2323
fn main() {
2424
while Foo {
25-
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
25+
x: 3 //~ ERROR expected type, found `3`
2626
}.hi() {
2727
println!("yo");
2828
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 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+
#![allow(unknown_features)]
12+
#![feature(box_syntax)]
13+
14+
use std::fmt::Debug;
15+
16+
// A version of coerce-expect-unsized that uses type ascription.
17+
18+
pub fn main() {
19+
let _ = box { [1, 2, 3] }: Box<[int]>;
20+
let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[int]>;
21+
let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[int]>;
22+
let _ = box { |x| (x as u8) }: Box<Fn(int) -> _>;
23+
let _ = box if true { false } else { true }: Box<Debug>;
24+
let _ = box match true { true => 'a', false => 'b' }: Box<Debug>;
25+
26+
let _ = &{ [1, 2, 3] }: &[int];
27+
let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[int];
28+
let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[int];
29+
let _ = &{ |x| (x as u8) }: &Fn(int) -> _;
30+
let _ = &if true { false } else { true }: &Debug;
31+
let _ = &match true { true => 'a', false => 'b' }: &Debug;
32+
33+
let _ = Box::new([1, 2, 3]): Box<[int]>;
34+
let _ = Box::new(|x| (x as u8)): Box<Fn(int) -> _>;
35+
36+
let _ = vec![
37+
Box::new(|x| (x as u8)),
38+
box |x| (x as i16 as u8),
39+
]: Vec<Box<Fn(int) -> _>>;
40+
}

0 commit comments

Comments
 (0)