Skip to content

Implement DerefImm and DerefMut #7141 #12491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -2485,8 +2485,11 @@ before the expression they apply to.
`*`
: Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location.
For pointers to mutable locations, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.
For [enums](#enumerated-types) that have only a single variant, containing a single parameter,
the dereference operator accesses this parameter.
On non-pointer types, it calls calls the `deref` method of the `std::ops::Deref` trait, or the
`deref_mut` method of the `std::ops::DerefMut` trait (if implemented by the type and required
for an outer expression that will or could mutate the dereference), and produces the
result of dereferencing the `&` or `&mut` borrowed pointer returned from the overload method.

`!`
: Logical negation. On the boolean type, this flips between `true` and
`false`. On integer types, this inverts the individual bits in the
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/middle/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,14 +921,17 @@ impl mc::Typer for TcxTyper {
Ok(ty::node_id_to_type(self.tcx, id))
}

fn node_method_ty(&mut self, id: ast::NodeId) -> Option<ty::t> {
self.method_map.borrow().get().find(&id).map(|method| method.ty)
}

fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
let adjustments = self.tcx.adjustments.borrow();
adjustments.get().find_copy(&id)
}

fn is_method_call(&mut self, id: ast::NodeId) -> bool {
let method_map = self.method_map.borrow();
method_map.get().contains_key(&id)
self.method_map.borrow().get().contains_key(&id)
}

fn temporary_scope(&mut self, id: ast::NodeId) -> Option<ast::NodeId> {
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ lets_do_this! {
ShrTraitLangItem, "shr", shr_trait;
IndexTraitLangItem, "index", index_trait;

DerefTraitLangItem, "deref", deref_trait;
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;

EqTraitLangItem, "eq", eq_trait;
OrdTraitLangItem, "ord", ord_trait;

Expand Down
13 changes: 8 additions & 5 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ pub type McResult<T> = Result<T, ()>;
pub trait Typer {
fn tcx(&self) -> ty::ctxt;
fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t>;
fn node_method_ty(&mut self, id: ast::NodeId) -> Option<ty::t>;
fn adjustment(&mut self, node_id: ast::NodeId) -> Option<@ty::AutoAdjustment>;
fn is_method_call(&mut self, id: ast::NodeId) -> bool;
fn temporary_scope(&mut self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
Expand Down Expand Up @@ -433,11 +434,13 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
let expr_ty = if_ok!(self.expr_ty(expr));
match expr.node {
ast::ExprUnary(ast::UnDeref, e_base) => {
if self.typer.is_method_call(expr.id) {
return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
}

let base_cmt = if_ok!(self.cat_expr(e_base));
let base_cmt = match self.typer.node_method_ty(expr.id) {
Some(method_ty) => {
let ref_ty = ty::ty_fn_ret(method_ty);
self.cat_rvalue_node(expr.id(), expr.span(), ref_ty)
}
None => if_ok!(self.cat_expr(e_base))
};
Ok(self.cat_deref(expr, base_cmt, 0))
}

Expand Down
15 changes: 4 additions & 11 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,14 +444,12 @@ pub fn trans_call<'a>(
call_ex: &ast::Expr,
f: &ast::Expr,
args: CallArgs,
id: ast::NodeId,
dest: expr::Dest)
-> &'a Block<'a> {
let _icx = push_ctxt("trans_call");
trans_call_inner(in_cx,
Some(common::expr_info(call_ex)),
expr_ty(in_cx, f),
node_id_type(in_cx, id),
|cx, _| trans(cx, f),
args,
Some(dest)).bcx
Expand All @@ -471,7 +469,6 @@ pub fn trans_method_call<'a>(
bcx,
Some(common::expr_info(call_ex)),
monomorphize_type(bcx, method_ty),
expr_ty(bcx, call_ex),
|cx, arg_cleanup_scope| {
meth::trans_method_callee(cx, call_ex.id, rcvr, arg_cleanup_scope)
},
Expand All @@ -490,11 +487,9 @@ pub fn trans_lang_call<'a>(
} else {
csearch::get_type(bcx.ccx().tcx, did).ty
};
let rty = ty::ty_fn_ret(fty);
callee::trans_call_inner(bcx,
None,
fty,
rty,
|bcx, _| {
trans_fn_ref_with_vtables_to_callee(bcx,
did,
Expand All @@ -520,12 +515,10 @@ pub fn trans_lang_call_with_type_params<'a>(
fty = csearch::get_type(bcx.tcx(), did).ty;
}

let rty = ty::ty_fn_ret(fty);
return callee::trans_call_inner(
bcx,
None,
fty,
rty,
|bcx, _| {
let callee =
trans_fn_ref_with_vtables_to_callee(bcx, did, 0,
Expand Down Expand Up @@ -554,7 +547,6 @@ pub fn trans_call_inner<'a>(
bcx: &'a Block<'a>,
call_info: Option<NodeInfo>,
callee_ty: ty::t,
ret_ty: ty::t,
get_callee: |bcx: &'a Block<'a>,
arg_cleanup_scope: cleanup::ScopeId|
-> Callee<'a>,
Expand Down Expand Up @@ -610,9 +602,10 @@ pub fn trans_call_inner<'a>(
}
};

let abi = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref f) => f.abis,
_ => AbiSet::Rust()
let (abi, ret_ty) = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref f) => (f.abis, f.sig.output),
ty::ty_closure(ref f) => (AbiSet::Rust(), f.sig.output),
_ => fail!("expected bare rust fn or closure in trans_call_inner")
};
let is_rust_fn =
abi.is_rust() ||
Expand Down
55 changes: 21 additions & 34 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,10 +467,6 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,

trans_binary(bcx, expr, op, lhs, rhs)
}
ast::ExprUnary(ast::UnDeref, base) => {
let basedatum = unpack_datum!(bcx, trans(bcx, base));
deref_once(bcx, expr, basedatum, 0)
}
ast::ExprUnary(op, x) => {
trans_unary_datum(bcx, expr, op, x)
}
Expand Down Expand Up @@ -782,12 +778,7 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest)
}
ast::ExprCall(f, ref args) => {
callee::trans_call(bcx,
expr,
f,
callee::ArgExprs(args.as_slice()),
expr.id,
dest)
callee::trans_call(bcx, expr, f, callee::ArgExprs(args.as_slice()), dest)
}
ast::ExprMethodCall(_, _, ref args) => {
callee::trans_method_call(bcx,
Expand All @@ -798,18 +789,15 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
}
ast::ExprBinary(_, lhs, rhs) => {
// if not overloaded, would be RvalueDatumExpr
trans_overloaded_op(bcx, expr, lhs,
Some(&*rhs), expr_ty(bcx, expr), dest)
trans_overloaded_op(bcx, expr, lhs, Some(&*rhs), Some(dest)).bcx
}
ast::ExprUnary(_, subexpr) => {
// if not overloaded, would be RvalueDatumExpr
trans_overloaded_op(bcx, expr, subexpr,
None, expr_ty(bcx, expr), dest)
trans_overloaded_op(bcx, expr, subexpr, None, Some(dest)).bcx
}
ast::ExprIndex(base, idx) => {
// if not overloaded, would be RvalueDatumExpr
trans_overloaded_op(bcx, expr, base,
Some(&*idx), expr_ty(bcx, expr), dest)
trans_overloaded_op(bcx, expr, base, Some(&*idx), Some(dest)).bcx
}
ast::ExprCast(val, _) => {
// DPS output mode means this is a trait cast:
Expand Down Expand Up @@ -1185,17 +1173,14 @@ fn trans_unary_datum<'a>(
let mut bcx = bcx;
let _icx = push_ctxt("trans_unary_datum");

// if deref, would be LvalueExpr
assert!(op != ast::UnDeref);

// if overloaded, would be RvalueDpsExpr
{
let overloaded = {
let method_map = bcx.ccx().maps.method_map.borrow();
assert!(!method_map.get().contains_key(&un_expr.id));
}
method_map.get().contains_key(&un_expr.id)
};
// if overloaded, would be RvalueDpsExpr
assert!(!overloaded || op == ast::UnDeref);

let un_ty = expr_ty(bcx, un_expr);
let sub_ty = expr_ty(bcx, sub_expr);

return match op {
ast::UnNot => {
Expand Down Expand Up @@ -1226,15 +1211,19 @@ fn trans_unary_datum<'a>(
immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
}
ast::UnBox => {
trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap_managed)
trans_boxed_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr), heap_managed)
}
ast::UnUniq => {
trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap_exchange)
trans_boxed_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr), heap_exchange)
}
ast::UnDeref => {
bcx.sess().bug("deref expressions should have been \
translated using trans_lvalue(), not \
trans_unary_datum()")
if overloaded {
let r = trans_overloaded_op(bcx, un_expr, sub_expr, None, None);
DatumBlock(r.bcx, Datum(r.val, un_ty, LvalueExpr))
} else {
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
deref_once(bcx, un_expr, datum, 0)
}
}
};
}
Expand Down Expand Up @@ -1506,22 +1495,20 @@ fn trans_overloaded_op<'a, 'b>(
expr: &ast::Expr,
rcvr: &'b ast::Expr,
arg: Option<&'b ast::Expr>,
ret_ty: ty::t,
dest: Dest)
-> &'a Block<'a> {
dest: Option<Dest>)
-> Result<'a> {
let method_ty = bcx.ccx().maps.method_map.borrow().get().get(&expr.id).ty;
callee::trans_call_inner(bcx,
Some(expr_info(expr)),
monomorphize_type(bcx, method_ty),
ret_ty,
|bcx, arg_cleanup_scope| {
meth::trans_method_callee(bcx,
expr.id,
rcvr,
arg_cleanup_scope)
},
callee::ArgAutorefSecond(rcvr, arg),
Some(dest)).bcx
dest)
}

fn int_cast(bcx: &Block,
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/trans/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,8 @@ impl<'a> Reflector<'a> {
for (i, a) in args.iter().enumerate() {
debug!("arg {}: {}", i, bcx.val_to_str(*a));
}
let bool_ty = ty::mk_bool();
let result = unpack_result!(bcx, callee::trans_call_inner(
self.bcx, None, mth_ty, bool_ty,
self.bcx, None, mth_ty,
|bcx, _| meth::trans_trait_callee_from_llval(bcx,
mth_ty,
mth_idx,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3284,6 +3284,7 @@ pub fn expr_kind(tcx: ctxt,
// exception, as its result is always unit.
return match expr.node {
ast::ExprAssignOp(..) => RvalueStmtExpr,
ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
_ => RvalueDpsExpr
};
}
Expand Down
Loading