diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2015-02-01 09:59:46 +0200 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2015-12-16 17:12:35 +0300 |
| commit | b8157cc67fa25f2944b24f4306151d53d1b80b56 (patch) | |
| tree | 0d9ddf074f25fec3fa9f56fc5c69c118f6dcd3af | |
| parent | ce7bc51933e2facb4eca029ac17b398f372f5b41 (diff) | |
| download | rust-b8157cc67fa25f2944b24f4306151d53d1b80b56.tar.gz rust-b8157cc67fa25f2944b24f4306151d53d1b80b56.zip | |
Implement type ascription.
| -rw-r--r-- | src/librustc/middle/cfg/construct.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/check_const.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/const_eval.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/expr_use_visitor.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/liveness.rs | 5 | ||||
| -rw-r--r-- | src/librustc/middle/mem_categorization.rs | 4 | ||||
| -rw-r--r-- | src/librustc_back/svh.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/consts.rs | 1 | ||||
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 9 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax_ext/asm.rs | 27 | ||||
| -rw-r--r-- | src/test/parse-fail/struct-literal-in-for.rs | 2 | ||||
| -rw-r--r-- | src/test/parse-fail/struct-literal-in-if.rs | 2 | ||||
| -rw-r--r-- | src/test/parse-fail/struct-literal-in-while.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/coerce-expect-unsized-ascribed.rs | 40 |
20 files changed, 112 insertions, 12 deletions
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 8baae99c2f2..abe85125215 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -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, _) => { diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 69d8dfc3613..d6f05ffd8a5 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -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). diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index f0cfd900fd7..f5d5fe1a734 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -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) => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 4861f0a6b64..73efd6a19fe 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 627df102b93..01f76a5051f 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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); } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 70ef112efba..d280f28dae1 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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(..) | diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index a5df0b94b33..2532882d012 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -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())), diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 77664f19aac..dc5659ca465 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -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( diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index d2cbb9892f6..e73afc46174 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -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) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f348d5411c3..eafbfe37e48 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b56846327c3..38cea3ea64b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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 }` diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c637813f07e..72314a35a9c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 9398f1a5733..e81f9a2a166 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0be62bc0a7f..2c11be3cea3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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))); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 22bf135f4f9..3c66220ae58 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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); diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 072be571221..20b89b0e9db 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -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); } diff --git a/src/test/parse-fail/struct-literal-in-for.rs b/src/test/parse-fail/struct-literal-in-for.rs index 8fb71e13f16..107b836d160 100644 --- a/src/test/parse-fail/struct-literal-in-for.rs +++ b/src/test/parse-fail/struct-literal-in-for.rs @@ -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"); } diff --git a/src/test/parse-fail/struct-literal-in-if.rs b/src/test/parse-fail/struct-literal-in-if.rs index 1560c83bc70..b1cccc51d7b 100644 --- a/src/test/parse-fail/struct-literal-in-if.rs +++ b/src/test/parse-fail/struct-literal-in-if.rs @@ -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"); } diff --git a/src/test/parse-fail/struct-literal-in-while.rs b/src/test/parse-fail/struct-literal-in-while.rs index 2052193df91..1c52dc48ccd 100644 --- a/src/test/parse-fail/struct-literal-in-while.rs +++ b/src/test/parse-fail/struct-literal-in-while.rs @@ -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"); } diff --git a/src/test/run-pass/coerce-expect-unsized-ascribed.rs b/src/test/run-pass/coerce-expect-unsized-ascribed.rs new file mode 100644 index 00000000000..2b1204483ba --- /dev/null +++ b/src/test/run-pass/coerce-expect-unsized-ascribed.rs @@ -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) -> _>>; +} |
