Remove old slicing hacks and make new slicing work
This commit is contained in:
parent
f7ff37e4c5
commit
e970db37a9
@ -441,28 +441,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||
}
|
||||
|
||||
ast::ExprIndex(ref lhs, ref rhs) => { // lhs[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);
|
||||
}
|
||||
}
|
||||
if !self.walk_overloaded_operator(expr,
|
||||
&**lhs,
|
||||
vec![&**rhs],
|
||||
PassArgs::ByRef) {
|
||||
self.select_from_expr(&**lhs);
|
||||
self.consume_expr(&**rhs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,8 +266,6 @@ lets_do_this! {
|
||||
ShrTraitLangItem, "shr", shr_trait;
|
||||
IndexTraitLangItem, "index", index_trait;
|
||||
IndexMutTraitLangItem, "index_mut", index_mut_trait;
|
||||
SliceTraitLangItem, "slice", slice_trait;
|
||||
SliceMutTraitLangItem, "slice_mut", slice_mut_trait;
|
||||
RangeStructLangItem, "range", range_struct;
|
||||
RangeFromStructLangItem, "range_from", range_from_struct;
|
||||
RangeToStructLangItem, "range_to", range_to_struct;
|
||||
|
@ -482,28 +482,20 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
|
||||
}
|
||||
|
||||
ast::ExprIndex(ref base, ref idx) => {
|
||||
match idx.node {
|
||||
ast::ExprRange(..) => {
|
||||
// Slicing syntax special case (KILLME).
|
||||
Ok(self.cat_rvalue_node(expr.id(), expr.span(), 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)
|
||||
}
|
||||
_ => {
|
||||
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 => {
|
||||
self.cat_index(expr, try!(self.cat_expr(&**base)))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.cat_index(expr, self.cat_expr(&**base))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1047,7 +1047,7 @@ pub struct ClosureTy<'tcx> {
|
||||
pub abi: abi::Abi,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Show)]
|
||||
pub enum FnOutput<'tcx> {
|
||||
FnConverging(Ty<'tcx>),
|
||||
FnDiverging
|
||||
@ -1699,8 +1699,7 @@ impl fmt::Show for RegionVid {
|
||||
|
||||
impl<'tcx> fmt::Show for FnSig<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// grr, without tcx not much we can do.
|
||||
write!(f, "(...)")
|
||||
write!(f, "({}; variadic: {})->{}", self.inputs, self.variadic, self.output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,7 @@ use trans::common;
|
||||
use trans::common::{Block, FunctionContext, ExprId, NodeInfo};
|
||||
use trans::debuginfo;
|
||||
use trans::glue;
|
||||
// Temporary due to slicing syntax hacks (KILLME)
|
||||
//use middle::region;
|
||||
use middle::region;
|
||||
use trans::type_::Type;
|
||||
use middle::ty::{self, Ty};
|
||||
use std::fmt;
|
||||
@ -129,8 +128,7 @@ 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.
|
||||
// Temporarily removed due to slicing syntax hacks (KILLME).
|
||||
/*let top_scope = self.top_ast_scope();
|
||||
let top_scope = self.top_ast_scope();
|
||||
if top_scope.is_some() {
|
||||
assert_eq!(self.ccx
|
||||
.tcx()
|
||||
@ -138,7 +136,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)));
|
||||
|
@ -573,40 +573,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
trans_rec_tup_field(bcx, &**base, idx.node)
|
||||
}
|
||||
ast::ExprIndex(ref base, ref idx) => {
|
||||
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))
|
||||
}
|
||||
trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
|
||||
}
|
||||
ast::ExprBox(_, ref contents) => {
|
||||
// Special case for `Box<T>`
|
||||
|
@ -2377,90 +2377,6 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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).
|
||||
fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
method_call: MethodCall,
|
||||
expr: &ast::Expr,
|
||||
base_expr: &ast::Expr,
|
||||
base_ty: Ty<'tcx>, // autoderef'd type
|
||||
autoderefref: ty::AutoDerefRef<'tcx>,
|
||||
lvalue_pref: LvaluePreference,
|
||||
start_expr: &Option<P<ast::Expr>>,
|
||||
end_expr: &Option<P<ast::Expr>>)
|
||||
-> Option<(Ty<'tcx>, /* index type */
|
||||
Ty<'tcx>)> /* return type */
|
||||
{
|
||||
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) => {
|
||||
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,
|
||||
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,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If some lookup succeeded, install method in table
|
||||
method.map(|method| {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
/// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
|
||||
/// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
|
||||
/// This loop implements one step in that search; the autoderef loop is implemented by
|
||||
@ -2474,26 +2390,17 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
lvalue_pref: LvaluePreference)
|
||||
-> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
|
||||
{
|
||||
let tcx = fcx.tcx();
|
||||
debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={})",
|
||||
expr.repr(fcx.tcx()),
|
||||
base_expr.repr(fcx.tcx()),
|
||||
adjusted_ty.repr(fcx.tcx()),
|
||||
expr.repr(tcx),
|
||||
base_expr.repr(tcx),
|
||||
adjusted_ty.repr(tcx),
|
||||
adjustment);
|
||||
|
||||
// Try built-in indexing first.
|
||||
match ty::index(adjusted_ty) {
|
||||
Some(ty) => {
|
||||
fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
|
||||
return Some((fcx.tcx().types.uint, ty));
|
||||
}
|
||||
|
||||
None => { }
|
||||
}
|
||||
|
||||
let input_ty = fcx.infcx().next_ty_var();
|
||||
|
||||
// Try `IndexMut` first, if preferred.
|
||||
let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
|
||||
let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
|
||||
(PreferMutLvalue, Some(trait_did)) => {
|
||||
method::lookup_in_trait_adjusted(fcx,
|
||||
expr.span,
|
||||
@ -2508,24 +2415,37 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
};
|
||||
|
||||
// Otherwise, fall back to `Index`.
|
||||
let method = match (method, fcx.tcx().lang_items.index_trait()) {
|
||||
let method = match (method, tcx.lang_items.index_trait()) {
|
||||
(None, Some(trait_did)) => {
|
||||
method::lookup_in_trait_adjusted(fcx,
|
||||
expr.span,
|
||||
Some(&*base_expr),
|
||||
token::intern("index"),
|
||||
trait_did,
|
||||
adjustment,
|
||||
adjustment.clone(),
|
||||
adjusted_ty,
|
||||
Some(vec![input_ty]))
|
||||
}
|
||||
(method, _) => method,
|
||||
};
|
||||
|
||||
if method.is_none() {
|
||||
// If there are no overridden index impls, use built-in indexing.
|
||||
match ty::index(adjusted_ty) {
|
||||
Some(ty) => {
|
||||
debug!("try_index_step: success, using built-in indexing");
|
||||
fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
|
||||
return Some((tcx.types.uint, ty));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
// If some lookup succeeds, write callee into table and extract index/element
|
||||
// type from the method signature.
|
||||
// If some lookup succeeded, install method in table
|
||||
method.and_then(|method| {
|
||||
debug!("try_index_step: success, using overloaded indexing");
|
||||
make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
|
||||
map(|ret| (input_ty, ret.ty))
|
||||
})
|
||||
@ -4270,91 +4190,42 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
if ty::type_is_error(base_t) {
|
||||
fcx.write_ty(id, base_t);
|
||||
} else {
|
||||
match idx.node {
|
||||
ast::ExprRange(ref start, ref end) => {
|
||||
// A slice, rather than an index. Special cased for now (KILLME).
|
||||
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_overloaded_slice_step(fcx,
|
||||
MethodCall::expr(expr.id),
|
||||
expr,
|
||||
&**base,
|
||||
adj_ty,
|
||||
adj,
|
||||
lvalue_pref,
|
||||
start,
|
||||
end)
|
||||
try_index_step(fcx,
|
||||
MethodCall::expr(expr.id),
|
||||
expr,
|
||||
&**base,
|
||||
adj_ty,
|
||||
adj,
|
||||
lvalue_pref)
|
||||
});
|
||||
|
||||
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)
|
||||
check_expr_has_type(fcx, &**idx, index_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 `{}`",
|
||||
check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
format!("cannot index a value of type `{}`",
|
||||
actual)
|
||||
},
|
||||
base_t,
|
||||
None);
|
||||
fcx.write_ty(idx.id, fcx.tcx().types.err);
|
||||
},
|
||||
base_t,
|
||||
None);
|
||||
fcx.write_ty(id, fcx.tcx().types.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, fcx.tcx().types.err);
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
format!("cannot index a value of type `{}`",
|
||||
actual)
|
||||
},
|
||||
base_t,
|
||||
None);
|
||||
fcx.write_ty(id, fcx.tcx().types.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4387,7 +4258,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
};
|
||||
|
||||
// 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
|
||||
// bounds because right now 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 = match idx_type {
|
||||
|
@ -63,7 +63,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use ast::{Visibility, WhereClause};
|
||||
use ast;
|
||||
use ast_util::{self, as_prec, ident_to_path, operator_prec};
|
||||
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, DUMMY_SP};
|
||||
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp};
|
||||
use diagnostic;
|
||||
use ext::tt::macro_parser;
|
||||
use parse;
|
||||
@ -2103,22 +2103,6 @@ impl<'a> Parser<'a> {
|
||||
ExprIndex(expr, idx)
|
||||
}
|
||||
|
||||
pub fn mk_slice(&mut self,
|
||||
expr: P<Expr>,
|
||||
start: Option<P<Expr>>,
|
||||
end: Option<P<Expr>>,
|
||||
_mutbl: Mutability)
|
||||
-> ast::Expr_ {
|
||||
// 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,
|
||||
start: Option<P<Expr>>,
|
||||
end: Option<P<Expr>>)
|
||||
@ -2550,87 +2534,28 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// expr[...]
|
||||
// Could be either an index expression or a slicing expression.
|
||||
// Any slicing non-terminal can have a mutable version with `mut`
|
||||
// after the opening square bracket.
|
||||
// An index expression.
|
||||
token::OpenDelim(token::Bracket) => {
|
||||
let bracket_pos = self.span.lo;
|
||||
self.bump();
|
||||
let mutbl = if self.eat_keyword(keywords::Mut) {
|
||||
MutMutable
|
||||
if self.eat(&token::CloseDelim(token::Bracket)) {
|
||||
// No expression, expand to a FullRange
|
||||
let ix = {
|
||||
hi = self.last_span.hi;
|
||||
let range = ExprStruct(ident_to_path(mk_sp(lo, hi),
|
||||
token::special_idents::FullRange),
|
||||
vec![],
|
||||
None);
|
||||
self.mk_expr(bracket_pos, hi, range)
|
||||
};
|
||||
let index = self.mk_index(e, ix);
|
||||
e = self.mk_expr(lo, hi, index)
|
||||
} else {
|
||||
MutImmutable
|
||||
};
|
||||
match self.token {
|
||||
// e.index(&FullRange)
|
||||
token::CloseDelim(token::Bracket) => {
|
||||
self.bump();
|
||||
hi = self.span.hi;
|
||||
let slice = self.mk_slice(e, None, None, mutbl);
|
||||
e = self.mk_expr(lo, hi, slice)
|
||||
}
|
||||
// e.index(&(0..e))
|
||||
token::DotDot => {
|
||||
self.bump();
|
||||
match self.token {
|
||||
// e.index(&(..))
|
||||
token::CloseDelim(token::Bracket) => {
|
||||
self.bump();
|
||||
hi = self.span.hi;
|
||||
let slice = self.mk_slice(e, None, None, mutbl);
|
||||
e = self.mk_expr(lo, hi, slice);
|
||||
|
||||
self.span_err(e.span, "incorrect slicing expression: `[..]`");
|
||||
self.span_note(e.span,
|
||||
"use `expr.index(&FullRange)` to construct a slice of the whole of expr");
|
||||
}
|
||||
// e.index(&(0..e))
|
||||
_ => {
|
||||
hi = self.span.hi;
|
||||
let e2 = self.parse_expr();
|
||||
self.commit_expr_expecting(&*e2, token::CloseDelim(token::Bracket));
|
||||
let slice = self.mk_slice(e, None, Some(e2), mutbl);
|
||||
e = self.mk_expr(lo, hi, slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
// e[e] | e.index(&(e..)) | e.index(&(e..e))
|
||||
_ => {
|
||||
let ix = self.parse_expr_res(RESTRICTION_NO_DOTS);
|
||||
match self.token {
|
||||
// e.index(&(e..)) | e.index(&(e..e))
|
||||
token::DotDot => {
|
||||
self.bump();
|
||||
let e2 = match self.token {
|
||||
// e.index(&(e..))
|
||||
token::CloseDelim(token::Bracket) => {
|
||||
self.bump();
|
||||
None
|
||||
}
|
||||
// e.index(&(e..e))
|
||||
_ => {
|
||||
let e2 = self.parse_expr_res(RESTRICTION_NO_DOTS);
|
||||
self.commit_expr_expecting(&*e2,
|
||||
token::CloseDelim(token::Bracket));
|
||||
Some(e2)
|
||||
}
|
||||
};
|
||||
hi = self.span.hi;
|
||||
let slice = self.mk_slice(e, Some(ix), e2, mutbl);
|
||||
e = self.mk_expr(lo, hi, slice)
|
||||
}
|
||||
// e[e]
|
||||
_ => {
|
||||
if mutbl == ast::MutMutable {
|
||||
self.span_err(e.span,
|
||||
"`mut` keyword is invalid in index expressions");
|
||||
}
|
||||
hi = self.span.hi;
|
||||
self.commit_expr_expecting(&*ix, token::CloseDelim(token::Bracket));
|
||||
let index = self.mk_index(e, ix);
|
||||
e = self.mk_expr(lo, hi, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
let ix = self.parse_expr();
|
||||
hi = self.span.hi;
|
||||
self.commit_expr_expecting(&*ix, token::CloseDelim(token::Bracket));
|
||||
let index = self.mk_index(e, ix);
|
||||
e = self.mk_expr(lo, hi, index)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,66 +515,66 @@ declare_special_idents_and_keywords! {
|
||||
(9, unnamed_field, "<unnamed_field>");
|
||||
(10, type_self, "Self");
|
||||
(11, prelude_import, "prelude_import");
|
||||
(12, FullRange, "FullRange");
|
||||
}
|
||||
|
||||
pub mod keywords {
|
||||
// These ones are variants of the Keyword enum
|
||||
|
||||
'strict:
|
||||
(12, As, "as");
|
||||
(13, Break, "break");
|
||||
(14, Crate, "crate");
|
||||
(15, Else, "else");
|
||||
(16, Enum, "enum");
|
||||
(17, Extern, "extern");
|
||||
(18, False, "false");
|
||||
(19, Fn, "fn");
|
||||
(20, For, "for");
|
||||
(21, If, "if");
|
||||
(22, Impl, "impl");
|
||||
(23, In, "in");
|
||||
(24, Let, "let");
|
||||
(25, Loop, "loop");
|
||||
(26, Match, "match");
|
||||
(27, Mod, "mod");
|
||||
(28, Move, "move");
|
||||
(29, Mut, "mut");
|
||||
(30, Pub, "pub");
|
||||
(31, Ref, "ref");
|
||||
(32, Return, "return");
|
||||
(13, As, "as");
|
||||
(14, Break, "break");
|
||||
(15, Crate, "crate");
|
||||
(16, Else, "else");
|
||||
(17, Enum, "enum");
|
||||
(18, Extern, "extern");
|
||||
(19, False, "false");
|
||||
(20, Fn, "fn");
|
||||
(21, For, "for");
|
||||
(22, If, "if");
|
||||
(23, Impl, "impl");
|
||||
(24, In, "in");
|
||||
(25, Let, "let");
|
||||
(26, Loop, "loop");
|
||||
(27, Match, "match");
|
||||
(28, Mod, "mod");
|
||||
(29, Move, "move");
|
||||
(30, Mut, "mut");
|
||||
(31, Pub, "pub");
|
||||
(32, Ref, "ref");
|
||||
(33, Return, "return");
|
||||
// Static and Self are also special idents (prefill de-dupes)
|
||||
(super::STATIC_KEYWORD_NAME_NUM, Static, "static");
|
||||
(super::SELF_KEYWORD_NAME_NUM, Self, "self");
|
||||
(33, Struct, "struct");
|
||||
(34, Struct, "struct");
|
||||
(super::SUPER_KEYWORD_NAME_NUM, Super, "super");
|
||||
(34, True, "true");
|
||||
(35, Trait, "trait");
|
||||
(36, Type, "type");
|
||||
(37, Unsafe, "unsafe");
|
||||
(38, Use, "use");
|
||||
(39, Virtual, "virtual");
|
||||
(40, While, "while");
|
||||
(41, Continue, "continue");
|
||||
(42, Proc, "proc");
|
||||
(43, Box, "box");
|
||||
(44, Const, "const");
|
||||
(45, Where, "where");
|
||||
|
||||
(35, True, "true");
|
||||
(36, Trait, "trait");
|
||||
(37, Type, "type");
|
||||
(38, Unsafe, "unsafe");
|
||||
(39, Use, "use");
|
||||
(40, Virtual, "virtual");
|
||||
(41, While, "while");
|
||||
(42, Continue, "continue");
|
||||
(43, Proc, "proc");
|
||||
(44, Box, "box");
|
||||
(45, Const, "const");
|
||||
(46, Where, "where");
|
||||
'reserved:
|
||||
(46, Alignof, "alignof");
|
||||
(47, Be, "be");
|
||||
(48, Offsetof, "offsetof");
|
||||
(49, Priv, "priv");
|
||||
(50, Pure, "pure");
|
||||
(51, Sizeof, "sizeof");
|
||||
(52, Typeof, "typeof");
|
||||
(53, Unsized, "unsized");
|
||||
(54, Yield, "yield");
|
||||
(55, Do, "do");
|
||||
(56, Abstract, "abstract");
|
||||
(57, Final, "final");
|
||||
(58, Override, "override");
|
||||
(59, Macro, "macro");
|
||||
(47, Alignof, "alignof");
|
||||
(48, Be, "be");
|
||||
(49, Offsetof, "offsetof");
|
||||
(50, Priv, "priv");
|
||||
(51, Pure, "pure");
|
||||
(52, Sizeof, "sizeof");
|
||||
(53, Typeof, "typeof");
|
||||
(54, Unsized, "unsized");
|
||||
(55, Yield, "yield");
|
||||
(56, Do, "do");
|
||||
(57, Abstract, "abstract");
|
||||
(58, Final, "final");
|
||||
(59, Override, "override");
|
||||
(60, Macro, "macro");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user