about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-07 15:57:51 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-10 00:20:25 +0300
commit8c44a9dca794afc58a876dd1e9223fdc469cabed (patch)
tree0378d8f2f034a2111bd1b059b7d1584f97a09aa6
parent287de2595a40c03d9ffe81f55c13c731fd01583f (diff)
downloadrust-8c44a9dca794afc58a876dd1e9223fdc469cabed.tar.gz
rust-8c44a9dca794afc58a876dd1e9223fdc469cabed.zip
Store all generic arguments for method calls in HIR
-rw-r--r--src/librustc/hir/intravisit.rs5
-rw-r--r--src/librustc/hir/lowering.rs11
-rw-r--r--src/librustc/hir/mod.rs17
-rw-r--r--src/librustc/hir/print.rs17
-rw-r--r--src/librustc/ich/impls_hir.rs2
-rw-r--r--src/librustc_privacy/lib.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs26
-rw-r--r--src/librustc_typeck/check/method/mod.rs11
-rw-r--r--src/librustc_typeck/check/mod.rs29
9 files changed, 55 insertions, 67 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 836d9775a3f..57198d8ca0b 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -944,10 +944,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             walk_list!(visitor, visit_expr, arguments);
             visitor.visit_expr(callee_expression)
         }
-        ExprMethodCall(ref name, ref types, ref arguments) => {
-            visitor.visit_name(name.span, name.node);
+        ExprMethodCall(ref segment, _, ref arguments) => {
+            visitor.visit_path_segment(expression.span, segment);
             walk_list!(visitor, visit_expr, arguments);
-            walk_list!(visitor, visit_ty, types);
         }
         ExprBinary(_, ref left_expression, ref right_expression) => {
             visitor.visit_expr(left_expression);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 1e9314cfde3..67dc069da41 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1845,16 +1845,9 @@ impl<'a> LoweringContext<'a> {
                 hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
             }
             ExprKind::MethodCall(ref seg, ref args) => {
-                let tps = match seg.parameters {
-                    Some(ref params) => match **params {
-                        PathParameters::AngleBracketed(ref param_data) => &param_data.types[..],
-                        _ => &[],
-                    },
-                    _ => &[],
-                };
-                let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
+                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
                 let args = args.iter().map(|x| self.lower_expr(x)).collect();
-                hir::ExprMethodCall(respan(seg.span, self.lower_ident(seg.identifier)), tps, args)
+                hir::ExprMethodCall(hir_seg, seg.span, args)
             }
             ExprKind::Binary(binop, ref lhs, ref rhs) => {
                 let binop = self.lower_binop(binop);
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 3443c6bb2c6..fd79ec3b6b9 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -972,19 +972,16 @@ pub enum Expr_ {
     /// The first field resolves to the function itself (usually an `ExprPath`),
     /// and the second field is the list of arguments
     ExprCall(P<Expr>, HirVec<Expr>),
-    /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
+    /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
     ///
-    /// The `Spanned<Name>` is the identifier for the method name.
-    /// The vector of `Ty`s are the ascripted type parameters for the method
+    /// The `PathSegment`/`Span` represent the method name and its generic arguments
     /// (within the angle brackets).
-    ///
-    /// The first element of the vector of `Expr`s is the expression that
-    /// evaluates to the object on which the method is being called on (the
-    /// receiver), and the remaining elements are the rest of the arguments.
-    ///
+    /// The first element of the vector of `Expr`s is the expression that evaluates
+    /// to the object on which the method is being called on (the receiver),
+    /// and the remaining elements are the rest of the arguments.
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
-    /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
-    ExprMethodCall(Spanned<Name>, HirVec<P<Ty>>, HirVec<Expr>),
+    /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
+    ExprMethodCall(PathSegment, Span, HirVec<Expr>),
     /// A tuple (`(a, b, c ,d)`)
     ExprTup(HirVec<Expr>),
     /// A binary operation (For example: `a + b`, `a * b`)
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index f32fab7d847..1f7b73d1345 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1188,18 +1188,17 @@ impl<'a> State<'a> {
     }
 
     fn print_expr_method_call(&mut self,
-                              name: Spanned<ast::Name>,
-                              tys: &[P<hir::Ty>],
+                              segment: &hir::PathSegment,
                               args: &[hir::Expr])
                               -> io::Result<()> {
         let base_args = &args[1..];
         self.print_expr(&args[0])?;
         word(&mut self.s, ".")?;
-        self.print_name(name.node)?;
-        if !tys.is_empty() {
-            word(&mut self.s, "::<")?;
-            self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?;
-            word(&mut self.s, ">")?;
+        self.print_name(segment.name)?;
+        if !segment.parameters.lifetimes().is_empty() ||
+                !segment.parameters.types().is_empty() ||
+                !segment.parameters.bindings().is_empty() {
+            self.print_path_parameters(&segment.parameters, true)?;
         }
         self.print_call_post(base_args)
     }
@@ -1254,8 +1253,8 @@ impl<'a> State<'a> {
             hir::ExprCall(ref func, ref args) => {
                 self.print_expr_call(&func, args)?;
             }
-            hir::ExprMethodCall(name, ref tys, ref args) => {
-                self.print_expr_method_call(name, &tys[..], args)?;
+            hir::ExprMethodCall(ref segment, _, ref args) => {
+                self.print_expr_method_call(segment, args)?;
             }
             hir::ExprBinary(op, ref lhs, ref rhs) => {
                 self.print_expr_binary(op, &lhs, &rhs)?;
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 7f7a545df96..c82fea197fb 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -626,7 +626,7 @@ impl_stable_hash_for!(enum hir::Expr_ {
     ExprBox(sub),
     ExprArray(subs),
     ExprCall(callee, args),
-    ExprMethodCall(name, ts, args),
+    ExprMethodCall(segment, span, args),
     ExprTup(fields),
     ExprBinary(op, lhs, rhs),
     ExprUnary(op, operand),
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 051b89219c1..4a74a9e524d 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -670,10 +670,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                     return;
                 }
             }
-            hir::ExprMethodCall(name, ..) => {
+            hir::ExprMethodCall(_, span, _) => {
                 // Method calls have to be checked specially.
                 let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
-                self.span = name.span;
+                self.span = span;
                 if self.tcx.type_of(def_id).visit_with(self) {
                     return;
                 }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 209245187b1..0829951e12d 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -44,15 +44,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                           call_expr: &'gcx hir::Expr,
                           unadjusted_self_ty: Ty<'tcx>,
                           pick: probe::Pick<'tcx>,
-                          supplied_method_types: Vec<Ty<'tcx>>)
+                          segment: &hir::PathSegment)
                           -> MethodCallee<'tcx> {
-        debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
+        debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
                unadjusted_self_ty,
                pick,
-               supplied_method_types);
+               segment.parameters);
 
         let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
-        confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
+        confirm_cx.confirm(unadjusted_self_ty, pick, segment)
     }
 }
 
@@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
     fn confirm(&mut self,
                unadjusted_self_ty: Ty<'tcx>,
                pick: probe::Pick<'tcx>,
-               supplied_method_types: Vec<Ty<'tcx>>)
+               segment: &hir::PathSegment)
                -> MethodCallee<'tcx> {
         // Adjust the self expression the user provided and obtain the adjusted type.
         let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
@@ -83,7 +83,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
         // Create substitutions for the method's type parameters.
         let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
-        let all_substs = self.instantiate_method_substs(&pick, supplied_method_types, rcvr_substs);
+        let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);
 
         debug!("all_substs={:?}", all_substs);
 
@@ -279,9 +279,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
     fn instantiate_method_substs(&mut self,
                                  pick: &probe::Pick<'tcx>,
-                                 mut supplied_method_types: Vec<Ty<'tcx>>,
+                                 segment: &hir::PathSegment,
                                  substs: &Substs<'tcx>)
                                  -> &'tcx Substs<'tcx> {
+        let supplied_method_types = match segment.parameters {
+            hir::AngleBracketedParameters(ref data) => &data.types,
+            _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
+        };
+
         // Determine the values for the generic parameters of the method.
         // If they were not explicitly supplied, just construct fresh
         // variables.
@@ -312,7 +317,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                                          num_method_types))
                     .emit();
             }
-            supplied_method_types = vec![self.tcx.types.err; num_method_types];
         }
 
         // Create subst for early-bound lifetime parameters, combining
@@ -331,10 +335,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             let i = def.index as usize;
             if i < substs.len() {
                 substs.type_at(i)
-            } else if supplied_method_types.is_empty() {
-                self.type_var_for_def(self.span, def, cur_substs)
+            } else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) {
+                self.to_ty(ast_ty)
             } else {
-                supplied_method_types[i - supplied_start]
+                self.type_var_for_def(self.span, def, cur_substs)
             }
         })
     }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 4f4169ac93d..c842e47aaf5 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -130,22 +130,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     /// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`)
     /// * `self_expr`:             the self expression (`foo`)
     pub fn lookup_method(&self,
-                         span: Span,
-                         method_name: ast::Name,
                          self_ty: ty::Ty<'tcx>,
-                         supplied_method_types: Vec<ty::Ty<'tcx>>,
+                         segment: &hir::PathSegment,
+                         span: Span,
                          call_expr: &'gcx hir::Expr,
                          self_expr: &'gcx hir::Expr)
                          -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
         debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
-               method_name,
+               segment.name,
                self_ty,
                call_expr,
                self_expr);
 
         let mode = probe::Mode::MethodCall;
         let self_ty = self.resolve_type_vars_if_possible(&self_ty);
-        let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false),
+        let pick = self.probe_for_name(span, mode, segment.name, IsSuggestion(false),
                                        self_ty, call_expr.id)?;
 
         if let Some(import_id) = pick.import_id {
@@ -161,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                call_expr,
                                self_ty,
                                pick,
-                               supplied_method_types))
+                               segment))
     }
 
     /// `lookup_method_in_trait` is used for overloaded operators.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f8c7bfc27a2..2634e8fcc00 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2771,22 +2771,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // Checks a method call.
     fn check_method_call(&self,
                          expr: &'gcx hir::Expr,
-                         method_name: Spanned<ast::Name>,
+                         segment: &hir::PathSegment,
+                         span: Span,
                          args: &'gcx [hir::Expr],
-                         tps: &[P<hir::Ty>],
                          expected: Expectation<'tcx>,
                          lvalue_pref: LvaluePreference) -> Ty<'tcx> {
         let rcvr = &args[0];
         let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref);
-
         // no need to check for bot/err -- callee does that
-        let expr_t = self.structurally_resolved_type(expr.span, rcvr_t);
+        let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t);
 
-        let tps = tps.iter().map(|ast_ty| self.to_ty(&ast_ty)).collect::<Vec<_>>();
-        let method = match self.lookup_method(method_name.span,
-                                              method_name.node,
-                                              expr_t,
-                                              tps,
+        let method = match self.lookup_method(rcvr_t,
+                                              segment,
+                                              span,
                                               expr,
                                               rcvr) {
             Ok(method) => {
@@ -2794,10 +2791,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 Ok(method)
             }
             Err(error) => {
-                if method_name.node != keywords::Invalid.name() {
-                    self.report_method_error(method_name.span,
-                                             expr_t,
-                                             method_name.node,
+                if segment.name != keywords::Invalid.name() {
+                    self.report_method_error(span,
+                                             rcvr_t,
+                                             segment.name,
                                              Some(rcvr),
                                              error,
                                              Some(args));
@@ -2807,7 +2804,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         };
 
         // Call the generic checker.
-        self.check_method_argument_types(method_name.span, method,
+        self.check_method_argument_types(span, method,
                                          &args[1..],
                                          DontTupleArguments,
                                          expected)
@@ -3735,8 +3732,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
           hir::ExprCall(ref callee, ref args) => {
               self.check_call(expr, &callee, args, expected)
           }
-          hir::ExprMethodCall(name, ref tps, ref args) => {
-              self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
+          hir::ExprMethodCall(ref segment, span, ref args) => {
+              self.check_method_call(expr, segment, span, args, expected, lvalue_pref)
           }
           hir::ExprCast(ref e, ref t) => {
             // Find the type of `e`. Supply hints based on the type we are casting to,