Autoref the argument to the index operator (#4920)
This commit is contained in:
parent
2c17ff7dbc
commit
069529bc5c
9 changed files with 88 additions and 49 deletions
|
|
@ -77,5 +77,5 @@ pub trait Shr<RHS,Result> {
|
|||
|
||||
#[lang="index"]
|
||||
pub trait Index<Index,Result> {
|
||||
fn index(&self, index: Index) -> Result;
|
||||
fn index(&self, index: &Index) -> Result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
|
|||
}
|
||||
|
||||
fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item {
|
||||
let chi_doc = par_doc[c::tag_tree as uint];
|
||||
let chi_doc = par_doc.get(c::tag_tree as uint);
|
||||
let d = &reader::Decoder(chi_doc);
|
||||
Decodable::decode(d)
|
||||
}
|
||||
|
|
@ -1089,9 +1089,9 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
|
|||
fn decode_side_tables(xcx: @ExtendedDecodeContext,
|
||||
ast_doc: ebml::Doc) {
|
||||
let dcx = xcx.dcx;
|
||||
let tbl_doc = ast_doc[c::tag_table as uint];
|
||||
let tbl_doc = ast_doc.get(c::tag_table as uint);
|
||||
for reader::docs(tbl_doc) |tag, entry_doc| {
|
||||
let id0 = entry_doc[c::tag_table_id as uint].as_int();
|
||||
let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
|
||||
let id = xcx.tr_id(id0);
|
||||
|
||||
debug!(">> Side table document with tag 0x%x \
|
||||
|
|
@ -1103,7 +1103,7 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
|
|||
} else if tag == (c::tag_table_moves_map as uint) {
|
||||
dcx.maps.moves_map.insert(id);
|
||||
} else {
|
||||
let val_doc = entry_doc[c::tag_table_val as uint];
|
||||
let val_doc = entry_doc.get(c::tag_table_val as uint);
|
||||
let val_dsr = &reader::Decoder(val_doc);
|
||||
if tag == (c::tag_table_def as uint) {
|
||||
let def = decode_def(xcx, val_doc);
|
||||
|
|
@ -1172,7 +1172,7 @@ fn encode_item_ast(ebml_w: writer::Encoder, item: @ast::item) {
|
|||
|
||||
#[cfg(test)]
|
||||
fn decode_item_ast(par_doc: ebml::Doc) -> @ast::item {
|
||||
let chi_doc = par_doc[c::tag_tree as uint];
|
||||
let chi_doc = par_doc.get(c::tag_tree as uint);
|
||||
let d = &reader::Decoder(chi_doc);
|
||||
@Decodable::decode(d)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ pub impl VisitContext {
|
|||
|
||||
expr_unary(deref, base) => { // *base
|
||||
if !self.use_overloaded_operator(
|
||||
expr, DontDerefArgs, base, [], visitor)
|
||||
expr, base, [], visitor)
|
||||
{
|
||||
// Moving out of *base moves out of base.
|
||||
self.use_expr(base, comp_mode, visitor);
|
||||
|
|
@ -450,7 +450,7 @@ pub impl VisitContext {
|
|||
|
||||
expr_index(lhs, rhs) => { // lhs[rhs]
|
||||
if !self.use_overloaded_operator(
|
||||
expr, DontDerefArgs, lhs, [rhs], visitor)
|
||||
expr, lhs, [rhs], visitor)
|
||||
{
|
||||
self.use_expr(lhs, comp_mode, visitor);
|
||||
self.consume_expr(rhs, visitor);
|
||||
|
|
@ -579,7 +579,7 @@ pub impl VisitContext {
|
|||
|
||||
expr_unary(_, lhs) => {
|
||||
if !self.use_overloaded_operator(
|
||||
expr, DontDerefArgs, lhs, [], visitor)
|
||||
expr, lhs, [], visitor)
|
||||
{
|
||||
self.consume_expr(lhs, visitor);
|
||||
}
|
||||
|
|
@ -587,7 +587,7 @@ pub impl VisitContext {
|
|||
|
||||
expr_binary(_, lhs, rhs) => {
|
||||
if !self.use_overloaded_operator(
|
||||
expr, DoDerefArgs, lhs, [rhs], visitor)
|
||||
expr, lhs, [rhs], visitor)
|
||||
{
|
||||
self.consume_expr(lhs, visitor);
|
||||
self.consume_expr(rhs, visitor);
|
||||
|
|
@ -659,7 +659,6 @@ pub impl VisitContext {
|
|||
|
||||
fn use_overloaded_operator(&self,
|
||||
expr: @expr,
|
||||
deref_args: DerefArgs,
|
||||
receiver_expr: @expr,
|
||||
arg_exprs: &[@expr],
|
||||
visitor: vt<VisitContext>) -> bool
|
||||
|
|
@ -670,21 +669,10 @@ pub impl VisitContext {
|
|||
|
||||
self.use_receiver(expr.id, expr.span, receiver_expr, visitor);
|
||||
|
||||
// The deref_args stuff should eventually be converted into
|
||||
// adjustments. Moreover, it should eventually be applied
|
||||
// consistently to all overloaded operators. But that's not
|
||||
// how it is today.
|
||||
match deref_args {
|
||||
DoDerefArgs => {
|
||||
// we are always passing in a borrowed pointer,
|
||||
// so it's always read mode:
|
||||
for arg_exprs.each |arg_expr| {
|
||||
self.use_expr(*arg_expr, Read, visitor);
|
||||
}
|
||||
}
|
||||
DontDerefArgs => {
|
||||
self.use_fn_args(expr.callee_id, arg_exprs, visitor);
|
||||
}
|
||||
// for overloaded operatrs, we are always passing in a
|
||||
// borrowed pointer, so it's always read mode:
|
||||
for arg_exprs.each |arg_expr| {
|
||||
self.use_expr(*arg_expr, Read, visitor);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -766,18 +766,15 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
|||
}
|
||||
ast::expr_binary(_, lhs, rhs) => {
|
||||
// if not overloaded, would be RvalueDatumExpr
|
||||
return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest,
|
||||
DoAutorefArg);
|
||||
return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest);
|
||||
}
|
||||
ast::expr_unary(_, subexpr) => {
|
||||
// if not overloaded, would be RvalueDatumExpr
|
||||
return trans_overloaded_op(bcx, expr, subexpr, ~[], dest,
|
||||
DontAutorefArg);
|
||||
return trans_overloaded_op(bcx, expr, subexpr, ~[], dest);
|
||||
}
|
||||
ast::expr_index(base, idx) => {
|
||||
// if not overloaded, would be RvalueDatumExpr
|
||||
return trans_overloaded_op(bcx, expr, base, ~[idx], dest,
|
||||
DontAutorefArg);
|
||||
return trans_overloaded_op(bcx, expr, base, ~[idx], dest);
|
||||
}
|
||||
ast::expr_cast(val, _) => {
|
||||
match ty::get(node_id_type(bcx, expr.id)).sty {
|
||||
|
|
@ -1644,8 +1641,7 @@ fn trans_overloaded_op(bcx: block,
|
|||
expr: @ast::expr,
|
||||
rcvr: @ast::expr,
|
||||
+args: ~[@ast::expr],
|
||||
dest: Dest,
|
||||
+autoref_arg: AutorefArg) -> block
|
||||
dest: Dest) -> block
|
||||
{
|
||||
let origin = *bcx.ccx().maps.method_map.get(&expr.id);
|
||||
let fty = node_id_type(bcx, expr.callee_id);
|
||||
|
|
@ -1653,7 +1649,7 @@ fn trans_overloaded_op(bcx: block,
|
|||
bcx, expr.info(), fty,
|
||||
expr_ty(bcx, expr),
|
||||
|bcx| meth::trans_method_callee(bcx, expr.callee_id, rcvr, origin),
|
||||
callee::ArgExprs(args), dest, autoref_arg);
|
||||
callee::ArgExprs(args), dest, DoAutorefArg);
|
||||
}
|
||||
|
||||
fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
||||
|
|
@ -1806,7 +1802,7 @@ fn trans_assign_op(bcx: block,
|
|||
// FIXME(#2528) evaluates the receiver twice!!
|
||||
let scratch = scratch_datum(bcx, dst_datum.ty, false);
|
||||
let bcx = trans_overloaded_op(bcx, expr, dst, ~[src],
|
||||
SaveIn(scratch.val), DoAutorefArg);
|
||||
SaveIn(scratch.val));
|
||||
return scratch.move_to_datum(bcx, DROP_EXISTING, dst_datum);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1549,7 +1549,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
lookup_op_method(
|
||||
fcx, ex, rhs_expr, rhs_t,
|
||||
fcx.tcx().sess.ident_of(mname), ~[],
|
||||
DontDerefArgs, DontAutoderefReceiver,
|
||||
DoDerefArgs, DontAutoderefReceiver,
|
||||
|| {
|
||||
fcx.type_error_message(ex.span, |actual| {
|
||||
fmt!("cannot apply unary operator `%s` to type `%s`",
|
||||
|
|
@ -2757,7 +2757,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
expr.span, raw_base_t);
|
||||
let ret_ty = lookup_op_method(fcx, expr, base, resolved,
|
||||
tcx.sess.ident_of(~"index"),
|
||||
~[idx], DontDerefArgs, AutoderefReceiver,
|
||||
~[idx], DoDerefArgs, AutoderefReceiver,
|
||||
|| {
|
||||
fcx.type_error_message(expr.span, |actual|
|
||||
fmt!("cannot index a value \
|
||||
|
|
|
|||
|
|
@ -437,7 +437,8 @@ pub impl Bitv {
|
|||
if offset >= bitv.nbits {
|
||||
0
|
||||
} else {
|
||||
bitv[offset] as u8 << (7 - bit)
|
||||
// NOTE cannot use bitv[offset] until snapshot
|
||||
bitv.index(&offset) as u8 << (7 - bit)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -459,7 +460,8 @@ pub impl Bitv {
|
|||
* Transform self into a [bool] by turning each bit into a bool
|
||||
*/
|
||||
fn to_bools(&self) -> ~[bool] {
|
||||
vec::from_fn(self.nbits, |i| self[i])
|
||||
// NOTE cannot use self[i] until snapshot
|
||||
vec::from_fn(self.nbits, |i| self.index(&i))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -555,8 +557,8 @@ pub fn from_fn(len: uint, f: &fn(index: uint) -> bool) -> Bitv {
|
|||
}
|
||||
|
||||
impl ops::Index<uint,bool> for Bitv {
|
||||
fn index(&self, i: uint) -> bool {
|
||||
self.get(i)
|
||||
fn index(&self, i: &uint) -> bool {
|
||||
self.get(*i)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,11 +68,9 @@ pub mod reader {
|
|||
|
||||
// ebml reading
|
||||
|
||||
impl ops::Index<uint,Doc> for Doc {
|
||||
fn index(&self, tag: uint) -> Doc {
|
||||
unsafe {
|
||||
get_doc(*self, tag)
|
||||
}
|
||||
pub impl Doc {
|
||||
fn get(&self, tag: uint) -> Doc {
|
||||
get_doc(*self, tag)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ impl ops::Not<Point> for Point {
|
|||
}
|
||||
|
||||
impl ops::Index<bool,int> for Point {
|
||||
fn index(&self, +x: bool) -> int {
|
||||
if x { self.x } else { self.y }
|
||||
fn index(&self, +x: &bool) -> int {
|
||||
if *x { self.x } else { self.y }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
55
src/test/run-pass/overload-index-operator.rs
Normal file
55
src/test/run-pass/overload-index-operator.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test overloading of the `[]` operator. In particular test that it
|
||||
// takes its argument *by reference*.
|
||||
|
||||
use core::ops::Index;
|
||||
|
||||
struct AssociationList<K,V> {
|
||||
pairs: ~[AssociationPair<K,V>]
|
||||
}
|
||||
|
||||
struct AssociationPair<K,V> {
|
||||
key: K,
|
||||
value: V
|
||||
}
|
||||
|
||||
impl<K,V> AssociationList<K,V> {
|
||||
fn push(&mut self, key: K, value: V) {
|
||||
self.pairs.push(AssociationPair {key: key, value: value});
|
||||
}
|
||||
}
|
||||
|
||||
impl<K:Eq,V:Copy> Index<K,V> for AssociationList<K,V> {
|
||||
fn index(&self, index: &K) -> V {
|
||||
for self.pairs.each |pair| {
|
||||
if pair.key == *index {
|
||||
return copy pair.value;
|
||||
}
|
||||
}
|
||||
fail!(fmt!("No value found for key: %?", index));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let foo = ~"foo";
|
||||
let bar = ~"bar";
|
||||
|
||||
let mut list = AssociationList {pairs: ~[]};
|
||||
list.push(copy foo, 22);
|
||||
list.push(copy bar, 44);
|
||||
|
||||
fail_unless!(list[foo] == 22)
|
||||
fail_unless!(list[bar] == 44)
|
||||
|
||||
fail_unless!(list[foo] == 22)
|
||||
fail_unless!(list[bar] == 44)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue