Apply @nikomatsakis' nits and comments patch.
This commit is contained in:
@@ -173,10 +173,13 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
|
|||||||
let type_params = node_id_type_params(bcx, node);
|
let type_params = node_id_type_params(bcx, node);
|
||||||
let vtables = match node {
|
let vtables = match node {
|
||||||
ExprId(id) => node_vtables(bcx, id),
|
ExprId(id) => node_vtables(bcx, id),
|
||||||
MethodCall(method_call) if method_call.autoderef == 0 => {
|
MethodCall(ref method_call) => {
|
||||||
|
if method_call.autoderef == 0 {
|
||||||
node_vtables(bcx, method_call.expr_id)
|
node_vtables(bcx, method_call.expr_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => None
|
|
||||||
};
|
};
|
||||||
debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
|
debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
|
||||||
def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
|
def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
|
||||||
@@ -381,15 +384,15 @@ pub fn trans_fn_ref_with_vtables(
|
|||||||
// Should be either intra-crate or inlined.
|
// Should be either intra-crate or inlined.
|
||||||
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
|
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
|
||||||
|
|
||||||
let ref_id = match node {
|
let opt_ref_id = match node {
|
||||||
ExprId(id) if id != 0 => Some(id),
|
ExprId(id) => if id != 0 { Some(id) } else { None },
|
||||||
_ => None
|
MethodCall(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (val, must_cast) =
|
let (val, must_cast) =
|
||||||
monomorphize::monomorphic_fn(ccx, def_id, &substs,
|
monomorphize::monomorphic_fn(ccx, def_id, &substs,
|
||||||
vtables, self_vtables,
|
vtables, self_vtables,
|
||||||
ref_id);
|
opt_ref_id);
|
||||||
let mut val = val;
|
let mut val = val;
|
||||||
if must_cast && node != ExprId(0) {
|
if must_cast && node != ExprId(0) {
|
||||||
// Monotype of the REFERENCE to the function (type params
|
// Monotype of the REFERENCE to the function (type params
|
||||||
@@ -758,9 +761,19 @@ pub fn trans_call_inner<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum CallArgs<'a> {
|
pub enum CallArgs<'a> {
|
||||||
|
// Supply value of arguments as a list of expressions that must be
|
||||||
|
// translated. This is used in the common case of `foo(bar, qux)`.
|
||||||
ArgExprs(&'a [@ast::Expr]),
|
ArgExprs(&'a [@ast::Expr]),
|
||||||
|
|
||||||
|
// Supply value of arguments as a list of LLVM value refs; frequently
|
||||||
|
// used with lang items and so forth, when the argument is an internal
|
||||||
|
// value.
|
||||||
|
ArgVals(&'a [ValueRef]),
|
||||||
|
|
||||||
|
// For overloaded operators: `(lhs, Option(rhs, rhs_id))`. `lhs`
|
||||||
|
// is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of
|
||||||
|
// the right-hand-side (if any).
|
||||||
ArgOverloadedOp(Datum<Expr>, Option<(Datum<Expr>, ast::NodeId)>),
|
ArgOverloadedOp(Datum<Expr>, Option<(Datum<Expr>, ast::NodeId)>),
|
||||||
ArgVals(&'a [ValueRef])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_args<'a>(cx: &'a Block<'a>,
|
fn trans_args<'a>(cx: &'a Block<'a>,
|
||||||
|
|||||||
@@ -809,9 +809,13 @@ pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
|
|||||||
monomorphize_type(bcx, t)
|
monomorphize_type(bcx, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key used to lookup values supplied for type parameters in an expr.
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub enum ExprOrMethodCall {
|
pub enum ExprOrMethodCall {
|
||||||
|
// Type parameters for a path like `None::<int>`
|
||||||
ExprId(ast::NodeId),
|
ExprId(ast::NodeId),
|
||||||
|
|
||||||
|
// Type parameters for a method call like `a.foo::<int>()`
|
||||||
MethodCall(typeck::MethodCall)
|
MethodCall(typeck::MethodCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1160,9 +1160,13 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
|
|||||||
let _icx = push_ctxt("trans_unary_datum");
|
let _icx = push_ctxt("trans_unary_datum");
|
||||||
|
|
||||||
let method_call = MethodCall::expr(expr.id);
|
let method_call = MethodCall::expr(expr.id);
|
||||||
let overloaded = bcx.ccx().maps.method_map.borrow().get().contains_key(&method_call);
|
|
||||||
// if overloaded, would be RvalueDpsExpr
|
// The only overloaded operator that is translated to a datum
|
||||||
assert!(!overloaded || op == ast::UnDeref);
|
// is an overloaded deref, since it is always yields a `&T`.
|
||||||
|
// Otherwise, we should be in the RvalueDpsExpr path.
|
||||||
|
assert!(
|
||||||
|
op == ast::UnDeref ||
|
||||||
|
!bcx.ccx().maps.method_map.borrow().get().contains_key(&method_call));
|
||||||
|
|
||||||
let un_ty = expr_ty(bcx, expr);
|
let un_ty = expr_ty(bcx, expr);
|
||||||
|
|
||||||
@@ -1779,6 +1783,7 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
|
|||||||
|
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
|
|
||||||
|
// Check for overloaded deref.
|
||||||
let method_call = MethodCall {
|
let method_call = MethodCall {
|
||||||
expr_id: expr.id,
|
expr_id: expr.id,
|
||||||
autoderef: derefs as u32
|
autoderef: derefs as u32
|
||||||
@@ -1787,6 +1792,11 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
|
|||||||
.find(&method_call).map(|method| method.ty);
|
.find(&method_call).map(|method| method.ty);
|
||||||
let datum = match method_ty {
|
let datum = match method_ty {
|
||||||
Some(method_ty) => {
|
Some(method_ty) => {
|
||||||
|
// Overloaded. Evaluate `trans_overloaded_op`, which will
|
||||||
|
// invoke the user's deref() method, which basically
|
||||||
|
// converts from the `Shaht<T>` pointer that we have into
|
||||||
|
// a `&T` pointer. We can then proceed down the normal
|
||||||
|
// path (below) to dereference that `&T`.
|
||||||
let datum = if derefs == 0 {
|
let datum = if derefs == 0 {
|
||||||
datum
|
datum
|
||||||
} else {
|
} else {
|
||||||
@@ -1798,7 +1808,10 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
|
|||||||
let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
|
let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
|
||||||
Datum(val, ref_ty, RvalueExpr(Rvalue(ByValue)))
|
Datum(val, ref_ty, RvalueExpr(Rvalue(ByValue)))
|
||||||
}
|
}
|
||||||
None => datum
|
None => {
|
||||||
|
// Not overloaded. We already have a pointer we know how to deref.
|
||||||
|
datum
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let r = match ty::get(datum.ty).sty {
|
let r = match ty::get(datum.ty).sty {
|
||||||
|
|||||||
@@ -335,10 +335,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
|
|||||||
// exist, in which case we need to make them.
|
// exist, in which case we need to make them.
|
||||||
let vtables = match node {
|
let vtables = match node {
|
||||||
ExprId(id) => node_vtables(bcx, id),
|
ExprId(id) => node_vtables(bcx, id),
|
||||||
MethodCall(method_call) if method_call.autoderef == 0 => {
|
MethodCall(method_call) => {
|
||||||
|
if method_call.autoderef == 0 {
|
||||||
node_vtables(bcx, method_call.expr_id)
|
node_vtables(bcx, method_call.expr_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => None
|
|
||||||
};
|
};
|
||||||
let r_m_origins = match vtables {
|
let r_m_origins = match vtables {
|
||||||
Some(vt) => vt,
|
Some(vt) => vt,
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ pub struct AutoDerefRef {
|
|||||||
autoref: Option<AutoRef>
|
autoref: Option<AutoRef>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Decodable, Encodable)]
|
#[deriving(Decodable, Encodable, Eq, Show)]
|
||||||
pub enum AutoRef {
|
pub enum AutoRef {
|
||||||
/// Convert from T to &T
|
/// Convert from T to &T
|
||||||
AutoPtr(Region, ast::Mutability),
|
AutoPtr(Region, ast::Mutability),
|
||||||
@@ -3271,11 +3271,15 @@ pub fn expr_kind(tcx: ctxt,
|
|||||||
expr: &ast::Expr) -> ExprKind {
|
expr: &ast::Expr) -> ExprKind {
|
||||||
if method_map.borrow().get().contains_key(&MethodCall::expr(expr.id)) {
|
if method_map.borrow().get().contains_key(&MethodCall::expr(expr.id)) {
|
||||||
// Overloaded operations are generally calls, and hence they are
|
// Overloaded operations are generally calls, and hence they are
|
||||||
// generated via DPS. However, assign_op (e.g., `x += y`) is an
|
// generated via DPS, but there are two exceptions:
|
||||||
// exception, as its result is always unit.
|
|
||||||
return match expr.node {
|
return match expr.node {
|
||||||
|
// `a += b` has a unit result.
|
||||||
ast::ExprAssignOp(..) => RvalueStmtExpr,
|
ast::ExprAssignOp(..) => RvalueStmtExpr,
|
||||||
|
|
||||||
|
// the deref method invoked for `*a` always yields an `&T`
|
||||||
ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
|
ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
|
||||||
|
|
||||||
|
// in the general case, result could be any type, use DPS
|
||||||
_ => RvalueDpsExpr
|
_ => RvalueDpsExpr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,7 +201,13 @@ pub fn lookup_in_trait<'a>(
|
|||||||
struct LookupContext<'a> {
|
struct LookupContext<'a> {
|
||||||
fcx: @FnCtxt,
|
fcx: @FnCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
||||||
|
// The receiver to the method call. Only `None` in the case of
|
||||||
|
// an overloaded autoderef, where the receiver may be an intermediate
|
||||||
|
// state like "the expression `x` when it has been autoderef'd
|
||||||
|
// twice already".
|
||||||
self_expr: Option<&'a ast::Expr>,
|
self_expr: Option<&'a ast::Expr>,
|
||||||
|
|
||||||
m_name: ast::Name,
|
m_name: ast::Name,
|
||||||
supplied_tps: &'a [ty::t],
|
supplied_tps: &'a [ty::t],
|
||||||
impl_dups: @RefCell<HashSet<DefId>>,
|
impl_dups: @RefCell<HashSet<DefId>>,
|
||||||
@@ -243,10 +249,30 @@ impl<'a> LookupContext<'a> {
|
|||||||
let span = self.self_expr.map_or(self.span, |e| e.span);
|
let span = self.self_expr.map_or(self.span, |e| e.span);
|
||||||
let self_expr_id = self.self_expr.map(|e| e.id);
|
let self_expr_id = self.self_expr.map(|e| e.id);
|
||||||
let (self_ty, autoderefs, result) =
|
let (self_ty, autoderefs, result) =
|
||||||
check::autoderef(self.fcx, span, self_ty, self_expr_id,
|
check::autoderef(
|
||||||
PreferMutLvalue, |self_ty, autoderefs| {
|
self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
|
||||||
|
|self_ty, autoderefs| self.search_step(self_ty, autoderefs));
|
||||||
|
|
||||||
debug!("loop: self_ty={} autoderefs={}",
|
match result {
|
||||||
|
Some(Some(result)) => Some(result),
|
||||||
|
_ => {
|
||||||
|
if self.is_overloaded_deref() {
|
||||||
|
// If we are searching for an overloaded deref, no
|
||||||
|
// need to try coercing a `~[T]` to an `&[T]` and
|
||||||
|
// searching for an overloaded deref on *that*.
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.search_for_autosliced_method(self_ty, autoderefs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_step(&self,
|
||||||
|
self_ty: ty::t,
|
||||||
|
autoderefs: uint)
|
||||||
|
-> Option<Option<MethodCallee>> {
|
||||||
|
debug!("search_step: self_ty={} autoderefs={}",
|
||||||
self.ty_to_str(self_ty), autoderefs);
|
self.ty_to_str(self_ty), autoderefs);
|
||||||
|
|
||||||
match self.deref_args {
|
match self.deref_args {
|
||||||
@@ -280,12 +306,10 @@ impl<'a> LookupContext<'a> {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
|
||||||
Some(Some(result)) => Some(result),
|
|
||||||
_ => self.search_for_autosliced_method(self_ty, autoderefs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_overloaded_deref(&self) -> bool {
|
||||||
|
self.self_expr.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ______________________________________________________________________
|
// ______________________________________________________________________
|
||||||
@@ -625,17 +649,13 @@ impl<'a> LookupContext<'a> {
|
|||||||
let (self_ty, auto_deref_ref) =
|
let (self_ty, auto_deref_ref) =
|
||||||
self.consider_reborrow(self_ty, autoderefs);
|
self.consider_reborrow(self_ty, autoderefs);
|
||||||
|
|
||||||
// HACK(eddyb) only overloaded auto-deref calls should be missing
|
// Hacky. For overloaded derefs, there may be an adjustment
|
||||||
// adjustments, because we imply an AutoPtr adjustment for them.
|
// added to the expression from the outside context, so we do not store
|
||||||
let adjustment = match auto_deref_ref {
|
// an explicit adjustment, but rather we hardwire the single deref
|
||||||
ty::AutoDerefRef {
|
// that occurs in trans and mem_categorization.
|
||||||
autoderefs: 0,
|
let adjustment = match self.self_expr {
|
||||||
autoref: Some(ty::AutoPtr(..))
|
|
||||||
} => None,
|
|
||||||
_ => match self.self_expr {
|
|
||||||
Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
|
Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
|
||||||
None => return None
|
None => return None
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.search_for_method(self_ty) {
|
match self.search_for_method(self_ty) {
|
||||||
@@ -733,9 +753,9 @@ impl<'a> LookupContext<'a> {
|
|||||||
autoderefs: uint)
|
autoderefs: uint)
|
||||||
-> Option<MethodCallee> {
|
-> Option<MethodCallee> {
|
||||||
/*!
|
/*!
|
||||||
*
|
|
||||||
* Searches for a candidate by converting things like
|
* Searches for a candidate by converting things like
|
||||||
* `~[]` to `&[]`. */
|
* `~[]` to `&[]`.
|
||||||
|
*/
|
||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let sty = ty::get(self_ty).sty.clone();
|
let sty = ty::get(self_ty).sty.clone();
|
||||||
@@ -843,15 +863,20 @@ impl<'a> LookupContext<'a> {
|
|||||||
mutbls: &[ast::Mutability],
|
mutbls: &[ast::Mutability],
|
||||||
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
|
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
|
||||||
-> Option<MethodCallee> {
|
-> Option<MethodCallee> {
|
||||||
// HACK(eddyb) only overloaded auto-deref calls should be missing
|
// Hacky. For overloaded derefs, there may be an adjustment
|
||||||
// adjustments, because we imply an AutoPtr adjustment for them.
|
// added to the expression from the outside context, so we do not store
|
||||||
|
// an explicit adjustment, but rather we hardwire the single deref
|
||||||
|
// that occurs in trans and mem_categorization.
|
||||||
let self_expr_id = match self.self_expr {
|
let self_expr_id = match self.self_expr {
|
||||||
Some(expr) => Some(expr.id),
|
Some(expr) => Some(expr.id),
|
||||||
None => match kind(ty::ReEmpty, ast::MutImmutable) {
|
None => {
|
||||||
ty::AutoPtr(..) if autoderefs == 0 => None,
|
assert_eq!(autoderefs, 0);
|
||||||
_ => return None
|
assert_eq!(kind(ty::ReEmpty, ast::MutImmutable),
|
||||||
|
ty::AutoPtr(ty::ReEmpty, ast::MutImmutable));
|
||||||
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is hokey. We should have mutability inference as a
|
// This is hokey. We should have mutability inference as a
|
||||||
// variable. But for now, try &const, then &, then &mut:
|
// variable. But for now, try &const, then &, then &mut:
|
||||||
let region =
|
let region =
|
||||||
@@ -1119,7 +1144,8 @@ impl<'a> LookupContext<'a> {
|
|||||||
&self,
|
&self,
|
||||||
trait_def_id: ast::DefId,
|
trait_def_id: ast::DefId,
|
||||||
rcvr_substs: &ty::substs,
|
rcvr_substs: &ty::substs,
|
||||||
method_ty: &ty::Method) -> ty::t {
|
method_ty: &ty::Method)
|
||||||
|
-> ty::t {
|
||||||
/*!
|
/*!
|
||||||
* This is a bit tricky. We have a match against a trait method
|
* This is a bit tricky. We have a match against a trait method
|
||||||
* being invoked on an object, and we want to generate the
|
* being invoked on an object, and we want to generate the
|
||||||
|
|||||||
@@ -1247,11 +1247,14 @@ pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, base_ty: ty::t,
|
|||||||
should_stop: |ty::t, uint| -> Option<T>)
|
should_stop: |ty::t, uint| -> Option<T>)
|
||||||
-> (ty::t, uint, Option<T>) {
|
-> (ty::t, uint, Option<T>) {
|
||||||
/*!
|
/*!
|
||||||
|
* Executes an autoderef loop for the type `t`. At each step, invokes
|
||||||
|
* `should_stop` to decide whether to terminate the loop. Returns
|
||||||
|
* the final type and number of derefs that it performed.
|
||||||
*
|
*
|
||||||
* Autoderefs the type `t` as many times as possible, returning a new type
|
* Note: this method does not modify the adjustments table. The caller is
|
||||||
* and an autoderef count. If the count is not zero, the receiver is
|
* responsible for inserting an AutoAdjustment record into the `fcx`
|
||||||
* responsible for inserting an AutoAdjustment record into `tcx.adjustments`
|
* using one of the suitable methods.
|
||||||
* so that trans/borrowck/etc know about this autoderef. */
|
*/
|
||||||
|
|
||||||
let mut t = base_ty;
|
let mut t = base_ty;
|
||||||
for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
|
for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ pub enum Pat_ {
|
|||||||
PatVec(Vec<@Pat> , Option<@Pat>, Vec<@Pat> )
|
PatVec(Vec<@Pat> , Option<@Pat>, Vec<@Pat> )
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone, Eq, Encodable, Decodable, Hash)]
|
#[deriving(Clone, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
pub enum Mutability {
|
pub enum Mutability {
|
||||||
MutMutable,
|
MutMutable,
|
||||||
MutImmutable,
|
MutImmutable,
|
||||||
|
|||||||
Reference in New Issue
Block a user