about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-12-10 11:05:16 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-12-10 12:02:18 -0800
commit5d1adbb629623b10324ba32a0ff2179b9358cab7 (patch)
treea937d47be2bee11b65af527f6272f83255c8ab41
parent6b76d82b1395e42693cf227169ef2bfd32b8418e (diff)
downloadrust-5d1adbb629623b10324ba32a0ff2179b9358cab7.tar.gz
rust-5d1adbb629623b10324ba32a0ff2179b9358cab7.zip
Use `generics_of` instead of incorrectly inspecting `FnSig` arguments
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs53
-rw-r--r--src/librustc/ty/context.rs16
-rw-r--r--src/librustc_typeck/check/expr.rs6
3 files changed, 48 insertions, 27 deletions
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 55a95d05698..487736dee30 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -377,7 +377,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             err.span_label(pattern.span, msg);
         } else if let Some(e) = local_visitor.found_method_call {
             if let ExprKind::MethodCall(segment, ..) = &e.kind {
-                // Suggest specifiying type params or point out the return type of the call.
+                // Suggest specifiying type params or point out the return type of the call:
+                //
+                // error[E0282]: type annotations needed
+                //   --> $DIR/type-annotations-needed-expr.rs:2:39
+                //    |
+                // LL |     let _ = x.into_iter().sum() as f64;
+                //    |                           ^^^
+                //    |                           |
+                //    |                           cannot infer type for `S`
+                //    |                           help: consider specifying the type argument in
+                //    |                           the method call: `sum::<S>`
+                //    |
+                //    = note: type must be known at this point
+                //
+                // or
+                //
+                // error[E0282]: type annotations needed
+                //   --> $DIR/issue-65611.rs:59:20
+                //    |
+                // LL |     let x = buffer.last().unwrap().0.clone();
+                //    |             -------^^^^--
+                //    |             |      |
+                //    |             |      cannot infer type for `T`
+                //    |             this method call resolves to `std::option::Option<&T>`
+                //    |
+                //    = note: type must be known at this point
                 self.annotate_method_call(segment, e, &mut err);
             }
         }
@@ -422,34 +447,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             &segment.args,
         ) {
             let borrow = tables.borrow();
-            let sigs = borrow.node_method_sig();
-            if let Some(sig) = sigs.get(e.hir_id) {
-                let mut params = vec![];
-                for arg in sig.inputs_and_output().skip_binder().iter() {
-                    if let ty::Param(param) = arg.kind {
-                        if param.name != kw::SelfUpper {
-                            let name = param.name.to_string();
-                            if !params.contains(&name) {
-                                params.push(name);
-                            }
-                        }
-                    }
-                }
-                if !params.is_empty() {
+            let method_defs = borrow.node_method_def_id();
+            if let Some(did) = method_defs.get(e.hir_id) {
+                let generics = self.tcx.generics_of(*did);
+                if !generics.params.is_empty() {
                     err.span_suggestion(
                         segment.ident.span,
                         &format!(
                             "consider specifying the type argument{} in the method call",
-                            if params.len() > 1 {
+                            if generics.params.len() > 1 {
                                 "s"
                             } else {
                                 ""
                             },
                         ),
-                        format!("{}::<{}>", snippet, params.join(", ")),
+                        format!("{}::<{}>", snippet, generics.params.iter()
+                            .map(|p| p.name.to_string())
+                            .collect::<Vec<String>>()
+                            .join(", ")),
                         Applicability::HasPlaceholders,
                     );
                 } else {
+                    let sig = self.tcx.fn_sig(*did);
                     err.span_label(e.span, &format!(
                         "this method call resolves to `{:?}`",
                         sig.output().skip_binder(),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 2da43bdcc1e..fa4ad021072 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -338,7 +338,7 @@ pub struct TypeckTables<'tcx> {
     /// typeck::check::fn_ctxt for details.
     node_types: ItemLocalMap<Ty<'tcx>>,
 
-    node_method_sig: ItemLocalMap<ty::PolyFnSig<'tcx>>,
+    node_method_def_id: ItemLocalMap<DefId>,
 
     /// Stores the type parameters which were substituted to obtain the type
     /// of this node. This only applies to nodes that refer to entities
@@ -444,7 +444,7 @@ impl<'tcx> TypeckTables<'tcx> {
             user_provided_types: Default::default(),
             user_provided_sigs: Default::default(),
             node_types: Default::default(),
-            node_method_sig: Default::default(),
+            node_method_def_id: Default::default(),
             node_substs: Default::default(),
             adjustments: Default::default(),
             pat_binding_modes: Default::default(),
@@ -545,17 +545,17 @@ impl<'tcx> TypeckTables<'tcx> {
         }
     }
 
-    pub fn node_method_sig(&self) -> LocalTableInContext<'_, ty::PolyFnSig<'tcx>> {
+    pub fn node_method_def_id(&self) -> LocalTableInContext<'_, DefId> {
         LocalTableInContext {
             local_id_root: self.local_id_root,
-            data: &self.node_method_sig
+            data: &self.node_method_def_id
         }
     }
 
-    pub fn node_method_sig_mut(&mut self) -> LocalTableInContextMut<'_, ty::PolyFnSig<'tcx>> {
+    pub fn node_method_def_id_mut(&mut self) -> LocalTableInContextMut<'_, DefId> {
         LocalTableInContextMut {
             local_id_root: self.local_id_root,
-            data: &mut self.node_method_sig
+            data: &mut self.node_method_def_id
         }
     }
 
@@ -765,7 +765,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             ref user_provided_types,
             ref user_provided_sigs,
             ref node_types,
-            ref node_method_sig,
+            ref node_method_def_id,
             ref node_substs,
             ref adjustments,
             ref pat_binding_modes,
@@ -792,7 +792,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             user_provided_types.hash_stable(hcx, hasher);
             user_provided_sigs.hash_stable(hcx, hasher);
             node_types.hash_stable(hcx, hasher);
-            node_method_sig.hash_stable(hcx, hasher);
+            node_method_def_id.hash_stable(hcx, hasher);
             node_substs.hash_stable(hcx, hasher);
             adjustments.hash_stable(hcx, hasher);
             pat_binding_modes.hash_stable(hcx, hasher);
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 5f971a1ad50..999038e7ea7 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -871,7 +871,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) {
             Ok(method) => {
-                let sig = self.tcx.fn_sig(method.def_id);
                 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
                 // trigger this codepath causing `structuraly_resolved_type` to emit an error.
 
@@ -890,7 +889,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 //    |
                 //    = note: type must be known at this point
                 // ```
-                self.tables.borrow_mut().node_method_sig_mut().insert(expr.hir_id, sig);
+                self.tables.borrow_mut().node_method_def_id_mut().insert(
+                    expr.hir_id,
+                    method.def_id,
+                );
 
                 self.write_method_call(expr.hir_id, method);
                 Ok(method)