1use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2use rustc_data_structures::sorted_map::SortedMap;
3use rustc_data_structures::unord::UnordMap;
4use rustc_errors::codes::*;
5use rustc_errors::{
6 Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, pluralize,
7 struct_span_code_err,
8};
9use rustc_hir::def::{CtorOf, DefKind, Res};
10use rustc_hir::def_id::DefId;
11use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
12use rustc_middle::bug;
13use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
14use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
15use rustc_middle::ty::{
16 self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
17 suggest_constraining_type_param,
18};
19use rustc_session::parse::feature_err;
20use rustc_span::edit_distance::find_best_match_for_name;
21use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, kw, sym};
22use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
23use rustc_trait_selection::traits::{
24 FulfillmentError, dyn_compatibility_violations_for_assoc_item,
25};
26use smallvec::SmallVec;
27use tracing::debug;
28
29use super::InherentAssocCandidate;
30use crate::errors::{
31 self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
32 ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
33};
34use crate::fluent_generated as fluent;
35use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
36
37impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
38 pub(crate) fn check_and_report_invalid_unbounds_on_param(
40 &self,
41 unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
42 ) {
43 let tcx = self.tcx();
44
45 let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
46
47 let mut unique_bounds = FxIndexSet::default();
48 let mut seen_repeat = false;
49 for unbound in &unbounds {
50 if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
51 seen_repeat |= !unique_bounds.insert(unbound_def_id);
52 }
53 }
54
55 if unbounds.len() > 1 {
56 let err = errors::MultipleRelaxedDefaultBounds {
57 spans: unbounds.iter().map(|ptr| ptr.span).collect(),
58 };
59
60 if seen_repeat {
61 tcx.dcx().emit_err(err);
62 } else if !tcx.features().more_maybe_bounds() {
63 tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit();
64 };
65 }
66
67 for unbound in unbounds {
68 if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
69 && ((did == sized_did) || tcx.is_default_trait(did))
70 {
71 continue;
72 }
73
74 let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
75 true => "`?Sized` and `experimental_default_bounds`",
76 false => "`?Sized`",
77 };
78 self.dcx().span_err(
79 unbound.span,
80 format!(
81 "relaxing a default bound only does something for {}; all other traits are \
82 not bound by default",
83 unbound_traits
84 ),
85 );
86 }
87 }
88
89 pub(crate) fn report_missing_type_params(
92 &self,
93 missing_type_params: Vec<Symbol>,
94 def_id: DefId,
95 span: Span,
96 empty_generic_args: bool,
97 ) {
98 if missing_type_params.is_empty() {
99 return;
100 }
101
102 self.dcx().emit_err(MissingTypeParams {
103 span,
104 def_span: self.tcx().def_span(def_id),
105 span_snippet: self.tcx().sess.source_map().span_to_snippet(span).ok(),
106 missing_type_params,
107 empty_generic_args,
108 });
109 }
110
111 pub(crate) fn report_internal_fn_trait(
114 &self,
115 span: Span,
116 trait_def_id: DefId,
117 trait_segment: &'_ hir::PathSegment<'_>,
118 is_impl: bool,
119 ) {
120 if self.tcx().features().unboxed_closures() {
121 return;
122 }
123
124 let trait_def = self.tcx().trait_def(trait_def_id);
125 if !trait_def.paren_sugar {
126 if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
127 feature_err(
129 &self.tcx().sess,
130 sym::unboxed_closures,
131 span,
132 "parenthetical notation is only stable when used with `Fn`-family traits",
133 )
134 .emit();
135 }
136
137 return;
138 }
139
140 let sess = self.tcx().sess;
141
142 if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
143 let mut err = feature_err(
145 sess,
146 sym::unboxed_closures,
147 span,
148 "the precise format of `Fn`-family traits' type parameters is subject to change",
149 );
150 if !is_impl {
153 err.span_suggestion(
154 span,
155 "use parenthetical notation instead",
156 fn_trait_to_string(self.tcx(), trait_segment, true),
157 Applicability::MaybeIncorrect,
158 );
159 }
160 err.emit();
161 }
162
163 if is_impl {
164 let trait_name = self.tcx().def_path_str(trait_def_id);
165 self.dcx().emit_err(ManualImplementation { span, trait_name });
166 }
167 }
168
169 pub(super) fn report_unresolved_assoc_item<I>(
170 &self,
171 all_candidates: impl Fn() -> I,
172 qself: AssocItemQSelf,
173 assoc_tag: ty::AssocTag,
174 assoc_ident: Ident,
175 span: Span,
176 constraint: Option<&hir::AssocItemConstraint<'tcx>>,
177 ) -> ErrorGuaranteed
178 where
179 I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
180 {
181 let tcx = self.tcx();
182
183 if let Some(assoc_item) = all_candidates().find_map(|r| {
185 tcx.associated_items(r.def_id())
186 .filter_by_name_unhygienic(assoc_ident.name)
187 .find(|item| tcx.hygienic_eq(assoc_ident, item.ident(tcx), r.def_id()))
188 }) {
189 return self.report_assoc_kind_mismatch(
190 assoc_item,
191 assoc_tag,
192 assoc_ident,
193 span,
194 constraint,
195 );
196 }
197
198 let assoc_kind_str = assoc_tag_str(assoc_tag);
199 let qself_str = qself.to_string(tcx);
200
201 let is_dummy = assoc_ident.span == DUMMY_SP;
204
205 let mut err = errors::AssocItemNotFound {
206 span: if is_dummy { span } else { assoc_ident.span },
207 assoc_ident,
208 assoc_kind: assoc_kind_str,
209 qself: &qself_str,
210 label: None,
211 sugg: None,
212 within_macro_span: assoc_ident.span.within_macro(span, tcx.sess.source_map()),
215 };
216
217 if is_dummy {
218 err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span });
219 return self.dcx().emit_err(err);
220 }
221
222 let all_candidate_names: Vec<_> = all_candidates()
223 .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
224 .filter_map(|item| {
225 if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag {
226 item.opt_name()
227 } else {
228 None
229 }
230 })
231 .collect();
232
233 if let Some(suggested_name) =
234 find_best_match_for_name(&all_candidate_names, assoc_ident.name, None)
235 {
236 err.sugg = Some(errors::AssocItemNotFoundSugg::Similar {
237 span: assoc_ident.span,
238 assoc_kind: assoc_kind_str,
239 suggested_name,
240 });
241 return self.dcx().emit_err(err);
242 }
243
244 let visible_traits: Vec<_> = tcx
249 .visible_traits()
250 .filter(|trait_def_id| {
251 let viz = tcx.visibility(*trait_def_id);
252 let def_id = self.item_def_id();
253 viz.is_accessible_from(def_id, tcx)
254 })
255 .collect();
256
257 let wider_candidate_names: Vec<_> = visible_traits
258 .iter()
259 .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
260 .filter_map(|item| {
261 (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
262 })
263 .collect();
264
265 if let Some(suggested_name) =
266 find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None)
267 {
268 if let [best_trait] = visible_traits
269 .iter()
270 .copied()
271 .filter(|trait_def_id| {
272 tcx.associated_items(trait_def_id)
273 .filter_by_name_unhygienic(suggested_name)
274 .any(|item| item.as_tag() == assoc_tag)
275 })
276 .collect::<Vec<_>>()[..]
277 {
278 let trait_name = tcx.def_path_str(best_trait);
279 err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait {
280 span: assoc_ident.span,
281 assoc_kind: assoc_kind_str,
282 trait_name: &trait_name,
283 suggested_name,
284 identically_named: suggested_name == assoc_ident.name,
285 });
286 if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
287 && let item_def_id =
291 tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
292 && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
294 {
295 if generics
299 .bounds_for_param(ty_param_def_id)
300 .flat_map(|pred| pred.bounds.iter())
301 .any(|b| match b {
302 hir::GenericBound::Trait(t, ..) => {
303 t.trait_ref.trait_def_id() == Some(best_trait)
304 }
305 _ => false,
306 })
307 {
308 err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
311 span: assoc_ident.span,
312 assoc_kind: assoc_kind_str,
313 suggested_name,
314 });
315 return self.dcx().emit_err(err);
316 }
317
318 let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
319 let mut trait_ref = trait_name.clone();
320 let applicability = if let [arg, args @ ..] = trait_args {
321 use std::fmt::Write;
322 write!(trait_ref, "</* {arg}").unwrap();
323 args.iter().try_for_each(|arg| write!(trait_ref, ", {arg}")).unwrap();
324 trait_ref += " */>";
325 Applicability::HasPlaceholders
326 } else {
327 Applicability::MaybeIncorrect
328 };
329
330 let identically_named = suggested_name == assoc_ident.name;
331
332 if let DefKind::TyAlias = tcx.def_kind(item_def_id)
333 && !tcx.type_alias_is_lazy(item_def_id)
334 {
335 err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
336 lo: ty_param_span.shrink_to_lo(),
337 mi: ty_param_span.shrink_to_hi(),
338 hi: (!identically_named).then_some(assoc_ident.span),
339 trait_ref,
340 identically_named,
341 suggested_name,
342 applicability,
343 });
344 } else {
345 let mut err = self.dcx().create_err(err);
346 if suggest_constraining_type_param(
347 tcx,
348 generics,
349 &mut err,
350 &qself_str,
351 &trait_ref,
352 Some(best_trait),
353 None,
354 ) && !identically_named
355 {
356 err.span_suggestion_verbose(
359 assoc_ident.span,
360 fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
361 suggested_name,
362 Applicability::MaybeIncorrect,
363 );
364 }
365 return err.emit();
366 }
367 }
368 return self.dcx().emit_err(err);
369 }
370 }
371
372 if let [candidate_name] = all_candidate_names.as_slice() {
375 err.sugg = Some(errors::AssocItemNotFoundSugg::Other {
376 span: assoc_ident.span,
377 qself: &qself_str,
378 assoc_kind: assoc_kind_str,
379 suggested_name: *candidate_name,
380 });
381 } else {
382 err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_ident.span });
383 }
384
385 self.dcx().emit_err(err)
386 }
387
388 fn report_assoc_kind_mismatch(
389 &self,
390 assoc_item: &ty::AssocItem,
391 assoc_tag: ty::AssocTag,
392 ident: Ident,
393 span: Span,
394 constraint: Option<&hir::AssocItemConstraint<'tcx>>,
395 ) -> ErrorGuaranteed {
396 let tcx = self.tcx();
397
398 let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
399 && let Some(constraint) = constraint
400 && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
401 {
402 let lo = if constraint.gen_args.span_ext.is_dummy() {
403 ident.span
404 } else {
405 constraint.gen_args.span_ext
406 };
407 Some(lo.between(span.shrink_to_hi()))
408 } else {
409 None
410 };
411
412 let wrap_in_braces_sugg = if let Some(constraint) = constraint
414 && let Some(hir_ty) = constraint.ty()
415 && let ty = self.lower_ty(hir_ty)
416 && (ty.is_enum() || ty.references_error())
417 && tcx.features().associated_const_equality()
418 {
419 Some(errors::AssocKindMismatchWrapInBracesSugg {
420 lo: hir_ty.span.shrink_to_lo(),
421 hi: hir_ty.span.shrink_to_hi(),
422 })
423 } else {
424 None
425 };
426
427 let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
430 && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
431 {
432 let span = match term {
433 hir::Term::Ty(ty) => ty.span,
434 hir::Term::Const(ct) => ct.span(),
435 };
436 (span, Some(ident.span), assoc_item.as_tag(), assoc_tag)
437 } else {
438 (ident.span, None, assoc_tag, assoc_item.as_tag())
439 };
440
441 self.dcx().emit_err(errors::AssocKindMismatch {
442 span,
443 expected: assoc_tag_str(expected),
444 got: assoc_tag_str(got),
445 expected_because_label,
446 assoc_kind: assoc_tag_str(assoc_item.as_tag()),
447 def_span: tcx.def_span(assoc_item.def_id),
448 bound_on_assoc_const_label,
449 wrap_in_braces_sugg,
450 })
451 }
452
453 pub(crate) fn report_missing_self_ty_for_resolved_path(
454 &self,
455 trait_def_id: DefId,
456 span: Span,
457 item_segment: &hir::PathSegment<'tcx>,
458 assoc_tag: ty::AssocTag,
459 ) -> ErrorGuaranteed {
460 let tcx = self.tcx();
461 let path_str = tcx.def_path_str(trait_def_id);
462
463 let def_id = self.item_def_id();
464 debug!(item_def_id = ?def_id);
465
466 let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
468 debug!(?parent_def_id);
469
470 let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
473 let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
474
475 let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
476 vec!["Self".to_string()]
477 } else {
478 tcx.all_impls(trait_def_id)
480 .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
481 .filter(|header| {
482 tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
484 && header.polarity != ty::ImplPolarity::Negative
485 })
486 .map(|header| header.trait_ref.instantiate_identity().self_ty())
487 .filter(|self_ty| !self_ty.has_non_region_param())
489 .map(|self_ty| tcx.erase_regions(self_ty).to_string())
490 .collect()
491 };
492 self.report_ambiguous_assoc_item_path(
496 span,
497 &type_names,
498 &[path_str],
499 item_segment.ident,
500 assoc_tag,
501 )
502 }
503
504 pub(super) fn report_unresolved_type_relative_path(
505 &self,
506 self_ty: Ty<'tcx>,
507 hir_self_ty: &hir::Ty<'_>,
508 assoc_tag: ty::AssocTag,
509 ident: Ident,
510 qpath_hir_id: HirId,
511 span: Span,
512 variant_def_id: Option<DefId>,
513 ) -> ErrorGuaranteed {
514 let tcx = self.tcx();
515 let kind_str = assoc_tag_str(assoc_tag);
516 if variant_def_id.is_some() {
517 let msg = format!("expected {kind_str}, found variant `{ident}`");
519 self.dcx().span_err(span, msg)
520 } else if self_ty.is_enum() {
521 let mut err = self.dcx().create_err(errors::NoVariantNamed {
522 span: ident.span,
523 ident,
524 ty: self_ty,
525 });
526
527 let adt_def = self_ty.ty_adt_def().expect("enum is not an ADT");
528 if let Some(variant_name) = find_best_match_for_name(
529 &adt_def.variants().iter().map(|variant| variant.name).collect::<Vec<Symbol>>(),
530 ident.name,
531 None,
532 ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == variant_name)
533 {
534 let mut suggestion = vec![(ident.span, variant_name.to_string())];
535 if let hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(expr), .. })
536 | hir::Node::Expr(expr) = tcx.parent_hir_node(qpath_hir_id)
537 && let hir::ExprKind::Struct(..) = expr.kind
538 {
539 match variant.ctor {
540 None => {
541 suggestion = vec![(
543 ident.span.with_hi(expr.span.hi()),
544 if variant.fields.is_empty() {
545 format!("{variant_name} {{}}")
546 } else {
547 format!(
548 "{variant_name} {{ {} }}",
549 variant
550 .fields
551 .iter()
552 .map(|f| format!("{}: /* value */", f.name))
553 .collect::<Vec<_>>()
554 .join(", ")
555 )
556 },
557 )];
558 }
559 Some((hir::def::CtorKind::Fn, def_id)) => {
560 let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
562 let inputs = fn_sig.inputs().skip_binder();
563 suggestion = vec![(
564 ident.span.with_hi(expr.span.hi()),
565 format!(
566 "{variant_name}({})",
567 inputs
568 .iter()
569 .map(|i| format!("/* {i} */"))
570 .collect::<Vec<_>>()
571 .join(", ")
572 ),
573 )];
574 }
575 Some((hir::def::CtorKind::Const, _)) => {
576 suggestion = vec![(
578 ident.span.with_hi(expr.span.hi()),
579 variant_name.to_string(),
580 )];
581 }
582 }
583 }
584 err.multipart_suggestion_verbose(
585 "there is a variant with a similar name",
586 suggestion,
587 Applicability::HasPlaceholders,
588 );
589 } else {
590 err.span_label(ident.span, format!("variant not found in `{self_ty}`"));
591 }
592
593 if let Some(sp) = tcx.hir_span_if_local(adt_def.did()) {
594 err.span_label(sp, format!("variant `{ident}` not found here"));
595 }
596
597 err.emit()
598 } else if let Err(reported) = self_ty.error_reported() {
599 reported
600 } else {
601 match self.maybe_report_similar_assoc_fn(span, self_ty, hir_self_ty) {
602 Ok(()) => {}
603 Err(reported) => return reported,
604 }
605
606 let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(self_ty, ident);
607
608 self.report_ambiguous_assoc_item_path(
609 span,
610 &[self_ty.to_string()],
611 &traits,
612 ident,
613 assoc_tag,
614 )
615 }
616 }
617
618 pub(super) fn report_ambiguous_assoc_item_path(
619 &self,
620 span: Span,
621 types: &[String],
622 traits: &[String],
623 ident: Ident,
624 assoc_tag: ty::AssocTag,
625 ) -> ErrorGuaranteed {
626 let kind_str = assoc_tag_str(assoc_tag);
627 let mut err =
628 struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
629 if self
630 .tcx()
631 .resolutions(())
632 .confused_type_with_std_module
633 .keys()
634 .any(|full_span| full_span.contains(span))
635 {
636 err.span_suggestion_verbose(
637 span.shrink_to_lo(),
638 "you are looking for the module in `std`, not the primitive type",
639 "std::",
640 Applicability::MachineApplicable,
641 );
642 } else {
643 let sugg_sp = span.until(ident.span);
644
645 let mut types = types.to_vec();
646 types.sort();
647 let mut traits = traits.to_vec();
648 traits.sort();
649 match (&types[..], &traits[..]) {
650 ([], []) => {
651 err.span_suggestion_verbose(
652 sugg_sp,
653 format!(
654 "if there were a type named `Type` that implements a trait named \
655 `Trait` with associated {kind_str} `{ident}`, you could use the \
656 fully-qualified path",
657 ),
658 "<Type as Trait>::",
659 Applicability::HasPlaceholders,
660 );
661 }
662 ([], [trait_str]) => {
663 err.span_suggestion_verbose(
664 sugg_sp,
665 format!(
666 "if there were a type named `Example` that implemented `{trait_str}`, \
667 you could use the fully-qualified path",
668 ),
669 format!("<Example as {trait_str}>::"),
670 Applicability::HasPlaceholders,
671 );
672 }
673 ([], traits) => {
674 err.span_suggestions_with_style(
675 sugg_sp,
676 format!(
677 "if there were a type named `Example` that implemented one of the \
678 traits with associated {kind_str} `{ident}`, you could use the \
679 fully-qualified path",
680 ),
681 traits.iter().map(|trait_str| format!("<Example as {trait_str}>::")),
682 Applicability::HasPlaceholders,
683 SuggestionStyle::ShowAlways,
684 );
685 }
686 ([type_str], []) => {
687 err.span_suggestion_verbose(
688 sugg_sp,
689 format!(
690 "if there were a trait named `Example` with associated {kind_str} `{ident}` \
691 implemented for `{type_str}`, you could use the fully-qualified path",
692 ),
693 format!("<{type_str} as Example>::"),
694 Applicability::HasPlaceholders,
695 );
696 }
697 (types, []) => {
698 err.span_suggestions_with_style(
699 sugg_sp,
700 format!(
701 "if there were a trait named `Example` with associated {kind_str} `{ident}` \
702 implemented for one of the types, you could use the fully-qualified \
703 path",
704 ),
705 types
706 .into_iter()
707 .map(|type_str| format!("<{type_str} as Example>::")),
708 Applicability::HasPlaceholders,
709 SuggestionStyle::ShowAlways,
710 );
711 }
712 (types, traits) => {
713 let mut suggestions = vec![];
714 for type_str in types {
715 for trait_str in traits {
716 suggestions.push(format!("<{type_str} as {trait_str}>::"));
717 }
718 }
719 err.span_suggestions_with_style(
720 sugg_sp,
721 "use fully-qualified syntax",
722 suggestions,
723 Applicability::MachineApplicable,
724 SuggestionStyle::ShowAlways,
725 );
726 }
727 }
728 }
729 err.emit()
730 }
731
732 pub(crate) fn report_ambiguous_inherent_assoc_item(
733 &self,
734 name: Ident,
735 candidates: Vec<DefId>,
736 span: Span,
737 ) -> ErrorGuaranteed {
738 let mut err = struct_span_code_err!(
739 self.dcx(),
740 name.span,
741 E0034,
742 "multiple applicable items in scope"
743 );
744 err.span_label(name.span, format!("multiple `{name}` found"));
745 self.note_ambiguous_inherent_assoc_item(&mut err, candidates, span);
746 err.emit()
747 }
748
749 fn note_ambiguous_inherent_assoc_item(
751 &self,
752 err: &mut Diag<'_>,
753 candidates: Vec<DefId>,
754 span: Span,
755 ) {
756 let tcx = self.tcx();
757
758 let limit = if candidates.len() == 5 { 5 } else { 4 };
760
761 for (index, &item) in candidates.iter().take(limit).enumerate() {
762 let impl_ = tcx.impl_of_method(item).unwrap();
763
764 let note_span = if item.is_local() {
765 Some(tcx.def_span(item))
766 } else if impl_.is_local() {
767 Some(tcx.def_span(impl_))
768 } else {
769 None
770 };
771
772 let title = if candidates.len() > 1 {
773 format!("candidate #{}", index + 1)
774 } else {
775 "the candidate".into()
776 };
777
778 let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity();
779 let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
780
781 if let Some(span) = note_span {
782 err.span_note(span, note);
783 } else {
784 err.note(note);
785 }
786 }
787 if candidates.len() > limit {
788 err.note(format!("and {} others", candidates.len() - limit));
789 }
790 }
791
792 pub(crate) fn report_unresolved_inherent_assoc_item(
794 &self,
795 name: Ident,
796 self_ty: Ty<'tcx>,
797 candidates: Vec<InherentAssocCandidate>,
798 fulfillment_errors: Vec<FulfillmentError<'tcx>>,
799 span: Span,
800 assoc_tag: ty::AssocTag,
801 ) -> ErrorGuaranteed {
802 let tcx = self.tcx();
809
810 let assoc_tag_str = assoc_tag_str(assoc_tag);
811 let adt_did = self_ty.ty_adt_def().map(|def| def.did());
812 let add_def_label = |err: &mut Diag<'_>| {
813 if let Some(did) = adt_did {
814 err.span_label(
815 tcx.def_span(did),
816 format!(
817 "associated {assoc_tag_str} `{name}` not found for this {}",
818 tcx.def_descr(did)
819 ),
820 );
821 }
822 };
823
824 if fulfillment_errors.is_empty() {
825 let limit = if candidates.len() == 5 { 5 } else { 4 };
828 let type_candidates = candidates
829 .iter()
830 .take(limit)
831 .map(|cand| {
832 format!("- `{}`", tcx.at(span).type_of(cand.impl_).instantiate_identity())
833 })
834 .collect::<Vec<_>>()
835 .join("\n");
836 let additional_types = if candidates.len() > limit {
837 format!("\nand {} more types", candidates.len() - limit)
838 } else {
839 String::new()
840 };
841
842 let mut err = struct_span_code_err!(
843 self.dcx(),
844 name.span,
845 E0220,
846 "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
847 );
848 err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
849 err.note(format!(
850 "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
851 ));
852 add_def_label(&mut err);
853 return err.emit();
854 }
855
856 let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
857
858 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
859 let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
860 match self_ty.kind() {
861 ty::Adt(def, _) => {
863 bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
864 }
865 ty::Dynamic(preds, _, _) => {
867 for pred in preds.iter() {
868 match pred.skip_binder() {
869 ty::ExistentialPredicate::Trait(tr) => {
870 bound_spans
871 .get_mut_or_insert_default(tcx.def_span(tr.def_id))
872 .push(msg.clone());
873 }
874 ty::ExistentialPredicate::Projection(_)
875 | ty::ExistentialPredicate::AutoTrait(_) => {}
876 }
877 }
878 }
879 ty::Closure(def_id, _) => {
881 bound_spans
882 .get_mut_or_insert_default(tcx.def_span(*def_id))
883 .push(format!("`{quiet}`"));
884 }
885 _ => {}
886 }
887 };
888
889 let format_pred = |pred: ty::Predicate<'tcx>| {
890 let bound_predicate = pred.kind();
891 match bound_predicate.skip_binder() {
892 ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
893 let projection_term = pred.projection_term;
895 let quiet_projection_term =
896 projection_term.with_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
897
898 let term = pred.term;
899 let obligation = format!("{projection_term} = {term}");
900 let quiet = format!("{quiet_projection_term} = {term}");
901
902 bound_span_label(projection_term.self_ty(), &obligation, &quiet);
903 Some((obligation, projection_term.self_ty()))
904 }
905 ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
906 let p = poly_trait_ref.trait_ref;
907 let self_ty = p.self_ty();
908 let path = p.print_only_trait_path();
909 let obligation = format!("{self_ty}: {path}");
910 let quiet = format!("_: {path}");
911 bound_span_label(self_ty, &obligation, &quiet);
912 Some((obligation, self_ty))
913 }
914 _ => None,
915 }
916 };
917
918 let mut bounds: Vec<_> = fulfillment_errors
921 .into_iter()
922 .map(|error| error.root_obligation.predicate)
923 .filter_map(format_pred)
924 .map(|(p, _)| format!("`{p}`"))
925 .collect();
926 bounds.sort();
927 bounds.dedup();
928
929 let mut err = self.dcx().struct_span_err(
930 name.span,
931 format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
932 );
933 if !bounds.is_empty() {
934 err.note(format!(
935 "the following trait bounds were not satisfied:\n{}",
936 bounds.join("\n")
937 ));
938 }
939 err.span_label(
940 name.span,
941 format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
942 );
943
944 for (span, mut bounds) in bound_spans {
945 if !tcx.sess.source_map().is_span_accessible(span) {
946 continue;
947 }
948 bounds.sort();
949 bounds.dedup();
950 let msg = match &bounds[..] {
951 [bound] => format!("doesn't satisfy {bound}"),
952 bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
953 [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")),
954 [] => unreachable!(),
955 };
956 err.span_label(span, msg);
957 }
958 add_def_label(&mut err);
959 err.emit()
960 }
961
962 pub(crate) fn check_for_required_assoc_tys(
967 &self,
968 spans: SmallVec<[Span; 1]>,
969 missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
970 potential_assoc_types: Vec<usize>,
971 trait_bounds: &[hir::PolyTraitRef<'_>],
972 ) -> Result<(), ErrorGuaranteed> {
973 if missing_assoc_types.is_empty() {
974 return Ok(());
975 }
976
977 let principal_span = *spans.first().unwrap();
978
979 let tcx = self.tcx();
980 let missing_assoc_types: Vec<_> = missing_assoc_types
982 .into_iter()
983 .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
984 .collect();
985 let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default();
986 let mut names_len = 0;
987
988 let mut dyn_compatibility_violations = Ok(());
991 for (assoc_item, trait_ref) in &missing_assoc_types {
992 names.entry(trait_ref).or_default().push(assoc_item.name());
993 names_len += 1;
994
995 let violations =
996 dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item);
997 if !violations.is_empty() {
998 dyn_compatibility_violations = Err(report_dyn_incompatibility(
999 tcx,
1000 principal_span,
1001 None,
1002 trait_ref.def_id(),
1003 &violations,
1004 )
1005 .emit());
1006 }
1007 }
1008
1009 if let Err(guar) = dyn_compatibility_violations {
1010 return Err(guar);
1011 }
1012
1013 let mut in_expr_or_pat = false;
1015 if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
1016 let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
1017 in_expr_or_pat = match grandparent {
1018 hir::Node::Expr(_) | hir::Node::Pat(_) => true,
1019 _ => false,
1020 };
1021 }
1022
1023 let bound_names = trait_bounds
1028 .iter()
1029 .filter_map(|poly_trait_ref| {
1030 let path = poly_trait_ref.trait_ref.path.segments.last()?;
1031 let args = path.args?;
1032
1033 Some(args.constraints.iter().filter_map(|constraint| {
1034 let ident = constraint.ident;
1035
1036 let Res::Def(DefKind::Trait, trait_def) = path.res else {
1037 return None;
1038 };
1039
1040 let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind(
1041 tcx,
1042 ident,
1043 ty::AssocTag::Type,
1044 trait_def,
1045 );
1046
1047 Some((ident.name, assoc_item?))
1048 }))
1049 })
1050 .flatten()
1051 .collect::<UnordMap<Symbol, &ty::AssocItem>>();
1052
1053 let mut names = names
1054 .into_iter()
1055 .map(|(trait_, mut assocs)| {
1056 assocs.sort();
1057 let trait_ = trait_.print_trait_sugared();
1058 format!(
1059 "{} in `{trait_}`",
1060 listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
1061 )
1062 })
1063 .collect::<Vec<String>>();
1064 names.sort();
1065 let names = names.join(", ");
1066
1067 let mut err = struct_span_code_err!(
1068 self.dcx(),
1069 principal_span,
1070 E0191,
1071 "the value of the associated type{} {} must be specified",
1072 pluralize!(names_len),
1073 names,
1074 );
1075 let mut suggestions = vec![];
1076 let mut types_count = 0;
1077 let mut where_constraints = vec![];
1078 let mut already_has_generics_args_suggestion = false;
1079
1080 let mut names: UnordMap<_, usize> = Default::default();
1081 for (item, _) in &missing_assoc_types {
1082 types_count += 1;
1083 *names.entry(item.name()).or_insert(0) += 1;
1084 }
1085 let mut dupes = false;
1086 let mut shadows = false;
1087 for (item, trait_ref) in &missing_assoc_types {
1088 let name = item.name();
1089 let prefix = if names[&name] > 1 {
1090 let trait_def_id = trait_ref.def_id();
1091 dupes = true;
1092 format!("{}::", tcx.def_path_str(trait_def_id))
1093 } else if bound_names.get(&name).is_some_and(|x| *x != item) {
1094 let trait_def_id = trait_ref.def_id();
1095 shadows = true;
1096 format!("{}::", tcx.def_path_str(trait_def_id))
1097 } else {
1098 String::new()
1099 };
1100
1101 let mut is_shadowed = false;
1102
1103 if let Some(assoc_item) = bound_names.get(&name)
1104 && *assoc_item != item
1105 {
1106 is_shadowed = true;
1107
1108 let rename_message =
1109 if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
1110 err.span_label(
1111 tcx.def_span(assoc_item.def_id),
1112 format!("`{}{}` shadowed here{}", prefix, name, rename_message),
1113 );
1114 }
1115
1116 let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
1117
1118 if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
1119 err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message));
1120 }
1121 }
1122 if potential_assoc_types.len() == missing_assoc_types.len() {
1123 already_has_generics_args_suggestion = true;
1127 } else if let (Ok(snippet), false, false) =
1128 (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
1129 {
1130 let types: Vec<_> = missing_assoc_types
1131 .iter()
1132 .map(|(item, _)| format!("{} = Type", item.name()))
1133 .collect();
1134 let code = if let Some(snippet) = snippet.strip_suffix('>') {
1135 format!("{}, {}>", snippet, types.join(", "))
1140 } else if in_expr_or_pat {
1141 format!("{}::<{}>", snippet, types.join(", "))
1144 } else {
1145 format!("{}<{}>", snippet, types.join(", "))
1148 };
1149 suggestions.push((principal_span, code));
1150 } else if dupes {
1151 where_constraints.push(principal_span);
1152 }
1153
1154 let where_msg = "consider introducing a new type parameter, adding `where` constraints \
1155 using the fully-qualified path to the associated types";
1156 if !where_constraints.is_empty() && suggestions.is_empty() {
1157 err.help(where_msg);
1161 }
1162 if suggestions.len() != 1 || already_has_generics_args_suggestion {
1163 let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
1165 for (item, _) in &missing_assoc_types {
1166 types_count += 1;
1167 *names.entry(item.name()).or_insert(0) += 1;
1168 }
1169 let mut label = vec![];
1170 for (item, trait_ref) in &missing_assoc_types {
1171 let name = item.name();
1172 let postfix = if names[&name] > 1 {
1173 format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
1174 } else {
1175 String::new()
1176 };
1177 label.push(format!("`{}`{}", name, postfix));
1178 }
1179 if !label.is_empty() {
1180 err.span_label(
1181 principal_span,
1182 format!(
1183 "associated type{} {} must be specified",
1184 pluralize!(label.len()),
1185 label.join(", "),
1186 ),
1187 );
1188 }
1189 }
1190 suggestions.sort_by_key(|&(span, _)| span);
1191 let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
1204 if !suggestions.is_empty() && !overlaps {
1205 err.multipart_suggestion(
1206 format!("specify the associated type{}", pluralize!(types_count)),
1207 suggestions,
1208 Applicability::HasPlaceholders,
1209 );
1210 if !where_constraints.is_empty() {
1211 err.span_help(where_constraints, where_msg);
1212 }
1213 }
1214
1215 Err(err.emit())
1216 }
1217
1218 pub(crate) fn maybe_report_similar_assoc_fn(
1222 &self,
1223 span: Span,
1224 qself_ty: Ty<'tcx>,
1225 qself: &hir::Ty<'_>,
1226 ) -> Result<(), ErrorGuaranteed> {
1227 let tcx = self.tcx();
1228 if let Some((_, node)) = tcx.hir_parent_iter(qself.hir_id).skip(1).next()
1229 && let hir::Node::Expr(hir::Expr {
1230 kind:
1231 hir::ExprKind::Path(hir::QPath::TypeRelative(
1232 hir::Ty {
1233 kind:
1234 hir::TyKind::Path(hir::QPath::TypeRelative(
1235 _,
1236 hir::PathSegment { ident: ident2, .. },
1237 )),
1238 ..
1239 },
1240 hir::PathSegment { ident: ident3, .. },
1241 )),
1242 ..
1243 }) = node
1244 && let Some(inherent_impls) = qself_ty
1245 .ty_adt_def()
1246 .map(|adt_def| tcx.inherent_impls(adt_def.did()))
1247 .or_else(|| {
1248 simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer)
1249 .map(|simple_ty| tcx.incoherent_impls(simple_ty))
1250 })
1251 && let name = Symbol::intern(&format!("{ident2}_{ident3}"))
1252 && let Some(item) = inherent_impls
1253 .iter()
1254 .flat_map(|inherent_impl| {
1255 tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
1256 })
1257 .next()
1258 && item.is_fn()
1259 {
1260 Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")
1261 .with_span_suggestion_verbose(
1262 ident2.span.to(ident3.span),
1263 format!("there is an associated function with a similar name: `{name}`"),
1264 name,
1265 Applicability::MaybeIncorrect,
1266 )
1267 .emit())
1268 } else {
1269 Ok(())
1270 }
1271 }
1272
1273 pub fn report_prohibited_generic_args<'a>(
1274 &self,
1275 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1276 args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1277 err_extend: GenericsArgsErrExtend<'a>,
1278 ) -> ErrorGuaranteed {
1279 #[derive(PartialEq, Eq, Hash)]
1280 enum ProhibitGenericsArg {
1281 Lifetime,
1282 Type,
1283 Const,
1284 Infer,
1285 }
1286
1287 let mut prohibit_args = FxIndexSet::default();
1288 args_visitors.for_each(|arg| {
1289 match arg {
1290 hir::GenericArg::Lifetime(_) => prohibit_args.insert(ProhibitGenericsArg::Lifetime),
1291 hir::GenericArg::Type(_) => prohibit_args.insert(ProhibitGenericsArg::Type),
1292 hir::GenericArg::Const(_) => prohibit_args.insert(ProhibitGenericsArg::Const),
1293 hir::GenericArg::Infer(_) => prohibit_args.insert(ProhibitGenericsArg::Infer),
1294 };
1295 });
1296
1297 let segments: Vec<_> = segments.collect();
1298 let types_and_spans: Vec<_> = segments
1299 .iter()
1300 .flat_map(|segment| {
1301 if segment.args().args.is_empty() {
1302 None
1303 } else {
1304 Some((
1305 match segment.res {
1306 Res::PrimTy(ty) => {
1307 format!("{} `{}`", segment.res.descr(), ty.name())
1308 }
1309 Res::Def(_, def_id)
1310 if let Some(name) = self.tcx().opt_item_name(def_id) =>
1311 {
1312 format!("{} `{name}`", segment.res.descr())
1313 }
1314 Res::Err => "this type".to_string(),
1315 _ => segment.res.descr().to_string(),
1316 },
1317 segment.ident.span,
1318 ))
1319 }
1320 })
1321 .collect();
1322 let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
1323 .expect("expected one segment to deny");
1324
1325 let arg_spans: Vec<Span> =
1326 segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
1327
1328 let mut kinds = Vec::with_capacity(4);
1329 prohibit_args.iter().for_each(|arg| match arg {
1330 ProhibitGenericsArg::Lifetime => kinds.push("lifetime"),
1331 ProhibitGenericsArg::Type => kinds.push("type"),
1332 ProhibitGenericsArg::Const => kinds.push("const"),
1333 ProhibitGenericsArg::Infer => kinds.push("generic"),
1334 });
1335
1336 let s = pluralize!(kinds.len());
1337 let kind =
1338 listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit");
1339 let last_span = *arg_spans.last().unwrap();
1340 let span: MultiSpan = arg_spans.into();
1341 let mut err = struct_span_code_err!(
1342 self.dcx(),
1343 span,
1344 E0109,
1345 "{kind} arguments are not allowed on {this_type}",
1346 );
1347 err.span_label(last_span, format!("{kind} argument{s} not allowed"));
1348 for (what, span) in types_and_spans {
1349 err.span_label(span, format!("not allowed on {what}"));
1350 }
1351 generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
1352 err.emit()
1353 }
1354
1355 pub fn report_trait_object_addition_traits(
1356 &self,
1357 regular_traits: &Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>,
1358 ) -> ErrorGuaranteed {
1359 let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap();
1362 let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap();
1363 let mut err = struct_span_code_err!(
1364 self.dcx(),
1365 *regular_traits[1].1.first().unwrap(),
1366 E0225,
1367 "only auto traits can be used as additional traits in a trait object"
1368 );
1369 err.span_label(first_span, "first non-auto trait");
1370 for &alias_span in first_alias_spans {
1371 err.span_label(alias_span, "first non-auto trait comes from this alias");
1372 }
1373 err.span_label(second_span, "additional non-auto trait");
1374 for &alias_span in second_alias_spans {
1375 err.span_label(alias_span, "second non-auto trait comes from this alias");
1376 }
1377 err.help(format!(
1378 "consider creating a new trait with all of these as supertraits and using that \
1379 trait here instead: `trait NewTrait: {} {{}}`",
1380 regular_traits
1381 .iter()
1382 .map(|(pred, _)| pred
1384 .map_bound(|pred| pred.trait_ref)
1385 .print_only_trait_path()
1386 .to_string())
1387 .collect::<Vec<_>>()
1388 .join(" + "),
1389 ));
1390 err.note(
1391 "auto-traits like `Send` and `Sync` are traits that have special properties; \
1392 for more information on them, visit \
1393 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1394 );
1395 err.emit()
1396 }
1397
1398 pub fn report_trait_object_with_no_traits(
1399 &self,
1400 span: Span,
1401 user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
1402 ) -> ErrorGuaranteed {
1403 let tcx = self.tcx();
1404 let trait_alias_span = user_written_clauses
1405 .into_iter()
1406 .filter_map(|(clause, _)| clause.as_trait_clause())
1407 .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id()))
1408 .map(|trait_ref| tcx.def_span(trait_ref.def_id()));
1409
1410 self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
1411 }
1412}
1413
1414pub fn prohibit_assoc_item_constraint(
1416 cx: &dyn HirTyLowerer<'_>,
1417 constraint: &hir::AssocItemConstraint<'_>,
1418 segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
1419) -> ErrorGuaranteed {
1420 let tcx = cx.tcx();
1421 let mut err = cx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
1422 span: constraint.span,
1423 fn_trait_expansion: if let Some((_, segment, span)) = segment
1424 && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
1425 {
1426 Some(ParenthesizedFnTraitExpansion {
1427 span,
1428 expanded_type: fn_trait_to_string(tcx, segment, false),
1429 })
1430 } else {
1431 None
1432 },
1433 });
1434
1435 if let Some((def_id, segment, _)) = segment
1439 && segment.args().parenthesized == hir::GenericArgsParentheses::No
1440 {
1441 let suggest_removal = |e: &mut Diag<'_>| {
1443 let constraints = segment.args().constraints;
1444 let args = segment.args().args;
1445
1446 let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
1458 bug!("a type binding exists but its HIR ID not found in generics");
1459 };
1460
1461 let preceding_span = if index > 0 {
1462 Some(constraints[index - 1].span)
1463 } else {
1464 args.last().map(|a| a.span())
1465 };
1466
1467 let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
1468
1469 let removal_span = match (preceding_span, next_span) {
1470 (Some(prec), _) => constraint.span.with_lo(prec.hi()),
1471 (None, Some(next)) => constraint.span.with_hi(next.lo()),
1472 (None, None) => {
1473 let Some(generics_span) = segment.args().span_ext() else {
1474 bug!("a type binding exists but generic span is empty");
1475 };
1476
1477 generics_span
1478 }
1479 };
1480
1481 e.span_suggestion_verbose(
1483 removal_span,
1484 format!("consider removing this associated item {}", constraint.kind.descr()),
1485 "",
1486 Applicability::MaybeIncorrect,
1487 );
1488 };
1489
1490 let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
1493 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
1494 e.span_suggestion_verbose(
1495 constraint.span,
1496 format!("to use `{snippet}` as a generic argument specify it directly"),
1497 snippet,
1498 Applicability::MaybeIncorrect,
1499 );
1500 }
1501 };
1502
1503 let generics = tcx.generics_of(def_id);
1506 let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
1507
1508 if let Some(matching_param) = matching_param {
1510 match (constraint.kind, &matching_param.kind) {
1511 (
1512 hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
1513 GenericParamDefKind::Type { .. },
1514 ) => suggest_direct_use(&mut err, ty.span),
1515 (
1516 hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
1517 GenericParamDefKind::Const { .. },
1518 ) => {
1519 suggest_direct_use(&mut err, c.span());
1520 }
1521 (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
1522 let impl_block = tcx
1528 .hir_parent_iter(constraint.hir_id)
1529 .find_map(|(_, node)| node.impl_block_of_trait(def_id));
1530
1531 let type_with_constraints =
1532 tcx.sess.source_map().span_to_snippet(constraint.span);
1533
1534 if let Some(impl_block) = impl_block
1535 && let Ok(type_with_constraints) = type_with_constraints
1536 {
1537 let lifetimes: String = bounds
1540 .iter()
1541 .filter_map(|bound| {
1542 if let hir::GenericBound::Outlives(lifetime) = bound {
1543 Some(format!("{lifetime}, "))
1544 } else {
1545 None
1546 }
1547 })
1548 .collect();
1549 let param_decl = if let Some(param_span) =
1552 impl_block.generics.span_for_param_suggestion()
1553 {
1554 (param_span, format!(", {lifetimes}{type_with_constraints}"))
1555 } else {
1556 (
1557 impl_block.generics.span.shrink_to_lo(),
1558 format!("<{lifetimes}{type_with_constraints}>"),
1559 )
1560 };
1561 let suggestions = vec![
1562 param_decl,
1563 (constraint.span.with_lo(constraint.ident.span.hi()), String::new()),
1564 ];
1565
1566 err.multipart_suggestion_verbose(
1567 "declare the type parameter right after the `impl` keyword",
1568 suggestions,
1569 Applicability::MaybeIncorrect,
1570 );
1571 }
1572 }
1573 _ => suggest_removal(&mut err),
1574 }
1575 } else {
1576 suggest_removal(&mut err);
1577 }
1578 }
1579
1580 err.emit()
1581}
1582
1583pub(crate) fn fn_trait_to_string(
1584 tcx: TyCtxt<'_>,
1585 trait_segment: &hir::PathSegment<'_>,
1586 parenthesized: bool,
1587) -> String {
1588 let args = trait_segment
1589 .args
1590 .and_then(|args| args.args.first())
1591 .and_then(|arg| match arg {
1592 hir::GenericArg::Type(ty) => match ty.kind {
1593 hir::TyKind::Tup(t) => t
1594 .iter()
1595 .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
1596 .collect::<Result<Vec<_>, _>>()
1597 .map(|a| a.join(", ")),
1598 _ => tcx.sess.source_map().span_to_snippet(ty.span),
1599 }
1600 .map(|s| {
1601 if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") }
1603 })
1604 .ok(),
1605 _ => None,
1606 })
1607 .unwrap_or_else(|| "()".to_string());
1608
1609 let ret = trait_segment
1610 .args()
1611 .constraints
1612 .iter()
1613 .find_map(|c| {
1614 if c.ident.name == sym::Output
1615 && let Some(ty) = c.ty()
1616 && ty.span != tcx.hir_span(trait_segment.hir_id)
1617 {
1618 tcx.sess.source_map().span_to_snippet(ty.span).ok()
1619 } else {
1620 None
1621 }
1622 })
1623 .unwrap_or_else(|| "()".to_string());
1624
1625 if parenthesized {
1626 format!("{}{} -> {}", trait_segment.ident, args, ret)
1627 } else {
1628 format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
1629 }
1630}
1631
1632pub enum GenericsArgsErrExtend<'tcx> {
1634 EnumVariant {
1635 qself: &'tcx hir::Ty<'tcx>,
1636 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1637 adt_def: AdtDef<'tcx>,
1638 },
1639 OpaqueTy,
1640 PrimTy(hir::PrimTy),
1641 SelfTyAlias {
1642 def_id: DefId,
1643 span: Span,
1644 },
1645 SelfTyParam(Span),
1646 Param(DefId),
1647 DefVariant(&'tcx [hir::PathSegment<'tcx>]),
1648 None,
1649}
1650
1651fn generics_args_err_extend<'a>(
1652 tcx: TyCtxt<'_>,
1653 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1654 err: &mut Diag<'_>,
1655 err_extend: GenericsArgsErrExtend<'a>,
1656) {
1657 match err_extend {
1658 GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
1659 err.note("enum variants can't have type parameters");
1660 let type_name = tcx.item_name(adt_def.did());
1661 let msg = format!(
1662 "you might have meant to specify type parameters on enum \
1663 `{type_name}`"
1664 );
1665 let Some(args) = assoc_segment.args else {
1666 return;
1667 };
1668 let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2));
1673 if tcx.generics_of(adt_def.did()).is_empty() {
1674 err.span_suggestion_verbose(
1677 args_span,
1678 format!("{type_name} doesn't have generic parameters"),
1679 "",
1680 Applicability::MachineApplicable,
1681 );
1682 return;
1683 }
1684 let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
1685 err.note(msg);
1686 return;
1687 };
1688 let (qself_sugg_span, is_self) =
1689 if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1690 match &path.segments {
1693 [
1697 ..,
1698 hir::PathSegment {
1699 ident, args, res: Res::Def(DefKind::Enum, _), ..
1700 },
1701 _,
1702 ] => (
1703 ident
1706 .span
1707 .shrink_to_hi()
1708 .to(args.map_or(ident.span.shrink_to_hi(), |a| a.span_ext)),
1709 false,
1710 ),
1711 [segment] => {
1712 (
1713 segment.ident.span.shrink_to_hi().to(segment
1716 .args
1717 .map_or(segment.ident.span.shrink_to_hi(), |a| a.span_ext)),
1718 kw::SelfUpper == segment.ident.name,
1719 )
1720 }
1721 _ => {
1722 err.note(msg);
1723 return;
1724 }
1725 }
1726 } else {
1727 err.note(msg);
1728 return;
1729 };
1730 let suggestion = vec![
1731 if is_self {
1732 (qself.span, format!("{type_name}{snippet}"))
1736 } else {
1737 (qself_sugg_span, snippet)
1738 },
1739 (args_span, String::new()),
1740 ];
1741 err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
1742 }
1743 GenericsArgsErrExtend::DefVariant(segments) => {
1744 let args: Vec<Span> = segments
1745 .iter()
1746 .filter_map(|segment| match segment.res {
1747 Res::Def(
1748 DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1749 _,
1750 ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1751 _ => None,
1752 })
1753 .collect();
1754 if args.len() > 1
1755 && let Some(span) = args.into_iter().next_back()
1756 {
1757 err.note(
1758 "generic arguments are not allowed on both an enum and its variant's path \
1759 segments simultaneously; they are only valid in one place or the other",
1760 );
1761 err.span_suggestion_verbose(
1762 span,
1763 "remove the generics arguments from one of the path segments",
1764 String::new(),
1765 Applicability::MaybeIncorrect,
1766 );
1767 }
1768 }
1769 GenericsArgsErrExtend::PrimTy(prim_ty) => {
1770 let name = prim_ty.name_str();
1771 for segment in segments {
1772 if let Some(args) = segment.args {
1773 err.span_suggestion_verbose(
1774 segment.ident.span.shrink_to_hi().to(args.span_ext),
1775 format!("primitive type `{name}` doesn't have generic parameters"),
1776 "",
1777 Applicability::MaybeIncorrect,
1778 );
1779 }
1780 }
1781 }
1782 GenericsArgsErrExtend::OpaqueTy => {
1783 err.note("`impl Trait` types can't have type parameters");
1784 }
1785 GenericsArgsErrExtend::Param(def_id) => {
1786 let span = tcx.def_ident_span(def_id).unwrap();
1787 let kind = tcx.def_descr(def_id);
1788 let name = tcx.item_name(def_id);
1789 err.span_note(span, format!("{kind} `{name}` defined here"));
1790 }
1791 GenericsArgsErrExtend::SelfTyParam(span) => {
1792 err.span_suggestion_verbose(
1793 span,
1794 "the `Self` type doesn't accept type parameters",
1795 "",
1796 Applicability::MaybeIncorrect,
1797 );
1798 }
1799 GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
1800 let ty = tcx.at(span).type_of(def_id).instantiate_identity();
1801 let span_of_impl = tcx.span_of_impl(def_id);
1802 let def_id = match *ty.kind() {
1803 ty::Adt(self_def, _) => self_def.did(),
1804 _ => return,
1805 };
1806
1807 let type_name = tcx.item_name(def_id);
1808 let span_of_ty = tcx.def_ident_span(def_id);
1809 let generics = tcx.generics_of(def_id).count();
1810
1811 let msg = format!("`Self` is of type `{ty}`");
1812 if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
1813 let mut span: MultiSpan = vec![t_sp].into();
1814 span.push_span_label(
1815 i_sp,
1816 format!("`Self` is on type `{type_name}` in this `impl`"),
1817 );
1818 let mut postfix = "";
1819 if generics == 0 {
1820 postfix = ", which doesn't have generic parameters";
1821 }
1822 span.push_span_label(t_sp, format!("`Self` corresponds to this type{postfix}"));
1823 err.span_note(span, msg);
1824 } else {
1825 err.note(msg);
1826 }
1827 for segment in segments {
1828 if let Some(args) = segment.args
1829 && segment.ident.name == kw::SelfUpper
1830 {
1831 if generics == 0 {
1832 err.span_suggestion_verbose(
1835 segment.ident.span.shrink_to_hi().to(args.span_ext),
1836 "the `Self` type doesn't accept type parameters",
1837 "",
1838 Applicability::MachineApplicable,
1839 );
1840 return;
1841 } else {
1842 err.span_suggestion_verbose(
1843 segment.ident.span,
1844 format!(
1845 "the `Self` type doesn't accept type parameters, use the \
1846 concrete type's name `{type_name}` instead if you want to \
1847 specify its type parameters"
1848 ),
1849 type_name,
1850 Applicability::MaybeIncorrect,
1851 );
1852 }
1853 }
1854 }
1855 }
1856 _ => {}
1857 }
1858}
1859
1860pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
1861 match assoc_tag {
1862 ty::AssocTag::Fn => "function",
1863 ty::AssocTag::Const => "constant",
1864 ty::AssocTag::Type => "type",
1865 }
1866}