about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2015-02-01 09:59:46 +0200
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2015-12-16 17:12:35 +0300
commitb8157cc67fa25f2944b24f4306151d53d1b80b56 (patch)
tree0d9ddf074f25fec3fa9f56fc5c69c118f6dcd3af
parentce7bc51933e2facb4eca029ac17b398f372f5b41 (diff)
downloadrust-b8157cc67fa25f2944b24f4306151d53d1b80b56.tar.gz
rust-b8157cc67fa25f2944b24f4306151d53d1b80b56.zip
Implement type ascription.
-rw-r--r--src/librustc/middle/cfg/construct.rs1
-rw-r--r--src/librustc/middle/check_const.rs1
-rw-r--r--src/librustc/middle/const_eval.rs1
-rw-r--r--src/librustc/middle/expr_use_visitor.rs4
-rw-r--r--src/librustc/middle/liveness.rs5
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc_back/svh.rs2
-rw-r--r--src/librustc_trans/trans/consts.rs1
-rw-r--r--src/librustc_trans/trans/expr.rs9
-rw-r--r--src/librustc_typeck/check/mod.rs5
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/parser.rs3
-rw-r--r--src/libsyntax/print/pprust.rs7
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/libsyntax_ext/asm.rs27
-rw-r--r--src/test/parse-fail/struct-literal-in-for.rs2
-rw-r--r--src/test/parse-fail/struct-literal-in-if.rs2
-rw-r--r--src/test/parse-fail/struct-literal-in-while.rs2
-rw-r--r--src/test/run-pass/coerce-expect-unsized-ascribed.rs40
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) -> _>>;
+}