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, listify, pluralize, struct_span_code_err,
7};
8use rustc_hir as hir;
9use rustc_hir::def::{CtorOf, DefKind, Res};
10use rustc_hir::def_id::DefId;
11use rustc_middle::bug;
12use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
13use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
14use rustc_middle::ty::{
15 self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
16 suggest_constraining_type_param,
17};
18use rustc_session::parse::feature_err;
19use rustc_span::edit_distance::find_best_match_for_name;
20use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, kw, sym};
21use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
22use rustc_trait_selection::traits::{
23 FulfillmentError, dyn_compatibility_violations_for_assoc_item,
24};
25use smallvec::SmallVec;
26
27use crate::errors::{
28 self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
29 ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
30};
31use crate::fluent_generated as fluent;
32use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
33
34impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
35 pub(crate) fn complain_about_missing_type_params(
38 &self,
39 missing_type_params: Vec<Symbol>,
40 def_id: DefId,
41 span: Span,
42 empty_generic_args: bool,
43 ) {
44 if missing_type_params.is_empty() {
45 return;
46 }
47
48 self.dcx().emit_err(MissingTypeParams {
49 span,
50 def_span: self.tcx().def_span(def_id),
51 span_snippet: self.tcx().sess.source_map().span_to_snippet(span).ok(),
52 missing_type_params,
53 empty_generic_args,
54 });
55 }
56
57 pub(crate) fn complain_about_internal_fn_trait(
60 &self,
61 span: Span,
62 trait_def_id: DefId,
63 trait_segment: &'_ hir::PathSegment<'_>,
64 is_impl: bool,
65 ) {
66 if self.tcx().features().unboxed_closures() {
67 return;
68 }
69
70 let trait_def = self.tcx().trait_def(trait_def_id);
71 if !trait_def.paren_sugar {
72 if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
73 feature_err(
75 &self.tcx().sess,
76 sym::unboxed_closures,
77 span,
78 "parenthetical notation is only stable when used with `Fn`-family traits",
79 )
80 .emit();
81 }
82
83 return;
84 }
85
86 let sess = self.tcx().sess;
87
88 if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
89 let mut err = feature_err(
91 sess,
92 sym::unboxed_closures,
93 span,
94 "the precise format of `Fn`-family traits' type parameters is subject to change",
95 );
96 if !is_impl {
99 err.span_suggestion(
100 span,
101 "use parenthetical notation instead",
102 fn_trait_to_string(self.tcx(), trait_segment, true),
103 Applicability::MaybeIncorrect,
104 );
105 }
106 err.emit();
107 }
108
109 if is_impl {
110 let trait_name = self.tcx().def_path_str(trait_def_id);
111 self.dcx().emit_err(ManualImplementation { span, trait_name });
112 }
113 }
114
115 pub(super) fn complain_about_assoc_item_not_found<I>(
116 &self,
117 all_candidates: impl Fn() -> I,
118 qself: AssocItemQSelf,
119 assoc_tag: ty::AssocTag,
120 assoc_ident: Ident,
121 span: Span,
122 constraint: Option<&hir::AssocItemConstraint<'tcx>>,
123 ) -> ErrorGuaranteed
124 where
125 I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
126 {
127 let tcx = self.tcx();
128
129 if let Some(assoc_item) = all_candidates().find_map(|r| {
131 tcx.associated_items(r.def_id())
132 .filter_by_name_unhygienic(assoc_ident.name)
133 .find(|item| tcx.hygienic_eq(assoc_ident, item.ident(tcx), r.def_id()))
134 }) {
135 return self.complain_about_assoc_kind_mismatch(
136 assoc_item,
137 assoc_tag,
138 assoc_ident,
139 span,
140 constraint,
141 );
142 }
143
144 let assoc_kind_str = assoc_tag_str(assoc_tag);
145 let qself_str = qself.to_string(tcx);
146
147 let is_dummy = assoc_ident.span == DUMMY_SP;
150
151 let mut err = errors::AssocItemNotFound {
152 span: if is_dummy { span } else { assoc_ident.span },
153 assoc_ident,
154 assoc_kind: assoc_kind_str,
155 qself: &qself_str,
156 label: None,
157 sugg: None,
158 within_macro_span: assoc_ident.span.within_macro(span, tcx.sess.source_map()),
161 };
162
163 if is_dummy {
164 err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span });
165 return self.dcx().emit_err(err);
166 }
167
168 let all_candidate_names: Vec<_> = all_candidates()
169 .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
170 .filter_map(|item| {
171 if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag {
172 item.opt_name()
173 } else {
174 None
175 }
176 })
177 .collect();
178
179 if let Some(suggested_name) =
180 find_best_match_for_name(&all_candidate_names, assoc_ident.name, None)
181 {
182 err.sugg = Some(errors::AssocItemNotFoundSugg::Similar {
183 span: assoc_ident.span,
184 assoc_kind: assoc_kind_str,
185 suggested_name,
186 });
187 return self.dcx().emit_err(err);
188 }
189
190 let visible_traits: Vec<_> = tcx
195 .visible_traits()
196 .filter(|trait_def_id| {
197 let viz = tcx.visibility(*trait_def_id);
198 let def_id = self.item_def_id();
199 viz.is_accessible_from(def_id, tcx)
200 })
201 .collect();
202
203 let wider_candidate_names: Vec<_> = visible_traits
204 .iter()
205 .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
206 .filter_map(|item| {
207 (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
208 })
209 .collect();
210
211 if let Some(suggested_name) =
212 find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None)
213 {
214 if let [best_trait] = visible_traits
215 .iter()
216 .copied()
217 .filter(|trait_def_id| {
218 tcx.associated_items(trait_def_id)
219 .filter_by_name_unhygienic(suggested_name)
220 .any(|item| item.as_tag() == assoc_tag)
221 })
222 .collect::<Vec<_>>()[..]
223 {
224 let trait_name = tcx.def_path_str(best_trait);
225 err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait {
226 span: assoc_ident.span,
227 assoc_kind: assoc_kind_str,
228 trait_name: &trait_name,
229 suggested_name,
230 identically_named: suggested_name == assoc_ident.name,
231 });
232 if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
233 && let item_def_id =
237 tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
238 && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
240 {
241 if generics
245 .bounds_for_param(ty_param_def_id)
246 .flat_map(|pred| pred.bounds.iter())
247 .any(|b| match b {
248 hir::GenericBound::Trait(t, ..) => {
249 t.trait_ref.trait_def_id() == Some(best_trait)
250 }
251 _ => false,
252 })
253 {
254 err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
257 span: assoc_ident.span,
258 assoc_kind: assoc_kind_str,
259 suggested_name,
260 });
261 return self.dcx().emit_err(err);
262 }
263
264 let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
265 let mut trait_ref = trait_name.clone();
266 let applicability = if let [arg, args @ ..] = trait_args {
267 use std::fmt::Write;
268 write!(trait_ref, "</* {arg}").unwrap();
269 args.iter().try_for_each(|arg| write!(trait_ref, ", {arg}")).unwrap();
270 trait_ref += " */>";
271 Applicability::HasPlaceholders
272 } else {
273 Applicability::MaybeIncorrect
274 };
275
276 let identically_named = suggested_name == assoc_ident.name;
277
278 if let DefKind::TyAlias = tcx.def_kind(item_def_id)
279 && !tcx.type_alias_is_lazy(item_def_id)
280 {
281 err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
282 lo: ty_param_span.shrink_to_lo(),
283 mi: ty_param_span.shrink_to_hi(),
284 hi: (!identically_named).then_some(assoc_ident.span),
285 trait_ref,
286 identically_named,
287 suggested_name,
288 applicability,
289 });
290 } else {
291 let mut err = self.dcx().create_err(err);
292 if suggest_constraining_type_param(
293 tcx,
294 generics,
295 &mut err,
296 &qself_str,
297 &trait_ref,
298 Some(best_trait),
299 None,
300 ) && !identically_named
301 {
302 err.span_suggestion_verbose(
305 assoc_ident.span,
306 fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
307 suggested_name,
308 Applicability::MaybeIncorrect,
309 );
310 }
311 return err.emit();
312 }
313 }
314 return self.dcx().emit_err(err);
315 }
316 }
317
318 if let [candidate_name] = all_candidate_names.as_slice() {
321 err.sugg = Some(errors::AssocItemNotFoundSugg::Other {
322 span: assoc_ident.span,
323 qself: &qself_str,
324 assoc_kind: assoc_kind_str,
325 suggested_name: *candidate_name,
326 });
327 } else {
328 err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_ident.span });
329 }
330
331 self.dcx().emit_err(err)
332 }
333
334 fn complain_about_assoc_kind_mismatch(
335 &self,
336 assoc_item: &ty::AssocItem,
337 assoc_tag: ty::AssocTag,
338 ident: Ident,
339 span: Span,
340 constraint: Option<&hir::AssocItemConstraint<'tcx>>,
341 ) -> ErrorGuaranteed {
342 let tcx = self.tcx();
343
344 let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
345 && let Some(constraint) = constraint
346 && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
347 {
348 let lo = if constraint.gen_args.span_ext.is_dummy() {
349 ident.span
350 } else {
351 constraint.gen_args.span_ext
352 };
353 Some(lo.between(span.shrink_to_hi()))
354 } else {
355 None
356 };
357
358 let wrap_in_braces_sugg = if let Some(constraint) = constraint
360 && let Some(hir_ty) = constraint.ty()
361 && let ty = self.lower_ty(hir_ty)
362 && (ty.is_enum() || ty.references_error())
363 && tcx.features().associated_const_equality()
364 {
365 Some(errors::AssocKindMismatchWrapInBracesSugg {
366 lo: hir_ty.span.shrink_to_lo(),
367 hi: hir_ty.span.shrink_to_hi(),
368 })
369 } else {
370 None
371 };
372
373 let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
376 && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
377 {
378 let span = match term {
379 hir::Term::Ty(ty) => ty.span,
380 hir::Term::Const(ct) => ct.span(),
381 };
382 (span, Some(ident.span), assoc_item.as_tag(), assoc_tag)
383 } else {
384 (ident.span, None, assoc_tag, assoc_item.as_tag())
385 };
386
387 self.dcx().emit_err(errors::AssocKindMismatch {
388 span,
389 expected: assoc_tag_str(expected),
390 got: assoc_tag_str(got),
391 expected_because_label,
392 assoc_kind: assoc_tag_str(assoc_item.as_tag()),
393 def_span: tcx.def_span(assoc_item.def_id),
394 bound_on_assoc_const_label,
395 wrap_in_braces_sugg,
396 })
397 }
398
399 pub(super) fn report_ambiguous_assoc(
400 &self,
401 span: Span,
402 types: &[String],
403 traits: &[String],
404 name: Symbol,
405 assoc_tag: ty::AssocTag,
406 ) -> ErrorGuaranteed {
407 let kind_str = assoc_tag_str(assoc_tag);
408 let mut err =
409 struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
410 if self
411 .tcx()
412 .resolutions(())
413 .confused_type_with_std_module
414 .keys()
415 .any(|full_span| full_span.contains(span))
416 {
417 err.span_suggestion_verbose(
418 span.shrink_to_lo(),
419 "you are looking for the module in `std`, not the primitive type",
420 "std::",
421 Applicability::MachineApplicable,
422 );
423 } else {
424 let mut types = types.to_vec();
425 types.sort();
426 let mut traits = traits.to_vec();
427 traits.sort();
428 match (&types[..], &traits[..]) {
429 ([], []) => {
430 err.span_suggestion_verbose(
431 span,
432 format!(
433 "if there were a type named `Type` that implements a trait named \
434 `Trait` with associated {kind_str} `{name}`, you could use the \
435 fully-qualified path",
436 ),
437 format!("<Type as Trait>::{name}"),
438 Applicability::HasPlaceholders,
439 );
440 }
441 ([], [trait_str]) => {
442 err.span_suggestion_verbose(
443 span,
444 format!(
445 "if there were a type named `Example` that implemented `{trait_str}`, \
446 you could use the fully-qualified path",
447 ),
448 format!("<Example as {trait_str}>::{name}"),
449 Applicability::HasPlaceholders,
450 );
451 }
452 ([], traits) => {
453 err.span_suggestions(
454 span,
455 format!(
456 "if there were a type named `Example` that implemented one of the \
457 traits with associated {kind_str} `{name}`, you could use the \
458 fully-qualified path",
459 ),
460 traits.iter().map(|trait_str| format!("<Example as {trait_str}>::{name}")),
461 Applicability::HasPlaceholders,
462 );
463 }
464 ([type_str], []) => {
465 err.span_suggestion_verbose(
466 span,
467 format!(
468 "if there were a trait named `Example` with associated {kind_str} `{name}` \
469 implemented for `{type_str}`, you could use the fully-qualified path",
470 ),
471 format!("<{type_str} as Example>::{name}"),
472 Applicability::HasPlaceholders,
473 );
474 }
475 (types, []) => {
476 err.span_suggestions(
477 span,
478 format!(
479 "if there were a trait named `Example` with associated {kind_str} `{name}` \
480 implemented for one of the types, you could use the fully-qualified \
481 path",
482 ),
483 types
484 .into_iter()
485 .map(|type_str| format!("<{type_str} as Example>::{name}")),
486 Applicability::HasPlaceholders,
487 );
488 }
489 (types, traits) => {
490 let mut suggestions = vec![];
491 for type_str in types {
492 for trait_str in traits {
493 suggestions.push(format!("<{type_str} as {trait_str}>::{name}"));
494 }
495 }
496 err.span_suggestions(
497 span,
498 "use fully-qualified syntax",
499 suggestions,
500 Applicability::MachineApplicable,
501 );
502 }
503 }
504 }
505 err.emit()
506 }
507
508 pub(crate) fn complain_about_ambiguous_inherent_assoc(
509 &self,
510 name: Ident,
511 candidates: Vec<DefId>,
512 span: Span,
513 ) -> ErrorGuaranteed {
514 let mut err = struct_span_code_err!(
515 self.dcx(),
516 name.span,
517 E0034,
518 "multiple applicable items in scope"
519 );
520 err.span_label(name.span, format!("multiple `{name}` found"));
521 self.note_ambiguous_inherent_assoc_ty(&mut err, candidates, span);
522 err.emit()
523 }
524
525 fn note_ambiguous_inherent_assoc_ty(
527 &self,
528 err: &mut Diag<'_>,
529 candidates: Vec<DefId>,
530 span: Span,
531 ) {
532 let tcx = self.tcx();
533
534 let limit = if candidates.len() == 5 { 5 } else { 4 };
536
537 for (index, &item) in candidates.iter().take(limit).enumerate() {
538 let impl_ = tcx.impl_of_method(item).unwrap();
539
540 let note_span = if item.is_local() {
541 Some(tcx.def_span(item))
542 } else if impl_.is_local() {
543 Some(tcx.def_span(impl_))
544 } else {
545 None
546 };
547
548 let title = if candidates.len() > 1 {
549 format!("candidate #{}", index + 1)
550 } else {
551 "the candidate".into()
552 };
553
554 let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity();
555 let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
556
557 if let Some(span) = note_span {
558 err.span_note(span, note);
559 } else {
560 err.note(note);
561 }
562 }
563 if candidates.len() > limit {
564 err.note(format!("and {} others", candidates.len() - limit));
565 }
566 }
567
568 pub(crate) fn complain_about_inherent_assoc_not_found(
570 &self,
571 name: Ident,
572 self_ty: Ty<'tcx>,
573 candidates: Vec<(DefId, (DefId, DefId))>,
574 fulfillment_errors: Vec<FulfillmentError<'tcx>>,
575 span: Span,
576 assoc_tag: ty::AssocTag,
577 ) -> ErrorGuaranteed {
578 let tcx = self.tcx();
585
586 let assoc_tag_str = assoc_tag_str(assoc_tag);
587 let adt_did = self_ty.ty_adt_def().map(|def| def.did());
588 let add_def_label = |err: &mut Diag<'_>| {
589 if let Some(did) = adt_did {
590 err.span_label(
591 tcx.def_span(did),
592 format!(
593 "associated {assoc_tag_str} `{name}` not found for this {}",
594 tcx.def_descr(did)
595 ),
596 );
597 }
598 };
599
600 if fulfillment_errors.is_empty() {
601 let limit = if candidates.len() == 5 { 5 } else { 4 };
604 let type_candidates = candidates
605 .iter()
606 .take(limit)
607 .map(|&(impl_, _)| {
608 format!("- `{}`", tcx.at(span).type_of(impl_).instantiate_identity())
609 })
610 .collect::<Vec<_>>()
611 .join("\n");
612 let additional_types = if candidates.len() > limit {
613 format!("\nand {} more types", candidates.len() - limit)
614 } else {
615 String::new()
616 };
617
618 let mut err = struct_span_code_err!(
619 self.dcx(),
620 name.span,
621 E0220,
622 "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
623 );
624 err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
625 err.note(format!(
626 "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
627 ));
628 add_def_label(&mut err);
629 return err.emit();
630 }
631
632 let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
633
634 let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
635 let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
636 match self_ty.kind() {
637 ty::Adt(def, _) => {
639 bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
640 }
641 ty::Dynamic(preds, _, _) => {
643 for pred in preds.iter() {
644 match pred.skip_binder() {
645 ty::ExistentialPredicate::Trait(tr) => {
646 bound_spans
647 .get_mut_or_insert_default(tcx.def_span(tr.def_id))
648 .push(msg.clone());
649 }
650 ty::ExistentialPredicate::Projection(_)
651 | ty::ExistentialPredicate::AutoTrait(_) => {}
652 }
653 }
654 }
655 ty::Closure(def_id, _) => {
657 bound_spans
658 .get_mut_or_insert_default(tcx.def_span(*def_id))
659 .push(format!("`{quiet}`"));
660 }
661 _ => {}
662 }
663 };
664
665 let format_pred = |pred: ty::Predicate<'tcx>| {
666 let bound_predicate = pred.kind();
667 match bound_predicate.skip_binder() {
668 ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
669 let projection_term = pred.projection_term;
671 let quiet_projection_term =
672 projection_term.with_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
673
674 let term = pred.term;
675 let obligation = format!("{projection_term} = {term}");
676 let quiet = format!("{quiet_projection_term} = {term}");
677
678 bound_span_label(projection_term.self_ty(), &obligation, &quiet);
679 Some((obligation, projection_term.self_ty()))
680 }
681 ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
682 let p = poly_trait_ref.trait_ref;
683 let self_ty = p.self_ty();
684 let path = p.print_only_trait_path();
685 let obligation = format!("{self_ty}: {path}");
686 let quiet = format!("_: {path}");
687 bound_span_label(self_ty, &obligation, &quiet);
688 Some((obligation, self_ty))
689 }
690 _ => None,
691 }
692 };
693
694 let mut bounds: Vec<_> = fulfillment_errors
697 .into_iter()
698 .map(|error| error.root_obligation.predicate)
699 .filter_map(format_pred)
700 .map(|(p, _)| format!("`{p}`"))
701 .collect();
702 bounds.sort();
703 bounds.dedup();
704
705 let mut err = self.dcx().struct_span_err(
706 name.span,
707 format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
708 );
709 if !bounds.is_empty() {
710 err.note(format!(
711 "the following trait bounds were not satisfied:\n{}",
712 bounds.join("\n")
713 ));
714 }
715 err.span_label(
716 name.span,
717 format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
718 );
719
720 for (span, mut bounds) in bound_spans {
721 if !tcx.sess.source_map().is_span_accessible(span) {
722 continue;
723 }
724 bounds.sort();
725 bounds.dedup();
726 let msg = match &bounds[..] {
727 [bound] => format!("doesn't satisfy {bound}"),
728 bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
729 [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")),
730 [] => unreachable!(),
731 };
732 err.span_label(span, msg);
733 }
734 add_def_label(&mut err);
735 err.emit()
736 }
737
738 pub(crate) fn check_for_required_assoc_tys(
743 &self,
744 spans: SmallVec<[Span; 1]>,
745 missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
746 potential_assoc_types: Vec<usize>,
747 trait_bounds: &[hir::PolyTraitRef<'_>],
748 ) -> Result<(), ErrorGuaranteed> {
749 if missing_assoc_types.is_empty() {
750 return Ok(());
751 }
752
753 let principal_span = *spans.first().unwrap();
754
755 let tcx = self.tcx();
756 let missing_assoc_types: Vec<_> = missing_assoc_types
758 .into_iter()
759 .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
760 .collect();
761 let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default();
762 let mut names_len = 0;
763
764 let mut dyn_compatibility_violations = Ok(());
767 for (assoc_item, trait_ref) in &missing_assoc_types {
768 names.entry(trait_ref).or_default().push(assoc_item.name());
769 names_len += 1;
770
771 let violations =
772 dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item);
773 if !violations.is_empty() {
774 dyn_compatibility_violations = Err(report_dyn_incompatibility(
775 tcx,
776 principal_span,
777 None,
778 trait_ref.def_id(),
779 &violations,
780 )
781 .emit());
782 }
783 }
784
785 if let Err(guar) = dyn_compatibility_violations {
786 return Err(guar);
787 }
788
789 let mut in_expr_or_pat = false;
791 if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
792 let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
793 in_expr_or_pat = match grandparent {
794 hir::Node::Expr(_) | hir::Node::Pat(_) => true,
795 _ => false,
796 };
797 }
798
799 let bound_names = trait_bounds
804 .iter()
805 .filter_map(|poly_trait_ref| {
806 let path = poly_trait_ref.trait_ref.path.segments.last()?;
807 let args = path.args?;
808
809 Some(args.constraints.iter().filter_map(|constraint| {
810 let ident = constraint.ident;
811
812 let Res::Def(DefKind::Trait, trait_def) = path.res else {
813 return None;
814 };
815
816 let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind(
817 tcx,
818 ident,
819 ty::AssocTag::Type,
820 trait_def,
821 );
822
823 Some((ident.name, assoc_item?))
824 }))
825 })
826 .flatten()
827 .collect::<UnordMap<Symbol, &ty::AssocItem>>();
828
829 let mut names = names
830 .into_iter()
831 .map(|(trait_, mut assocs)| {
832 assocs.sort();
833 let trait_ = trait_.print_trait_sugared();
834 format!(
835 "{} in `{trait_}`",
836 listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
837 )
838 })
839 .collect::<Vec<String>>();
840 names.sort();
841 let names = names.join(", ");
842
843 let mut err = struct_span_code_err!(
844 self.dcx(),
845 principal_span,
846 E0191,
847 "the value of the associated type{} {} must be specified",
848 pluralize!(names_len),
849 names,
850 );
851 let mut suggestions = vec![];
852 let mut types_count = 0;
853 let mut where_constraints = vec![];
854 let mut already_has_generics_args_suggestion = false;
855
856 let mut names: UnordMap<_, usize> = Default::default();
857 for (item, _) in &missing_assoc_types {
858 types_count += 1;
859 *names.entry(item.name()).or_insert(0) += 1;
860 }
861 let mut dupes = false;
862 let mut shadows = false;
863 for (item, trait_ref) in &missing_assoc_types {
864 let name = item.name();
865 let prefix = if names[&name] > 1 {
866 let trait_def_id = trait_ref.def_id();
867 dupes = true;
868 format!("{}::", tcx.def_path_str(trait_def_id))
869 } else if bound_names.get(&name).is_some_and(|x| *x != item) {
870 let trait_def_id = trait_ref.def_id();
871 shadows = true;
872 format!("{}::", tcx.def_path_str(trait_def_id))
873 } else {
874 String::new()
875 };
876
877 let mut is_shadowed = false;
878
879 if let Some(assoc_item) = bound_names.get(&name)
880 && *assoc_item != item
881 {
882 is_shadowed = true;
883
884 let rename_message =
885 if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
886 err.span_label(
887 tcx.def_span(assoc_item.def_id),
888 format!("`{}{}` shadowed here{}", prefix, name, rename_message),
889 );
890 }
891
892 let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
893
894 if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
895 err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message));
896 }
897 }
898 if potential_assoc_types.len() == missing_assoc_types.len() {
899 already_has_generics_args_suggestion = true;
903 } else if let (Ok(snippet), false, false) =
904 (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
905 {
906 let types: Vec<_> = missing_assoc_types
907 .iter()
908 .map(|(item, _)| format!("{} = Type", item.name()))
909 .collect();
910 let code = if let Some(snippet) = snippet.strip_suffix('>') {
911 format!("{}, {}>", snippet, types.join(", "))
916 } else if in_expr_or_pat {
917 format!("{}::<{}>", snippet, types.join(", "))
920 } else {
921 format!("{}<{}>", snippet, types.join(", "))
924 };
925 suggestions.push((principal_span, code));
926 } else if dupes {
927 where_constraints.push(principal_span);
928 }
929
930 let where_msg = "consider introducing a new type parameter, adding `where` constraints \
931 using the fully-qualified path to the associated types";
932 if !where_constraints.is_empty() && suggestions.is_empty() {
933 err.help(where_msg);
937 }
938 if suggestions.len() != 1 || already_has_generics_args_suggestion {
939 let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
941 for (item, _) in &missing_assoc_types {
942 types_count += 1;
943 *names.entry(item.name()).or_insert(0) += 1;
944 }
945 let mut label = vec![];
946 for (item, trait_ref) in &missing_assoc_types {
947 let name = item.name();
948 let postfix = if names[&name] > 1 {
949 format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
950 } else {
951 String::new()
952 };
953 label.push(format!("`{}`{}", name, postfix));
954 }
955 if !label.is_empty() {
956 err.span_label(
957 principal_span,
958 format!(
959 "associated type{} {} must be specified",
960 pluralize!(label.len()),
961 label.join(", "),
962 ),
963 );
964 }
965 }
966 suggestions.sort_by_key(|&(span, _)| span);
967 let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
980 if !suggestions.is_empty() && !overlaps {
981 err.multipart_suggestion(
982 format!("specify the associated type{}", pluralize!(types_count)),
983 suggestions,
984 Applicability::HasPlaceholders,
985 );
986 if !where_constraints.is_empty() {
987 err.span_help(where_constraints, where_msg);
988 }
989 }
990
991 Err(err.emit())
992 }
993
994 pub(crate) fn maybe_report_similar_assoc_fn(
998 &self,
999 span: Span,
1000 qself_ty: Ty<'tcx>,
1001 qself: &hir::Ty<'_>,
1002 ) -> Result<(), ErrorGuaranteed> {
1003 let tcx = self.tcx();
1004 if let Some((_, node)) = tcx.hir_parent_iter(qself.hir_id).skip(1).next()
1005 && let hir::Node::Expr(hir::Expr {
1006 kind:
1007 hir::ExprKind::Path(hir::QPath::TypeRelative(
1008 hir::Ty {
1009 kind:
1010 hir::TyKind::Path(hir::QPath::TypeRelative(
1011 _,
1012 hir::PathSegment { ident: ident2, .. },
1013 )),
1014 ..
1015 },
1016 hir::PathSegment { ident: ident3, .. },
1017 )),
1018 ..
1019 }) = node
1020 && let Some(inherent_impls) = qself_ty
1021 .ty_adt_def()
1022 .map(|adt_def| tcx.inherent_impls(adt_def.did()))
1023 .or_else(|| {
1024 simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer)
1025 .map(|simple_ty| tcx.incoherent_impls(simple_ty))
1026 })
1027 && let name = Symbol::intern(&format!("{ident2}_{ident3}"))
1028 && let Some(item) = inherent_impls
1029 .iter()
1030 .flat_map(|inherent_impl| {
1031 tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
1032 })
1033 .next()
1034 && item.is_fn()
1035 {
1036 Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")
1037 .with_span_suggestion_verbose(
1038 ident2.span.to(ident3.span),
1039 format!("there is an associated function with a similar name: `{name}`"),
1040 name,
1041 Applicability::MaybeIncorrect,
1042 )
1043 .emit())
1044 } else {
1045 Ok(())
1046 }
1047 }
1048
1049 pub fn report_prohibit_generics_error<'a>(
1050 &self,
1051 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1052 args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1053 err_extend: GenericsArgsErrExtend<'a>,
1054 ) -> ErrorGuaranteed {
1055 #[derive(PartialEq, Eq, Hash)]
1056 enum ProhibitGenericsArg {
1057 Lifetime,
1058 Type,
1059 Const,
1060 Infer,
1061 }
1062
1063 let mut prohibit_args = FxIndexSet::default();
1064 args_visitors.for_each(|arg| {
1065 match arg {
1066 hir::GenericArg::Lifetime(_) => prohibit_args.insert(ProhibitGenericsArg::Lifetime),
1067 hir::GenericArg::Type(_) => prohibit_args.insert(ProhibitGenericsArg::Type),
1068 hir::GenericArg::Const(_) => prohibit_args.insert(ProhibitGenericsArg::Const),
1069 hir::GenericArg::Infer(_) => prohibit_args.insert(ProhibitGenericsArg::Infer),
1070 };
1071 });
1072
1073 let segments: Vec<_> = segments.collect();
1074 let types_and_spans: Vec<_> = segments
1075 .iter()
1076 .flat_map(|segment| {
1077 if segment.args().args.is_empty() {
1078 None
1079 } else {
1080 Some((
1081 match segment.res {
1082 Res::PrimTy(ty) => {
1083 format!("{} `{}`", segment.res.descr(), ty.name())
1084 }
1085 Res::Def(_, def_id)
1086 if let Some(name) = self.tcx().opt_item_name(def_id) =>
1087 {
1088 format!("{} `{name}`", segment.res.descr())
1089 }
1090 Res::Err => "this type".to_string(),
1091 _ => segment.res.descr().to_string(),
1092 },
1093 segment.ident.span,
1094 ))
1095 }
1096 })
1097 .collect();
1098 let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
1099 .expect("expected one segment to deny");
1100
1101 let arg_spans: Vec<Span> =
1102 segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
1103
1104 let mut kinds = Vec::with_capacity(4);
1105 prohibit_args.iter().for_each(|arg| match arg {
1106 ProhibitGenericsArg::Lifetime => kinds.push("lifetime"),
1107 ProhibitGenericsArg::Type => kinds.push("type"),
1108 ProhibitGenericsArg::Const => kinds.push("const"),
1109 ProhibitGenericsArg::Infer => kinds.push("generic"),
1110 });
1111
1112 let s = pluralize!(kinds.len());
1113 let kind =
1114 listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit");
1115 let last_span = *arg_spans.last().unwrap();
1116 let span: MultiSpan = arg_spans.into();
1117 let mut err = struct_span_code_err!(
1118 self.dcx(),
1119 span,
1120 E0109,
1121 "{kind} arguments are not allowed on {this_type}",
1122 );
1123 err.span_label(last_span, format!("{kind} argument{s} not allowed"));
1124 for (what, span) in types_and_spans {
1125 err.span_label(span, format!("not allowed on {what}"));
1126 }
1127 generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
1128 err.emit()
1129 }
1130
1131 pub fn report_trait_object_addition_traits_error(
1132 &self,
1133 regular_traits: &Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>,
1134 ) -> ErrorGuaranteed {
1135 let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap();
1138 let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap();
1139 let mut err = struct_span_code_err!(
1140 self.dcx(),
1141 *regular_traits[1].1.first().unwrap(),
1142 E0225,
1143 "only auto traits can be used as additional traits in a trait object"
1144 );
1145 err.span_label(first_span, "first non-auto trait");
1146 for &alias_span in first_alias_spans {
1147 err.span_label(alias_span, "first non-auto trait comes from this alias");
1148 }
1149 err.span_label(second_span, "additional non-auto trait");
1150 for &alias_span in second_alias_spans {
1151 err.span_label(alias_span, "second non-auto trait comes from this alias");
1152 }
1153 err.help(format!(
1154 "consider creating a new trait with all of these as supertraits and using that \
1155 trait here instead: `trait NewTrait: {} {{}}`",
1156 regular_traits
1157 .iter()
1158 .map(|(pred, _)| pred
1160 .map_bound(|pred| pred.trait_ref)
1161 .print_only_trait_path()
1162 .to_string())
1163 .collect::<Vec<_>>()
1164 .join(" + "),
1165 ));
1166 err.note(
1167 "auto-traits like `Send` and `Sync` are traits that have special properties; \
1168 for more information on them, visit \
1169 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1170 );
1171 err.emit()
1172 }
1173
1174 pub fn report_trait_object_with_no_traits_error(
1175 &self,
1176 span: Span,
1177 user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
1178 ) -> ErrorGuaranteed {
1179 let tcx = self.tcx();
1180 let trait_alias_span = user_written_clauses
1181 .into_iter()
1182 .filter_map(|(clause, _)| clause.as_trait_clause())
1183 .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id()))
1184 .map(|trait_ref| tcx.def_span(trait_ref.def_id()));
1185
1186 self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
1187 }
1188}
1189
1190pub fn prohibit_assoc_item_constraint(
1192 cx: &dyn HirTyLowerer<'_>,
1193 constraint: &hir::AssocItemConstraint<'_>,
1194 segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
1195) -> ErrorGuaranteed {
1196 let tcx = cx.tcx();
1197 let mut err = cx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
1198 span: constraint.span,
1199 fn_trait_expansion: if let Some((_, segment, span)) = segment
1200 && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
1201 {
1202 Some(ParenthesizedFnTraitExpansion {
1203 span,
1204 expanded_type: fn_trait_to_string(tcx, segment, false),
1205 })
1206 } else {
1207 None
1208 },
1209 });
1210
1211 if let Some((def_id, segment, _)) = segment
1215 && segment.args().parenthesized == hir::GenericArgsParentheses::No
1216 {
1217 let suggest_removal = |e: &mut Diag<'_>| {
1219 let constraints = segment.args().constraints;
1220 let args = segment.args().args;
1221
1222 let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
1234 bug!("a type binding exists but its HIR ID not found in generics");
1235 };
1236
1237 let preceding_span = if index > 0 {
1238 Some(constraints[index - 1].span)
1239 } else {
1240 args.last().map(|a| a.span())
1241 };
1242
1243 let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
1244
1245 let removal_span = match (preceding_span, next_span) {
1246 (Some(prec), _) => constraint.span.with_lo(prec.hi()),
1247 (None, Some(next)) => constraint.span.with_hi(next.lo()),
1248 (None, None) => {
1249 let Some(generics_span) = segment.args().span_ext() else {
1250 bug!("a type binding exists but generic span is empty");
1251 };
1252
1253 generics_span
1254 }
1255 };
1256
1257 e.span_suggestion_verbose(
1259 removal_span,
1260 format!("consider removing this associated item {}", constraint.kind.descr()),
1261 "",
1262 Applicability::MaybeIncorrect,
1263 );
1264 };
1265
1266 let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
1269 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
1270 e.span_suggestion_verbose(
1271 constraint.span,
1272 format!("to use `{snippet}` as a generic argument specify it directly"),
1273 snippet,
1274 Applicability::MaybeIncorrect,
1275 );
1276 }
1277 };
1278
1279 let generics = tcx.generics_of(def_id);
1282 let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
1283
1284 if let Some(matching_param) = matching_param {
1286 match (constraint.kind, &matching_param.kind) {
1287 (
1288 hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
1289 GenericParamDefKind::Type { .. },
1290 ) => suggest_direct_use(&mut err, ty.span),
1291 (
1292 hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
1293 GenericParamDefKind::Const { .. },
1294 ) => {
1295 suggest_direct_use(&mut err, c.span());
1296 }
1297 (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
1298 let impl_block = tcx
1304 .hir_parent_iter(constraint.hir_id)
1305 .find_map(|(_, node)| node.impl_block_of_trait(def_id));
1306
1307 let type_with_constraints =
1308 tcx.sess.source_map().span_to_snippet(constraint.span);
1309
1310 if let Some(impl_block) = impl_block
1311 && let Ok(type_with_constraints) = type_with_constraints
1312 {
1313 let lifetimes: String = bounds
1316 .iter()
1317 .filter_map(|bound| {
1318 if let hir::GenericBound::Outlives(lifetime) = bound {
1319 Some(format!("{lifetime}, "))
1320 } else {
1321 None
1322 }
1323 })
1324 .collect();
1325 let param_decl = if let Some(param_span) =
1328 impl_block.generics.span_for_param_suggestion()
1329 {
1330 (param_span, format!(", {lifetimes}{type_with_constraints}"))
1331 } else {
1332 (
1333 impl_block.generics.span.shrink_to_lo(),
1334 format!("<{lifetimes}{type_with_constraints}>"),
1335 )
1336 };
1337 let suggestions = vec![
1338 param_decl,
1339 (constraint.span.with_lo(constraint.ident.span.hi()), String::new()),
1340 ];
1341
1342 err.multipart_suggestion_verbose(
1343 "declare the type parameter right after the `impl` keyword",
1344 suggestions,
1345 Applicability::MaybeIncorrect,
1346 );
1347 }
1348 }
1349 _ => suggest_removal(&mut err),
1350 }
1351 } else {
1352 suggest_removal(&mut err);
1353 }
1354 }
1355
1356 err.emit()
1357}
1358
1359pub(crate) fn fn_trait_to_string(
1360 tcx: TyCtxt<'_>,
1361 trait_segment: &hir::PathSegment<'_>,
1362 parenthesized: bool,
1363) -> String {
1364 let args = trait_segment
1365 .args
1366 .and_then(|args| args.args.first())
1367 .and_then(|arg| match arg {
1368 hir::GenericArg::Type(ty) => match ty.kind {
1369 hir::TyKind::Tup(t) => t
1370 .iter()
1371 .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
1372 .collect::<Result<Vec<_>, _>>()
1373 .map(|a| a.join(", ")),
1374 _ => tcx.sess.source_map().span_to_snippet(ty.span),
1375 }
1376 .map(|s| {
1377 if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") }
1379 })
1380 .ok(),
1381 _ => None,
1382 })
1383 .unwrap_or_else(|| "()".to_string());
1384
1385 let ret = trait_segment
1386 .args()
1387 .constraints
1388 .iter()
1389 .find_map(|c| {
1390 if c.ident.name == sym::Output
1391 && let Some(ty) = c.ty()
1392 && ty.span != tcx.hir_span(trait_segment.hir_id)
1393 {
1394 tcx.sess.source_map().span_to_snippet(ty.span).ok()
1395 } else {
1396 None
1397 }
1398 })
1399 .unwrap_or_else(|| "()".to_string());
1400
1401 if parenthesized {
1402 format!("{}{} -> {}", trait_segment.ident, args, ret)
1403 } else {
1404 format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
1405 }
1406}
1407
1408pub enum GenericsArgsErrExtend<'tcx> {
1410 EnumVariant {
1411 qself: &'tcx hir::Ty<'tcx>,
1412 assoc_segment: &'tcx hir::PathSegment<'tcx>,
1413 adt_def: AdtDef<'tcx>,
1414 },
1415 OpaqueTy,
1416 PrimTy(hir::PrimTy),
1417 SelfTyAlias {
1418 def_id: DefId,
1419 span: Span,
1420 },
1421 SelfTyParam(Span),
1422 Param(DefId),
1423 DefVariant(&'tcx [hir::PathSegment<'tcx>]),
1424 None,
1425}
1426
1427fn generics_args_err_extend<'a>(
1428 tcx: TyCtxt<'_>,
1429 segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1430 err: &mut Diag<'_>,
1431 err_extend: GenericsArgsErrExtend<'a>,
1432) {
1433 match err_extend {
1434 GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
1435 err.note("enum variants can't have type parameters");
1436 let type_name = tcx.item_name(adt_def.did());
1437 let msg = format!(
1438 "you might have meant to specify type parameters on enum \
1439 `{type_name}`"
1440 );
1441 let Some(args) = assoc_segment.args else {
1442 return;
1443 };
1444 let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2));
1449 if tcx.generics_of(adt_def.did()).is_empty() {
1450 err.span_suggestion_verbose(
1453 args_span,
1454 format!("{type_name} doesn't have generic parameters"),
1455 "",
1456 Applicability::MachineApplicable,
1457 );
1458 return;
1459 }
1460 let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
1461 err.note(msg);
1462 return;
1463 };
1464 let (qself_sugg_span, is_self) =
1465 if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1466 match &path.segments {
1469 [
1473 ..,
1474 hir::PathSegment {
1475 ident, args, res: Res::Def(DefKind::Enum, _), ..
1476 },
1477 _,
1478 ] => (
1479 ident
1482 .span
1483 .shrink_to_hi()
1484 .to(args.map_or(ident.span.shrink_to_hi(), |a| a.span_ext)),
1485 false,
1486 ),
1487 [segment] => {
1488 (
1489 segment.ident.span.shrink_to_hi().to(segment
1492 .args
1493 .map_or(segment.ident.span.shrink_to_hi(), |a| a.span_ext)),
1494 kw::SelfUpper == segment.ident.name,
1495 )
1496 }
1497 _ => {
1498 err.note(msg);
1499 return;
1500 }
1501 }
1502 } else {
1503 err.note(msg);
1504 return;
1505 };
1506 let suggestion = vec![
1507 if is_self {
1508 (qself.span, format!("{type_name}{snippet}"))
1512 } else {
1513 (qself_sugg_span, snippet)
1514 },
1515 (args_span, String::new()),
1516 ];
1517 err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
1518 }
1519 GenericsArgsErrExtend::DefVariant(segments) => {
1520 let args: Vec<Span> = segments
1521 .iter()
1522 .filter_map(|segment| match segment.res {
1523 Res::Def(
1524 DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1525 _,
1526 ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1527 _ => None,
1528 })
1529 .collect();
1530 if args.len() > 1
1531 && let Some(span) = args.into_iter().next_back()
1532 {
1533 err.note(
1534 "generic arguments are not allowed on both an enum and its variant's path \
1535 segments simultaneously; they are only valid in one place or the other",
1536 );
1537 err.span_suggestion_verbose(
1538 span,
1539 "remove the generics arguments from one of the path segments",
1540 String::new(),
1541 Applicability::MaybeIncorrect,
1542 );
1543 }
1544 }
1545 GenericsArgsErrExtend::PrimTy(prim_ty) => {
1546 let name = prim_ty.name_str();
1547 for segment in segments {
1548 if let Some(args) = segment.args {
1549 err.span_suggestion_verbose(
1550 segment.ident.span.shrink_to_hi().to(args.span_ext),
1551 format!("primitive type `{name}` doesn't have generic parameters"),
1552 "",
1553 Applicability::MaybeIncorrect,
1554 );
1555 }
1556 }
1557 }
1558 GenericsArgsErrExtend::OpaqueTy => {
1559 err.note("`impl Trait` types can't have type parameters");
1560 }
1561 GenericsArgsErrExtend::Param(def_id) => {
1562 let span = tcx.def_ident_span(def_id).unwrap();
1563 let kind = tcx.def_descr(def_id);
1564 let name = tcx.item_name(def_id);
1565 err.span_note(span, format!("{kind} `{name}` defined here"));
1566 }
1567 GenericsArgsErrExtend::SelfTyParam(span) => {
1568 err.span_suggestion_verbose(
1569 span,
1570 "the `Self` type doesn't accept type parameters",
1571 "",
1572 Applicability::MaybeIncorrect,
1573 );
1574 }
1575 GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
1576 let ty = tcx.at(span).type_of(def_id).instantiate_identity();
1577 let span_of_impl = tcx.span_of_impl(def_id);
1578 let def_id = match *ty.kind() {
1579 ty::Adt(self_def, _) => self_def.did(),
1580 _ => return,
1581 };
1582
1583 let type_name = tcx.item_name(def_id);
1584 let span_of_ty = tcx.def_ident_span(def_id);
1585 let generics = tcx.generics_of(def_id).count();
1586
1587 let msg = format!("`Self` is of type `{ty}`");
1588 if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
1589 let mut span: MultiSpan = vec![t_sp].into();
1590 span.push_span_label(
1591 i_sp,
1592 format!("`Self` is on type `{type_name}` in this `impl`"),
1593 );
1594 let mut postfix = "";
1595 if generics == 0 {
1596 postfix = ", which doesn't have generic parameters";
1597 }
1598 span.push_span_label(t_sp, format!("`Self` corresponds to this type{postfix}"));
1599 err.span_note(span, msg);
1600 } else {
1601 err.note(msg);
1602 }
1603 for segment in segments {
1604 if let Some(args) = segment.args
1605 && segment.ident.name == kw::SelfUpper
1606 {
1607 if generics == 0 {
1608 err.span_suggestion_verbose(
1611 segment.ident.span.shrink_to_hi().to(args.span_ext),
1612 "the `Self` type doesn't accept type parameters",
1613 "",
1614 Applicability::MachineApplicable,
1615 );
1616 return;
1617 } else {
1618 err.span_suggestion_verbose(
1619 segment.ident.span,
1620 format!(
1621 "the `Self` type doesn't accept type parameters, use the \
1622 concrete type's name `{type_name}` instead if you want to \
1623 specify its type parameters"
1624 ),
1625 type_name,
1626 Applicability::MaybeIncorrect,
1627 );
1628 }
1629 }
1630 }
1631 }
1632 _ => {}
1633 }
1634}
1635
1636pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
1637 match assoc_tag {
1638 ty::AssocTag::Fn => "function",
1639 ty::AssocTag::Const => "constant",
1640 ty::AssocTag::Type => "type",
1641 }
1642}