1
Fork 0

Type checking and trans for ranges

This commit is contained in:
Nick Cameron 2014-12-15 13:17:11 +13:00
parent 8a357e1d87
commit 17826e10a2
8 changed files with 102 additions and 29 deletions

View file

@ -439,8 +439,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
start.iter().chain(end.iter()).map(|x| &**x)) start.iter().chain(end.iter()).map(|x| &**x))
} }
ast::ExprRange(..) => { ast::ExprRange(ref start, ref end) => {
self.tcx.sess.span_bug(expr.span, "non-desugared range"); let fields = Some(&**start).into_iter()
.chain(end.as_ref().map(|e| &**e).into_iter());
self.straightline(expr, pred, fields)
} }
ast::ExprUnary(_, ref e) if self.is_method_call(expr) => { ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {

View file

@ -465,8 +465,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
assert!(overloaded); assert!(overloaded);
} }
ast::ExprRange(..) => { ast::ExprRange(ref start, ref end) => {
self.tcx().sess.span_bug(expr.span, "non-desugared range"); self.consume_expr(&**start);
end.as_ref().map(|e| self.consume_expr(&**e));
} }
ast::ExprCall(ref callee, ref args) => { // callee(args) ast::ExprCall(ref callee, ref args) => { // callee(args)

View file

@ -486,9 +486,6 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
} }
ast::ExprRange(..) => {
ir.tcx.sess.span_bug(expr.span, "non-desugared range");
}
ast::ExprForLoop(ref pat, _, _, _) => { ast::ExprForLoop(ref pat, _, _, _) => {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| { pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
debug!("adding local variable {} from for loop with bm {}", debug!("adding local variable {} from for loop with bm {}",
@ -517,7 +514,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
ast::ExprBlock(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) | ast::ExprBlock(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) |
ast::ExprMac(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprMac(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
ast::ExprParen(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) | ast::ExprParen(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) |
ast::ExprSlice(..) => { ast::ExprSlice(..) | ast::ExprRange(..) => {
visit::walk_expr(ir, expr); visit::walk_expr(ir, expr);
} }
} }
@ -1200,8 +1197,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(&**e1, succ) self.propagate_through_expr(&**e1, succ)
} }
ast::ExprRange(..) => { ast::ExprRange(ref e1, ref e2) => {
self.ir.tcx.sess.span_bug(expr.span, "non-desugared range"); let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
self.propagate_through_expr(&**e1, succ)
} }
ast::ExprBox(None, ref e) | ast::ExprBox(None, ref e) |
@ -1496,7 +1494,8 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) | ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) |
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) | ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) | ast::ExprSlice(..) => { ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
ast::ExprSlice(..) | ast::ExprRange(..) => {
visit::walk_expr(this, expr); visit::walk_expr(this, expr);
} }
ast::ExprIfLet(..) => { ast::ExprIfLet(..) => {
@ -1505,9 +1504,6 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
} }
ast::ExprRange(..) => {
this.ir.tcx.sess.span_bug(expr.span, "non-desugared range");
}
} }
} }

View file

@ -541,7 +541,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
ast::ExprAddrOf(..) | ast::ExprCall(..) | ast::ExprAddrOf(..) | ast::ExprCall(..) |
ast::ExprAssign(..) | ast::ExprAssignOp(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) |
ast::ExprClosure(..) | ast::ExprRet(..) | ast::ExprClosure(..) | ast::ExprRet(..) |
ast::ExprUnary(..) | ast::ExprSlice(..) | ast::ExprUnary(..) | ast::ExprSlice(..) | ast::ExprRange(..) |
ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprMethodCall(..) | ast::ExprCast(..) |
ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) | ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
ast::ExprBinary(..) | ast::ExprWhile(..) | ast::ExprBinary(..) | ast::ExprWhile(..) |
@ -559,9 +559,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet"); self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
} }
ast::ExprRange(..) => {
self.tcx().sess.span_bug(expr.span, "non-desugared range");
}
} }
} }

View file

@ -4257,6 +4257,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
ast::ExprCall(..) | ast::ExprCall(..) |
ast::ExprMethodCall(..) | ast::ExprMethodCall(..) |
ast::ExprStruct(..) | ast::ExprStruct(..) |
ast::ExprRange(..) |
ast::ExprTup(..) | ast::ExprTup(..) |
ast::ExprIf(..) | ast::ExprIf(..) |
ast::ExprMatch(..) | ast::ExprMatch(..) |
@ -4273,9 +4274,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
} }
ast::ExprRange(..) => {
tcx.sess.span_bug(expr.span, "non-desugared range");
}
ast::ExprLit(ref lit) if lit_is_str(&**lit) => { ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
RvalueDpsExpr RvalueDpsExpr

View file

@ -3494,9 +3494,9 @@ fn populate_scope_map(cx: &CrateContext,
end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map)); end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map));
} }
ast::ExprRange(..) => { ast::ExprRange(ref start, ref end) => {
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \ walk_expr(cx, &**start, scope_stack, scope_map);
Found unexpanded range."); end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
} }
ast::ExprVec(ref init_expressions) | ast::ExprVec(ref init_expressions) |

View file

@ -39,7 +39,7 @@ use back::abi;
use llvm::{mod, ValueRef}; use llvm::{mod, ValueRef};
use middle::def; use middle::def;
use middle::mem_categorization::Typer; use middle::mem_categorization::Typer;
use middle::subst::{mod, Subst}; use middle::subst::{mod, Subst, Substs};
use trans::{_match, adt, asm, base, callee, closure, consts, controlflow}; use trans::{_match, adt, asm, base, callee, closure, consts, controlflow};
use trans::base::*; use trans::base::*;
use trans::build::*; use trans::build::*;
@ -66,6 +66,7 @@ use trans::type_::Type;
use syntax::{ast, ast_util, codemap}; use syntax::{ast, ast_util, codemap};
use syntax::print::pprust::{expr_to_string}; use syntax::print::pprust::{expr_to_string};
use syntax::ptr::P; use syntax::ptr::P;
use syntax::parse::token;
use std::rc::Rc; use std::rc::Rc;
// Destinations // Destinations
@ -1048,8 +1049,49 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
base.as_ref().map(|e| &**e), base.as_ref().map(|e| &**e),
expr.span, expr.span,
expr.id, expr.id,
node_id_type(bcx, expr.id),
dest) dest)
} }
ast::ExprRange(ref start, ref end) => {
// FIXME it is just not right that we are synthesising ast nodes in
// trans. Shudder.
fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
ast::Field {
ident: codemap::dummy_spanned(token::str_to_ident(field_name)),
expr: expr,
span: codemap::DUMMY_SP,
}
}
// A range just desugars into a struct.
let (did, fields) = match end {
&Some(ref end) => {
// Desugar to Range
let fields = vec!(make_field("start", start.clone()),
make_field("end", end.clone()));
(tcx.lang_items.range_struct(), fields)
}
&None => {
// Desugar to RangeFrom
let fields = vec!(make_field("start", start.clone()));
(tcx.lang_items.range_from_struct(), fields)
}
};
if let Some(did) = did {
let substs = Substs::new_type(vec![node_id_type(bcx, start.id)], vec![]);
trans_struct(bcx,
fields.as_slice(),
None,
expr.span,
expr.id,
ty::mk_struct(tcx, did, substs),
dest)
} else {
tcx.sess.span_bug(expr.span,
"No lang item for ranges (how did we get this far?)")
}
}
ast::ExprTup(ref args) => { ast::ExprTup(ref args) => {
let numbered_fields: Vec<(uint, &ast::Expr)> = let numbered_fields: Vec<(uint, &ast::Expr)> =
args.iter().enumerate().map(|(i, arg)| (i, &**arg)).collect(); args.iter().enumerate().map(|(i, arg)| (i, &**arg)).collect();
@ -1347,10 +1389,10 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
base: Option<&ast::Expr>, base: Option<&ast::Expr>,
expr_span: codemap::Span, expr_span: codemap::Span,
expr_id: ast::NodeId, expr_id: ast::NodeId,
ty: Ty<'tcx>,
dest: Dest) -> Block<'blk, 'tcx> { dest: Dest) -> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_rec"); let _icx = push_ctxt("trans_rec");
let ty = node_id_type(bcx, expr_id);
let tcx = bcx.tcx(); let tcx = bcx.tcx();
with_field_tys(tcx, ty, Some(expr_id), |discr, field_tys| { with_field_tys(tcx, ty, Some(expr_id), |discr, field_tys| {
let mut need_base = Vec::from_elem(field_tys.len(), true); let mut need_base = Vec::from_elem(field_tys.len(), true);

View file

@ -4238,7 +4238,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
check_expr(fcx, e); check_expr(fcx, e);
let e_t = fcx.expr_ty(e); let e_t = fcx.expr_ty(e);
if ty::type_is_error(e_t) { if ty::type_is_error(e_t) {
fcx.write_ty(id, e_t); fcx.write_ty(e.id, e_t);
some_err = true; some_err = true;
} }
}; };
@ -4278,8 +4278,45 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
} }
} }
} }
ast::ExprRange(..) => { ast::ExprRange(ref start, ref end) => {
tcx.sess.span_bug(expr.span, "non-desugared range"); let mut some_err = false;
check_expr(fcx, &**start);
let t_start = fcx.expr_ty(&**start);
if ty::type_is_error(t_start) {
fcx.write_ty(start.id, t_start);
some_err = true;
}
if let &Some(ref e) = end {
check_expr_has_type(fcx, &**e, t_start);
let t_end = fcx.expr_ty(&**e);
if ty::type_is_error(t_end) {
fcx.write_ty(e.id, t_end);
some_err = true;
}
}
// Note that we don't check the type of the start/end satisfy any
// bounds because right the range structs do not have any. If we add
// some bounds, then we'll need to check `t_start` against them here.
if !some_err {
// Find the did from the appropriate lang item.
let did = if end.is_some() {
// Range
fcx.tcx().lang_items.range_struct()
} else {
// RangeFrom
fcx.tcx().lang_items.range_from_struct()
};
if let Some(did) = did {
let substs = Substs::new_type(vec![t_start], vec![]);
fcx.write_ty(id, ty::mk_struct(tcx, did, substs));
} else {
fcx.write_ty(id, ty::mk_err());
}
}
} }
} }