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.
This commit is contained in:
parent
ed8f503911
commit
4e2afb0052
18 changed files with 244 additions and 309 deletions
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -431,13 +431,9 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprSlice(ref base, ref start, ref end, _) => { // base[start..end]
|
||||
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],
|
||||
|
@ -445,9 +441,20 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||
(&None, &None) => Vec::new()
|
||||
};
|
||||
let overloaded =
|
||||
self.walk_overloaded_operator(expr, &**base, args, PassArgs::ByRef);
|
||||
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::ExprRange(ref start, ref end) => {
|
||||
start.as_ref().map(|e| self.consume_expr(&**e));
|
||||
|
|
|
@ -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(..) => {
|
||||
|
|
|
@ -500,7 +500,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
|||
self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)
|
||||
}
|
||||
|
||||
ast::ExprIndex(ref base, _) => {
|
||||
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)
|
||||
}
|
||||
_ => {
|
||||
let method_call = ty::MethodCall::expr(expr.id());
|
||||
match self.typer.node_method_ty(method_call) {
|
||||
Some(method_ty) => {
|
||||
|
@ -513,11 +519,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
|||
ret_ty), 1, true)
|
||||
}
|
||||
None => {
|
||||
let base_cmt = self.cat_expr(&**base);
|
||||
let base_cmt = if_ok!(self.cat_expr(&**base));
|
||||
self.cat_index(expr, base_cmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprPath(_) => {
|
||||
let def = (*self.tcx().def_map.borrow())[expr.id];
|
||||
|
@ -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(..) |
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -3539,12 +3539,6 @@ fn create_scope_map(cx: &CrateContext,
|
|||
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));
|
||||
|
|
|
@ -585,9 +585,9 @@ 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, _) => {
|
||||
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();
|
||||
|
||||
|
@ -603,7 +603,8 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
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 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,
|
||||
|
@ -616,6 +617,9 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
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>`
|
||||
let box_ty = expr_ty(bcx, expr);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,13 +2223,17 @@ 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 {
|
||||
let input_ty = fcx.infcx().next_ty_var();
|
||||
let return_ty = fcx.infcx().next_ty_var();
|
||||
|
||||
let method = match lvalue_pref {
|
||||
PreferMutLvalue => {
|
||||
// Try `SliceMut` first, if preferred.
|
||||
match fcx.tcx().lang_items.slice_mut_trait() {
|
||||
Some(trait_did) => {
|
||||
|
@ -2298,14 +2251,13 @@ fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
trait_did,
|
||||
autoderefref,
|
||||
base_ty,
|
||||
None)
|
||||
Some(vec![input_ty, return_ty]))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
}
|
||||
NoPreference => {
|
||||
// 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) {
|
||||
|
@ -2322,17 +2274,28 @@ fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
trait_did,
|
||||
autoderefref,
|
||||
base_ty,
|
||||
None)
|
||||
Some(vec![input_ty, return_ty]))
|
||||
}
|
||||
_ => 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,12 +4174,63 @@ 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) {
|
||||
} else {
|
||||
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);
|
||||
|
||||
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,
|
||||
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);
|
||||
|
@ -4252,58 +4266,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)) => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1739,31 +1739,13 @@ 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));
|
||||
}
|
||||
}
|
||||
if let &Some(ref e) = start {
|
||||
try!(self.print_expr(&**e));
|
||||
}
|
||||
if start.is_some() || end.is_some() {
|
||||
try!(word(&mut self.s, ".."));
|
||||
}
|
||||
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));
|
||||
}
|
||||
if start.is_some() || end.is_some() {
|
||||
try!(word(&mut self.s, ".."));
|
||||
}
|
||||
if let &Some(ref e) = end {
|
||||
try!(self.print_expr(&**e));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue