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