]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/check/method/suggest.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / compiler / rustc_typeck / src / check / method / suggest.rs
CommitLineData
d9579d0f 1//! Give useful errors and suggestions to users when an item can't be
85aaf69f
SL
2//! found or is otherwise invalid.
3
9fa01778 4use crate::check::FnCtxt;
74b04a01 5use rustc_data_structures::fx::{FxHashMap, FxHashSet};
dfeec247
XL
6use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
7use rustc_hir as hir;
74b04a01 8use rustc_hir::def::{DefKind, Namespace, Res};
dfeec247
XL
9use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
10use rustc_hir::intravisit;
3dfed10e 11use rustc_hir::lang_items::LangItem;
dfeec247 12use rustc_hir::{ExprKind, Node, QPath};
74b04a01 13use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
fc512014 14use rustc_middle::ty::fast_reject::simplify_type;
ba9703b0
XL
15use rustc_middle::ty::print::with_crate_prefix;
16use rustc_middle::ty::{
17 self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
18};
fc512014 19use rustc_span::lev_distance;
3dfed10e 20use rustc_span::symbol::{kw, sym, Ident};
dfeec247 21use rustc_span::{source_map, FileName, Span};
ba9703b0
XL
22use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
23use rustc_trait_selection::traits::Obligation;
85aaf69f 24
85aaf69f 25use std::cmp::Ordering;
6a06907d 26use std::iter;
85aaf69f 27
d9579d0f 28use super::probe::Mode;
dfeec247 29use super::{CandidateSource, MethodError, NoMatchData};
85aaf69f 30
dc9dc135 31impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
48663c56 32 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
a7813a04 33 let tcx = self.tcx;
1b1a35ee 34 match ty.kind() {
0731742a
XL
35 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
36 // so we look for these beforehand.
dfeec247 37 ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
0731742a 38 // If it's not a simple function, look for things which implement `FnOnce`.
a7813a04 39 _ => {
3dfed10e 40 let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
3157f602 41 Ok(fn_once) => fn_once,
c30ab7b3 42 Err(..) => return false,
3157f602 43 };
a7813a04 44
c30ab7b3
SL
45 self.autoderef(span, ty).any(|(ty, _)| {
46 self.probe(|_| {
dfeec247
XL
47 let fn_once_substs = tcx.mk_substs_trait(
48 ty,
49 &[self
50 .next_ty_var(TypeVariableOrigin {
51 kind: TypeVariableOriginKind::MiscVariable,
52 span,
53 })
54 .into()],
55 );
c30ab7b3
SL
56 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
57 let poly_trait_ref = trait_ref.to_poly_trait_ref();
dfeec247
XL
58 let obligation = Obligation::misc(
59 span,
60 self.body_id,
61 self.param_env,
f9f354fc 62 poly_trait_ref.without_const().to_predicate(tcx),
dfeec247 63 );
83c7162d 64 self.predicate_may_hold(&obligation)
c30ab7b3
SL
65 })
66 })
54a0048b
SL
67 }
68 }
69 }
3157f602 70
532ac7d7
XL
71 pub fn report_method_error<'b>(
72 &self,
73 span: Span,
74 rcvr_ty: Ty<'tcx>,
f9f354fc 75 item_name: Ident,
532ac7d7
XL
76 source: SelfSource<'b>,
77 error: MethodError<'tcx>,
dfeec247 78 args: Option<&'tcx [hir::Expr<'tcx>]>,
e1599b0c 79 ) -> Option<DiagnosticBuilder<'_>> {
532ac7d7
XL
80 let orig_span = span;
81 let mut span = span;
0731742a 82 // Avoid suggestions when we don't know what's going on.
a7813a04 83 if rcvr_ty.references_error() {
e1599b0c 84 return None;
a7813a04 85 }
85aaf69f 86
dfeec247
XL
87 let report_candidates = |span: Span,
88 err: &mut DiagnosticBuilder<'_>,
89 mut sources: Vec<CandidateSource>,
90 sugg_span: Span| {
a7813a04
XL
91 sources.sort();
92 sources.dedup();
93 // Dynamic limit to avoid hiding just one candidate, which is silly.
94 let limit = if sources.len() == 5 { 5 } else { 4 };
95
96 for (idx, source) in sources.iter().take(limit).enumerate() {
97 match *source {
98 CandidateSource::ImplSource(impl_did) => {
99 // Provide the best span we can. Use the item, if local to crate, else
100 // the impl, if local to crate (item may be defaulted), else nothing.
dfeec247 101 let item = match self
74b04a01 102 .associated_item(impl_did, item_name, Namespace::ValueNS)
dfeec247
XL
103 .or_else(|| {
104 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
105 self.associated_item(
106 impl_trait_ref.def_id,
107 item_name,
74b04a01 108 Namespace::ValueNS,
dfeec247
XL
109 )
110 }) {
48663c56
XL
111 Some(item) => item,
112 None => continue,
113 };
dfeec247
XL
114 let note_span = self
115 .tcx
116 .hir()
117 .span_if_local(item.def_id)
118 .or_else(|| self.tcx.hir().span_if_local(impl_did));
a7813a04 119
ba9703b0 120 let impl_ty = self.tcx.at(span).type_of(impl_did);
a7813a04
XL
121
122 let insertion = match self.tcx.impl_trait_ref(impl_did) {
8faf50e0 123 None => String::new(),
dfeec247
XL
124 Some(trait_ref) => format!(
125 " of the trait `{}`",
126 self.tcx.def_path_str(trait_ref.def_id)
127 ),
a7813a04
XL
128 };
129
dfeec247
XL
130 let (note_str, idx) = if sources.len() > 1 {
131 (
132 format!(
133 "candidate #{} is defined in an impl{} for the type `{}`",
94b46f34
XL
134 idx + 1,
135 insertion,
dfeec247
XL
136 impl_ty,
137 ),
138 Some(idx + 1),
139 )
94b46f34 140 } else {
dfeec247
XL
141 (
142 format!(
143 "the candidate is defined in an impl{} for the type `{}`",
144 insertion, impl_ty,
145 ),
146 None,
147 )
94b46f34 148 };
a7813a04
XL
149 if let Some(note_span) = note_span {
150 // We have a span pointing to the method. Show note with snippet.
dfeec247 151 err.span_note(
ba9703b0 152 self.tcx.sess.source_map().guess_head_span(note_span),
dfeec247
XL
153 &note_str,
154 );
a7813a04
XL
155 } else {
156 err.note(&note_str);
157 }
416331ca 158 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
dfeec247
XL
159 let path = self.tcx.def_path_str(trait_ref.def_id);
160
161 let ty = match item.kind {
f035d41b 162 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
ba9703b0 163 ty::AssocKind::Fn => self
dfeec247
XL
164 .tcx
165 .fn_sig(item.def_id)
166 .inputs()
167 .skip_binder()
168 .get(0)
169 .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
74b04a01 170 .copied()
dfeec247
XL
171 .unwrap_or(rcvr_ty),
172 };
173 print_disambiguation_help(
174 item_name,
175 args,
176 err,
177 path,
178 ty,
179 item.kind,
ba9703b0 180 item.def_id,
dfeec247
XL
181 sugg_span,
182 idx,
183 self.tcx.sess.source_map(),
184 );
416331ca 185 }
a7813a04
XL
186 }
187 CandidateSource::TraitSource(trait_did) => {
dfeec247 188 let item =
74b04a01 189 match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
dfeec247
XL
190 Some(item) => item,
191 None => continue,
192 };
ba9703b0
XL
193 let item_span = self
194 .tcx
195 .sess
196 .source_map()
197 .guess_head_span(self.tcx.def_span(item.def_id));
dfeec247
XL
198 let idx = if sources.len() > 1 {
199 let msg = &format!(
200 "candidate #{} is defined in the trait `{}`",
201 idx + 1,
202 self.tcx.def_path_str(trait_did)
203 );
204 err.span_note(item_span, msg);
205 Some(idx + 1)
94b46f34 206 } else {
dfeec247
XL
207 let msg = &format!(
208 "the candidate is defined in the trait `{}`",
209 self.tcx.def_path_str(trait_did)
210 );
211 err.span_note(item_span, msg);
212 None
213 };
214 let path = self.tcx.def_path_str(trait_did);
215 print_disambiguation_help(
216 item_name,
217 args,
218 err,
219 path,
220 rcvr_ty,
221 item.kind,
ba9703b0 222 item.def_id,
dfeec247
XL
223 sugg_span,
224 idx,
225 self.tcx.sess.source_map(),
226 );
9cc50fc6 227 }
54a0048b
SL
228 }
229 }
a7813a04
XL
230 if sources.len() > limit {
231 err.note(&format!("and {} others", sources.len() - limit));
232 }
233 };
62682a34 234
dfeec247
XL
235 let sugg_span = if let SelfSource::MethodCall(expr) = source {
236 // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
237 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
238 } else {
239 span
240 };
241
a7813a04 242 match error {
ff7c6d11
XL
243 MethodError::NoMatch(NoMatchData {
244 static_candidates: static_sources,
245 unsatisfied_predicates,
246 out_of_scope_traits,
247 lev_candidate,
248 mode,
ff7c6d11 249 }) => {
a7813a04
XL
250 let tcx = self.tcx;
251
fc512014 252 let actual = self.resolve_vars_if_possible(rcvr_ty);
0731742a 253 let ty_str = self.ty_to_string(actual);
ff7c6d11 254 let is_method = mode == Mode::MethodCall;
94b46f34 255 let item_kind = if is_method {
ff7c6d11
XL
256 "method"
257 } else if actual.is_enum() {
48663c56 258 "variant or associated item"
ff7c6d11
XL
259 } else {
260 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
dfeec247 261 (Some(name), false) if name.is_lowercase() => "function or associated item",
ff7c6d11 262 (Some(_), false) => "associated item",
dfeec247 263 (Some(_), true) | (None, false) => "variant or associated item",
ff7c6d11
XL
264 (None, true) => "variant",
265 }
266 };
7cac9316 267 let mut err = if !actual.references_error() {
2c00a5a8 268 // Suggest clamping down the type if the method that is being attempted to
e74abb32 269 // be used exists at all, and the type is an ambiguous numeric type
2c00a5a8 270 // ({integer}/{float}).
dfeec247 271 let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
74b04a01 272 self.associated_item(info.def_id, item_name, Namespace::ValueNS)
dfeec247 273 });
ba9703b0
XL
274 // There are methods that are defined on the primitive types and won't be
275 // found when exploring `all_traits`, but we also need them to be acurate on
276 // our suggestions (#47759).
277 let fund_assoc = |opt_def_id: Option<DefId>| {
278 opt_def_id
279 .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
280 .is_some()
281 };
282 let lang_items = tcx.lang_items();
283 let found_candidate = candidates.next().is_some()
284 || fund_assoc(lang_items.i8_impl())
285 || fund_assoc(lang_items.i16_impl())
286 || fund_assoc(lang_items.i32_impl())
287 || fund_assoc(lang_items.i64_impl())
288 || fund_assoc(lang_items.i128_impl())
289 || fund_assoc(lang_items.u8_impl())
290 || fund_assoc(lang_items.u16_impl())
291 || fund_assoc(lang_items.u32_impl())
292 || fund_assoc(lang_items.u64_impl())
293 || fund_assoc(lang_items.u128_impl())
294 || fund_assoc(lang_items.f32_impl())
295 || fund_assoc(lang_items.f32_runtime_impl())
296 || fund_assoc(lang_items.f64_impl())
297 || fund_assoc(lang_items.f64_runtime_impl());
298 if let (true, false, SelfSource::MethodCall(expr), true) = (
dfeec247
XL
299 actual.is_numeric(),
300 actual.has_concrete_skeleton(),
301 source,
ba9703b0 302 found_candidate,
dfeec247 303 ) {
2c00a5a8
XL
304 let mut err = struct_span_err!(
305 tcx.sess,
306 span,
307 E0689,
308 "can't call {} `{}` on ambiguous numeric type `{}`",
94b46f34 309 item_kind,
2c00a5a8 310 item_name,
0731742a 311 ty_str
2c00a5a8 312 );
dfeec247 313 let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
e74abb32 314 match expr.kind {
0731742a
XL
315 ExprKind::Lit(ref lit) => {
316 // numeric literal
dfeec247
XL
317 let snippet = tcx
318 .sess
319 .source_map()
320 .span_to_snippet(lit.span)
0bf4aa26 321 .unwrap_or_else(|_| "<numeric literal>".to_owned());
2c00a5a8 322
9fa01778
XL
323 err.span_suggestion(
324 lit.span,
dfeec247
XL
325 &format!(
326 "you must specify a concrete type for \
327 this numeric value, like `{}`",
328 concrete_type
329 ),
9fa01778
XL
330 format!("{}_{}", snippet, concrete_type),
331 Applicability::MaybeIncorrect,
0bf4aa26 332 );
2c00a5a8 333 }
0731742a
XL
334 ExprKind::Path(ref qpath) => {
335 // local binding
5869c6ff 336 if let QPath::Resolved(_, path) = qpath {
48663c56 337 if let hir::def::Res::Local(hir_id) = path.res {
dc9dc135 338 let span = tcx.hir().span(hir_id);
48663c56 339 let snippet = tcx.sess.source_map().span_to_snippet(span);
b7449926 340 let filename = tcx.sess.source_map().span_to_filename(span);
8faf50e0 341
dfeec247
XL
342 let parent_node = self
343 .tcx
344 .hir()
345 .get(self.tcx.hir().get_parent_node(hir_id));
8faf50e0
XL
346 let msg = format!(
347 "you must specify a type for this binding, like `{}`",
348 concrete_type,
349 );
350
48663c56 351 match (filename, parent_node, snippet) {
dfeec247
XL
352 (
353 FileName::Real(_),
354 Node::Local(hir::Local {
355 source: hir::LocalSource::Normal,
356 ty,
357 ..
358 }),
359 Ok(ref snippet),
360 ) => {
9fa01778 361 err.span_suggestion(
8faf50e0
XL
362 // account for `let x: _ = 42;`
363 // ^^^^
dfeec247
XL
364 span.to(ty
365 .as_ref()
366 .map(|ty| ty.span)
8faf50e0
XL
367 .unwrap_or(span)),
368 &msg,
369 format!("{}: {}", snippet, concrete_type),
0bf4aa26 370 Applicability::MaybeIncorrect,
8faf50e0
XL
371 );
372 }
373 _ => {
374 err.span_label(span, msg);
375 }
376 }
2c00a5a8
XL
377 }
378 }
379 }
380 _ => {}
381 }
382 err.emit();
e1599b0c 383 return None;
2c00a5a8 384 } else {
532ac7d7 385 span = item_name.span;
0531ce1d 386 let mut err = struct_span_err!(
2c00a5a8 387 tcx.sess,
532ac7d7 388 span,
2c00a5a8 389 E0599,
dfeec247 390 "no {} named `{}` found for {} `{}` in the current scope",
94b46f34 391 item_kind,
2c00a5a8 392 item_name,
6a06907d 393 actual.prefix_string(self.tcx),
dfeec247 394 ty_str,
0531ce1d 395 );
1b1a35ee
XL
396 if let Mode::MethodCall = mode {
397 if let SelfSource::MethodCall(call) = source {
398 self.suggest_await_before_method(
399 &mut err, item_name, actual, call, span,
400 );
401 }
402 }
dfeec247
XL
403 if let Some(span) =
404 tcx.sess.confused_type_with_std_module.borrow().get(&span)
48663c56
XL
405 {
406 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
407 err.span_suggestion(
408 *span,
409 "you are looking for the module in `std`, \
410 not the primitive type",
411 format!("std::{}", snippet),
412 Applicability::MachineApplicable,
413 );
414 }
0531ce1d 415 }
1b1a35ee 416 if let ty::RawPtr(_) = &actual.kind() {
dfeec247
XL
417 err.note(
418 "try using `<*const T>::as_ref()` to get a reference to the \
dc9dc135 419 type behind the pointer: https://doc.rust-lang.org/std/\
dfeec247
XL
420 primitive.pointer.html#method.as_ref",
421 );
422 err.note(
423 "using `<*const T>::as_ref()` on a pointer \
416331ca 424 which is unaligned or points to invalid \
dfeec247
XL
425 or uninitialized memory is undefined behavior",
426 );
dc9dc135 427 }
0531ce1d 428 err
2c00a5a8 429 }
7cac9316 430 } else {
ff7c6d11 431 tcx.sess.diagnostic().struct_dummy()
7cac9316 432 };
5bcae85e 433
94b46f34 434 if let Some(def) = actual.ty_adt_def() {
0731742a 435 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
ba9703b0 436 let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
dfeec247
XL
437 err.span_label(
438 def_sp,
439 format!(
440 "{} `{}` not found {}",
441 item_kind,
442 item_name,
443 if def.is_enum() && !is_method { "here" } else { "for this" }
444 ),
445 );
ff7c6d11
XL
446 }
447 }
448
5869c6ff
XL
449 let mut label_span_not_found = || {
450 if unsatisfied_predicates.is_empty() {
451 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
452 } else {
453 err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
454 }
455 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
456 };
457
5bcae85e 458 // If the method name is the name of a field with a function or closure type,
0731742a
XL
459 // give a helping note that it has to be called as `(x.f)(...)`.
460 if let SelfSource::MethodCall(expr) = source {
dfeec247 461 let field_receiver =
1b1a35ee 462 self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
532ac7d7 463 ty::Adt(def, substs) if !def.is_enum() => {
83c7162d 464 let variant = &def.non_enum_variant();
532ac7d7 465 self.tcx.find_field_index(item_name, variant).map(|index| {
83c7162d 466 let field = &variant.fields[index];
9e0c209e 467 let field_ty = field.ty(tcx, substs);
532ac7d7
XL
468 (field, field_ty)
469 })
470 }
471 _ => None,
472 });
473
474 if let Some((field, field_ty)) = field_receiver {
ba9703b0 475 let scope = self.tcx.parent_module(self.body_id).to_def_id();
532ac7d7
XL
476 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
477
478 if is_accessible {
479 if self.is_fn_ty(&field_ty, span) {
480 let expr_span = expr.span.to(item_name.span);
481 err.multipart_suggestion(
482 &format!(
483 "to call the function stored in `{}`, \
484 surround the field access with parentheses",
485 item_name,
486 ),
487 vec![
488 (expr_span.shrink_to_lo(), '('.to_string()),
489 (expr_span.shrink_to_hi(), ')'.to_string()),
490 ],
491 Applicability::MachineApplicable,
492 );
493 } else {
dfeec247
XL
494 let call_expr = self
495 .tcx
496 .hir()
497 .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
532ac7d7 498
48663c56
XL
499 if let Some(span) = call_expr.span.trim_start(item_name.span) {
500 err.span_suggestion(
501 span,
502 "remove the arguments",
503 String::new(),
504 Applicability::MaybeIncorrect,
505 );
506 }
5bcae85e 507 }
a7813a04 508 }
532ac7d7 509
dfeec247 510 let field_kind = if is_accessible { "field" } else { "private field" };
532ac7d7 511 err.span_label(item_name.span, format!("{}, not a method", field_kind));
e1599b0c 512 } else if lev_candidate.is_none() && static_sources.is_empty() {
5869c6ff 513 label_span_not_found();
54a0048b 514 }
ff7c6d11 515 } else {
5869c6ff 516 label_span_not_found();
54a0048b 517 }
92a42be0 518
a7813a04 519 if self.is_fn_ty(&rcvr_ty, span) {
6a06907d
XL
520 fn report_function<T: std::fmt::Display>(
521 err: &mut DiagnosticBuilder<'_>,
522 name: T,
523 ) {
524 err.note(
525 &format!("`{}` is a function, perhaps you wish to call it", name,),
526 );
54a0048b 527 }
a7813a04 528
0731742a 529 if let SelfSource::MethodCall(expr) = source {
b7449926 530 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
6a06907d 531 report_function(&mut err, expr_string);
dfeec247 532 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
a7813a04 533 if let Some(segment) = path.segments.last() {
6a06907d 534 report_function(&mut err, segment.ident);
a7813a04 535 }
62682a34
SL
536 }
537 }
c34b1796 538 }
85aaf69f 539
a7813a04 540 if !static_sources.is_empty() {
dfeec247
XL
541 err.note(
542 "found the following associated functions; to be used as methods, \
74b04a01 543 functions must have a `self` parameter",
dfeec247 544 );
94b46f34
XL
545 err.span_label(span, "this is an associated function, not a method");
546 }
547 if static_sources.len() == 1 {
dfeec247
XL
548 let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
549 static_sources.get(0)
550 {
e74abb32
XL
551 // When the "method" is resolved through dereferencing, we really want the
552 // original type that has the associated function for accurate suggestions.
553 // (#61411)
ba9703b0 554 let ty = tcx.at(span).type_of(*impl_did);
1b1a35ee 555 match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
e74abb32
XL
556 (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
557 // Use `actual` as it will have more `substs` filled in.
558 self.ty_to_value_string(actual.peel_refs())
559 }
560 _ => self.ty_to_value_string(ty.peel_refs()),
561 }
562 } else {
563 self.ty_to_value_string(actual.peel_refs())
564 };
0731742a 565 if let SelfSource::MethodCall(expr) = source {
e74abb32
XL
566 err.span_suggestion(
567 expr.span.to(span),
568 "use associated function syntax instead",
569 format!("{}::{}", ty_str, item_name),
570 Applicability::MachineApplicable,
571 );
94b46f34 572 } else {
dfeec247 573 err.help(&format!("try with `{}::{}`", ty_str, item_name,));
94b46f34
XL
574 }
575
dfeec247 576 report_candidates(span, &mut err, static_sources, sugg_span);
94b46f34 577 } else if static_sources.len() > 1 {
dfeec247 578 report_candidates(span, &mut err, static_sources, sugg_span);
a7813a04 579 }
85aaf69f 580
74b04a01 581 let mut restrict_type_params = false;
a7813a04 582 if !unsatisfied_predicates.is_empty() {
ba9703b0
XL
583 let def_span = |def_id| {
584 self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
585 };
74b04a01
XL
586 let mut type_params = FxHashMap::default();
587 let mut bound_spans = vec![];
3dfed10e 588
74b04a01 589 let mut collect_type_param_suggestions =
3dfed10e
XL
590 |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
591 // We don't care about regions here, so it's fine to skip the binder here.
5869c6ff
XL
592 if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
593 (self_ty.kind(), parent_pred.kind().skip_binder())
74b04a01 594 {
1b1a35ee 595 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
f9f354fc 596 let node = def.did.as_local().map(|def_id| {
3dfed10e
XL
597 self.tcx
598 .hir()
599 .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
f9f354fc 600 });
ba9703b0
XL
601 if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
602 if let Some(g) = kind.generics() {
6a06907d 603 let key = match g.where_clause.predicates {
ba9703b0
XL
604 [.., pred] => (pred.span().shrink_to_hi(), false),
605 [] => (
606 g.where_clause
607 .span_for_predicates_or_empty_place(),
608 true,
609 ),
610 };
611 type_params
612 .entry(key)
613 .or_insert_with(FxHashSet::default)
614 .insert(obligation.to_owned());
74b04a01 615 }
74b04a01
XL
616 }
617 }
618 }
619 };
620 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
621 let msg = format!(
622 "doesn't satisfy `{}`",
623 if obligation.len() > 50 { quiet } else { obligation }
624 );
1b1a35ee 625 match &self_ty.kind() {
74b04a01
XL
626 // Point at the type that couldn't satisfy the bound.
627 ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
628 // Point at the trait object that couldn't satisfy the bound.
629 ty::Dynamic(preds, _) => {
fc512014
XL
630 for pred in preds.iter() {
631 match pred.skip_binder() {
74b04a01
XL
632 ty::ExistentialPredicate::Trait(tr) => {
633 bound_spans.push((def_span(tr.def_id), msg.clone()))
634 }
635 ty::ExistentialPredicate::Projection(_)
636 | ty::ExistentialPredicate::AutoTrait(_) => {}
637 }
638 }
639 }
640 // Point at the closure that couldn't satisfy the bound.
641 ty::Closure(def_id, _) => bound_spans
642 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
643 _ => {}
644 }
645 };
f9f354fc 646 let mut format_pred = |pred: ty::Predicate<'tcx>| {
5869c6ff 647 let bound_predicate = pred.kind();
29967ef6 648 match bound_predicate.skip_binder() {
5869c6ff 649 ty::PredicateKind::Projection(pred) => {
29967ef6 650 let pred = bound_predicate.rebind(pred);
74b04a01 651 // `<Foo as Iterator>::Item = String`.
6a06907d
XL
652 let projection_ty = pred.skip_binder().projection_ty;
653
654 let substs_with_infer_self = tcx.mk_substs(
655 iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
656 .chain(projection_ty.substs.iter().skip(1)),
74b04a01 657 );
6a06907d
XL
658
659 let quiet_projection_ty = ty::ProjectionTy {
660 substs: substs_with_infer_self,
661 item_def_id: projection_ty.item_def_id,
662 };
663
664 let ty = pred.skip_binder().ty;
665
666 let obligation = format!("{} = {}", projection_ty, ty);
667 let quiet = format!("{} = {}", quiet_projection_ty, ty);
668
669 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
670 Some((obligation, projection_ty.self_ty()))
74b04a01 671 }
5869c6ff 672 ty::PredicateKind::Trait(poly_trait_ref, _) => {
29967ef6 673 let p = poly_trait_ref.trait_ref;
74b04a01
XL
674 let self_ty = p.self_ty();
675 let path = p.print_only_trait_path();
676 let obligation = format!("{}: {}", self_ty, path);
677 let quiet = format!("_: {}", path);
678 bound_span_label(self_ty, &obligation, &quiet);
679 Some((obligation, self_ty))
680 }
681 _ => None,
682 }
683 };
dfeec247
XL
684 let mut bound_list = unsatisfied_predicates
685 .iter()
74b04a01
XL
686 .filter_map(|(pred, parent_pred)| {
687 format_pred(*pred).map(|(p, self_ty)| match parent_pred {
fc512014 688 None => format!("`{}`", &p),
74b04a01 689 Some(parent_pred) => match format_pred(*parent_pred) {
fc512014 690 None => format!("`{}`", &p),
74b04a01
XL
691 Some((parent_p, _)) => {
692 collect_type_param_suggestions(self_ty, parent_pred, &p);
693 format!("`{}`\nwhich is required by `{}`", p, parent_p)
694 }
695 },
696 })
697 })
698 .enumerate()
699 .collect::<Vec<(usize, String)>>();
700 for ((span, empty_where), obligations) in type_params.into_iter() {
701 restrict_type_params = true;
3dfed10e
XL
702 // #74886: Sort here so that the output is always the same.
703 let mut obligations = obligations.into_iter().collect::<Vec<_>>();
704 obligations.sort();
74b04a01
XL
705 err.span_suggestion_verbose(
706 span,
707 &format!(
708 "consider restricting the type parameter{s} to satisfy the \
709 trait bound{s}",
710 s = pluralize!(obligations.len())
711 ),
712 format!(
713 "{} {}",
714 if empty_where { " where" } else { "," },
3dfed10e 715 obligations.join(", ")
74b04a01
XL
716 ),
717 Applicability::MaybeIncorrect,
718 );
719 }
720
721 bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
722 bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
723 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
724 bound_spans.sort();
725 bound_spans.dedup();
726 for (span, msg) in bound_spans.into_iter() {
727 err.span_label(span, &msg);
728 }
729 if !bound_list.is_empty() {
730 let bound_list = bound_list
731 .into_iter()
732 .map(|(_, path)| path)
733 .collect::<Vec<_>>()
734 .join("\n");
6a06907d 735 let actual_prefix = actual.prefix_string(self.tcx);
5869c6ff
XL
736 err.set_primary_message(&format!(
737 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
738 ));
74b04a01 739 err.note(&format!(
5869c6ff 740 "the following trait bounds were not satisfied:\n{bound_list}"
74b04a01
XL
741 ));
742 }
a7813a04 743 }
62682a34 744
74b04a01 745 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
2c00a5a8 746 } else {
dfeec247
XL
747 self.suggest_traits_to_import(
748 &mut err,
749 span,
750 rcvr_ty,
751 item_name,
752 source,
753 out_of_scope_traits,
74b04a01 754 &unsatisfied_predicates,
dfeec247 755 );
2c00a5a8 756 }
ea8adc8c 757
5869c6ff
XL
758 // Don't emit a suggestion if we found an actual method
759 // that had unsatisfied trait bounds
760 if unsatisfied_predicates.is_empty() && actual.is_enum() {
48663c56
XL
761 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
762 if let Some(suggestion) = lev_distance::find_best_match_for_name(
fc512014 763 &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
3dfed10e 764 item_name.name,
48663c56
XL
765 None,
766 ) {
767 err.span_suggestion(
768 span,
769 "there is a variant with a similar name",
770 suggestion.to_string(),
771 Applicability::MaybeIncorrect,
772 );
773 }
774 }
775
e74abb32
XL
776 let mut fallback_span = true;
777 let msg = "remove this method call";
3dfed10e 778 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
e74abb32 779 if let SelfSource::MethodCall(expr) = source {
dfeec247
XL
780 let call_expr =
781 self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
e74abb32
XL
782 if let Some(span) = call_expr.span.trim_start(expr.span) {
783 err.span_suggestion(
784 span,
785 msg,
786 String::new(),
787 Applicability::MachineApplicable,
788 );
789 fallback_span = false;
790 }
791 }
792 if fallback_span {
793 err.span_label(span, msg);
794 }
795 } else if let Some(lev_candidate) = lev_candidate {
5869c6ff
XL
796 // Don't emit a suggestion if we found an actual method
797 // that had unsatisfied trait bounds
798 if unsatisfied_predicates.is_empty() {
799 let def_kind = lev_candidate.kind.as_def_kind();
800 err.span_suggestion(
801 span,
802 &format!(
803 "there is {} {} with a similar name",
804 def_kind.article(),
805 def_kind.descr(lev_candidate.def_id),
806 ),
807 lev_candidate.ident.to_string(),
808 Applicability::MaybeIncorrect,
809 );
810 }
ea8adc8c 811 }
48663c56 812
e1599b0c 813 return Some(err);
a7813a04 814 }
85aaf69f 815
a7813a04 816 MethodError::Ambiguity(sources) => {
dfeec247
XL
817 let mut err = struct_span_err!(
818 self.sess(),
ba9703b0 819 item_name.span,
dfeec247
XL
820 E0034,
821 "multiple applicable items in scope"
822 );
ba9703b0 823 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
85aaf69f 824
dfeec247 825 report_candidates(span, &mut err, sources, sugg_span);
a7813a04
XL
826 err.emit();
827 }
85aaf69f 828
416331ca 829 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
ba9703b0 830 let kind = kind.descr(def_id);
dfeec247
XL
831 let mut err = struct_span_err!(
832 self.tcx.sess,
ba9703b0 833 item_name.span,
dfeec247
XL
834 E0624,
835 "{} `{}` is private",
ba9703b0 836 kind,
dfeec247
XL
837 item_name
838 );
ba9703b0 839 err.span_label(item_name.span, &format!("private {}", kind));
3b2f2976
XL
840 self.suggest_valid_traits(&mut err, out_of_scope_traits);
841 err.emit();
a7813a04 842 }
3b2f2976 843
74b04a01 844 MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
3b2f2976
XL
845 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
846 let mut err = self.sess().struct_span_err(span, &msg);
74b04a01 847 err.span_label(bound_span, "this has a `Sized` requirement");
3b2f2976 848 if !candidates.is_empty() {
e74abb32
XL
849 let help = format!(
850 "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
851 add a `use` for {one_of_them}:",
dfeec247 852 an = if candidates.len() == 1 { "an" } else { "" },
60c5eb7d 853 s = pluralize!(candidates.len()),
e74abb32 854 were = if candidates.len() == 1 { "was" } else { "were" },
dfeec247 855 one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
e74abb32 856 );
3b2f2976
XL
857 self.suggest_use_candidates(&mut err, help, candidates);
858 }
1b1a35ee 859 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
e74abb32 860 if needs_mut {
dfeec247
XL
861 let trait_type = self.tcx.mk_ref(
862 region,
863 ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
864 );
e74abb32
XL
865 err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
866 }
867 }
3b2f2976
XL
868 err.emit();
869 }
ea8adc8c 870
dfeec247 871 MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
3b2f2976 872 }
e1599b0c 873 None
3b2f2976
XL
874 }
875
e74abb32
XL
876 /// Print out the type for use in value namespace.
877 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
1b1a35ee 878 match ty.kind() {
e74abb32
XL
879 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
880 _ => self.ty_to_string(ty),
881 }
882 }
883
1b1a35ee
XL
884 fn suggest_await_before_method(
885 &self,
886 err: &mut DiagnosticBuilder<'_>,
887 item_name: Ident,
888 ty: Ty<'tcx>,
889 call: &hir::Expr<'_>,
890 span: Span,
891 ) {
29967ef6 892 let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
fc512014 893 Some(output_ty) => self.resolve_vars_if_possible(output_ty),
29967ef6
XL
894 _ => return,
895 };
896 let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
897 debug!("suggest_await_before_method: is_method_exist={}", method_exists);
898 if method_exists {
899 err.span_suggestion_verbose(
900 span.shrink_to_lo(),
901 "consider `await`ing on the `Future` and calling the method on its `Output`",
902 "await.".to_string(),
903 Applicability::MaybeIncorrect,
904 );
1b1a35ee
XL
905 }
906 }
907
dfeec247
XL
908 fn suggest_use_candidates(
909 &self,
910 err: &mut DiagnosticBuilder<'_>,
911 mut msg: String,
912 candidates: Vec<DefId>,
913 ) {
74b04a01 914 let module_did = self.tcx.parent_module(self.body_id);
3dfed10e 915 let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
0731742a 916 let krate = self.tcx.hir().krate();
ff7c6d11
XL
917 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
918 if let Some(span) = span {
919 let path_strings = candidates.iter().map(|did| {
0731742a 920 // Produce an additional newline to separate the new use statement
ff7c6d11 921 // from the directly following item.
dfeec247 922 let additional_newline = if found_use { "" } else { "\n" };
0bf4aa26
XL
923 format!(
924 "use {};\n{}",
532ac7d7 925 with_crate_prefix(|| self.tcx.def_path_str(*did)),
0bf4aa26
XL
926 additional_newline
927 )
a1dfa0c6 928 });
ff7c6d11 929
9fa01778 930 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
ff7c6d11
XL
931 } else {
932 let limit = if candidates.len() == 5 { 5 } else { 4 };
933 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
94b46f34 934 if candidates.len() > 1 {
dfeec247
XL
935 msg.push_str(&format!(
936 "\ncandidate #{}: `use {};`",
937 i + 1,
938 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
939 ));
94b46f34 940 } else {
dfeec247
XL
941 msg.push_str(&format!(
942 "\n`use {};`",
943 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
944 ));
94b46f34 945 }
ff7c6d11
XL
946 }
947 if candidates.len() > limit {
948 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
949 }
950 err.note(&msg[..]);
3b2f2976 951 }
3b2f2976
XL
952 }
953
e74abb32
XL
954 fn suggest_valid_traits(
955 &self,
956 err: &mut DiagnosticBuilder<'_>,
957 valid_out_of_scope_traits: Vec<DefId>,
958 ) -> bool {
3b2f2976
XL
959 if !valid_out_of_scope_traits.is_empty() {
960 let mut candidates = valid_out_of_scope_traits;
961 candidates.sort();
962 candidates.dedup();
963 err.help("items from traits can only be used if the trait is in scope");
e74abb32
XL
964 let msg = format!(
965 "the following {traits_are} implemented but not in scope; \
966 perhaps add a `use` for {one_of_them}:",
dfeec247
XL
967 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
968 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
e74abb32 969 );
3b2f2976
XL
970
971 self.suggest_use_candidates(err, msg, candidates);
972 true
973 } else {
974 false
54a0048b 975 }
85aaf69f
SL
976 }
977
416331ca
XL
978 fn suggest_traits_to_import<'b>(
979 &self,
980 err: &mut DiagnosticBuilder<'_>,
981 span: Span,
982 rcvr_ty: Ty<'tcx>,
f9f354fc 983 item_name: Ident,
416331ca
XL
984 source: SelfSource<'b>,
985 valid_out_of_scope_traits: Vec<DefId>,
74b04a01 986 unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
416331ca 987 ) {
3b2f2976 988 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
c30ab7b3 989 return;
85aaf69f 990 }
85aaf69f 991
0731742a 992 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
a7813a04 993
74b04a01 994 let mut arbitrary_rcvr = vec![];
0731742a 995 // There are no traits implemented, so lets suggest some traits to
a7813a04
XL
996 // implement, by finding ones that have the item name, and are
997 // legal to implement.
8bb4bdeb 998 let mut candidates = all_traits(self.tcx)
83c7162d 999 .into_iter()
3dfed10e
XL
1000 // Don't issue suggestions for unstable traits since they're
1001 // unlikely to be implementable anyway
1002 .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1003 Some(attr) => attr.level.is_stable(),
1004 None => true,
1005 })
a7813a04 1006 .filter(|info| {
0731742a 1007 // We approximate the coherence rules to only suggest
a7813a04 1008 // traits that are legal to implement by requiring that
0731742a 1009 // either the type or trait is local. Multi-dispatch means
a7813a04
XL
1010 // this isn't perfect (that is, there are cases when
1011 // implementing a trait would be legal but is rejected
1012 // here).
3dfed10e 1013 unsatisfied_predicates.iter().all(|(p, _)| {
5869c6ff 1014 match p.kind().skip_binder() {
3dfed10e
XL
1015 // Hide traits if they are present in predicates as they can be fixed without
1016 // having to implement them.
5869c6ff
XL
1017 ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
1018 ty::PredicateKind::Projection(p) => {
3dfed10e
XL
1019 p.projection_ty.item_def_id == info.def_id
1020 }
1021 _ => false,
1022 }
74b04a01 1023 }) && (type_is_local || info.def_id.is_local())
dfeec247 1024 && self
74b04a01 1025 .associated_item(info.def_id, item_name, Namespace::ValueNS)
2c00a5a8 1026 .filter(|item| {
ba9703b0 1027 if let ty::AssocKind::Fn = item.kind {
f9f354fc
XL
1028 let id = item
1029 .def_id
1030 .as_local()
3dfed10e 1031 .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
74b04a01 1032 if let Some(hir::Node::TraitItem(hir::TraitItem {
ba9703b0 1033 kind: hir::TraitItemKind::Fn(fn_sig, method),
74b04a01
XL
1034 ..
1035 })) = id.map(|id| self.tcx.hir().get(id))
1036 {
1037 let self_first_arg = match method {
ba9703b0 1038 hir::TraitFn::Required([ident, ..]) => {
74b04a01
XL
1039 ident.name == kw::SelfLower
1040 }
ba9703b0 1041 hir::TraitFn::Provided(body_id) => {
f9f354fc
XL
1042 self.tcx.hir().body(*body_id).params.first().map_or(
1043 false,
1044 |param| {
1045 matches!(
1046 param.pat.kind,
1047 hir::PatKind::Binding(_, _, ident, _)
1048 if ident.name == kw::SelfLower
1049 )
1050 },
1051 )
74b04a01
XL
1052 }
1053 _ => false,
1054 };
1055
1056 if !fn_sig.decl.implicit_self.has_implicit_self()
1057 && self_first_arg
1058 {
1059 if let Some(ty) = fn_sig.decl.inputs.get(0) {
1060 arbitrary_rcvr.push(ty.span);
1061 }
1062 return false;
1063 }
1064 }
1065 }
2c00a5a8
XL
1066 // We only want to suggest public or local traits (#45781).
1067 item.vis == ty::Visibility::Public || info.def_id.is_local()
1068 })
1069 .is_some()
a7813a04
XL
1070 })
1071 .collect::<Vec<_>>();
74b04a01
XL
1072 for span in &arbitrary_rcvr {
1073 err.span_label(
1074 *span,
1075 "the method might not be found because of this arbitrary self type",
1076 );
1077 }
a7813a04
XL
1078
1079 if !candidates.is_empty() {
0731742a 1080 // Sort from most relevant to least relevant.
a7813a04
XL
1081 candidates.sort_by(|a, b| a.cmp(b).reverse());
1082 candidates.dedup();
1083
1b1a35ee 1084 let param_type = match rcvr_ty.kind() {
416331ca 1085 ty::Param(param) => Some(param),
1b1a35ee 1086 ty::Ref(_, ty, _) => match ty.kind() {
416331ca
XL
1087 ty::Param(param) => Some(param),
1088 _ => None,
dfeec247 1089 },
416331ca
XL
1090 _ => None,
1091 };
1092 err.help(if param_type.is_some() {
1093 "items from traits can only be used if the type parameter is bounded by the trait"
1094 } else {
1095 "items from traits can only be used if the trait is implemented and in scope"
1096 });
fc512014 1097 let candidates_len = candidates.len();
dfeec247
XL
1098 let message = |action| {
1099 format!(
1100 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
74b04a01 1101 {one_of_them}:",
dfeec247 1102 traits_define =
fc512014 1103 if candidates_len == 1 { "trait defines" } else { "traits define" },
dfeec247 1104 action = action,
fc512014 1105 one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
dfeec247
XL
1106 name = item_name,
1107 )
1108 };
416331ca 1109 // Obtain the span for `param` and use it for a structured suggestion.
3dfed10e
XL
1110 if let (Some(ref param), Some(ref table)) =
1111 (param_type, self.in_progress_typeck_results)
1112 {
ba9703b0 1113 let table_owner = table.borrow().hir_owner;
f035d41b
XL
1114 let generics = self.tcx.generics_of(table_owner.to_def_id());
1115 let type_param = generics.type_param(param, self.tcx);
1116 let hir = &self.tcx.hir();
1117 if let Some(def_id) = type_param.def_id.as_local() {
3dfed10e 1118 let id = hir.local_def_id_to_hir_id(def_id);
f035d41b
XL
1119 // Get the `hir::Param` to verify whether it already has any bounds.
1120 // We do this to avoid suggesting code that ends up as `T: FooBar`,
1121 // instead we suggest `T: Foo + Bar` in that case.
1122 match hir.get(id) {
1123 Node::GenericParam(ref param) => {
1124 let mut impl_trait = false;
1125 let has_bounds =
1126 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1127 &param.kind
dfeec247 1128 {
e1599b0c
XL
1129 // We've found `fn foo(x: impl Trait)` instead of
1130 // `fn foo<T>(x: T)`. We want to suggest the correct
1131 // `fn foo(x: impl Trait + TraitBound)` instead of
1132 // `fn foo<T: TraitBound>(x: T)`. (#63706)
1133 impl_trait = true;
e74abb32
XL
1134 param.bounds.get(1)
1135 } else {
1136 param.bounds.get(0)
1137 };
f035d41b
XL
1138 let sp = hir.span(id);
1139 let sp = if let Some(first_bound) = has_bounds {
1140 // `sp` only covers `T`, change it so that it covers
1141 // `T:` when appropriate
1142 sp.until(first_bound.span())
1143 } else {
1144 sp
1145 };
1146 let trait_def_ids: FxHashSet<DefId> = param
1147 .bounds
1148 .iter()
6a06907d 1149 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
f035d41b
XL
1150 .collect();
1151 if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
e74abb32
XL
1152 err.span_suggestions(
1153 sp,
f035d41b
XL
1154 &message(format!(
1155 "restrict type parameter `{}` with",
1156 param.name.ident(),
1157 )),
dfeec247 1158 candidates.iter().map(|t| {
f035d41b
XL
1159 format!(
1160 "{}{} {}{}",
1161 param.name.ident(),
1162 if impl_trait { " +" } else { ":" },
1163 self.tcx.def_path_str(t.def_id),
1164 if has_bounds.is_some() { " + " } else { "" },
1165 )
dfeec247 1166 }),
e74abb32
XL
1167 Applicability::MaybeIncorrect,
1168 );
e1599b0c 1169 }
fc512014 1170 return;
f035d41b
XL
1171 }
1172 Node::Item(hir::Item {
1173 kind: hir::ItemKind::Trait(.., bounds, _),
1174 ident,
1175 ..
1176 }) => {
1177 let (sp, sep, article) = if bounds.is_empty() {
1178 (ident.span.shrink_to_hi(), ":", "a")
1179 } else {
1180 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1181 };
1182 err.span_suggestions(
1183 sp,
1184 &message(format!("add {} supertrait for", article)),
1185 candidates.iter().map(|t| {
1186 format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1187 }),
1188 Applicability::MaybeIncorrect,
1189 );
fc512014 1190 return;
416331ca 1191 }
f035d41b 1192 _ => {}
416331ca 1193 }
f035d41b 1194 }
416331ca
XL
1195 }
1196
fc512014
XL
1197 let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1198 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1199 // cases where a positive bound implies a negative impl.
1200 (candidates, Vec::new())
1201 } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1202 let mut potential_candidates = Vec::new();
1203 let mut explicitly_negative = Vec::new();
1204 for candidate in candidates {
1205 // Check if there's a negative impl of `candidate` for `rcvr_ty`
1206 if self
1207 .tcx
1208 .all_impls(candidate.def_id)
1209 .filter(|imp_did| {
1210 self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1211 })
1212 .any(|imp_did| {
1213 let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1214 let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
5869c6ff 1215 imp_simp.map_or(false, |s| s == simp_rcvr_ty)
fc512014
XL
1216 })
1217 {
1218 explicitly_negative.push(candidate);
1219 } else {
1220 potential_candidates.push(candidate);
74b04a01
XL
1221 }
1222 }
fc512014
XL
1223 (potential_candidates, explicitly_negative)
1224 } else {
1225 // We don't know enough about `recv_ty` to make proper suggestions.
1226 (candidates, Vec::new())
1227 };
1228
1229 let action = if let Some(param) = param_type {
1230 format!("restrict type parameter `{}` with", param)
1231 } else {
1232 // FIXME: it might only need to be imported into scope, not implemented.
1233 "implement".to_string()
1234 };
1235 match &potential_candidates[..] {
1236 [] => {}
1237 [trait_info] if trait_info.def_id.is_local() => {
1238 let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1239 err.span_note(
1240 self.tcx.sess.source_map().guess_head_span(span),
1241 &format!(
1242 "`{}` defines an item `{}`, perhaps you need to {} it",
1243 self.tcx.def_path_str(trait_info.def_id),
1244 item_name,
1245 action
1246 ),
1247 );
1248 }
1249 trait_infos => {
74b04a01 1250 let mut msg = message(action);
fc512014 1251 for (i, trait_info) in trait_infos.iter().enumerate() {
74b04a01
XL
1252 msg.push_str(&format!(
1253 "\ncandidate #{}: `{}`",
1254 i + 1,
1255 self.tcx.def_path_str(trait_info.def_id),
1256 ));
1257 }
fc512014
XL
1258 err.note(&msg);
1259 }
1260 }
1261 match &explicitly_negative[..] {
1262 [] => {}
1263 [trait_info] => {
1264 let msg = format!(
1265 "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1266 self.tcx.def_path_str(trait_info.def_id),
1267 item_name
1268 );
1269 err.note(&msg);
1270 }
1271 trait_infos => {
1272 let mut msg = format!(
1273 "the following traits define an item `{}`, but are explicitely unimplemented:",
1274 item_name
1275 );
1276 for trait_info in trait_infos {
1277 msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1278 }
1279 err.note(&msg);
416331ca 1280 }
a7813a04 1281 }
85aaf69f 1282 }
85aaf69f
SL
1283 }
1284
a7813a04
XL
1285 /// Checks whether there is a local type somewhere in the chain of
1286 /// autoderefs of `rcvr_ty`.
dfeec247 1287 fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool {
9fa01778 1288 fn is_local(ty: Ty<'_>) -> bool {
1b1a35ee 1289 match ty.kind() {
b7449926
XL
1290 ty::Adt(def, _) => def.did.is_local(),
1291 ty::Foreign(did) => did.is_local(),
5869c6ff 1292 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
b7449926 1293 ty::Param(_) => true,
a7813a04 1294
0731742a
XL
1295 // Everything else (primitive types, etc.) is effectively
1296 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
a7813a04
XL
1297 // the noise from these sort of types is usually just really
1298 // annoying, rather than any sort of help).
c30ab7b3 1299 _ => false,
a7813a04 1300 }
85aaf69f 1301 }
85aaf69f 1302
a7813a04
XL
1303 // This occurs for UFCS desugaring of `T::method`, where there is no
1304 // receiver expression for the method call, and thus no autoderef.
0731742a 1305 if let SelfSource::QPath(_) = source {
e74abb32 1306 return is_local(self.resolve_vars_with_obligations(rcvr_ty));
c34b1796 1307 }
c34b1796 1308
3157f602 1309 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
c34b1796 1310 }
85aaf69f
SL
1311}
1312
0731742a
XL
1313#[derive(Copy, Clone)]
1314pub enum SelfSource<'a> {
dfeec247
XL
1315 QPath(&'a hir::Ty<'a>),
1316 MethodCall(&'a hir::Expr<'a> /* rcvr */),
0731742a
XL
1317}
1318
c34b1796 1319#[derive(Copy, Clone)]
85aaf69f 1320pub struct TraitInfo {
e9174d1e 1321 pub def_id: DefId,
85aaf69f
SL
1322}
1323
85aaf69f
SL
1324impl PartialEq for TraitInfo {
1325 fn eq(&self, other: &TraitInfo) -> bool {
1326 self.cmp(other) == Ordering::Equal
1327 }
1328}
1329impl Eq for TraitInfo {}
1330impl PartialOrd for TraitInfo {
c30ab7b3
SL
1331 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1332 Some(self.cmp(other))
1333 }
85aaf69f
SL
1334}
1335impl Ord for TraitInfo {
1336 fn cmp(&self, other: &TraitInfo) -> Ordering {
0731742a
XL
1337 // Local crates are more important than remote ones (local:
1338 // `cnum == 0`), and otherwise we throw in the defid for totality.
85aaf69f 1339
b039eaaf
SL
1340 let lhs = (other.def_id.krate, other.def_id);
1341 let rhs = (self.def_id.krate, self.def_id);
85aaf69f
SL
1342 lhs.cmp(&rhs)
1343 }
1344}
1345
9fa01778 1346/// Retrieves all traits in this crate and any dependent crates.
416331ca 1347pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
83c7162d
XL
1348 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
1349}
1350
9fa01778 1351/// Computes all traits in this crate and any dependent crates.
416331ca 1352fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
0731742a 1353 use hir::itemlikevisit;
85aaf69f 1354
0731742a 1355 let mut traits = vec![];
85aaf69f 1356
0731742a 1357 // Crate-local:
476ff2be 1358
6a06907d 1359 struct Visitor<'a> {
0731742a
XL
1360 traits: &'a mut Vec<DefId>,
1361 }
32a655c1 1362
6a06907d 1363 impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
dfeec247 1364 fn visit_item(&mut self, i: &'v hir::Item<'v>) {
e74abb32 1365 match i.kind {
dfeec247 1366 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
6a06907d 1367 self.traits.push(i.def_id.to_def_id());
532ac7d7 1368 }
dfeec247 1369 _ => (),
476ff2be 1370 }
85aaf69f 1371 }
0731742a 1372
dfeec247 1373 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
0731742a 1374
dfeec247 1375 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
fc512014
XL
1376
1377 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
0731742a
XL
1378 }
1379
6a06907d 1380 tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
0731742a
XL
1381
1382 // Cross-crate:
1383
1384 let mut external_mods = FxHashSet::default();
dc9dc135
XL
1385 fn handle_external_res(
1386 tcx: TyCtxt<'_>,
1387 traits: &mut Vec<DefId>,
1388 external_mods: &mut FxHashSet<DefId>,
1389 res: Res,
1390 ) {
48663c56 1391 match res {
ba9703b0 1392 Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
0731742a
XL
1393 traits.push(def_id);
1394 }
48663c56 1395 Res::Def(DefKind::Mod, def_id) => {
0731742a
XL
1396 if !external_mods.insert(def_id) {
1397 return;
85aaf69f 1398 }
0731742a 1399 for child in tcx.item_children(def_id).iter() {
48663c56 1400 handle_external_res(tcx, traits, external_mods, child.res)
85aaf69f 1401 }
85aaf69f 1402 }
0731742a 1403 _ => {}
85aaf69f 1404 }
0731742a
XL
1405 }
1406 for &cnum in tcx.crates().iter() {
dfeec247 1407 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
48663c56 1408 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
0731742a 1409 }
85aaf69f 1410
83c7162d 1411 traits
85aaf69f
SL
1412}
1413
f035d41b 1414pub fn provide(providers: &mut ty::query::Providers) {
83c7162d
XL
1415 providers.all_traits = |tcx, cnum| {
1416 assert_eq!(cnum, LOCAL_CRATE);
dc9dc135 1417 &tcx.arena.alloc(compute_all_traits(tcx))[..]
0531ce1d 1418 }
85aaf69f 1419}
ff7c6d11 1420
dc9dc135 1421struct UsePlacementFinder<'tcx> {
9fa01778 1422 target_module: hir::HirId,
ff7c6d11
XL
1423 span: Option<Span>,
1424 found_use: bool,
dc9dc135 1425 tcx: TyCtxt<'tcx>,
ff7c6d11
XL
1426}
1427
dc9dc135 1428impl UsePlacementFinder<'tcx> {
ff7c6d11 1429 fn check(
dc9dc135 1430 tcx: TyCtxt<'tcx>,
dfeec247 1431 krate: &'tcx hir::Crate<'tcx>,
9fa01778 1432 target_module: hir::HirId,
ff7c6d11 1433 ) -> (Option<Span>, bool) {
dfeec247
XL
1434 let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1435 intravisit::walk_crate(&mut finder, krate);
ff7c6d11
XL
1436 (finder.span, finder.found_use)
1437 }
1438}
1439
dfeec247
XL
1440impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1441 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
ff7c6d11
XL
1442 if self.span.is_some() {
1443 return;
1444 }
9fa01778 1445 if hir_id != self.target_module {
dfeec247 1446 intravisit::walk_mod(self, module, hir_id);
ff7c6d11
XL
1447 return;
1448 }
0731742a 1449 // Find a `use` statement.
6a06907d
XL
1450 for &item_id in module.item_ids {
1451 let item = self.tcx.hir().item(item_id);
e74abb32 1452 match item.kind {
8faf50e0 1453 hir::ItemKind::Use(..) => {
0731742a
XL
1454 // Don't suggest placing a `use` before the prelude
1455 // import or other generated ones.
e1599b0c 1456 if !item.span.from_expansion() {
0531ce1d 1457 self.span = Some(item.span.shrink_to_lo());
ff7c6d11
XL
1458 self.found_use = true;
1459 return;
1460 }
dfeec247 1461 }
0731742a 1462 // Don't place `use` before `extern crate`...
8faf50e0 1463 hir::ItemKind::ExternCrate(_) => {}
0731742a 1464 // ...but do place them before the first other item.
dfeec247
XL
1465 _ => {
1466 if self.span.map_or(true, |span| item.span < span) {
1467 if !item.span.from_expansion() {
1468 // Don't insert between attributes and an item.
6a06907d
XL
1469 let attrs = self.tcx.hir().attrs(item.hir_id());
1470 if attrs.is_empty() {
dfeec247
XL
1471 self.span = Some(item.span.shrink_to_lo());
1472 } else {
1473 // Find the first attribute on the item.
6a06907d 1474 for attr in attrs {
dfeec247
XL
1475 if self.span.map_or(true, |span| attr.span < span) {
1476 self.span = Some(attr.span.shrink_to_lo());
1477 }
ff7c6d11
XL
1478 }
1479 }
1480 }
1481 }
dfeec247 1482 }
ff7c6d11
XL
1483 }
1484 }
1485 }
0731742a 1486
ba9703b0 1487 type Map = intravisit::ErasedMap<'tcx>;
dfeec247 1488
ba9703b0 1489 fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
dfeec247 1490 intravisit::NestedVisitorMap::None
ff7c6d11
XL
1491 }
1492}
dfeec247
XL
1493
1494fn print_disambiguation_help(
f9f354fc 1495 item_name: Ident,
dfeec247
XL
1496 args: Option<&'tcx [hir::Expr<'tcx>]>,
1497 err: &mut DiagnosticBuilder<'_>,
1498 trait_name: String,
1499 rcvr_ty: Ty<'_>,
1500 kind: ty::AssocKind,
ba9703b0 1501 def_id: DefId,
dfeec247
XL
1502 span: Span,
1503 candidate: Option<usize>,
1504 source_map: &source_map::SourceMap,
1505) {
1506 let mut applicability = Applicability::MachineApplicable;
ba9703b0 1507 let sugg_args = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
dfeec247
XL
1508 format!(
1509 "({}{})",
1510 if rcvr_ty.is_region_ptr() {
1511 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1512 } else {
1513 ""
1514 },
1515 args.iter()
1516 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1517 applicability = Applicability::HasPlaceholders;
1518 "_".to_owned()
1519 }))
1520 .collect::<Vec<_>>()
1521 .join(", "),
1522 )
1523 } else {
1524 String::new()
1525 };
1526 let sugg = format!("{}::{}{}", trait_name, item_name, sugg_args);
1527 err.span_suggestion(
1528 span,
1529 &format!(
1530 "disambiguate the {} for {}",
ba9703b0 1531 kind.as_def_kind().descr(def_id),
dfeec247
XL
1532 if let Some(candidate) = candidate {
1533 format!("candidate #{}", candidate)
1534 } else {
1535 "the candidate".to_string()
1536 },
1537 ),
1538 sugg,
1539 applicability,
1540 );
1541}