提交 e970db37 编写于 作者: N Nick Cameron

Remove old slicing hacks and make new slicing work

上级 f7ff37e4
......@@ -441,28 +441,12 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
}
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 @@ pub fn collect_language_items(krate: &ast::Crate,
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 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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::{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 @@ fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) {
// 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 @@ fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) {
.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_struct_fields_on_error(fcx: &FnCtxt,
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_struct_fields_on_error(fcx: &FnCtxt,
};
// 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::{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 @@ pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::Expr_ {
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 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P<Expr>) -> 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)
}
}
......
......@@ -515,66 +515,66 @@ pub mod special_idents {
(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");
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册