Skip to content

Commit

Permalink
Autoref the argument to the index operator (rust-lang#4920)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Mar 27, 2013
1 parent 2c17ff7 commit 069529b
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
10 changes: 5 additions & 5 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 \
Expand All @@ -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);
Expand Down Expand Up @@ -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)
}
Expand Down
28 changes: 8 additions & 20 deletions src/librustc/middle/moves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -579,15 +579,15 @@ pub impl VisitContext {

expr_unary(_, lhs) => {
if !self.use_overloaded_operator(
expr, DontDerefArgs, lhs, [], visitor)
expr, lhs, [], visitor)
{
self.consume_expr(lhs, visitor);
}
}

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);
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down
16 changes: 6 additions & 10 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -1644,16 +1641,15 @@ 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);
return callee::trans_call_inner(
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,
Expand Down Expand Up @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`",
Expand Down Expand Up @@ -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 \
Expand Down
10 changes: 6 additions & 4 deletions src/libstd/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand All @@ -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))
}

/**
Expand Down Expand Up @@ -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)
}
}

Expand Down
8 changes: 3 additions & 5 deletions src/libstd/ebml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/run-pass/operator-overloading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
}

Expand Down
55 changes: 55 additions & 0 deletions src/test/run-pass/overload-index-operator.rs
Original file line number Diff line number Diff line change
@@ -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)
}

1 comment on commit 069529b

@nikomatsakis
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+ (pcwalton)

Please sign in to comment.