about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2014-12-19 11:47:48 +1300
committerNick Cameron <ncameron@mozilla.com>2014-12-30 13:06:25 +1300
commit4e2afb0052618ca3d758fffd0cf50559be774391 (patch)
tree1d15ea3b8b2c53b1e8f1599578325af3840edc04 /src
parented8f5039115308ca9d5591126e4d8a77864d4730 (diff)
downloadrust-4e2afb0052618ca3d758fffd0cf50559be774391.tar.gz
rust-4e2afb0052618ca3d758fffd0cf50559be774391.zip
Remove ExprSlice by hacking the compiler
[breaking-change]

The `mut` in slices is now redundant. Mutability is 'inferred' from position. This means that if mutability is only obvious from the type, you will need to use explicit calls to the slicing methods.
Diffstat (limited to 'src')
-rw-r--r--src/libcore/slice.rs4
-rw-r--r--src/librustc/middle/cfg/construct.rs7
-rw-r--r--src/librustc/middle/expr_use_visitor.rs37
-rw-r--r--src/librustc/middle/liveness.rs10
-rw-r--r--src/librustc/middle/mem_categorization.rs38
-rw-r--r--src/librustc/middle/ty.rs6
-rw-r--r--src/librustc_back/svh.rs2
-rw-r--r--src/librustc_trans/trans/cleanup.rs8
-rw-r--r--src/librustc_trans/trans/debuginfo.rs8
-rw-r--r--src/librustc_trans/trans/expr.rs64
-rw-r--r--src/librustc_typeck/check/method/confirm.rs1
-rw-r--r--src/librustc_typeck/check/mod.rs337
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/feature_gate.rs4
-rw-r--r--src/libsyntax/fold.rs6
-rw-r--r--src/libsyntax/parse/parser.rs15
-rw-r--r--src/libsyntax/print/pprust.rs20
-rw-r--r--src/libsyntax/visit.rs5
18 files changed, 254 insertions, 319 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 26684864c4c..3830a7eb9f6 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -990,7 +990,7 @@ impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T)
             Some(idx) => {
                 let tmp = mem::replace(&mut self.v, &mut []);
                 let (head, tail) = tmp.split_at_mut(idx);
-                self.v = tail[mut 1..];
+                self.v = tail.slice_from_mut(1);
                 Some(head)
             }
         }
@@ -1026,7 +1026,7 @@ impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where
                 let tmp = mem::replace(&mut self.v, &mut []);
                 let (head, tail) = tmp.split_at_mut(idx);
                 self.v = head;
-                Some(tail[mut 1..])
+                Some(tail.slice_from_mut(1))
             }
         }
     }
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 540f8a20dde..92aa70548c8 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -432,13 +432,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.call(expr, pred, &**l, Some(&**r).into_iter())
             }
 
-            ast::ExprSlice(ref base, ref start, ref end, _) => {
-                self.call(expr,
-                          pred,
-                          &**base,
-                          start.iter().chain(end.iter()).map(|x| &**x))
-            }
-
             ast::ExprRange(ref start, ref end) => {
                 let fields = start.as_ref().map(|e| &**e).into_iter()
                     .chain(end.as_ref().map(|e| &**e).into_iter());
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index f564e5cfefb..b7cfb22b85f 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -431,24 +431,31 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             }
 
             ast::ExprIndex(ref lhs, ref rhs) => {       // lhs[rhs]
-                if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], PassArgs::ByRef) {
-                    self.select_from_expr(&**lhs);
-                    self.consume_expr(&**rhs);
+                match rhs.node {
+                    ast::ExprRange(ref start, ref end) => {
+                        // Hacked slicing syntax (KILLME).
+                        let args = match (start, end) {
+                            (&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
+                            (&Some(ref e), &None) => vec![&**e],
+                            (&None, &Some(ref e)) => vec![&**e],
+                            (&None, &None) => Vec::new()
+                        };
+                        let overloaded =
+                            self.walk_overloaded_operator(expr, &**lhs, args, PassArgs::ByRef);
+                        assert!(overloaded);
+                    }
+                    _ => {
+                        if !self.walk_overloaded_operator(expr,
+                                                          &**lhs,
+                                                          vec![&**rhs],
+                                                          PassArgs::ByRef) {
+                            self.select_from_expr(&**lhs);
+                            self.consume_expr(&**rhs);
+                        }
+                    }
                 }
             }
 
-            ast::ExprSlice(ref base, ref start, ref end, _) => {    // base[start..end]
-                let args = match (start, end) {
-                    (&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
-                    (&Some(ref e), &None) => vec![&**e],
-                    (&None, &Some(ref e)) => vec![&**e],
-                    (&None, &None) => Vec::new()
-                };
-                let overloaded =
-                    self.walk_overloaded_operator(expr, &**base, args, PassArgs::ByRef);
-                assert!(overloaded);
-            }
-
             ast::ExprRange(ref start, ref end) => {
                 start.as_ref().map(|e| self.consume_expr(&**e));
                 end.as_ref().map(|e| self.consume_expr(&**e));
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index cbd34c7f258..d3859ca12a9 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -514,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::ExprRange(..) => {
+      ast::ExprRange(..) => {
           visit::walk_expr(ir, expr);
       }
     }
@@ -1191,12 +1191,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**l, r_succ)
           }
 
-          ast::ExprSlice(ref e1, ref e2, ref e3, _) => {
-            let succ = e3.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
-            let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
-            self.propagate_through_expr(&**e1, succ)
-          }
-
           ast::ExprRange(ref e1, ref e2) => {
             let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
             e1.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ))
@@ -1495,7 +1489,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::ExprSlice(..) | ast::ExprRange(..) => {
+      ast::ExprRange(..) => {
         visit::walk_expr(this, expr);
       }
       ast::ExprIfLet(..) => {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 87841c7675b..b48e41ceb73 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -500,21 +500,29 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)
           }
 
-          ast::ExprIndex(ref base, _) => {
-            let method_call = ty::MethodCall::expr(expr.id());
-            match self.typer.node_method_ty(method_call) {
-                Some(method_ty) => {
-                    // If this is an index implemented by a method call, then it will
-                    // include an implicit deref of the result.
-                    let ret_ty = ty::ty_fn_ret(method_ty).unwrap();
-                    self.cat_deref(expr,
-                                   self.cat_rvalue_node(expr.id(),
-                                                        expr.span(),
-                                                        ret_ty), 1, true)
+          ast::ExprIndex(ref base, ref idx) => {
+            match idx.node {
+                ast::ExprRange(..) => {
+                    // Slicing syntax special case (KILLME).
+                    self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
                 }
-                None => {
-                    let base_cmt = self.cat_expr(&**base);
-                    self.cat_index(expr, base_cmt)
+                _ => {
+                    let method_call = ty::MethodCall::expr(expr.id());
+                    match self.typer.node_method_ty(method_call) {
+                        Some(method_ty) => {
+                            // If this is an index implemented by a method call, then it will
+                            // include an implicit deref of the result.
+                            let ret_ty = ty::ty_fn_ret(method_ty).unwrap();
+                            self.cat_deref(expr,
+                                           self.cat_rvalue_node(expr.id(),
+                                                                expr.span(),
+                                                                ret_ty), 1, true)
+                        }
+                        None => {
+                            let base_cmt = if_ok!(self.cat_expr(&**base));
+                            self.cat_index(expr, base_cmt)
+                        }
+                    }
                 }
             }
           }
@@ -531,7 +539,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::ExprRange(..) |
+          ast::ExprUnary(..) | ast::ExprRange(..) |
           ast::ExprMethodCall(..) | ast::ExprCast(..) |
           ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
           ast::ExprBinary(..) | ast::ExprWhile(..) |
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 398e52cf043..232646f64a7 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4322,9 +4322,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             // the index method invoked for `a[i]` always yields an `&T`
             ast::ExprIndex(..) => LvalueExpr,
 
-            // the slice method invoked for `a[..]` always yields an `&T`
-            ast::ExprSlice(..) => LvalueExpr,
-
             // `for` loops are statements
             ast::ExprForLoop(..) => RvalueStmtExpr,
 
@@ -4389,8 +4386,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprUnary(ast::UnDeref, _) |
         ast::ExprField(..) |
         ast::ExprTupField(..) |
-        ast::ExprIndex(..) |
-        ast::ExprSlice(..) => {
+        ast::ExprIndex(..) => {
             LvalueExpr
         }
 
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index c68e9055269..2374e8b340b 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -246,7 +246,6 @@ mod svh_visitor {
         SawExprAssign,
         SawExprAssignOp(ast::BinOp),
         SawExprIndex,
-        SawExprSlice,
         SawExprRange,
         SawExprPath,
         SawExprAddrOf(ast::Mutability),
@@ -280,7 +279,6 @@ mod svh_visitor {
             ExprField(_, id)         => SawExprField(content(id.node)),
             ExprTupField(_, id)      => SawExprTupField(id.node),
             ExprIndex(..)            => SawExprIndex,
-            ExprSlice(..)            => SawExprSlice,
             ExprRange(..)            => SawExprRange,
             ExprPath(..)             => SawExprPath,
             ExprAddrOf(m, _)         => SawExprAddrOf(m),
diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs
index c1bb21c496a..f96aa484ffc 100644
--- a/src/librustc_trans/trans/cleanup.rs
+++ b/src/librustc_trans/trans/cleanup.rs
@@ -24,7 +24,8 @@ use trans::common;
 use trans::common::{Block, FunctionContext, ExprId, NodeInfo};
 use trans::debuginfo;
 use trans::glue;
-use middle::region;
+// Temporary due to slicing syntax hacks (KILLME)
+//use middle::region;
 use trans::type_::Type;
 use middle::ty::{mod, Ty};
 use std::fmt;
@@ -128,7 +129,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
         // excluding id's that correspond to closure bodies only). For
         // now we just say that if there is already an AST scope on the stack,
         // this new AST scope had better be its immediate child.
-        let top_scope = self.top_ast_scope();
+        // Temporarily removed due to slicing syntax hacks (KILLME).
+        /*let top_scope = self.top_ast_scope();
         if top_scope.is_some() {
             assert_eq!(self.ccx
                            .tcx()
@@ -136,7 +138,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
                            .opt_encl_scope(region::CodeExtent::from_node_id(debug_loc.id))
                            .map(|s|s.node_id()),
                        top_scope);
-        }
+        }*/
 
         self.push_scope(CleanupScope::new(AstScopeKind(debug_loc.id),
                                           Some(debug_loc)));
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index 0b0a5ecb59e..56c42c7afde 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -3533,18 +3533,12 @@ fn create_scope_map(cx: &CrateContext,
             }
 
             ast::ExprAssignOp(_, ref lhs, ref rhs) |
-            ast::ExprIndex(ref lhs, ref rhs)        |
+            ast::ExprIndex(ref lhs, ref rhs) |
             ast::ExprBinary(_, ref lhs, ref rhs)    => {
                 walk_expr(cx, &**lhs, scope_stack, scope_map);
                 walk_expr(cx, &**rhs, scope_stack, scope_map);
             }
 
-            ast::ExprSlice(ref base, ref start, ref end, _) => {
-                walk_expr(cx, &**base, scope_stack, scope_map);
-                start.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(ref start, ref end) => {
                 start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
                 end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 7c4788a29ef..c88a1b5e187 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -585,36 +585,40 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             trans_rec_tup_field(bcx, &**base, idx.node)
         }
         ast::ExprIndex(ref base, ref idx) => {
-            trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
-        }
-        ast::ExprSlice(ref base, ref start, ref end, _) => {
-            let _icx = push_ctxt("trans_slice");
-            let ccx = bcx.ccx();
-
-            let method_call = MethodCall::expr(expr.id);
-            let method_ty = ccx.tcx()
-                               .method_map
-                               .borrow()
-                               .get(&method_call)
-                               .map(|method| method.ty);
-            let base_datum = unpack_datum!(bcx, trans(bcx, &**base));
-
-            let mut args = vec![];
-            start.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
-            end.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
-
-            let result_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty.unwrap())).unwrap();
-            let scratch = rvalue_scratch_datum(bcx, result_ty, "trans_slice");
-
-            unpack_result!(bcx,
-                           trans_overloaded_op(bcx,
-                                               expr,
-                                               method_call,
-                                               base_datum,
-                                               args,
-                                               Some(SaveIn(scratch.val)),
-                                               true));
-            DatumBlock::new(bcx, scratch.to_expr_datum())
+            match idx.node {
+                ast::ExprRange(ref start, ref end) => {
+                    // Special case for slicing syntax (KILLME).
+                    let _icx = push_ctxt("trans_slice");
+                    let ccx = bcx.ccx();
+
+                    let method_call = MethodCall::expr(expr.id);
+                    let method_ty = ccx.tcx()
+                                       .method_map
+                                       .borrow()
+                                       .get(&method_call)
+                                       .map(|method| method.ty);
+                    let base_datum = unpack_datum!(bcx, trans(bcx, &**base));
+
+                    let mut args = vec![];
+                    start.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
+                    end.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
+
+                    let result_ty = ty::ty_fn_ret(monomorphize_type(bcx,
+                                                                    method_ty.unwrap())).unwrap();
+                    let scratch = rvalue_scratch_datum(bcx, result_ty, "trans_slice");
+
+                    unpack_result!(bcx,
+                                   trans_overloaded_op(bcx,
+                                                       expr,
+                                                       method_call,
+                                                       base_datum,
+                                                       args,
+                                                       Some(SaveIn(scratch.val)),
+                                                       true));
+                    DatumBlock::new(bcx, scratch.to_expr_datum())
+                }
+                _ => trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
+            }
         }
         ast::ExprBox(_, ref contents) => {
             // Special case for `Box<T>`
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 8ce7a7edb46..cf6715e2d73 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -488,7 +488,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                 ast::ExprParen(ref expr) |
                 ast::ExprField(ref expr, _) |
                 ast::ExprTupField(ref expr, _) |
-                ast::ExprSlice(ref expr, _, _, _) |
                 ast::ExprIndex(ref expr, _) |
                 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
                 _ => break,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b677fb1af92..9ae42fed07f 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2003,7 +2003,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 }
 
-#[deriving(Copy, Show)]
+#[deriving(Copy, Show,PartialEq,Eq)]
 pub enum LvaluePreference {
     PreferMutLvalue,
     NoPreference
@@ -2214,57 +2214,6 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
     }
 }
 
-/// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant
-/// method info and returns the result type (else None).
-fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  method_call: MethodCall,
-                                  expr: &ast::Expr,
-                                  base_expr: &ast::Expr,
-                                  base_ty: Ty<'tcx>,
-                                  start_expr: &Option<P<ast::Expr>>,
-                                  end_expr: &Option<P<ast::Expr>>,
-                                  mutbl: ast::Mutability)
-                                  -> Option<Ty<'tcx>> // return type is result of slice
-{
-    let lvalue_pref = match mutbl {
-        ast::MutMutable => PreferMutLvalue,
-        ast::MutImmutable => NoPreference
-    };
-
-    let opt_method_ty =
-        autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| {
-            try_overloaded_slice_step(fcx, method_call, expr, base_expr,
-                                      adjusted_ty, autoderefref, mutbl,
-                                      start_expr, end_expr)
-        });
-
-    // Regardless of whether the lookup succeeds, check the method arguments
-    // so that we have *some* type for each argument.
-    let method_ty_or_err = opt_method_ty.unwrap_or(ty::mk_err());
-
-    let mut args = vec![];
-    start_expr.as_ref().map(|x| args.push(x));
-    end_expr.as_ref().map(|x| args.push(x));
-
-    check_method_argument_types(fcx,
-                                expr.span,
-                                method_ty_or_err,
-                                expr,
-                                args.as_slice(),
-                                AutorefArgs::Yes,
-                                DontTupleArguments);
-
-    opt_method_ty.map(|method_ty| {
-        let result_ty = ty::ty_fn_ret(method_ty);
-        match result_ty {
-            ty::FnConverging(result_ty) => result_ty,
-            ty::FnDiverging => {
-                fcx.tcx().sess.span_bug(expr.span,
-                                        "slice trait does not define a `!` return")
-            }
-        }
-    })
-}
 
 /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one,
 /// installs method info and returns type of method (else None).
@@ -2274,65 +2223,79 @@ fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                        base_expr: &ast::Expr,
                                        base_ty: Ty<'tcx>, // autoderef'd type
                                        autoderefref: ty::AutoDerefRef<'tcx>,
-                                       mutbl: ast::Mutability,
+                                       lvalue_pref: LvaluePreference,
                                        start_expr: &Option<P<ast::Expr>>,
                                        end_expr: &Option<P<ast::Expr>>)
-                                       // result type is type of method being called
-                                       -> Option<Ty<'tcx>>
+                                       -> Option<(Ty<'tcx>, /* index type */
+                                                  Ty<'tcx>)> /* return type */
 {
-    let method = if mutbl == ast::MutMutable {
-        // Try `SliceMut` first, if preferred.
-        match fcx.tcx().lang_items.slice_mut_trait() {
-            Some(trait_did) => {
-                let method_name = match (start_expr, end_expr) {
-                    (&Some(_), &Some(_)) => "slice_or_fail_mut",
-                    (&Some(_), &None) => "slice_from_or_fail_mut",
-                    (&None, &Some(_)) => "slice_to_or_fail_mut",
-                    (&None, &None) => "as_mut_slice_",
-                };
+    let input_ty = fcx.infcx().next_ty_var();
+    let return_ty = fcx.infcx().next_ty_var();
 
-                method::lookup_in_trait_adjusted(fcx,
-                                                 expr.span,
-                                                 Some(&*base_expr),
-                                                 token::intern(method_name),
-                                                 trait_did,
-                                                 autoderefref,
-                                                 base_ty,
-                                                 None)
-            }
-            _ => None,
-        }
-    } else {
-        // Otherwise, fall back to `Slice`.
-        // FIXME(#17293) this will not coerce base_expr, so we miss the Slice
-        // trait for `&mut [T]`.
-        match fcx.tcx().lang_items.slice_trait() {
-            Some(trait_did) => {
-                let method_name = match (start_expr, end_expr) {
-                    (&Some(_), &Some(_)) => "slice_or_fail",
-                    (&Some(_), &None) => "slice_from_or_fail",
-                    (&None, &Some(_)) => "slice_to_or_fail",
-                    (&None, &None) => "as_slice_",
-                };
+    let method = match lvalue_pref {
+        PreferMutLvalue => {
+            // Try `SliceMut` first, if preferred.
+            match fcx.tcx().lang_items.slice_mut_trait() {
+                Some(trait_did) => {
+                    let method_name = match (start_expr, end_expr) {
+                        (&Some(_), &Some(_)) => "slice_or_fail_mut",
+                        (&Some(_), &None) => "slice_from_or_fail_mut",
+                        (&None, &Some(_)) => "slice_to_or_fail_mut",
+                        (&None, &None) => "as_mut_slice_",
+                    };
 
-                method::lookup_in_trait_adjusted(fcx,
-                                                 expr.span,
-                                                 Some(&*base_expr),
-                                                 token::intern(method_name),
-                                                 trait_did,
-                                                 autoderefref,
-                                                 base_ty,
-                                                 None)
+                    method::lookup_in_trait_adjusted(fcx,
+                                                     expr.span,
+                                                     Some(&*base_expr),
+                                                     token::intern(method_name),
+                                                     trait_did,
+                                                     autoderefref,
+                                                     base_ty,
+                                                     Some(vec![input_ty, return_ty]))
+                }
+                _ => None,
+            }
+        }
+        NoPreference => {
+            // Otherwise, fall back to `Slice`.
+            match fcx.tcx().lang_items.slice_trait() {
+                Some(trait_did) => {
+                    let method_name = match (start_expr, end_expr) {
+                        (&Some(_), &Some(_)) => "slice_or_fail",
+                        (&Some(_), &None) => "slice_from_or_fail",
+                        (&None, &Some(_)) => "slice_to_or_fail",
+                        (&None, &None) => "as_slice_",
+                    };
+
+                    method::lookup_in_trait_adjusted(fcx,
+                                                     expr.span,
+                                                     Some(&*base_expr),
+                                                     token::intern(method_name),
+                                                     trait_did,
+                                                     autoderefref,
+                                                     base_ty,
+                                                     Some(vec![input_ty, return_ty]))
+                }
+                _ => None,
             }
-            _ => None,
         }
     };
 
     // If some lookup succeeded, install method in table
     method.map(|method| {
-        let ty = method.ty;
-        fcx.inh.method_map.borrow_mut().insert(method_call, method);
-        ty
+        let method_ty = method.ty;
+        make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method));
+
+        let result_ty = ty::ty_fn_ret(method_ty);
+        let result_ty = match result_ty {
+            ty::FnConverging(result_ty) => result_ty,
+            ty::FnDiverging => {
+                fcx.tcx().sess.span_bug(expr.span,
+                "slice trait does not define a `!` return")
+            }
+        };
+
+        (input_ty, result_ty)
     })
 }
 
@@ -4211,99 +4174,98 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       }
       ast::ExprIndex(ref base, ref idx) => {
           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
-          check_expr(fcx, &**idx);
           let base_t = fcx.expr_ty(&**base);
-          let idx_t = fcx.expr_ty(&**idx);
           if ty::type_is_error(base_t) {
               fcx.write_ty(id, base_t);
-          } else if ty::type_is_error(idx_t) {
-              fcx.write_ty(id, idx_t);
           } else {
-              let base_t = structurally_resolved_type(fcx, expr.span, base_t);
-
-              let result =
-                  autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
-                      try_index_step(fcx,
-                                     MethodCall::expr(expr.id),
-                                     expr,
-                                     &**base,
-                                     adj_ty,
-                                     adj,
-                                     lvalue_pref)
-                  });
-
-              match result {
-                  Some((index_ty, element_ty)) => {
-                      check_expr_has_type(fcx, &**idx, index_ty);
-                      fcx.write_ty(id, element_ty);
-                  }
-                  _ => {
-                      check_expr_has_type(fcx, &**idx, ty::mk_err());
-                      fcx.type_error_message(
-                          expr.span,
-                          |actual| {
-                              format!("cannot index a value of type `{}`",
-                                      actual)
-                          },
-                          base_t,
-                          None);
-                      fcx.write_ty(id, ty::mk_err())
-                  }
-              }
-          }
-       }
-       ast::ExprSlice(ref base, ref start, ref end, mutbl) => {
-          check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
-          let raw_base_t = fcx.expr_ty(&**base);
-
-          let mut some_err = false;
-          if ty::type_is_error(raw_base_t) {
-              fcx.write_ty(id, raw_base_t);
-              some_err = true;
-          }
+              match idx.node {
+                ast::ExprRange(ref start, ref end) => {
+                  // A slice, rather than an index. Special cased for now (KILLME).
+                  let base_t = structurally_resolved_type(fcx, expr.span, base_t);
 
-          {
-              let check_slice_idx = |e: &ast::Expr| {
-                  check_expr(fcx, e);
-                  let e_t = fcx.expr_ty(e);
-                  if ty::type_is_error(e_t) {
-                    fcx.write_ty(e.id, e_t);
-                    some_err = true;
+                  if lvalue_pref == PreferMutLvalue {
+                    println!("mutable lvalue_pref");
                   }
-              };
-              start.as_ref().map(|e| check_slice_idx(&**e));
-              end.as_ref().map(|e| check_slice_idx(&**e));
-          }
-
-          if !some_err {
-              let base_t = structurally_resolved_type(fcx,
-                                                      expr.span,
-                                                      raw_base_t);
-              let method_call = MethodCall::expr(expr.id);
-              match try_overloaded_slice(fcx,
-                                         method_call,
-                                         expr,
-                                         &**base,
-                                         base_t,
-                                         start,
-                                         end,
-                                         mutbl) {
-                  Some(ty) => fcx.write_ty(id, ty),
-                  None => {
-                        fcx.type_error_message(expr.span,
-                           |actual| {
-                                format!("cannot take a {}slice of a value with type `{}`",
-                                        if mutbl == ast::MutMutable {
-                                            "mutable "
-                                        } else {
-                                            ""
-                                        },
-                                        actual)
-                           },
-                           base_t,
-                           None);
-                        fcx.write_ty(id, ty::mk_err())
+                  let result =
+                      autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
+                          try_overloaded_slice_step(fcx,
+                                                    MethodCall::expr(expr.id),
+                                                    expr,
+                                                    &**base,
+                                                    adj_ty,
+                                                    adj,
+                                                    lvalue_pref,
+                                                    start,
+                                                    end)
+                      });
+
+                  let mut args = vec![];
+                  start.as_ref().map(|x| args.push(x));
+                  end.as_ref().map(|x| args.push(x));
+
+                  match result {
+                      Some((index_ty, element_ty)) => {
+                          for a in args.iter() {
+                            check_expr_has_type(fcx, &***a, index_ty);
+                          }
+                          fcx.write_ty(idx.id, element_ty);
+                          fcx.write_ty(id, element_ty)
+                      }
+                      _ => {
+                          for a in args.iter() {
+                            check_expr(fcx, &***a);
+                          }
+                          fcx.type_error_message(expr.span,
+                             |actual| {
+                                  format!("cannot take a slice of a value with type `{}`",
+                                          actual)
+                             },
+                             base_t,
+                             None);
+                          fcx.write_ty(idx.id, ty::mk_err());
+                          fcx.write_ty(id, ty::mk_err())
+                      }
                   }
+                }
+                _ => {
+                  check_expr(fcx, &**idx);
+                  let idx_t = fcx.expr_ty(&**idx);
+                  if ty::type_is_error(idx_t) {
+                      fcx.write_ty(id, idx_t);
+                  } else {
+                      let base_t = structurally_resolved_type(fcx, expr.span, base_t);
+
+                      let result =
+                          autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
+                              try_index_step(fcx,
+                                             MethodCall::expr(expr.id),
+                                             expr,
+                                             &**base,
+                                             adj_ty,
+                                             adj,
+                                             lvalue_pref)
+                          });
+
+                      match result {
+                          Some((index_ty, element_ty)) => {
+                              check_expr_has_type(fcx, &**idx, index_ty);
+                              fcx.write_ty(id, element_ty);
+                          }
+                          _ => {
+                              check_expr_has_type(fcx, &**idx, ty::mk_err());
+                              fcx.type_error_message(
+                                  expr.span,
+                                  |actual| {
+                                      format!("cannot index a value of type `{}`",
+                                              actual)
+                                  },
+                                  base_t,
+                                  None);
+                              fcx.write_ty(id, ty::mk_err())
+                          }
+                      }
+                  }
+                }
               }
           }
        }
@@ -4319,7 +4281,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
           let idx_type = match (t_start, t_end) {
             (Some(ty), None) | (None, Some(ty)) => Some(ty),
-            (Some(t_start), Some(t_end)) if t_start == ty::mk_err() || t_end == ty::mk_err() => {
+            (Some(t_start), Some(t_end))
+              if ty::type_is_error(t_start) || ty::type_is_error(t_end) => {
                 Some(ty::mk_err())
             }
             (Some(t_start), Some(t_end)) => {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e53e2cea1cc..debcbcd2154 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -723,7 +723,6 @@ pub enum Expr_ {
     ExprField(P<Expr>, SpannedIdent),
     ExprTupField(P<Expr>, Spanned<uint>),
     ExprIndex(P<Expr>, P<Expr>),
-    ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability),
     ExprRange(Option<P<Expr>>, Option<P<Expr>>),
 
     /// Variable reference, possibly containing `::` and/or
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 28f7a78ddd0..4607520655e 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -307,10 +307,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprSlice(..) => {
+            ast::ExprRange(..) => {
                 self.gate_feature("slicing_syntax",
                                   e.span,
-                                  "slicing syntax is experimental");
+                                  "range syntax is experimental");
             }
             _ => {}
         }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ede023c4e8b..11a9fdee0b9 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1384,12 +1384,6 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
             ExprIndex(el, er) => {
                 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
             }
-            ExprSlice(e, e1, e2, m) => {
-                ExprSlice(folder.fold_expr(e),
-                          e1.map(|x| folder.fold_expr(x)),
-                          e2.map(|x| folder.fold_expr(x)),
-                          m)
-            }
             ExprRange(e1, e2) => {
                 ExprRange(e1.map(|x| folder.fold_expr(x)),
                           e2.map(|x| folder.fold_expr(x)))
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ec1e966926a..2f43661eebe 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -25,7 +25,7 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
 use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
 use ast::{ExprBreak, ExprCall, ExprCast};
-use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice};
+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};
@@ -66,7 +66,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
 use ast;
 use ast_util::{mod, as_prec, ident_to_path, operator_prec};
-use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp};
+use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp, DUMMY_SP};
 use diagnostic;
 use ext::tt::macro_parser;
 use parse;
@@ -2135,9 +2135,16 @@ impl<'a> Parser<'a> {
                     expr: P<Expr>,
                     start: Option<P<Expr>>,
                     end: Option<P<Expr>>,
-                    mutbl: Mutability)
+                    _mutbl: Mutability)
                     -> ast::Expr_ {
-        ExprSlice(expr, start, end, mutbl)
+        // FIXME: we could give more accurate span info here.
+        let (lo, hi) = match (&start, &end) {
+            (&Some(ref s), &Some(ref e)) => (s.span.lo, e.span.hi),
+            (&Some(ref s), &None) => (s.span.lo, s.span.hi),
+            (&None, &Some(ref e)) => (e.span.lo, e.span.hi),
+            (&None, &None) => (DUMMY_SP.lo, DUMMY_SP.hi),
+        };
+        ExprIndex(expr, self.mk_expr(lo, hi, ExprRange(start, end)))
     }
 
     pub fn mk_range(&mut self,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a4b349c5f23..accffbc35ba 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1739,15 +1739,7 @@ impl<'a> State<'a> {
                 try!(self.print_expr(&**index));
                 try!(word(&mut self.s, "]"));
             }
-            ast::ExprSlice(ref e, ref start, ref end, ref mutbl) => {
-                try!(self.print_expr(&**e));
-                try!(word(&mut self.s, "["));
-                if mutbl == &ast::MutMutable {
-                    try!(word(&mut self.s, "mut"));
-                    if start.is_some() || end.is_some() {
-                        try!(space(&mut self.s));
-                    }
-                }
+            ast::ExprRange(ref start, ref end) => {
                 if let &Some(ref e) = start {
                     try!(self.print_expr(&**e));
                 }
@@ -1757,16 +1749,6 @@ impl<'a> State<'a> {
                 if let &Some(ref e) = end {
                     try!(self.print_expr(&**e));
                 }
-                try!(word(&mut self.s, "]"));
-            }
-            ast::ExprRange(ref start, ref end) => {
-                if let &Some(ref e) = start {
-                    try!(self.print_expr(&**e));
-                }
-                try!(word(&mut self.s, ".."));
-                if let &Some(ref e) = end {
-                    try!(self.print_expr(&**e));
-                }
             }
             ast::ExprPath(ref path) => try!(self.print_path(path, true)),
             ast::ExprBreak(opt_ident) => {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index cde9ba932be..22cfea86251 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -866,11 +866,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(&**main_expression);
             visitor.visit_expr(&**index_expression)
         }
-        ExprSlice(ref main_expression, ref start, ref end, _) => {
-            visitor.visit_expr(&**main_expression);
-            walk_expr_opt(visitor, start);
-            walk_expr_opt(visitor, end)
-        }
         ExprRange(ref start, ref end) => {
             walk_expr_opt(visitor, start);
             walk_expr_opt(visitor, end)