Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement type ascription. #23773

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/librustc/middle/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
ast::ExprBox(None, ref e) |
ast::ExprAddrOf(_, ref e) |
ast::ExprCast(ref e, _) |
ast::ExprType(ref e, _) |
ast::ExprUnary(_, ref e) |
ast::ExprParen(ref e) |
ast::ExprField(ref e, _) |
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
ast::ExprTupField(..) |
ast::ExprVec(_) |
ast::ExprParen(..) |
ast::ExprType(..) |
ast::ExprTup(..) => {}

// Conditional control flow (possible to implement).
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
ast::ExprLit(ref lit) => {
lit_to_const(&**lit, ety)
}
ast::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ety)),
ast::ExprParen(ref e) |
ast::ExprType(ref e, _) => try!(eval_const_expr_partial(tcx, &**e, ety)),
ast::ExprBlock(ref block) => {
match block.expr {
Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ety)),
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
self.walk_adjustment(expr);

match expr.node {
ast::ExprParen(ref subexpr) => {
ast::ExprParen(ref subexpr) |
ast::ExprType(ref subexpr, _) => {
self.walk_expr(&**subexpr)
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
ast::ExprBlock(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) |
ast::ExprMac(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
ast::ExprParen(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) |
ast::ExprRange(..) => {
ast::ExprRange(..) | ast::ExprType(..) => {
visit::walk_expr(ir, expr);
}
}
Expand Down Expand Up @@ -1190,6 +1190,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
ast::ExprBox(None, ref e) |
ast::ExprAddrOf(_, ref e) |
ast::ExprCast(ref e, _) |
ast::ExprType(ref e, _) |
ast::ExprUnary(_, ref e) |
ast::ExprParen(ref e) => {
self.propagate_through_expr(&**e, succ)
Expand Down Expand Up @@ -1470,7 +1471,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
ast::ExprRange(..) => {
ast::ExprRange(..) | ast::ExprType(..) => {
visit::walk_expr(this, expr);
}
ast::ExprIfLet(..) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
self.cat_def(expr.id, expr.span, expr_ty, def)
}

ast::ExprParen(ref e) => {
ast::ExprParen(ref e) | ast::ExprType(ref e, _) => {
self.cat_expr(&**e)
}

Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4859,7 +4859,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
}
}

ast::ExprParen(ref e) => expr_kind(tcx, &**e),
ast::ExprParen(ref e) |
ast::ExprType(ref e, _) => expr_kind(tcx, &**e),

ast::ExprMac(..) => {
tcx.sess.span_bug(
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ mod svh_visitor {
SawExprUnary(ast::UnOp),
SawExprLit(ast::Lit_),
SawExprCast,
SawExprType,
SawExprIf,
SawExprWhile,
SawExprMatch,
Expand Down Expand Up @@ -263,6 +264,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(content)),
Expand Down
1 change: 1 addition & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,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, _) => {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_trans/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
_ => cx.sess().span_bug(e.span, "expected a struct or variant def")
}
}
ast::ExprParen(ref e) => const_expr(cx, &**e, param_substs).0,
ast::ExprParen(ref e) |
ast::ExprType(ref e, _) => const_expr(cx, &**e, param_substs).0,
ast::ExprBlock(ref block) => {
match block.expr {
Some(ref expr) => const_expr(cx, &**expr, param_substs).0,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_trans/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3529,7 +3529,8 @@ fn create_scope_map(cx: &CrateContext,
ast::ExprAddrOf(_, ref sub_exp) |
ast::ExprField(ref sub_exp, _) |
ast::ExprTupField(ref sub_exp, _) |
ast::ExprParen(ref sub_exp) =>
ast::ExprParen(ref sub_exp) |
ast::ExprType(ref sub_exp, _) =>
walk_expr(cx, &**sub_exp, scope_stack, scope_map),

ast::ExprBox(ref place, ref sub_expr) => {
Expand Down
9 changes: 6 additions & 3 deletions src/librustc_trans/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,8 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_datum_unadjusted");

match expr.node {
ast::ExprParen(ref e) => {
ast::ExprParen(ref e) |
ast::ExprType(ref e, _) => {
trans(bcx, &**e)
}
ast::ExprPath(..) => {
Expand Down Expand Up @@ -972,7 +973,8 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);

match expr.node {
ast::ExprParen(ref e) => {
ast::ExprParen(ref e) |
ast::ExprType(ref e, _) => {
trans_into(bcx, &**e, Ignore)
}
ast::ExprBreak(label_opt) => {
Expand Down Expand Up @@ -1072,7 +1074,8 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);

match expr.node {
ast::ExprParen(ref e) => {
ast::ExprParen(ref e) |
ast::ExprType(ref e, _) => {
trans_into(bcx, &**e, dest)
}
ast::ExprPath(..) => {
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3864,6 +3864,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
});
}
}
ast::ExprType(ref e, ref t) => {
let typ = fcx.to_ty(&**t);
check_expr_coercable_to_type(fcx, &**e, typ);
fcx.write_ty(id, typ);
}
ast::ExprVec(ref args) => {
let uty = expected.to_option(fcx).and_then(|uty| {
match uty.sty {
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,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 }`
Expand Down
28 changes: 23 additions & 5 deletions src/libsyntax/ext/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use codemap::Span;
use ext::base;
use ext::base::*;
use feature_gate;
use parse::token::InternedString;
use parse::token;
use parse::{self, token};
use ptr::P;

enum State {
Expand Down Expand Up @@ -55,8 +54,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();
Expand All @@ -76,12 +84,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, 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, 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);
}
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,9 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
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),
Expand Down
30 changes: 18 additions & 12 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use ast::{ExprBreak, ExprCall, ExprCast};
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};
Expand Down Expand Up @@ -2661,23 +2661,29 @@ impl<'a> Parser<'a> {
let rhs_span = rhs.span;
let binary = self.mk_binary(codemap::respan(cur_op_span, cur_op), lhs, rhs);
let bin = self.mk_expr(lhs_span.lo, rhs_span.hi, binary);
self.parse_more_binops(bin, min_prec)
} else {
lhs
return self.parse_more_binops(bin, min_prec);
}
}
None => {
if AS_PREC >= min_prec && self.eat_keyword_noexpect(keywords::As) {
let rhs = self.parse_ty();
let _as = self.mk_expr(lhs.span.lo,
rhs.span.hi,
ExprCast(lhs, rhs));
self.parse_more_binops(_as, min_prec)
} else {
lhs
if AS_PREC >= min_prec {
if self.eat_keyword_noexpect(keywords::As) {
let rhs = self.parse_ty();
let _as = self.mk_expr(lhs.span.lo,
rhs.span.hi,
ExprCast(lhs, rhs));
return self.parse_more_binops(_as, min_prec);
} else if self.token == token::Colon {
self.bump();
let rhs = self.parse_ty();
let ex = self.mk_expr(lhs.span.lo,
rhs.span.hi,
ExprType(lhs, rhs));
return self.parse_more_binops(ex, min_prec);
}
}
}
}
lhs
}

/// Produce an error if comparison operators are chained (RFC #558).
Expand Down
8 changes: 7 additions & 1 deletion src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,8 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
match expr.node {
ast::ExprAssign(..) | ast::ExprBinary(..) |
ast::ExprClosure(..) |
ast::ExprAssignOp(..) | ast::ExprCast(..) => true,
ast::ExprAssignOp(..) | ast::ExprCast(..) |
ast::ExprType(..) => true,
_ => false,
}
}
Expand Down Expand Up @@ -1721,6 +1722,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)));
}
Expand Down
4 changes: 4 additions & 0 deletions src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,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);
Expand Down
2 changes: 1 addition & 1 deletion src/test/parse-fail/struct-literal-in-for.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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");
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/parse-fail/struct-literal-in-if.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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");
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/parse-fail/struct-literal-in-while.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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");
}
Expand Down
40 changes: 40 additions & 0 deletions src/test/run-pass/coerce-expect-unsized-ascribed.rs
Original file line number Diff line number Diff line change
@@ -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) -> _>>;
}