Add ExprType to HIR and make everything compile

+ Apply parser changes manually
+ Add feature gate
This commit is contained in:
Vadim Petrochenkov 2015-12-03 05:37:48 +03:00
parent b8157cc67f
commit e0ceef5a9e
19 changed files with 83 additions and 31 deletions

View File

@ -1126,7 +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::ExprType(ref e, _) => try!(eval_const_expr_partial(tcx, &**e, ty_hint, fn_args)),
hir::ExprTup(_) => Tuple(e.id),
hir::ExprStruct(..) => Struct(e.id),
hir::ExprIndex(ref arr, ref idx) => {

View File

@ -2108,6 +2108,10 @@ impl<'tcx> ctxt<'tcx> {
}
}
hir::ExprType(ref e, _) => {
self.expr_is_lval(e)
}
hir::ExprUnary(hir::UnDeref, _) |
hir::ExprField(..) |
hir::ExprTupField(..) |

View File

@ -1042,6 +1042,9 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
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

@ -720,6 +720,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

@ -732,7 +732,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(subexpression)
}
ExprLit(_) => {}
ExprCast(ref subexpression, ref typ) => {
ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => {
visitor.visit_expr(subexpression);
visitor.visit_ty(typ)
}

View File

@ -1125,6 +1125,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let expr = lower_expr(lctx, expr);
hir::ExprCast(expr, lower_ty(lctx, ty))
}
ExprType(ref expr, ref ty) => {
let expr = lower_expr(lctx, expr);
hir::ExprType(expr, lower_ty(lctx, ty))
}
ExprAddrOf(m, ref ohs) => {
let m = lower_mutability(lctx, m);
let ohs = lower_expr(lctx, ohs);

View File

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

View File

@ -319,6 +319,7 @@ impl UnusedParens {
}
ast::ExprUnary(_, ref x) |
ast::ExprCast(ref x, _) |
ast::ExprType(ref x, _) |
ast::ExprField(ref x, _) |
ast::ExprTupField(ref x, _) |
ast::ExprIndex(ref x, _) => {

View File

@ -320,6 +320,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
name: Field::new(index.node as usize) },
hir::ExprCast(ref source, _) =>
ExprKind::Cast { source: source.to_ref() },
hir::ExprType(ref source, _) =>
return source.make_mirror(cx),
hir::ExprBox(ref value) =>
ExprKind::Box { value: value.to_ref() },
hir::ExprVec(ref fields) =>

View File

@ -1004,7 +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::ExprType(ref e, _) => try!(const_expr(cx, &**e, param_substs, fn_args, trueconst)).0,
hir::ExprBlock(ref block) => {
match block.expr {
Some(ref expr) => try!(const_expr(

View File

@ -320,6 +320,7 @@ fn walk_expr(cx: &CrateContext,
hir::ExprPath(..) => {}
hir::ExprCast(ref sub_exp, _) |
hir::ExprType(ref sub_exp, _) |
hir::ExprAddrOf(_, ref sub_exp) |
hir::ExprField(ref sub_exp, _) |
hir::ExprTupField(ref sub_exp, _) =>

View File

@ -2610,6 +2610,10 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
}
}
hir::ExprType(ref expr, _) => {
expr_kind(tcx, expr)
}
hir::ExprUnary(hir::UnDeref, _) |
hir::ExprField(..) |
hir::ExprTupField(..) |

View File

@ -233,6 +233,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
// Allows `#[deprecated]` attribute
("deprecated", "1.6.0", Some(29935), Active),
// allow using type ascription in expressions
("type_ascription", "1.6.0", Some(23416), Active),
];
// (changing above list without updating src/doc/reference.md makes @cmr sad)
@ -960,6 +963,10 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
"box expression syntax is experimental; \
you can call `Box::new` instead.");
}
ast::ExprType(..) => {
self.gate_feature("type_ascription", e.span,
"type ascription is experimental");
}
_ => {}
}
visit::walk_expr(self, e);

View File

@ -2789,6 +2789,10 @@ impl<'a> Parser<'a> {
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
ExprCast(lhs, rhs), None);
continue
} else if op == AssocOp::Colon {
let rhs = try!(self.parse_ty());
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi, ExprType(lhs, rhs));
continue
} else if op == AssocOp::DotDot {
// If we didnt have to handle `x..`, it would be pretty easy to generalise
// it to the Fixity::None code.
@ -2857,7 +2861,9 @@ impl<'a> Parser<'a> {
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
}
AssocOp::As | AssocOp::DotDot => self.bug("As or DotDot branch reached")
AssocOp::As | AssocOp::Colon | AssocOp::DotDot => {
self.bug("As, Colon or DotDot branch reached")
}
};
if op.fixity() == Fixity::None { break }

View File

@ -60,7 +60,9 @@ pub enum AssocOp {
/// `as`
As,
/// `..` range
DotDot
DotDot,
/// `:`
Colon,
}
#[derive(Debug, PartialEq, Eq)]
@ -100,6 +102,7 @@ impl AssocOp {
Token::AndAnd => Some(LAnd),
Token::OrOr => Some(LOr),
Token::DotDot => Some(DotDot),
Token::Colon => Some(Colon),
_ if t.is_keyword(keywords::As) => Some(As),
_ => None
}
@ -134,7 +137,7 @@ impl AssocOp {
pub fn precedence(&self) -> usize {
use self::AssocOp::*;
match *self {
As => 14,
As | Colon => 14,
Multiply | Divide | Modulus => 13,
Add | Subtract => 12,
ShiftLeft | ShiftRight => 11,
@ -158,7 +161,7 @@ impl AssocOp {
Inplace | Assign | AssignOp(_) => Fixity::Right,
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
LAnd | LOr => Fixity::Left,
LAnd | LOr | Colon => Fixity::Left,
DotDot => Fixity::None
}
}
@ -168,7 +171,7 @@ impl AssocOp {
match *self {
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot => false
ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | Colon => false
}
}
@ -178,7 +181,7 @@ impl AssocOp {
Assign | AssignOp(_) | Inplace => true,
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
LOr | DotDot => false
LOr | DotDot | Colon => false
}
}
@ -203,8 +206,7 @@ impl AssocOp {
BitOr => Some(ast::BiBitOr),
LAnd => Some(ast::BiAnd),
LOr => Some(ast::BiOr),
Inplace | Assign | AssignOp(_) | As | DotDot => None
Inplace | Assign | AssignOp(_) | As | DotDot | Colon => None
}
}
}

View File

@ -693,14 +693,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(subexpression)
}
ExprLit(_) => {}
ExprCast(ref subexpression, ref typ) => {
ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => {
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

@ -62,8 +62,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
// 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,
ast::TokenTree::Token(_, token::Colon) |
ast::TokenTree::Token(_, token::ModSep) => true,
_ => false
}
}).unwrap_or(tts.len());
@ -99,7 +99,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
// This is most likely malformed.
if p2.token != token::Eof {
let mut extra_tts = p2.parse_all_token_trees();
let mut extra_tts = panictry!(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());
}

View File

@ -0,0 +1,15 @@
// 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 <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.
// Type ascription is feature gated
fn main() {
let a = 10: u8; //~ ERROR type ascription is experimental
}

View File

@ -16,25 +16,25 @@ 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 { [1, 2, 3] }: Box<[i32]>;
let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>;
let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>;
let _ = box { |x| (x as u8) }: Box<Fn(i32) -> _>;
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 _ = &{ [1, 2, 3] }: &[i32];
let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32];
let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32];
let _ = &{ |x| (x as u8) }: &Fn(i32) -> _;
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 _ = Box::new([1, 2, 3]): Box<[i32]>;
let _ = Box::new(|x| (x as u8)): Box<Fn(i32) -> _>;
let _ = vec![
Box::new(|x| (x as u8)),
box |x| (x as i16 as u8),
]: Vec<Box<Fn(int) -> _>>;
]: Vec<Box<Fn(i32) -> _>>;
}