}
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);
}
}
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;
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))
}
}
}
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
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)
}
}
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;
// 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()
.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)));
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>`
}
}
-/// 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
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,
};
// 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))
})
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);
- }
- }
- }
- }
}
}
}
};
// 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 {
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;
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>>)
}
// 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)
}
}
(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");
}
}