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