Skip to content

Commit 3b1ab62

Browse files
committed
WIP method suggestion jamboree
1 parent d8d5b61 commit 3b1ab62

File tree

2 files changed

+36
-40
lines changed

2 files changed

+36
-40
lines changed

Diff for: src/librustc_typeck/check/demand.rs

+34-38
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::ops::Deref;
1112

1213
use check::FnCtxt;
1314
use rustc::infer::InferOk;
@@ -18,7 +19,7 @@ use syntax_pos::{self, Span};
1819
use rustc::hir;
1920
use rustc::hir::print;
2021
use rustc::hir::def::Def;
21-
use rustc::ty::{self, Ty, AssociatedItem};
22+
use rustc::ty::{self, Ty, AssociatedItem, AssociatedItemContainer};
2223
use errors::{DiagnosticBuilder, CodeMapper};
2324

2425
use super::method::probe;
@@ -139,49 +140,44 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
139140
expected) {
140141
err.help(&suggestion);
141142
} else {
142-
let mode = probe::Mode::MethodCall;
143-
let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
144-
mode,
145-
expected,
146-
checked_ty,
147-
ast::DUMMY_NODE_ID);
148-
if suggestions.len() > 0 {
149-
err.help(&format!("here are some functions which \
150-
might fulfill your needs:\n{}",
151-
self.get_best_match(&suggestions).join("\n")));
152-
}
143+
let suggestions = self.get_conversion_suggestions(expected, checked_ty);
144+
err.span_suggestions(expr.span.next_point(),
145+
"try using a conversion method",
146+
suggestions);
153147
}
154148
(expected, Some(err))
155149
}
156150

157-
fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
158-
format!("- .{}({})",
159-
method.name,
160-
if self.has_no_input_arg(method) {
161-
""
162-
} else {
163-
"..."
164-
})
165-
}
151+
fn get_conversion_suggestions(&self, expected: Ty<'tcx>, checked_ty: Ty<'tcx>) -> Vec<String> {
152+
let mut methods = self.probe_for_return_type(syntax_pos::DUMMY_SP,
153+
probe::Mode::MethodCall,
154+
expected,
155+
checked_ty,
156+
ast::DUMMY_NODE_ID);
166157

167-
fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> Vec<String> {
168-
methods.iter()
169-
.take(5)
170-
.map(|method| self.format_method_suggestion(&*method))
171-
.collect::<Vec<String>>()
172-
}
158+
// We want methods with no arguments that are plausibly conversions:
159+
// though a whitelist of trait DefIDs might be a better way of doing
160+
// this (FIXME!), we presently resort to the expediency of detecting
161+
// conversions by both name, and whether the method comes from a trait
162+
// (thereby picking methods from traits like `Into<_>` and `ToString`,
163+
// rather than inherent methods that merely have a suggestive name)
164+
let conversion_method_name = |n: &str| {
165+
n.starts_with("to_") || n.starts_with("into") ||
166+
n.starts_with("as_") || n.starts_with("borrow")
167+
};
168+
methods.retain(|m| {
169+
if !self.has_no_input_arg(m) {
170+
return false;
171+
}
172+
if let AssociatedItemContainer::TraitContainer(_def_id) = m.container {
173+
let name = m.name.as_str();
174+
conversion_method_name(name.deref())
175+
} else {
176+
false
177+
}
178+
});
173179

174-
fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
175-
let no_argument_methods: Vec<_> =
176-
methods.iter()
177-
.filter(|ref x| self.has_no_input_arg(&*x))
178-
.map(|x| x.clone())
179-
.collect();
180-
if no_argument_methods.len() > 0 {
181-
self.display_suggested_methods(&no_argument_methods)
182-
} else {
183-
self.display_suggested_methods(&methods)
184-
}
180+
methods.into_iter().map(|m| format!(".{}()", m.name)).collect()
185181
}
186182

187183
// This function checks if the method isn't static and takes other arguments than `self`.

Diff for: src/librustc_typeck/check/method/probe.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
183183
scope_expr_id);
184184
let method_names =
185185
self.probe_op(span, mode, None, Some(return_type), IsSuggestion(true),
186-
self_ty, scope_expr_id, ProbeScope::TraitsInScope,
186+
self_ty, scope_expr_id, ProbeScope::AllTraits,
187187
|probe_cx| Ok(probe_cx.candidate_method_names()))
188188
.unwrap_or(vec![]);
189189
method_names
@@ -192,7 +192,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
192192
self.probe_op(
193193
span, mode, Some(method_name), Some(return_type),
194194
IsSuggestion(true), self_ty, scope_expr_id,
195-
ProbeScope::TraitsInScope, |probe_cx| probe_cx.pick()
195+
ProbeScope::AllTraits, |probe_cx| probe_cx.pick()
196196
).ok().map(|pick| pick.item)
197197
})
198198
.collect()

0 commit comments

Comments
 (0)