Type checking and trans for ranges
This commit is contained in:
parent
8a357e1d87
commit
17826e10a2
8 changed files with 102 additions and 29 deletions
|
@ -439,8 +439,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
|||
start.iter().chain(end.iter()).map(|x| &**x))
|
||||
}
|
||||
|
||||
ast::ExprRange(..) => {
|
||||
self.tcx.sess.span_bug(expr.span, "non-desugared range");
|
||||
ast::ExprRange(ref start, ref end) => {
|
||||
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) => {
|
||||
|
|
|
@ -465,8 +465,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||
assert!(overloaded);
|
||||
}
|
||||
|
||||
ast::ExprRange(..) => {
|
||||
self.tcx().sess.span_bug(expr.span, "non-desugared range");
|
||||
ast::ExprRange(ref start, ref end) => {
|
||||
self.consume_expr(&**start);
|
||||
end.as_ref().map(|e| self.consume_expr(&**e));
|
||||
}
|
||||
|
||||
ast::ExprCall(ref callee, ref args) => { // callee(args)
|
||||
|
|
|
@ -486,9 +486,6 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
|||
ast::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, _, _, _) => {
|
||||
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
|
||||
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::ExprMac(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
|
||||
ast::ExprParen(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) |
|
||||
ast::ExprSlice(..) => {
|
||||
ast::ExprSlice(..) | ast::ExprRange(..) => {
|
||||
visit::walk_expr(ir, expr);
|
||||
}
|
||||
}
|
||||
|
@ -1200,8 +1197,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
self.propagate_through_expr(&**e1, succ)
|
||||
}
|
||||
|
||||
ast::ExprRange(..) => {
|
||||
self.ir.tcx.sess.span_bug(expr.span, "non-desugared range");
|
||||
ast::ExprRange(ref e1, ref e2) => {
|
||||
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) |
|
||||
|
@ -1496,7 +1494,8 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
|||
ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) |
|
||||
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
|
||||
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);
|
||||
}
|
||||
ast::ExprIfLet(..) => {
|
||||
|
@ -1505,9 +1504,6 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
|||
ast::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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -541,7 +541,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
|||
ast::ExprAddrOf(..) | ast::ExprCall(..) |
|
||||
ast::ExprAssign(..) | ast::ExprAssignOp(..) |
|
||||
ast::ExprClosure(..) | ast::ExprRet(..) |
|
||||
ast::ExprUnary(..) | ast::ExprSlice(..) |
|
||||
ast::ExprUnary(..) | ast::ExprSlice(..) | ast::ExprRange(..) |
|
||||
ast::ExprMethodCall(..) | ast::ExprCast(..) |
|
||||
ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
|
||||
ast::ExprBinary(..) | ast::ExprWhile(..) |
|
||||
|
@ -559,9 +559,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
|||
ast::ExprWhileLet(..) => {
|
||||
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
ast::ExprRange(..) => {
|
||||
self.tcx().sess.span_bug(expr.span, "non-desugared range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4257,6 +4257,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
|||
ast::ExprCall(..) |
|
||||
ast::ExprMethodCall(..) |
|
||||
ast::ExprStruct(..) |
|
||||
ast::ExprRange(..) |
|
||||
ast::ExprTup(..) |
|
||||
ast::ExprIf(..) |
|
||||
ast::ExprMatch(..) |
|
||||
|
@ -4273,9 +4274,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
|||
ast::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) => {
|
||||
RvalueDpsExpr
|
||||
|
|
|
@ -3494,9 +3494,9 @@ fn populate_scope_map(cx: &CrateContext,
|
|||
end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map));
|
||||
}
|
||||
|
||||
ast::ExprRange(..) => {
|
||||
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
|
||||
Found unexpanded range.");
|
||||
ast::ExprRange(ref start, ref end) => {
|
||||
walk_expr(cx, &**start, scope_stack, scope_map);
|
||||
end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
|
||||
}
|
||||
|
||||
ast::ExprVec(ref init_expressions) |
|
||||
|
|
|
@ -39,7 +39,7 @@ use back::abi;
|
|||
use llvm::{mod, ValueRef};
|
||||
use middle::def;
|
||||
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::base::*;
|
||||
use trans::build::*;
|
||||
|
@ -66,6 +66,7 @@ use trans::type_::Type;
|
|||
use syntax::{ast, ast_util, codemap};
|
||||
use syntax::print::pprust::{expr_to_string};
|
||||
use syntax::ptr::P;
|
||||
use syntax::parse::token;
|
||||
use std::rc::Rc;
|
||||
|
||||
// Destinations
|
||||
|
@ -1048,8 +1049,49 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
base.as_ref().map(|e| &**e),
|
||||
expr.span,
|
||||
expr.id,
|
||||
node_id_type(bcx, expr.id),
|
||||
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) => {
|
||||
let numbered_fields: Vec<(uint, &ast::Expr)> =
|
||||
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>,
|
||||
expr_span: codemap::Span,
|
||||
expr_id: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
dest: Dest) -> Block<'blk, 'tcx> {
|
||||
let _icx = push_ctxt("trans_rec");
|
||||
|
||||
let ty = node_id_type(bcx, expr_id);
|
||||
let tcx = bcx.tcx();
|
||||
with_field_tys(tcx, ty, Some(expr_id), |discr, field_tys| {
|
||||
let mut need_base = Vec::from_elem(field_tys.len(), true);
|
||||
|
|
|
@ -4238,7 +4238,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
check_expr(fcx, e);
|
||||
let e_t = fcx.expr_ty(e);
|
||||
if ty::type_is_error(e_t) {
|
||||
fcx.write_ty(id, e_t);
|
||||
fcx.write_ty(e.id, e_t);
|
||||
some_err = true;
|
||||
}
|
||||
};
|
||||
|
@ -4278,8 +4278,45 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
}
|
||||
}
|
||||
}
|
||||
ast::ExprRange(..) => {
|
||||
tcx.sess.span_bug(expr.span, "non-desugared range");
|
||||
ast::ExprRange(ref start, ref end) => {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue