]> git.lizzy.rs Git - rust.git/commitdiff
Apply @nikomatsakis' nits and comments patch.
authorEduard Burtescu <edy.burt@gmail.com>
Sat, 8 Mar 2014 16:33:39 +0000 (18:33 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Thu, 13 Mar 2014 12:21:45 +0000 (14:21 +0200)
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/mod.rs
src/libsyntax/ast.rs

index 5e2a8792abf86fd3321a2c23aa12da709a9ce64d..ff63b74444c614238e4c9d78dc6983b2aeaab7a8 100644 (file)
@@ -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 vtables = match node {
         ExprId(id) => node_vtables(bcx, id),
-        MethodCall(method_call) if method_call.autoderef == 0 => {
-            node_vtables(bcx, method_call.expr_id)
+        MethodCall(ref method_call) => {
+            if method_call.autoderef == 0 {
+                node_vtables(bcx, method_call.expr_id)
+            } else {
+                None
+            }
         }
-        _ => None
     };
     debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
            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.
         assert_eq!(def_id.krate, ast::LOCAL_CRATE);
 
-        let ref_id = match node {
-            ExprId(id) if id != 0 => Some(id),
-            _ => None
+        let opt_ref_id = match node {
+            ExprId(id) => if id != 0 { Some(id) } else { None },
+            MethodCall(_) => None,
         };
 
         let (val, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, &substs,
                                          vtables, self_vtables,
-                                         ref_id);
+                                         opt_ref_id);
         let mut val = val;
         if must_cast && node != ExprId(0) {
             // Monotype of the REFERENCE to the function (type params
@@ -758,9 +761,19 @@ pub fn trans_call_inner<'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]),
+
+    // 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)>),
-    ArgVals(&'a [ValueRef])
 }
 
 fn trans_args<'a>(cx: &'a Block<'a>,
index 759e5e872d4be85236dc0e837e929f012a27f289..e3a996e33d392d62f3e5f5cfce730e1cb9edfcac 100644 (file)
@@ -809,9 +809,13 @@ pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
     monomorphize_type(bcx, t)
 }
 
+// Key used to lookup values supplied for type parameters in an expr.
 #[deriving(Eq)]
 pub enum ExprOrMethodCall {
+    // Type parameters for a path like `None::<int>`
     ExprId(ast::NodeId),
+
+    // Type parameters for a method call like `a.foo::<int>()`
     MethodCall(typeck::MethodCall)
 }
 
index 056ac62183f90d560fa42d1fcf474cb93af293e1..d143d6743052cb9a5722b2665263c64c1c88e8c5 100644 (file)
@@ -1160,9 +1160,13 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
     let _icx = push_ctxt("trans_unary_datum");
 
     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
-    assert!(!overloaded || op == ast::UnDeref);
+
+    // The only overloaded operator that is translated to a datum
+    // 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);
 
@@ -1779,6 +1783,7 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
 
     let mut bcx = bcx;
 
+    // Check for overloaded deref.
     let method_call = MethodCall {
         expr_id: expr.id,
         autoderef: derefs as u32
@@ -1787,6 +1792,11 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
                        .find(&method_call).map(|method| method.ty);
     let datum = match 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 {
                 datum
             } 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));
             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 {
index b3d69043d33e397ddcda5506d3cbba927416bfa9..89f3377643142985a1e14e81a415d2f6e0c333da 100644 (file)
@@ -335,10 +335,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
     // exist, in which case we need to make them.
     let vtables = match node {
         ExprId(id) => node_vtables(bcx, id),
-        MethodCall(method_call) if method_call.autoderef == 0 => {
-            node_vtables(bcx, method_call.expr_id)
+        MethodCall(method_call) => {
+            if method_call.autoderef == 0 {
+                node_vtables(bcx, method_call.expr_id)
+            } else {
+                None
+            }
         }
-        _ => None
     };
     let r_m_origins = match vtables {
         Some(vt) => vt,
index 9d0fb8669169845880d5912a40175c5487b6edbc..c0ad18d9520e3f52abecb2ae7fa85378579cc16a 100644 (file)
@@ -229,7 +229,7 @@ pub struct AutoDerefRef {
     autoref: Option<AutoRef>
 }
 
-#[deriving(Decodable, Encodable)]
+#[deriving(Decodable, Encodable, Eq, Show)]
 pub enum AutoRef {
     /// Convert from T to &T
     AutoPtr(Region, ast::Mutability),
@@ -3271,11 +3271,15 @@ pub fn expr_kind(tcx: ctxt,
                  expr: &ast::Expr) -> ExprKind {
     if method_map.borrow().get().contains_key(&MethodCall::expr(expr.id)) {
         // Overloaded operations are generally calls, and hence they are
-        // generated via DPS.  However, assign_op (e.g., `x += y`) is an
-        // exception, as its result is always unit.
+        // generated via DPS, but there are two exceptions:
         return match expr.node {
+            // `a += b` has a unit result.
             ast::ExprAssignOp(..) => RvalueStmtExpr,
+
+            // the deref method invoked for `*a` always yields an `&T`
             ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
+
+            // in the general case, result could be any type, use DPS
             _ => RvalueDpsExpr
         };
     }
index 89658b32be89a9764b23b2dd49000e163ca89c95..0d37904445ff6c4482f1786028747dcc6ef760ad 100644 (file)
@@ -201,7 +201,13 @@ pub fn lookup_in_trait<'a>(
 struct LookupContext<'a> {
     fcx: @FnCtxt,
     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>,
+
     m_name: ast::Name,
     supplied_tps: &'a [ty::t],
     impl_dups: @RefCell<HashSet<DefId>>,
@@ -243,51 +249,69 @@ fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
         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_ty, autoderefs, result) =
-            check::autoderef(self.fcx, span, self_ty, self_expr_id,
-                             PreferMutLvalue, |self_ty, autoderefs| {
-
-            debug!("loop: self_ty={} autoderefs={}",
-                   self.ty_to_str(self_ty), autoderefs);
+            check::autoderef(
+                self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
+                |self_ty, autoderefs| self.search_step(self_ty, autoderefs));
 
-            match self.deref_args {
-                check::DontDerefArgs => {
-                    match self.search_for_autoderefd_method(self_ty, autoderefs) {
-                        Some(result) => return Some(Some(result)),
-                        None => {}
-                    }
+        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)
+                }
+            }
+        }
+    }
 
-                    match self.search_for_autoptrd_method(self_ty, autoderefs) {
-                        Some(result) => return Some(Some(result)),
-                        None => {}
-                    }
+    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);
+
+        match self.deref_args {
+            check::DontDerefArgs => {
+                match self.search_for_autoderefd_method(self_ty, autoderefs) {
+                    Some(result) => return Some(Some(result)),
+                    None => {}
                 }
-                check::DoDerefArgs => {
-                    match self.search_for_autoptrd_method(self_ty, autoderefs) {
-                        Some(result) => return Some(Some(result)),
-                        None => {}
-                    }
 
-                    match self.search_for_autoderefd_method(self_ty, autoderefs) {
-                        Some(result) => return Some(Some(result)),
-                        None => {}
-                    }
+                match self.search_for_autoptrd_method(self_ty, autoderefs) {
+                    Some(result) => return Some(Some(result)),
+                    None => {}
                 }
             }
+            check::DoDerefArgs => {
+                match self.search_for_autoptrd_method(self_ty, autoderefs) {
+                    Some(result) => return Some(Some(result)),
+                    None => {}
+                }
 
-            // Don't autoderef if we aren't supposed to.
-            if self.autoderef_receiver == DontAutoderefReceiver {
-                Some(None)
-            } else {
-                None
+                match self.search_for_autoderefd_method(self_ty, autoderefs) {
+                    Some(result) => return Some(Some(result)),
+                    None => {}
+                }
             }
-        });
+        }
 
-        match result {
-            Some(Some(result)) => Some(result),
-            _ => self.search_for_autosliced_method(self_ty, autoderefs)
+        // Don't autoderef if we aren't supposed to.
+        if self.autoderef_receiver == DontAutoderefReceiver {
+            Some(None)
+        } else {
+            None
         }
     }
 
+    fn is_overloaded_deref(&self) -> bool {
+        self.self_expr.is_none()
+    }
+
     // ______________________________________________________________________
     // Candidate collection (see comment at start of file)
 
@@ -625,17 +649,13 @@ fn search_for_autoderefd_method(&self,
         let (self_ty, auto_deref_ref) =
             self.consider_reborrow(self_ty, autoderefs);
 
-        // HACK(eddyb) only overloaded auto-deref calls should be missing
-        // adjustments, because we imply an AutoPtr adjustment for them.
-        let adjustment = match auto_deref_ref {
-            ty::AutoDerefRef {
-                autoderefs: 0,
-                autoref: Some(ty::AutoPtr(..))
-            } => None,
-            _ => match self.self_expr {
-                Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
-                None => return None
-            }
+        // Hacky. For overloaded derefs, there may be an adjustment
+        // 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 adjustment = match self.self_expr {
+            Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
+            None => return None
         };
 
         match self.search_for_method(self_ty) {
@@ -733,9 +753,9 @@ fn search_for_autosliced_method(&self,
                                     autoderefs: uint)
                                     -> Option<MethodCallee> {
         /*!
-         *
          * Searches for a candidate by converting things like
-         * `~[]` to `&[]`. */
+         * `~[]` to `&[]`.
+         */
 
         let tcx = self.tcx();
         let sty = ty::get(self_ty).sty.clone();
@@ -843,15 +863,20 @@ fn search_for_some_kind_of_autorefd_method(
             mutbls: &[ast::Mutability],
             mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
             -> Option<MethodCallee> {
-        // HACK(eddyb) only overloaded auto-deref calls should be missing
-        // adjustments, because we imply an AutoPtr adjustment for them.
+        // Hacky. For overloaded derefs, there may be an adjustment
+        // 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 {
             Some(expr) => Some(expr.id),
-            None => match kind(ty::ReEmpty, ast::MutImmutable) {
-                ty::AutoPtr(..) if autoderefs == 0 => None,
-                _ => return None
+            None => {
+                assert_eq!(autoderefs, 0);
+                assert_eq!(kind(ty::ReEmpty, ast::MutImmutable),
+                           ty::AutoPtr(ty::ReEmpty, ast::MutImmutable));
+                None
             }
         };
+
         // This is hokey. We should have mutability inference as a
         // variable.  But for now, try &const, then &, then &mut:
         let region =
@@ -1119,7 +1144,8 @@ fn construct_transformed_self_ty_for_object(
         &self,
         trait_def_id: ast::DefId,
         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
          * being invoked on an object, and we want to generate the
index e3db7f16064a4a44f53f0663cd1dfa1de959834b..51efcb7d1c3879c613480ceaec1fd394522ed624 100644 (file)
@@ -1247,11 +1247,14 @@ pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, base_ty: ty::t,
                     should_stop: |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
-     * and an autoderef count. If the count is not zero, the receiver is
-     * responsible for inserting an AutoAdjustment record into `tcx.adjustments`
-     * so that trans/borrowck/etc know about this autoderef. */
+     * Note: this method does not modify the adjustments table. The caller is
+     * responsible for inserting an AutoAdjustment record into the `fcx`
+     * using one of the suitable methods.
+     */
 
     let mut t = base_ty;
     for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
@@ -2282,15 +2285,15 @@ fn check_field(fcx: @FnCtxt,
         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
         let (_, autoderefs, field_ty) =
             autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
-            match ty::get(base_t).sty {
-                ty::ty_struct(base_id, ref substs) => {
-                    debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
-                    let fields = ty::lookup_struct_fields(tcx, base_id);
-                    lookup_field_ty(tcx, base_id, fields.as_slice(), field, &(*substs))
+                match ty::get(base_t).sty {
+                    ty::ty_struct(base_id, ref substs) => {
+                        debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
+                        let fields = ty::lookup_struct_fields(tcx, base_id);
+                        lookup_field_ty(tcx, base_id, fields.as_slice(), field, &(*substs))
+                    }
+                    _ => None
                 }
-                _ => None
-            }
-        });
+            });
         match field_ty {
             Some(field_ty) => {
                 fcx.write_ty(expr.id, field_ty);
index b6b18f6671d311a1cb85655586ce97ca4e5e4416..7fef6da560783c3b5327e3888b9e99d5d28c4982 100644 (file)
@@ -354,7 +354,7 @@ pub enum Pat_ {
     PatVec(Vec<@Pat> , Option<@Pat>, Vec<@Pat> )
 }
 
-#[deriving(Clone, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Mutability {
     MutMutable,
     MutImmutable,