Implement type ascription.

This commit is contained in:
Eduard Burtescu 2015-02-01 09:59:46 +02:00 committed by Vadim Petrochenkov
parent ce7bc51933
commit b8157cc67f
20 changed files with 112 additions and 12 deletions

View File

@ -352,6 +352,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
hir::ExprBox(ref e) |
hir::ExprAddrOf(_, ref e) |
hir::ExprCast(ref e, _) |
hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) |
hir::ExprField(ref e, _) |
hir::ExprTupField(ref e, _) => {

View File

@ -784,6 +784,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
hir::ExprField(..) |
hir::ExprTupField(..) |
hir::ExprVec(_) |
hir::ExprType(..) |
hir::ExprTup(..) => {}
// Conditional control flow (possible to implement).

View File

@ -1126,6 +1126,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
None => unreachable!(),
}
}
hir::ExprType(ref e, _) => try!(eval_const_expr_partial(tcx, &**e, ety)),
hir::ExprTup(_) => Tuple(e.id),
hir::ExprStruct(..) => Struct(e.id),
hir::ExprIndex(ref arr, ref idx) => {

View File

@ -373,6 +373,10 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
match expr.node {
hir::ExprPath(..) => { }
hir::ExprType(ref subexpr, _) => {
self.walk_expr(&**subexpr)
}
hir::ExprUnary(hir::UnDeref, ref base) => { // *base
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
self.select_from_expr(&**base);

View File

@ -496,7 +496,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprInlineAsm(..) | hir::ExprBox(..) |
hir::ExprRange(..) => {
hir::ExprRange(..) | hir::ExprType(..) => {
intravisit::walk_expr(ir, expr);
}
}
@ -1160,6 +1160,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprBox(ref e) |
hir::ExprAddrOf(_, ref e) |
hir::ExprCast(ref e, _) |
hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) => {
self.propagate_through_expr(&**e, succ)
}
@ -1443,7 +1444,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
hir::ExprBlock(..) | hir::ExprAddrOf(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
hir::ExprRange(..) => {
hir::ExprRange(..) | hir::ExprType(..) => {
intravisit::walk_expr(this, expr);
}
}

View File

@ -518,6 +518,10 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
self.cat_def(expr.id, expr.span, expr_ty, def)
}
hir::ExprType(ref e, _) => {
self.cat_expr(&**e)
}
hir::ExprAddrOf(..) | hir::ExprCall(..) |
hir::ExprAssign(..) | hir::ExprAssignOp(..) |
hir::ExprClosure(..) | hir::ExprRet(..) |

View File

@ -234,6 +234,7 @@ mod svh_visitor {
SawExprUnary(hir::UnOp),
SawExprLit(ast::Lit_),
SawExprCast,
SawExprType,
SawExprIf,
SawExprWhile,
SawExprMatch,
@ -262,6 +263,7 @@ mod svh_visitor {
ExprUnary(op, _) => SawExprUnary(op),
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
ExprCast(..) => SawExprCast,
ExprType(..) => SawExprType,
ExprIf(..) => SawExprIf,
ExprWhile(..) => SawExprWhile,
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.name.as_str())),

View File

@ -1004,6 +1004,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
try!(const_fn_call(cx, MethodCallKey(method_call),
method_did, &arg_vals, param_substs, trueconst))
},
hir::ExprType(ref e, _) => const_expr(cx, &**e, param_substs).0,
hir::ExprBlock(ref block) => {
match block.expr {
Some(ref expr) => try!(const_expr(

View File

@ -656,6 +656,9 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_datum_unadjusted");
match expr.node {
hir::ExprType(ref e, _) => {
trans(bcx, &**e)
}
hir::ExprPath(..) => {
trans_def(bcx, expr, bcx.def(expr.id))
}
@ -941,6 +944,9 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
hir::ExprBreak(label_opt) => {
controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node.name))
}
hir::ExprType(ref e, _) => {
trans_into(bcx, &**e, Ignore)
}
hir::ExprAgain(label_opt) => {
controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node.name))
}
@ -1064,6 +1070,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
match expr.node {
hir::ExprType(ref e, _) => {
trans_into(bcx, &**e, dest)
}
hir::ExprPath(..) => {
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
}

View File

@ -3525,6 +3525,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
deferred_cast_checks.push(cast_check);
}
}
hir::ExprType(ref e, ref t) => {
let typ = fcx.to_ty(&**t);
check_expr_coercable_to_type(fcx, &**e, typ);
fcx.write_ty(id, typ);
}
hir::ExprVec(ref args) => {
let uty = expected.to_option(fcx).and_then(|uty| {
match uty.sty {

View File

@ -943,6 +943,7 @@ pub enum Expr_ {
ExprLit(P<Lit>),
/// A cast (`foo as f64`)
ExprCast(P<Expr>, P<Ty>),
ExprType(P<Expr>, P<Ty>),
/// An `if` block, with an optional else block
///
/// `if expr { block } else { expr }`

View File

@ -1203,6 +1203,9 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprCast(expr, ty) => {
ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
}
ExprType(expr, ty) => {
ExprType(folder.fold_expr(expr), folder.fold_ty(ty))
}
ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
ExprIf(cond, tr, fl) => {
ExprIf(folder.fold_expr(cond),

View File

@ -26,7 +26,7 @@ use ast::{ExprBreak, ExprCall, ExprCast, ExprInPlace};
use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
use ast::{ExprMethodCall, ExprParen, ExprPath};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprType, ExprUnary};
use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
@ -2811,7 +2811,6 @@ impl<'a> Parser<'a> {
break
}
let rhs = try!(match op.fixity() {
Fixity::Right => self.with_res(restrictions, |this|{
this.parse_assoc_expr_with(op.precedence(), LhsExpr::NotYetParsed)

View File

@ -445,7 +445,7 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
ast::ExprAssign(..) | ast::ExprBinary(..) |
ast::ExprClosure(..) |
ast::ExprAssignOp(..) | ast::ExprCast(..) |
ast::ExprInPlace(..) => true,
ast::ExprInPlace(..) | ast::ExprType(..) => true,
_ => false,
}
}
@ -2036,6 +2036,11 @@ impl<'a> State<'a> {
try!(self.word_space("as"));
try!(self.print_type(&**ty));
}
ast::ExprType(ref expr, ref ty) => {
try!(self.print_expr(&**expr));
try!(self.word_space(":"));
try!(self.print_type(&**ty));
}
ast::ExprIf(ref test, ref blk, ref elseopt) => {
try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
}

View File

@ -697,6 +697,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(subexpression);
visitor.visit_ty(typ)
}
ExprType(ref subexpression, ref typ) => {
visitor.visit_expr(&**subexpression);
visitor.visit_ty(&**typ)
}
ExprIf(ref head_expression, ref if_block, ref optional_else) => {
visitor.visit_expr(head_expression);
visitor.visit_block(if_block);

View File

@ -20,7 +20,7 @@ use syntax::ext::base;
use syntax::ext::base::*;
use syntax::feature_gate;
use syntax::parse::token::{intern, InternedString};
use syntax::parse::token;
use syntax::parse::{self, token};
use syntax::ptr::P;
use syntax::ast::AsmDialect;
@ -58,8 +58,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
return DummyResult::expr(sp);
}
let mut p = cx.new_parser_from_tts(tts);
let mut asm = InternedString::new("");
// Split the tts before the first colon, to avoid `asm!("x": y)` being
// parsed as `asm!(z)` with `z = "x": y` which is type ascription.
let first_colon = tts.iter().position(|tt| {
match *tt {
ast::TtToken(_, token::Colon) |
ast::TtToken(_, token::ModSep) => true,
_ => false
}
}).unwrap_or(tts.len());
let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
let mut asm = token::InternedString::new("");
let mut asm_str_style = None;
let mut outputs = Vec::new();
let mut inputs = Vec::new();
@ -79,12 +88,22 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
cx.span_err(sp, "malformed inline assembly");
return DummyResult::expr(sp);
}
let (s, style) = match expr_to_string(cx, panictry!(p.parse_expr()),
// Nested parser, stop before the first colon (see above).
let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
let (s, style) = match expr_to_string(cx, panictry!(p2.parse_expr()),
"inline assembly must be a string literal") {
Some((s, st)) => (s, st),
// let compilation continue
None => return DummyResult::expr(sp),
};
// This is most likely malformed.
if p2.token != token::Eof {
let mut extra_tts = p2.parse_all_token_trees();
extra_tts.extend(tts[first_colon..].iter().cloned());
p = parse::tts_to_parser(cx.parse_sess, extra_tts, cx.cfg());
}
asm = s;
asm_str_style = Some(style);
}

View File

@ -22,7 +22,7 @@ impl Foo {
fn main() {
for x in Foo {
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
x: 3 //~ ERROR expected type, found `3`
}.hi() {
println!("yo");
}

View File

@ -22,7 +22,7 @@ impl Foo {
fn main() {
if Foo {
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
x: 3 //~ ERROR expected type, found `3`
}.hi() {
println!("yo");
}

View File

@ -22,7 +22,7 @@ impl Foo {
fn main() {
while Foo {
x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
x: 3 //~ ERROR expected type, found `3`
}.hi() {
println!("yo");
}

View File

@ -0,0 +1,40 @@
// Copyright 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(unknown_features)]
#![feature(box_syntax)]
use std::fmt::Debug;
// A version of coerce-expect-unsized that uses type ascription.
pub fn main() {
let _ = box { [1, 2, 3] }: Box<[int]>;
let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[int]>;
let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[int]>;
let _ = box { |x| (x as u8) }: Box<Fn(int) -> _>;
let _ = box if true { false } else { true }: Box<Debug>;
let _ = box match true { true => 'a', false => 'b' }: Box<Debug>;
let _ = &{ [1, 2, 3] }: &[int];
let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[int];
let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[int];
let _ = &{ |x| (x as u8) }: &Fn(int) -> _;
let _ = &if true { false } else { true }: &Debug;
let _ = &match true { true => 'a', false => 'b' }: &Debug;
let _ = Box::new([1, 2, 3]): Box<[int]>;
let _ = Box::new(|x| (x as u8)): Box<Fn(int) -> _>;
let _ = vec![
Box::new(|x| (x as u8)),
box |x| (x as i16 as u8),
]: Vec<Box<Fn(int) -> _>>;
}