about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/cfg/construct.rs6
-rw-r--r--src/librustc/middle/expr_use_visitor.rs5
-rw-r--r--src/librustc/middle/liveness.rs16
-rw-r--r--src/librustc/middle/mem_categorization.rs5
-rw-r--r--src/librustc/middle/ty.rs4
-rw-r--r--src/librustc_trans/trans/debuginfo.rs6
-rw-r--r--src/librustc_trans/trans/expr.rs46
-rw-r--r--src/librustc_typeck/check/mod.rs43
8 files changed, 102 insertions, 29 deletions
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index fe8e90bc32c..f50790f7e9b 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -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) => {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 6a2bb2fc5a3..bf939e98338 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -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)
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index fe2d7d47cb9..f59a67e2e80 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -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");
-      }
     }
 }
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index e605471fc06..932a124ed33 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -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");
-          }
         }
     }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 4c5d3cb5c74..236312dac6e 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -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
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index f402f1d7c31..8fadaa05203 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -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) |
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 3388a7623e3..6f9990a3e9e 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -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);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 02811861551..4a10954729d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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());
+            }
+          }
        }
 
     }