Add ExprType to HIR and make everything compile
+ Apply parser changes manually + Add feature gate
This commit is contained in:
parent
b8157cc67f
commit
e0ceef5a9e
@ -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) => {
|
||||
|
@ -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(..) |
|
||||
|
@ -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),
|
||||
|
@ -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 }`
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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, _) => {
|
||||
|
@ -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) =>
|
||||
|
@ -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(
|
||||
|
@ -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, _) =>
|
||||
|
@ -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(..) |
|
||||
|
@ -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);
|
||||
|
@ -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 didn’t 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 }
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
15
src/test/compile-fail/type-ascription-feature-gate.rs
Normal file
15
src/test/compile-fail/type-ascription-feature-gate.rs
Normal 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
|
||||
}
|
@ -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) -> _>>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user