Autoref the argument to the index operator (#4920)

This commit is contained in:
Niko Matsakis 2013-03-26 15:04:30 -04:00
parent 2c17ff7dbc
commit 069529bc5c
9 changed files with 88 additions and 49 deletions

View file

@ -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;
}

View file

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

View file

@ -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;

View file

@ -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);
}

View file

@ -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 \

View file

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

View file

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

View file

@ -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 }
}
}

View 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)
}