From ed8f5039115308ca9d5591126e4d8a77864d4730 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 18 Dec 2014 17:55:04 +1300 Subject: [PATCH 1/4] Add hypothetical support for ranges with only an upper bound Note that this doesn't add the surface syntax. --- src/libcore/ops.rs | 8 ++++ src/libcoretest/ops.rs | 6 +++ src/librustc/middle/cfg/construct.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/lang_items.rs | 1 + src/librustc/middle/liveness.rs | 2 +- src/librustc_trans/trans/debuginfo.rs | 2 +- src/librustc_trans/trans/expr.rs | 24 +++++++--- src/librustc_typeck/check/mod.rs | 62 +++++++++++++++---------- src/libsyntax/ast.rs | 2 +- src/libsyntax/fold.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax/visit.rs | 2 +- 14 files changed, 81 insertions(+), 40 deletions(-) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 0cd8c1d69d1a1..f6b79ccc42b01 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -908,6 +908,14 @@ impl Iterator for RangeFrom { } } +/// A range which is only bounded above. +#[deriving(Copy)] +#[lang="range_to"] +pub struct RangeTo { + /// The upper bound of the range (exclusive). + pub end: Idx, +} + /// The `Deref` trait is used to specify the functionality of dereferencing /// operations like `*v`. diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs index a8889ce9e348b..3c8a6d480f74e 100644 --- a/src/libcoretest/ops.rs +++ b/src/libcoretest/ops.rs @@ -55,6 +55,12 @@ fn test_range_from() { assert!(count == 10); } +#[test] +fn test_range_to() { + // Not much to test. + let _ = RangeTo { end: 42u }; +} + #[test] fn test_full_range() { // Not much to test. diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index f50790f7e9b15..540f8a20dde2d 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::ExprRange(ref start, ref end) => { - let fields = Some(&**start).into_iter() + let fields = start.as_ref().map(|e| &**e).into_iter() .chain(end.as_ref().map(|e| &**e).into_iter()); self.straightline(expr, pred, fields) } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 1dfd602794f80..f564e5cfefbab 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -450,7 +450,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } ast::ExprRange(ref start, ref end) => { - self.consume_expr(&**start); + start.as_ref().map(|e| self.consume_expr(&**e)); end.as_ref().map(|e| self.consume_expr(&**e)); } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 90e3e2bb34aba..2aef430719923 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -269,6 +269,7 @@ lets_do_this! { SliceMutTraitLangItem, "slice_mut", slice_mut_trait; RangeStructLangItem, "range", range_struct; RangeFromStructLangItem, "range_from", range_from_struct; + RangeToStructLangItem, "range_to", range_to_struct; FullRangeStructLangItem, "full_range", full_range_struct; UnsafeTypeLangItem, "unsafe", unsafe_type; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index f59a67e2e806d..cbd34c7f25816 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1199,7 +1199,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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) + e1.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ)) } ast::ExprBox(None, ref e) | diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index ea2d42bebdfc4..0b0a5ecb59e1b 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3546,7 +3546,7 @@ fn create_scope_map(cx: &CrateContext, } ast::ExprRange(ref start, ref end) => { - walk_expr(cx, &**start, scope_stack, scope_map); + 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 60b5a08c7c5df..7c4788a29efe4 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1064,22 +1064,34 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } // A range just desugars into a struct. - let (did, fields) = match end { - &Some(ref end) => { + // Note that the type of the start and end may not be the same, but + // they should only differ in their lifetime, which should not matter + // in trans. + let (did, fields, ty_params) = match (start, end) { + (&Some(ref start), &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) + (tcx.lang_items.range_struct(), fields, vec![node_id_type(bcx, start.id)]) } - &None => { + (&Some(ref start), &None) => { // Desugar to RangeFrom let fields = vec!(make_field("start", start.clone())); - (tcx.lang_items.range_from_struct(), fields) + (tcx.lang_items.range_from_struct(), fields, vec![node_id_type(bcx, start.id)]) + } + (&None, &Some(ref end)) => { + // Desugar to RangeTo + let fields = vec!(make_field("end", end.clone())); + (tcx.lang_items.range_to_struct(), fields, vec![node_id_type(bcx, end.id)]) + } + _ => { + // Desugar to FullRange + (tcx.lang_items.full_range_struct(), vec![], vec![]) } }; if let Some(did) = did { - let substs = Substs::new_type(vec![node_id_type(bcx, start.id)], vec![]); + let substs = Substs::new_type(ty_params, vec![]); trans_struct(bcx, fields.as_slice(), None, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 68cf139338aa2..b677fb1af92eb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4308,46 +4308,58 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } ast::ExprRange(ref start, ref end) => { - check_expr(fcx, &**start); - let t_start = fcx.expr_ty(&**start); - - let idx_type = if let &Some(ref e) = end { + let t_start = start.as_ref().map(|e| { check_expr(fcx, &**e); - let t_end = fcx.expr_ty(&**e); - if ty::type_is_error(t_end) { - ty::mk_err() - } else if t_start == ty::mk_err() { - ty::mk_err() - } else { - infer::common_supertype(fcx.infcx(), - infer::RangeExpression(expr.span), - true, - t_start, - t_end) + fcx.expr_ty(&**e) + }); + let t_end = end.as_ref().map(|e| { + check_expr(fcx, &**e); + fcx.expr_ty(&**e) + }); + + 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(ty::mk_err()) } - } else { - t_start + (Some(t_start), Some(t_end)) => { + Some(infer::common_supertype(fcx.infcx(), + infer::RangeExpression(expr.span), + true, + t_start, + t_end)) + } + _ => None }; // Note that we don't check the type of 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. - let range_type = if idx_type == ty::mk_err() { + let range_type = if idx_type == Some(ty::mk_err()) { ty::mk_err() + } else if idx_type.is_none() { + // Neither start nor end => FullRange + if let Some(did) = tcx.lang_items.full_range_struct() { + let substs = Substs::new_type(vec![], vec![]); + ty::mk_struct(tcx, did, substs) + } else { + ty::mk_err() + } } else { // Find the did from the appropriate lang item. - let did = if end.is_some() { - // Range - tcx.lang_items.range_struct() - } else { - // RangeFrom - tcx.lang_items.range_from_struct() + let did = match (start, end) { + (&Some(_), &Some(_)) => tcx.lang_items.range_struct(), + (&Some(_), &None) => tcx.lang_items.range_from_struct(), + (&None, &Some(_)) => tcx.lang_items.range_to_struct(), + (&None, &None) => { + tcx.sess.span_bug(expr.span,"full range should be dealt with above") + } }; if let Some(did) = did { let polytype = ty::lookup_item_type(tcx, did); - let substs = Substs::new_type(vec![idx_type], vec![]); + let substs = Substs::new_type(vec![idx_type.unwrap()], vec![]); let bounds = polytype.generics.to_bounds(tcx, &substs); fcx.add_obligations_for_parameters( traits::ObligationCause::new(expr.span, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d4932fbb5f1c5..e53e2cea1ccab 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -724,7 +724,7 @@ pub enum Expr_ { ExprTupField(P, Spanned), ExprIndex(P, P), ExprSlice(P, Option>, Option>, Mutability), - ExprRange(P, Option>), + ExprRange(Option>, Option>), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar:: diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c58901701f530..ede023c4e8bbc 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1391,7 +1391,7 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> m) } ExprRange(e1, e2) => { - ExprRange(folder.fold_expr(e1), + ExprRange(e1.map(|x| folder.fold_expr(x)), e2.map(|x| folder.fold_expr(x))) } ExprPath(pth) => ExprPath(folder.fold_path(pth)), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2e2abab03e55..ec1e966926a3b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2144,7 +2144,7 @@ impl<'a> Parser<'a> { start: P, end: Option>) -> ast::Expr_ { - ExprRange(start, end) + ExprRange(Some(start), end) } pub fn mk_field(&mut self, expr: P, ident: ast::SpannedIdent) -> ast::Expr_ { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 623f20bccd2ee..a4b349c5f23ec 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1760,7 +1760,9 @@ impl<'a> State<'a> { try!(word(&mut self.s, "]")); } ast::ExprRange(ref start, ref end) => { - try!(self.print_expr(&**start)); + 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)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 714339d0f0aaa..cde9ba932be33 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -872,7 +872,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, end) } ExprRange(ref start, ref end) => { - visitor.visit_expr(&**start); + walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } ExprPath(ref path) => { From 4e2afb0052618ca3d758fffd0cf50559be774391 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 19 Dec 2014 11:47:48 +1300 Subject: [PATCH 2/4] 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. --- src/libcore/slice.rs | 4 +- src/librustc/middle/cfg/construct.rs | 7 - src/librustc/middle/expr_use_visitor.rs | 37 ++- src/librustc/middle/liveness.rs | 10 +- src/librustc/middle/mem_categorization.rs | 38 ++- src/librustc/middle/ty.rs | 6 +- src/librustc_back/svh.rs | 2 - src/librustc_trans/trans/cleanup.rs | 8 +- src/librustc_trans/trans/debuginfo.rs | 8 +- src/librustc_trans/trans/expr.rs | 64 ++-- src/librustc_typeck/check/method/confirm.rs | 1 - src/librustc_typeck/check/mod.rs | 337 +++++++++----------- src/libsyntax/ast.rs | 1 - src/libsyntax/feature_gate.rs | 4 +- src/libsyntax/fold.rs | 6 - src/libsyntax/parse/parser.rs | 15 +- src/libsyntax/print/pprust.rs | 20 +- src/libsyntax/visit.rs | 5 - 18 files changed, 254 insertions(+), 319 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 26684864c4c49..3830a7eb9f6ac 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 540f8a20dde2d..92aa70548c82b 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 f564e5cfefbab..b7cfb22b85f8c 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 cbd34c7f25816..d3859ca12a971 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 87841c7675b91..b48e41ceb7358 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 398e52cf0430b..232646f64a7d1 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 c68e9055269c0..2374e8b340be7 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 c1bb21c496adf..f96aa484ffc95 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 0b0a5ecb59e1b..56c42c7afdeb8 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 7c4788a29efe4..c88a1b5e18736 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` diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 8ce7a7edb46d1..cf6715e2d7320 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 b677fb1af92eb..9ae42fed07f73 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>, - end_expr: &Option>, - mutbl: ast::Mutability) - -> Option> // 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>, end_expr: &Option>) - // result type is type of method being called - -> Option> + -> 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 e53e2cea1ccab..debcbcd2154bd 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -723,7 +723,6 @@ pub enum Expr_ { ExprField(P, SpannedIdent), ExprTupField(P, Spanned), ExprIndex(P, P), - ExprSlice(P, Option>, Option>, Mutability), ExprRange(Option>, Option>), /// Variable reference, possibly containing `::` and/or diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 28f7a78ddd08a..4607520655ea1 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 ede023c4e8bbc..11a9fdee0b9b0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1384,12 +1384,6 @@ pub fn noop_fold_expr(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 ec1e966926a3b..2f43661eebeba 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, start: Option>, end: Option>, - 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 a4b349c5f23ec..accffbc35babe 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 cde9ba932be33..22cfea862517e 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) From 3bf405682df4dfb55b969640b811b317fa55447d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 19 Dec 2014 12:44:24 +1300 Subject: [PATCH 3/4] Fallout from mut slices --- src/libcollections/slice.rs | 14 +++++----- src/libcore/fmt/float.rs | 4 +-- src/libcore/slice.rs | 19 +++++++------ src/libcore/str/mod.rs | 1 + src/libcoretest/ops.rs | 2 +- src/librbml/io.rs | 2 +- src/librustc/middle/region.rs | 1 + src/librustc_back/sha2.rs | 28 +++++++++---------- src/libstd/io/buffered.rs | 4 +-- src/libstd/io/comm_adapters.rs | 2 +- src/libstd/io/fs.rs | 4 +-- src/libstd/io/mem.rs | 10 +++---- src/libstd/io/mod.rs | 6 ++-- src/libstd/io/net/ip.rs | 2 +- src/libstd/io/net/udp.rs | 2 +- src/libstd/io/util.rs | 2 +- src/libstd/rand/os.rs | 2 +- src/libstd/rt/util.rs | 2 +- src/test/bench/shootout-fannkuch-redux.rs | 4 +-- src/test/bench/shootout-fasta-redux.rs | 2 +- src/test/bench/shootout-reverse-complement.rs | 2 +- src/test/compile-fail/range-1.rs | 1 + src/test/compile-fail/range-2.rs | 1 + src/test/compile-fail/slice-2.rs | 4 --- src/test/compile-fail/slice-mut-2.rs | 3 +- src/test/compile-fail/slice-mut.rs | 5 ---- src/test/run-pass/range.rs | 2 ++ 27 files changed, 65 insertions(+), 66 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index d6d94f57acf45..404804cd91d2e 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -94,7 +94,7 @@ use core::iter::{range_step, MultiplicativeIterator}; use core::kinds::Sized; use core::mem::size_of; use core::mem; -use core::ops::FnMut; +use core::ops::{FnMut,SliceMut}; use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; use core::prelude::{Ord, Ordering, RawPtr, Some, range}; use core::ptr; @@ -1110,7 +1110,7 @@ impl SliceExt for [T] { #[inline] fn move_from(&mut self, mut src: Vec, start: uint, end: uint) -> uint { - for (a, b) in self.iter_mut().zip(src[mut start..end].iter_mut()) { + for (a, b) in self.iter_mut().zip(src.slice_mut(start, end).iter_mut()) { mem::swap(a, b); } cmp::min(self.len(), end-start) @@ -1326,7 +1326,7 @@ impl BorrowFrom> for [T] { #[unstable = "trait is unstable"] impl BorrowFromMut> for [T] { - fn borrow_from_mut(owned: &mut Vec) -> &mut [T] { owned[mut] } + fn borrow_from_mut(owned: &mut Vec) -> &mut [T] { owned.as_mut_slice_() } } #[unstable = "trait is unstable"] @@ -2491,14 +2491,14 @@ mod tests { assert!(a == [7i,2,3,4]); let mut a = [1i,2,3,4,5]; let b = vec![5i,6,7,8,9,0]; - assert_eq!(a[mut 2..4].move_from(b,1,6), 2); + assert_eq!(a.slice_mut(2, 4).move_from(b,1,6), 2); assert!(a == [1i,2,6,7,5]); } #[test] fn test_reverse_part() { let mut values = [1i,2,3,4,5]; - values[mut 1..4].reverse(); + values.slice_mut(1, 4).reverse(); assert!(values == [1,4,3,2,5]); } @@ -2545,9 +2545,9 @@ mod tests { fn test_bytes_set_memory() { use slice::bytes::MutableByteVector; let mut values = [1u8,2,3,4,5]; - values[mut 0..5].set_memory(0xAB); + values.slice_mut(0, 5).set_memory(0xAB); assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); - values[mut 2..4].set_memory(0xFF); + values.slice_mut(2, 4).set_memory(0xFF); assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); } diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 47701ab8ffd63..329fe7c7b4913 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -179,7 +179,7 @@ pub fn float_to_str_bytes_common( _ => () } - buf[mut ..end].reverse(); + buf.slice_to_mut(end).reverse(); // Remember start of the fractional digits. // Points one beyond end of buf if none get generated, @@ -316,7 +316,7 @@ pub fn float_to_str_bytes_common( impl<'a> fmt::FormatWriter for Filler<'a> { fn write(&mut self, bytes: &[u8]) -> fmt::Result { - slice::bytes::copy_memory(self.buf[mut *self.end..], + slice::bytes::copy_memory(self.buf.slice_from_mut(*self.end), bytes); *self.end += bytes.len(); Ok(()) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 3830a7eb9f6ac..d25f96ac15fa6 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -264,24 +264,26 @@ impl SliceExt for [T] { fn as_mut_slice(&mut self) -> &mut [T] { self } fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T] { - self[mut start..end] + ops::SliceMut::slice_or_fail_mut(self, &start, &end) } #[inline] fn slice_from_mut(&mut self, start: uint) -> &mut [T] { - self[mut start..] + ops::SliceMut::slice_from_or_fail_mut(self, &start) } #[inline] fn slice_to_mut(&mut self, end: uint) -> &mut [T] { - self[mut ..end] + ops::SliceMut::slice_to_or_fail_mut(self, &end) } #[inline] fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]) { unsafe { let self2: &mut [T] = mem::transmute_copy(&self); - (self[mut ..mid], self2[mut mid..]) + + (ops::SliceMut::slice_to_or_fail_mut(self, &mid), + ops::SliceMut::slice_from_or_fail_mut(self2, &mid)) } } @@ -315,14 +317,13 @@ impl SliceExt for [T] { #[inline] fn tail_mut(&mut self) -> &mut [T] { - let len = self.len(); - self[mut 1..len] + self.slice_from_mut(1) } #[inline] fn init_mut(&mut self) -> &mut [T] { let len = self.len(); - self[mut 0..len - 1] + self.slice_to_mut(len-1) } #[inline] @@ -560,7 +561,7 @@ impl OrdSliceExt for [T] { self.swap(j, i-1); // Step 4: Reverse the (previously) weakly decreasing part - self[mut i..].reverse(); + self.slice_from_mut(i).reverse(); true } @@ -582,7 +583,7 @@ impl OrdSliceExt for [T] { } // Step 2: Reverse the weakly increasing part - self[mut i..].reverse(); + self.slice_from_mut(i).reverse(); // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1) let mut j = self.len() - 1; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 1e7fe8f060c3e..1fc5f90028dad 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -897,6 +897,7 @@ impl<'a> Iterator<&'a str> for SplitStr<'a> { } } + /* Section: Comparing strings */ diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs index 3c8a6d480f74e..430188c7e4322 100644 --- a/src/libcoretest/ops.rs +++ b/src/libcoretest/ops.rs @@ -9,7 +9,7 @@ // except according to those terms. use test::Bencher; -use core::ops::{Range, FullRange, RangeFrom}; +use core::ops::{Range, FullRange, RangeFrom, RangeTo}; // Overhead of dtors diff --git a/src/librbml/io.rs b/src/librbml/io.rs index b46b977d7012d..cbe69295050ec 100644 --- a/src/librbml/io.rs +++ b/src/librbml/io.rs @@ -102,7 +102,7 @@ impl Writer for SeekableMemWriter { // Do the necessary writes if left.len() > 0 { - slice::bytes::copy_memory(self.buf[mut self.pos..], left); + slice::bytes::copy_memory(self.buf.slice_from_mut(self.pos), left); } if right.len() > 0 { self.buf.push_all(right); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 8df78281cc227..392724bc9a18e 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -485,6 +485,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { let prev_cx = visitor.cx; visitor.cx.parent = Some(expr.id); + { let region_maps = &mut visitor.region_maps; let terminating = |id| { diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 074341ccff49d..e1f0168d86be4 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -139,14 +139,14 @@ impl FixedBuffer for FixedBuffer64 { let buffer_remaining = size - self.buffer_idx; if input.len() >= buffer_remaining { copy_memory( - self.buffer[mut self.buffer_idx..size], + self.buffer.slice_mut(self.buffer_idx, size), input[..buffer_remaining]); self.buffer_idx = 0; func(&self.buffer); i += buffer_remaining; } else { copy_memory( - self.buffer[mut self.buffer_idx..self.buffer_idx + input.len()], + self.buffer.slice_mut(self.buffer_idx, self.buffer_idx + input.len()), input); self.buffer_idx += input.len(); return; @@ -165,7 +165,7 @@ impl FixedBuffer for FixedBuffer64 { // be empty. let input_remaining = input.len() - i; copy_memory( - self.buffer[mut ..input_remaining], + self.buffer.slice_to_mut(input_remaining), input[i..]); self.buffer_idx += input_remaining; } @@ -176,13 +176,13 @@ impl FixedBuffer for FixedBuffer64 { fn zero_until(&mut self, idx: uint) { assert!(idx >= self.buffer_idx); - self.buffer[mut self.buffer_idx..idx].set_memory(0); + self.buffer.slice_mut(self.buffer_idx, idx).set_memory(0); self.buffer_idx = idx; } fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] { self.buffer_idx += len; - return self.buffer[mut self.buffer_idx - len..self.buffer_idx]; + return self.buffer.slice_mut(self.buffer_idx - len, self.buffer_idx); } fn full_buffer<'s>(&'s mut self) -> &'s [u8] { @@ -362,7 +362,7 @@ impl Engine256State { ) ); - read_u32v_be(w[mut 0..16], data); + read_u32v_be(w.slice_mut(0, 16), data); // Putting the message schedule inside the same loop as the round calculations allows for // the compiler to generate better code. @@ -498,14 +498,14 @@ impl Digest for Sha256 { fn result(&mut self, out: &mut [u8]) { self.engine.finish(); - write_u32_be(out[mut 0..4], self.engine.state.h0); - write_u32_be(out[mut 4..8], self.engine.state.h1); - write_u32_be(out[mut 8..12], self.engine.state.h2); - write_u32_be(out[mut 12..16], self.engine.state.h3); - write_u32_be(out[mut 16..20], self.engine.state.h4); - write_u32_be(out[mut 20..24], self.engine.state.h5); - write_u32_be(out[mut 24..28], self.engine.state.h6); - write_u32_be(out[mut 28..32], self.engine.state.h7); + write_u32_be(out.slice_mut(0, 4), self.engine.state.h0); + write_u32_be(out.slice_mut(4, 8), self.engine.state.h1); + write_u32_be(out.slice_mut(8, 12), self.engine.state.h2); + write_u32_be(out.slice_mut(12, 16), self.engine.state.h3); + write_u32_be(out.slice_mut(16, 20), self.engine.state.h4); + write_u32_be(out.slice_mut(20, 24), self.engine.state.h5); + write_u32_be(out.slice_mut(24, 28), self.engine.state.h6); + write_u32_be(out.slice_mut(28, 32), self.engine.state.h7); } fn reset(&mut self) { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index c26450310a9b2..fdbce101c1d6c 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -104,7 +104,7 @@ impl BufferedReader { impl Buffer for BufferedReader { fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { if self.pos == self.cap { - self.cap = try!(self.inner.read(self.buf[mut])); + self.cap = try!(self.inner.read(self.buf.as_mut_slice())); self.pos = 0; } Ok(self.buf[self.pos..self.cap]) @@ -219,7 +219,7 @@ impl Writer for BufferedWriter { if buf.len() > self.buf.len() { self.inner.as_mut().unwrap().write(buf) } else { - let dst = self.buf[mut self.pos..]; + let dst = self.buf.slice_from_mut(self.pos); slice::bytes::copy_memory(dst, buf); self.pos += buf.len(); Ok(()) diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 3a18b0dc1b525..5f68bbef93220 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -87,7 +87,7 @@ impl Reader for ChanReader { loop { let count = match self.fill_buf().ok() { Some(src) => { - let dst = buf[mut num_read..]; + let dst = buf.slice_from_mut(num_read); let count = cmp::min(src.len(), dst.len()); bytes::copy_memory(dst, src[..count]); count diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 4e736908c3720..f2db2875ebf2c 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -931,11 +931,11 @@ mod test { { let mut read_stream = File::open_mode(filename, Open, Read); { - let read_buf = read_mem[mut 0..4]; + let read_buf = read_mem.slice_mut(0, 4); check!(read_stream.read(read_buf)); } { - let read_buf = read_mem[mut 4..8]; + let read_buf = read_mem.slice_mut(4, 8); check!(read_stream.read(read_buf)); } } diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 01151059530f0..20b1162d859c7 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -169,7 +169,7 @@ impl Reader for MemReader { let write_len = min(buf.len(), self.buf.len() - self.pos); { let input = self.buf[self.pos.. self.pos + write_len]; - let output = buf[mut ..write_len]; + let output = buf.slice_to_mut(write_len); assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); } @@ -214,7 +214,7 @@ impl<'a> Reader for &'a [u8] { let write_len = min(buf.len(), self.len()); { let input = self[..write_len]; - let output = buf[mut ..write_len]; + let output = buf.slice_to_mut(write_len); slice::bytes::copy_memory(output, input); } @@ -279,7 +279,7 @@ impl<'a> BufWriter<'a> { impl<'a> Writer for BufWriter<'a> { #[inline] fn write(&mut self, src: &[u8]) -> IoResult<()> { - let dst = self.buf[mut self.pos..]; + let dst = self.buf.slice_from_mut(self.pos); let dst_len = dst.len(); if dst_len == 0 { @@ -359,7 +359,7 @@ impl<'a> Reader for BufReader<'a> { let write_len = min(buf.len(), self.buf.len() - self.pos); { let input = self.buf[self.pos.. self.pos + write_len]; - let output = buf[mut ..write_len]; + let output = buf.slice_to_mut(write_len); assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); } @@ -652,7 +652,7 @@ mod test { assert!(r.read_at_least(buf.len(), &mut buf).is_ok()); let b: &[_] = &[1, 2, 3]; assert_eq!(buf, b); - assert!(r.read_at_least(0, buf[mut ..0]).is_ok()); + assert!(r.read_at_least(0, buf.slice_to_mut(0)).is_ok()); assert_eq!(buf, b); assert!(r.read_at_least(buf.len(), &mut buf).is_ok()); let b: &[_] = &[4, 5, 6]; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b6f8bb25b6531..e1f5efae79fc7 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -513,7 +513,7 @@ pub trait Reader { while read < min { let mut zeroes = 0; loop { - match self.read(buf[mut read..]) { + match self.read(buf.slice_from_mut(read)) { Ok(0) => { zeroes += 1; if zeroes >= NO_PROGRESS_LIMIT { @@ -1123,7 +1123,7 @@ pub trait Writer { #[inline] fn write_char(&mut self, c: char) -> IoResult<()> { let mut buf = [0u8, ..4]; - let n = c.encode_utf8(buf[mut]).unwrap_or(0); + let n = c.encode_utf8(buf.as_mut_slice()).unwrap_or(0); self.write(buf[..n]) } @@ -1555,7 +1555,7 @@ pub trait Buffer: Reader { { let mut start = 1; while start < width { - match try!(self.read(buf[mut start..width])) { + match try!(self.read(buf.slice_mut(start, width))) { n if n == width - start => break, n if n < width - start => { start += n; } _ => return Err(standard_error(InvalidInput)), diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index add986387daf7..4830b15a8432e 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -250,7 +250,7 @@ impl<'a> Parser<'a> { assert!(head.len() + tail.len() <= 8); let mut gs = [0u16, ..8]; gs.clone_from_slice(head); - gs[mut 8 - tail.len() .. 8].clone_from_slice(tail); + gs.slice_mut(8 - tail.len(), 8).clone_from_slice(tail); Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) } diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index a36703172c3ca..5bf47dceb5a0e 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -49,7 +49,7 @@ use sys_common; /// match socket.recv_from(&mut buf) { /// Ok((amt, src)) => { /// // Send a reply to the socket we received data from -/// let buf = buf[mut ..amt]; +/// let buf = buf.slice_to_mut(amt); /// buf.reverse(); /// socket.send_to(buf, src); /// } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 18fabcbd1a2a4..43893ca012653 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -51,7 +51,7 @@ impl Reader for LimitReader { } let len = cmp::min(self.limit, buf.len()); - let res = self.inner.read(buf[mut ..len]); + let res = self.inner.read(buf.slice_to_mut(len)); match res { Ok(len) => self.limit -= len, _ => {} diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 68c99b1275855..46c3a4f622a54 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -55,7 +55,7 @@ mod imp { let mut read = 0; let len = v.len(); while read < len { - let result = getrandom(v[mut read..]); + let result = getrandom(v.slice_from_mut(read)); if result == -1 { let err = errno() as libc::c_int; if err == libc::EINTR { diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 26dadfd9fb1db..6b007056a5114 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -139,7 +139,7 @@ fn abort_(args: &fmt::Arguments) -> ! { } impl<'a> FormatWriter for BufWriter<'a> { fn write(&mut self, bytes: &[u8]) -> fmt::Result { - let left = self.buf[mut self.pos..]; + let left = self.buf.slice_from_mut(self.pos); let to_write = bytes[..cmp::min(bytes.len(), left.len())]; slice::bytes::copy_memory(left, to_write); self.pos += to_write.len(); diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index 723b2b722d7e1..ef38f5ef74341 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -52,7 +52,7 @@ fn rotate(x: &mut [i32]) { fn next_permutation(perm: &mut [i32], count: &mut [i32]) { for i in range(1, perm.len()) { - rotate(perm[mut ..i + 1]); + rotate(perm.slice_to_mut(i + 1)); let count_i = &mut count[i]; if *count_i >= i as i32 { *count_i = 0; @@ -131,7 +131,7 @@ impl Perm { fn reverse(tperm: &mut [i32], mut k: uint) { - tperm[mut ..k].reverse() + tperm.slice_to_mut(k).reverse() } fn work(mut perm: Perm, n: uint, max: uint) -> (i32, i32) { diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index eb18cfdaed3ad..178d6777939d8 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -128,7 +128,7 @@ impl<'a, W: Writer> RepeatFasta<'a, W> { copy_memory(buf.as_mut_slice(), alu); let buf_len = buf.len(); - copy_memory(buf[mut alu_len..buf_len], + copy_memory(buf.slice_mut(alu_len, buf_len), alu[..LINE_LEN]); let mut pos = 0; diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 66965110f73ee..6ee2233f16862 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -254,6 +254,6 @@ fn parallel<'a, I, T, F>(mut iter: I, f: F) fn main() { let mut data = read_to_end(&mut stdin_raw()).unwrap(); let tables = &Tables::new(); - parallel(mut_dna_seqs(data[mut]), |&: seq| reverse_complement(seq, tables)); + parallel(mut_dna_seqs(data.as_mut_slice()), |&: seq| reverse_complement(seq, tables)); stdout_raw().write(data.as_mut_slice()).unwrap(); } diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index ca7401dc26c8c..4af748661fd12 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -9,6 +9,7 @@ // except according to those terms. // Test range syntax - type errors. +#![feature(slicing_syntax)] pub fn main() { // Mixed types. diff --git a/src/test/compile-fail/range-2.rs b/src/test/compile-fail/range-2.rs index 40690bd844bce..74c304884a07c 100644 --- a/src/test/compile-fail/range-2.rs +++ b/src/test/compile-fail/range-2.rs @@ -9,6 +9,7 @@ // except according to those terms. // Test range syntax - borrow errors. +#![feature(slicing_syntax)] pub fn main() { let r = { diff --git a/src/test/compile-fail/slice-2.rs b/src/test/compile-fail/slice-2.rs index 63f79c808ae22..24f710d2ae3f4 100644 --- a/src/test/compile-fail/slice-2.rs +++ b/src/test/compile-fail/slice-2.rs @@ -20,8 +20,4 @@ fn main() { x[Foo..]; //~ ERROR cannot take a slice of a value with type `Foo` x[..Foo]; //~ ERROR cannot take a slice of a value with type `Foo` x[Foo..Foo]; //~ ERROR cannot take a slice of a value with type `Foo` - x[mut]; //~ ERROR cannot take a mutable slice of a value with type `Foo` - x[mut Foo..]; //~ ERROR cannot take a mutable slice of a value with type `Foo` - x[mut ..Foo]; //~ ERROR cannot take a mutable slice of a value with type `Foo` - x[mut Foo..Foo]; //~ ERROR cannot take a mutable slice of a value with type `Foo` } diff --git a/src/test/compile-fail/slice-mut-2.rs b/src/test/compile-fail/slice-mut-2.rs index 6778ed88ff70b..8970bcfd153a1 100644 --- a/src/test/compile-fail/slice-mut-2.rs +++ b/src/test/compile-fail/slice-mut-2.rs @@ -15,5 +15,6 @@ fn main() { let x: &[int] = &[1, 2, 3, 4, 5]; // Can't mutably slice an immutable slice - let y = x[mut 2..4]; //~ ERROR cannot borrow + let slice: &mut [int] = &mut [0, 1]; + x[2..4] = slice; //~ ERROR cannot borrow } diff --git a/src/test/compile-fail/slice-mut.rs b/src/test/compile-fail/slice-mut.rs index cbfa3ed85fd6c..ad6b384d74701 100644 --- a/src/test/compile-fail/slice-mut.rs +++ b/src/test/compile-fail/slice-mut.rs @@ -16,9 +16,4 @@ fn main() { let x: &[int] = &[1, 2, 3, 4, 5]; // Immutable slices are not mutable. let y: &mut[_] = x[2..4]; //~ ERROR cannot borrow immutable dereference of `&`-pointer as mutabl - - let x: &mut [int] = &mut [1, 2, 3, 4, 5]; - // Can't borrow mutably twice - let y = x[mut 1..2]; - let y = x[mut 4..5]; //~ERROR cannot borrow } diff --git a/src/test/run-pass/range.rs b/src/test/run-pass/range.rs index 027121dd4229d..864cee03f24da 100644 --- a/src/test/run-pass/range.rs +++ b/src/test/run-pass/range.rs @@ -10,6 +10,8 @@ // Test range syntax. +#![feature(slicing_syntax)] + fn foo() -> int { 42 } pub fn main() { From 113f8aa86b64c0be1981a69d110e42d22460b33c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 23 Dec 2014 16:23:11 +1300 Subject: [PATCH 4/4] Rebasing and reviewer changes --- src/libcollections/ring_buf.rs | 2 +- src/libgraphviz/lib.rs | 4 +- src/librustc/middle/mem_categorization.rs | 3 +- src/librustc_trans/trans/expr.rs | 8 +-- src/librustc_typeck/check/mod.rs | 72 ++++++++++++----------- src/libunicode/u_str.rs | 2 +- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 2715ff0678af7..df8e08f07a321 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -453,7 +453,7 @@ impl RingBuf { if contiguous { let (empty, buf) = buf.split_at_mut(0); - (buf[mut tail..head], empty) + (buf.slice_mut(tail, head), empty) } else { let (mid, right) = buf.split_at_mut(tail); let (left, _) = mid.split_at_mut(head); diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index ce3df1090bd58..7dd0649e4837d 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -735,7 +735,7 @@ mod tests { fn test_input(g: LabelledGraph) -> IoResult { let mut writer = Vec::new(); render(&g, &mut writer).unwrap(); - (&mut writer[]).read_to_string() + (&mut writer.as_slice()).read_to_string() } // All of the tests use raw-strings as the format for the expected outputs, @@ -847,7 +847,7 @@ r#"digraph hasse_diagram { edge(1, 3, ";"), edge(2, 3, ";" ))); render(&g, &mut writer).unwrap(); - let r = (&mut writer[]).read_to_string(); + let r = (&mut writer.as_slice()).read_to_string(); assert_eq!(r.unwrap(), r#"digraph syntax_tree { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b48e41ceb7358..5d3134b9629b2 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -519,8 +519,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ret_ty), 1, true) } None => { - let base_cmt = if_ok!(self.cat_expr(&**base)); - self.cat_index(expr, base_cmt) + self.cat_index(expr, self.cat_expr(&**base)) } } } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index c88a1b5e18736..f49769ba0d9c6 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1074,18 +1074,18 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let (did, fields, ty_params) = match (start, end) { (&Some(ref start), &Some(ref end)) => { // Desugar to Range - let fields = vec!(make_field("start", start.clone()), - make_field("end", end.clone())); + let fields = vec![make_field("start", start.clone()), + make_field("end", end.clone())]; (tcx.lang_items.range_struct(), fields, vec![node_id_type(bcx, start.id)]) } (&Some(ref start), &None) => { // Desugar to RangeFrom - let fields = vec!(make_field("start", start.clone())); + let fields = vec![make_field("start", start.clone())]; (tcx.lang_items.range_from_struct(), fields, vec![node_id_type(bcx, start.id)]) } (&None, &Some(ref end)) => { // Desugar to RangeTo - let fields = vec!(make_field("end", end.clone())); + let fields = vec![make_field("end", end.clone())]; (tcx.lang_items.range_to_struct(), fields, vec![node_id_type(bcx, end.id)]) } _ => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9ae42fed07f73..fb23ad8e340ce 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4183,9 +4183,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // A slice, rather than an index. Special cased for now (KILLME). let base_t = structurally_resolved_type(fcx, expr.span, base_t); - if lvalue_pref == PreferMutLvalue { - println!("mutable lvalue_pref"); - } let result = autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| { try_overloaded_slice_step(fcx, @@ -4299,42 +4296,49 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // 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. - let range_type = if idx_type == Some(ty::mk_err()) { - ty::mk_err() - } else if idx_type.is_none() { - // Neither start nor end => FullRange - if let Some(did) = tcx.lang_items.full_range_struct() { - let substs = Substs::new_type(vec![], vec![]); - ty::mk_struct(tcx, did, substs) - } else { + let range_type = match idx_type { + Some(idx_type) if ty::type_is_error(idx_type) => { ty::mk_err() } - } else { - // Find the did from the appropriate lang item. - let did = match (start, end) { - (&Some(_), &Some(_)) => tcx.lang_items.range_struct(), - (&Some(_), &None) => tcx.lang_items.range_from_struct(), - (&None, &Some(_)) => tcx.lang_items.range_to_struct(), - (&None, &None) => { - tcx.sess.span_bug(expr.span,"full range should be dealt with above") - } - }; + Some(idx_type) => { + // Find the did from the appropriate lang item. + let did = match (start, end) { + (&Some(_), &Some(_)) => tcx.lang_items.range_struct(), + (&Some(_), &None) => tcx.lang_items.range_from_struct(), + (&None, &Some(_)) => tcx.lang_items.range_to_struct(), + (&None, &None) => { + tcx.sess.span_bug(expr.span, "full range should be dealt with above") + } + }; - if let Some(did) = did { - let polytype = ty::lookup_item_type(tcx, did); - let substs = Substs::new_type(vec![idx_type.unwrap()], vec![]); - let bounds = polytype.generics.to_bounds(tcx, &substs); - fcx.add_obligations_for_parameters( - traits::ObligationCause::new(expr.span, - fcx.body_id, - traits::ItemObligation(did)), - &bounds); - - ty::mk_struct(tcx, did, tcx.mk_substs(substs)) - } else { - ty::mk_err() + if let Some(did) = did { + let polytype = ty::lookup_item_type(tcx, did); + let substs = Substs::new_type(vec![idx_type], vec![]); + let bounds = polytype.generics.to_bounds(tcx, &substs); + fcx.add_obligations_for_parameters( + traits::ObligationCause::new(expr.span, + fcx.body_id, + traits::ItemObligation(did)), + &bounds); + + ty::mk_struct(tcx, did, tcx.mk_substs(substs)) + } else { + tcx.sess.span_err(expr.span, "No lang item for range syntax"); + ty::mk_err() + } + } + None => { + // Neither start nor end => FullRange + if let Some(did) = tcx.lang_items.full_range_struct() { + let substs = Substs::new_type(vec![], vec![]); + ty::mk_struct(tcx, did, tcx.mk_substs(substs)) + } else { + tcx.sess.span_err(expr.span, "No lang item for range syntax"); + ty::mk_err() + } } }; + fcx.write_ty(id, range_type); } diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 3b0cc1443f0c7..398728bb51652 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -521,7 +521,7 @@ impl Iterator for Utf16Encoder where I: Iterator { let mut buf = [0u16, ..2]; self.chars.next().map(|ch| { - let n = ch.encode_utf16(buf[mut]).unwrap_or(0); + let n = ch.encode_utf16(buf.as_mut_slice()).unwrap_or(0); if n == 2 { self.extra = buf[1]; } buf[0] })