Implement type ascription.
This commit is contained in:
parent
ce7bc51933
commit
b8157cc67f
@ -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, _) => {
|
||||
|
@ -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).
|
||||
|
@ -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) => {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(..) |
|
||||
|
@ -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())),
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 }`
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
40
src/test/run-pass/coerce-expect-unsized-ascribed.rs
Normal file
40
src/test/run-pass/coerce-expect-unsized-ascribed.rs
Normal 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) -> _>>;
|
||||
}
|
Loading…
Reference in New Issue
Block a user