Skip to main content

rustc_hir_analysis/hir_ty_lowering/
errors.rs

1use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2use rustc_data_structures::sorted_map::SortedMap;
3use rustc_data_structures::thin_vec::ThinVec;
4use rustc_data_structures::unord::UnordMap;
5use rustc_errors::codes::*;
6use rustc_errors::{
7    Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, msg, pluralize,
8    struct_span_code_err,
9};
10use rustc_hir::def::{CtorOf, DefKind, Res};
11use rustc_hir::def_id::DefId;
12use rustc_hir::{self as hir, HirId};
13use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
14use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
15use rustc_middle::ty::{
16    self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
17    suggest_constraining_type_param,
18};
19use rustc_session::diagnostics::feature_err;
20use rustc_span::edit_distance::find_best_match_for_name;
21use rustc_span::{BytePos, DUMMY_SP, Ident, OrdSpan, Span, Symbol, bug, kw, sym};
22use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
23use rustc_trait_selection::traits::{
24    FulfillmentError, dyn_compatibility_violations_for_assoc_item,
25};
26use smallvec::SmallVec;
27use tracing::debug;
28
29use super::InherentAssocCandidate;
30use crate::diagnostics::{
31    self, AssocItemConstraintsNotAllowedHere, ManualImplementation, ParenthesizedFnTraitExpansion,
32    TraitObjectDeclaredWithNoTraits,
33};
34use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
35
36impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
37    pub(crate) fn report_missing_generic_params(
38        &self,
39        missing_generic_params: Vec<(Symbol, ty::GenericParamDefKind)>,
40        def_id: DefId,
41        span: Span,
42        empty_generic_args: bool,
43    ) {
44        if missing_generic_params.is_empty() {
45            return;
46        }
47
48        self.dcx().emit_err(diagnostics::MissingGenericParams {
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_generic_params,
53            empty_generic_args,
54        });
55    }
56
57    /// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
58    /// an error and attempt to build a reasonable structured suggestion.
59    pub(crate) fn report_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                // For now, require that parenthetical notation be used only with `Fn()` etc.
74                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            // For now, require that parenthetical notation be used only with `Fn()` etc.
90            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            // Do not suggest the other syntax if we are in trait impl:
97            // the desugaring would contain an associated type constraint.
98            if !is_impl {
99                err.span_suggestion_verbose(
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 report_unresolved_assoc_item<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<'_>>,
123    ) -> ErrorGuaranteed
124    where
125        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
126    {
127        let tcx = self.tcx();
128
129        // First and foremost, provide a more user-friendly & “intuitive” error on kind mismatches.
130        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.report_assoc_kind_mismatch(
136                assoc_item,
137                assoc_tag,
138                assoc_ident,
139                span,
140                constraint,
141            );
142        }
143
144        let assoc_kind = assoc_tag_str(assoc_tag);
145        let qself_str = qself.to_string(tcx);
146
147        // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
148        // valid span, so we point at the whole path segment instead.
149        let is_dummy = assoc_ident.span == DUMMY_SP;
150
151        let mut err = diagnostics::AssocItemNotFound {
152            span: if is_dummy { span } else { assoc_ident.span },
153            assoc_ident,
154            assoc_kind,
155            qself: &qself_str,
156            label: None,
157            sugg: None,
158            // Try to get the span of the identifier within the path's syntax context
159            // (if that's different).
160            within_macro_span: assoc_ident.span.within_macro(span, tcx.sess.source_map()),
161        };
162
163        if is_dummy {
164            err.label = Some(diagnostics::AssocItemNotFoundLabel::NotFound {
165                span,
166                assoc_ident,
167                assoc_kind,
168            });
169            return self.dcx().emit_err(err);
170        }
171
172        let all_candidate_names: Vec<_> = all_candidates()
173            .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
174            .filter_map(|item| {
175                if !item.is_impl_trait_in_trait() && item.tag() == assoc_tag {
176                    item.opt_name()
177                } else {
178                    None
179                }
180            })
181            .collect();
182
183        if let Some(suggested_name) =
184            find_best_match_for_name(&all_candidate_names, assoc_ident.name, None)
185        {
186            err.sugg = Some(diagnostics::AssocItemNotFoundSugg::Similar {
187                span: assoc_ident.span,
188                assoc_kind,
189                suggested_name,
190            });
191            return self.dcx().emit_err(err);
192        }
193
194        // If we didn't find a good item in the supertraits (or couldn't get
195        // the supertraits), like in ItemCtxt, then look more generally from
196        // all visible traits. If there's one clear winner, just suggest that.
197
198        let visible_traits: Vec<_> = tcx
199            .visible_traits()
200            .filter(|trait_def_id| {
201                let viz = tcx.visibility(*trait_def_id);
202                viz.is_accessible_from(self.mod_id(), tcx)
203            })
204            .collect();
205
206        let wider_candidate_names: Vec<_> = visible_traits
207            .iter()
208            .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
209            .filter_map(|item| {
210                (!item.is_impl_trait_in_trait() && item.tag() == assoc_tag).then(|| item.name())
211            })
212            .collect();
213
214        if let Some(suggested_name) =
215            find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None)
216        {
217            if let [best_trait] = visible_traits
218                .iter()
219                .copied()
220                .filter(|&trait_def_id| {
221                    tcx.associated_items(trait_def_id)
222                        .filter_by_name_unhygienic(suggested_name)
223                        .any(|item| item.tag() == assoc_tag)
224                })
225                .collect::<Vec<_>>()[..]
226            {
227                let trait_name = tcx.def_path_str(best_trait);
228                err.label = Some(diagnostics::AssocItemNotFoundLabel::FoundInOtherTrait {
229                    span: assoc_ident.span,
230                    assoc_kind,
231                    trait_name: &trait_name,
232                    suggested_name,
233                    identically_named: suggested_name == assoc_ident.name,
234                });
235                if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
236                    // Not using `self.item_def_id()` here as that would yield the opaque type itself if we're
237                    // inside an opaque type while we're interested in the overarching type alias (TAIT).
238                    // FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
239                    && let item_def_id =
240                        tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
241                    // FIXME: ...which obviously won't have any generics.
242                    && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
243                {
244                    // FIXME: Suggest adding supertrait bounds if we have a `Self` type param.
245                    // FIXME(trait_alias): Suggest adding `Self: Trait` to
246                    // `trait Alias = where Self::Proj:;` with `trait Trait { type Proj; }`.
247                    if generics
248                        .bounds_for_param(ty_param_def_id)
249                        .flat_map(|pred| pred.bounds.iter())
250                        .any(|b| match b {
251                            hir::GenericBound::Trait(t, ..) => {
252                                t.trait_ref.trait_def_id() == Some(best_trait)
253                            }
254                            _ => false,
255                        })
256                    {
257                        // The type param already has a bound for `trait_name`, we just need to
258                        // change the associated item.
259                        err.sugg = Some(diagnostics::AssocItemNotFoundSugg::SimilarInOtherTrait {
260                            span: assoc_ident.span,
261                            trait_name: &trait_name,
262                            assoc_kind,
263                            suggested_name,
264                        });
265                        return self.dcx().emit_err(err);
266                    }
267
268                    let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
269                    let mut trait_ref = trait_name.clone();
270                    let applicability = if let [arg, args @ ..] = trait_args {
271                        use std::fmt::Write;
272                        trait_ref.write_fmt(format_args!("</* {0}", arg))write!(trait_ref, "</* {arg}").unwrap();
273                        args.iter().try_for_each(|arg| trait_ref.write_fmt(format_args!(", {0}", arg))write!(trait_ref, ", {arg}")).unwrap();
274                        trait_ref += " */>";
275                        Applicability::HasPlaceholders
276                    } else {
277                        Applicability::MaybeIncorrect
278                    };
279
280                    let identically_named = suggested_name == assoc_ident.name;
281
282                    if let DefKind::TyAlias = tcx.def_kind(item_def_id)
283                        && !tcx.type_alias_is_checked(item_def_id)
284                    {
285                        err.sugg =
286                            Some(diagnostics::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
287                                lo: ty_param_span.shrink_to_lo(),
288                                mi: ty_param_span.shrink_to_hi(),
289                                hi: (!identically_named).then_some(assoc_ident.span),
290                                trait_ref,
291                                identically_named,
292                                suggested_name,
293                                assoc_kind,
294                                applicability,
295                            });
296                    } else {
297                        let mut err = self.dcx().create_err(err);
298                        if suggest_constraining_type_param(
299                            tcx,
300                            generics,
301                            &mut err,
302                            &qself_str,
303                            &trait_ref,
304                            Some(best_trait),
305                            None,
306                        ) && !identically_named
307                        {
308                            // We suggested constraining a type parameter, but the associated item on it
309                            // was also not an exact match, so we also suggest changing it.
310                            err.span_suggestion_verbose(
311                                assoc_ident.span,
312                                rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("...and changing the associated {$assoc_kind} name"))msg!("...and changing the associated {$assoc_kind} name"),
313                                suggested_name,
314                                Applicability::MaybeIncorrect,
315                            );
316                        }
317                        return err.emit_err();
318                    }
319                }
320                return self.dcx().emit_err(err);
321            }
322        }
323
324        // If we still couldn't find any associated item, and only one associated item exists,
325        // suggest using it.
326        if let [candidate_name] = all_candidate_names.as_slice() {
327            err.sugg = Some(diagnostics::AssocItemNotFoundSugg::Other {
328                span: assoc_ident.span,
329                qself: &qself_str,
330                assoc_kind,
331                suggested_name: *candidate_name,
332            });
333        } else {
334            err.label = Some(diagnostics::AssocItemNotFoundLabel::NotFound {
335                span: assoc_ident.span,
336                assoc_ident,
337                assoc_kind,
338            });
339        }
340
341        self.dcx().emit_err(err)
342    }
343
344    fn report_assoc_kind_mismatch(
345        &self,
346        assoc_item: &ty::AssocItem,
347        assoc_tag: ty::AssocTag,
348        ident: Ident,
349        span: Span,
350        constraint: Option<&hir::AssocItemConstraint<'_>>,
351    ) -> ErrorGuaranteed {
352        let tcx = self.tcx();
353
354        let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
355            && let Some(constraint) = constraint
356            && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
357        {
358            let lo = if constraint.gen_args.span_ext.is_dummy() {
359                ident.span
360            } else {
361                constraint.gen_args.span_ext
362            };
363            Some(lo.between(span.shrink_to_hi()))
364        } else {
365            None
366        };
367
368        // FIXME(mgca): This has quite a few false positives and negatives.
369        let wrap_in_braces_sugg = if let Some(constraint) = constraint
370            && let Some(hir_ty) = constraint.ty()
371            && let ty = self.lower_ty(hir_ty)
372            && (ty.is_enum() || ty.references_error())
373            && tcx.features().gca()
374        {
375            Some(diagnostics::AssocKindMismatchWrapInBracesSugg {
376                lo: hir_ty.span.shrink_to_lo(),
377                hi: hir_ty.span.shrink_to_hi(),
378            })
379        } else {
380            None
381        };
382
383        // For equality constraints, we want to blame the term (RHS) instead of the item (LHS) since
384        // one can argue that that's more “intuitive” to the user.
385        let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
386            && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
387        {
388            let span = match term {
389                hir::Term::Ty(ty) => ty.span,
390                hir::Term::Const(ct) => ct.span,
391            };
392            (span, Some(ident.span), assoc_item.tag(), assoc_tag)
393        } else {
394            (ident.span, None, assoc_tag, assoc_item.tag())
395        };
396        let mut def_span: MultiSpan = tcx.def_span(assoc_item.def_id).into();
397        def_span.push_span_context(tcx.def_span(tcx.parent(assoc_item.def_id)));
398
399        let def_kind = tcx.def_kind(self.item_def_id());
400        let item_span = tcx.def_span(self.item_def_id()).shrink_to_lo();
401        let (item_span, enclosing_span) = match def_kind {
402            DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => (
403                item_span,
404                Some(tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo()),
405            ),
406            DefKind::OpaqueTy => {
407                let item_span = tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo();
408                let enclosing_span =
409                    if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy =
410                        tcx.def_kind(tcx.parent(self.item_def_id().into()))
411                    {
412                        Some(tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo())
413                    } else {
414                        None
415                    };
416                (item_span, enclosing_span)
417            }
418            _ => (item_span, None),
419        };
420        self.dcx().emit_err(diagnostics::AssocKindMismatch {
421            span,
422            item_span,
423            enclosing_span,
424            expected: assoc_tag_str(expected),
425            got: assoc_tag_str(got),
426            expected_because_label,
427            assoc_kind: assoc_tag_str(assoc_item.tag()),
428            def_span,
429            bound_on_assoc_const_label,
430            wrap_in_braces_sugg,
431        })
432    }
433
434    pub(super) fn report_ambiguous_assoc_item(
435        &self,
436        matching_candidates: &[ty::PolyTraitRef<'tcx>],
437        qself: AssocItemQSelf,
438        assoc_tag: ty::AssocTag,
439        assoc_ident: Ident,
440        span: Span,
441        constraint: Option<&hir::AssocItemConstraint<'_>>,
442    ) -> ErrorGuaranteed {
443        let tcx = self.tcx();
444
445        let assoc_kind_str = assoc_tag_str(assoc_tag);
446        let qself_str = qself.to_string(tcx);
447        let mut err = self.dcx().create_err(crate::diagnostics::AmbiguousAssocItem {
448            span,
449            assoc_kind: assoc_kind_str,
450            assoc_ident,
451            qself: &qself_str,
452        });
453        // Provide a more specific error code index entry for equality bindings.
454        err.code(
455            if let Some(constraint) = constraint
456                && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
457            {
458                E0222
459            } else {
460                E0221
461            },
462        );
463
464        // FIXME(#97583): Print associated item bindings properly (i.e., not as equality
465        // predicates!).
466        // FIXME: Turn this into a structured, translatable & more actionable suggestion.
467        let mut where_bounds = ::alloc::vec::Vec::new()vec![];
468        for &bound in matching_candidates {
469            let bound_id = bound.def_id();
470            let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind(
471                tcx,
472                assoc_ident,
473                assoc_tag,
474                bound_id,
475            );
476            let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id));
477
478            if let Some(bound_span) = bound_span {
479                err.span_label(
480                    bound_span,
481                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("ambiguous `{1}` from `{0}`",
                bound.print_trait_sugared(), assoc_ident))
    })format!("ambiguous `{assoc_ident}` from `{}`", bound.print_trait_sugared(),),
482                );
483                if let Some(constraint) = constraint {
484                    match constraint.kind {
485                        hir::AssocItemConstraintKind::Equality { term } => {
486                            let term: ty::Term<'_> = match term {
487                                hir::Term::Ty(ty) => self.lower_ty(ty).into(),
488                                hir::Term::Const(ct) => {
489                                    let assoc_item =
490                                        assoc_item.expect("assoc_item should be present");
491                                    let projection_term = bound.map_bound(|trait_ref| {
492                                        let item_segment = hir::PathSegment {
493                                            ident: constraint.ident,
494                                            hir_id: constraint.hir_id,
495                                            res: Res::Err,
496                                            args: Some(constraint.gen_args),
497                                            infer_args: false,
498                                            delegation_child_segment: false,
499                                        };
500
501                                        let alias_args = self.lower_generic_args_of_assoc_item(
502                                            constraint.ident.span,
503                                            assoc_item.def_id,
504                                            &item_segment,
505                                            trait_ref.args,
506                                        );
507                                        let kind = ty::AliasTermKind::ProjectionConst {
508                                            def_id: assoc_item.def_id,
509                                        };
510                                        ty::AliasTerm::new_from_args(tcx, kind, alias_args)
511                                    });
512
513                                    // FIXME(mgca): code duplication with other places we lower
514                                    // the rhs' of associated const bindings
515                                    let ty = projection_term.map_bound(|alias| {
516                                        alias.expect_ct().type_of(tcx).skip_norm_wip()
517                                    });
518                                    let ty = super::bounds::check_assoc_const_binding_type(
519                                        self,
520                                        constraint.ident,
521                                        ty,
522                                        constraint.hir_id,
523                                    );
524
525                                    self.lower_const_arg(ct, ty).into()
526                                }
527                            };
528                            if term.references_error() {
529                                continue;
530                            }
531                            // FIXME(#97583): This isn't syntactically well-formed!
532                            where_bounds.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("        T: {0}::{1} = {2}",
                bound.print_only_trait_path(), assoc_ident, term))
    })format!(
533                                "        T: {trait}::{assoc_ident} = {term}",
534                                trait = bound.print_only_trait_path(),
535                            ));
536                        }
537                        // FIXME: Provide a suggestion.
538                        hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
539                    }
540                } else {
541                    err.span_suggestion_verbose(
542                        span.with_hi(assoc_ident.span.lo()),
543                        "use fully-qualified syntax to disambiguate",
544                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{1} as {0}>::",
                bound.print_only_trait_path(), qself_str))
    })format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
545                        Applicability::MaybeIncorrect,
546                    );
547                }
548            } else {
549                let trait_ = tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
550                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("associated {0} `{1}` could derive from `{2}`",
                assoc_kind_str, assoc_ident, trait_))
    })format!(
551                    "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
552                ));
553            }
554        }
555        if !where_bounds.is_empty() {
556            err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider introducing a new type parameter `T` and adding `where` constraints:\n    where\n        T: {1},\n{0}",
                where_bounds.join(",\n"), qself_str))
    })format!(
557                "consider introducing a new type parameter `T` and adding `where` constraints:\
558                     \n    where\n        T: {qself_str},\n{}",
559                where_bounds.join(",\n"),
560            ));
561        }
562        err.emit_err()
563    }
564
565    pub(crate) fn report_missing_self_ty_for_resolved_path(
566        &self,
567        trait_def_id: DefId,
568        span: Span,
569        item_segment: &hir::PathSegment<'_>,
570        assoc_tag: ty::AssocTag,
571    ) -> ErrorGuaranteed {
572        let tcx = self.tcx();
573        let path_str = tcx.def_path_str(trait_def_id);
574
575        let def_id = self.item_def_id();
576        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs:576",
                        "rustc_hir_analysis::hir_ty_lowering::errors",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs"),
                        ::tracing_core::__macro_support::Option::Some(576u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::errors"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("item_def_id")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("item_def_id");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(item_def_id = ?def_id);
577
578        // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
579        let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
580        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs:580",
                        "rustc_hir_analysis::hir_ty_lowering::errors",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs"),
                        ::tracing_core::__macro_support::Option::Some(580u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::errors"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("parent_def_id")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("parent_def_id");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&parent_def_id)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?parent_def_id);
581
582        // If the trait in segment is the same as the trait defining the item,
583        // use the `<Self as ..>` syntax in the error.
584        let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
585        let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
586
587        let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
588            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        ["Self".to_string()]))vec!["Self".to_string()]
589        } else {
590            // Find all the types that have an `impl` for the trait.
591            tcx.all_impls(trait_def_id)
592                .map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
593                .filter(|header| {
594                    // Consider only accessible traits
595                    tcx.visibility(trait_def_id).is_accessible_from(self.mod_id(), tcx)
596                        && header.polarity != ty::ImplPolarity::Negative
597                })
598                .map(|header| header.trait_ref.instantiate_identity().skip_norm_wip().self_ty())
599                // We don't care about blanket impls.
600                .filter(|self_ty| !self_ty.has_non_region_param())
601                .map(|self_ty| tcx.erase_and_anonymize_regions(self_ty).to_string())
602                .collect()
603        };
604        // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
605        // references the trait. Relevant for the first case in
606        // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
607        self.report_ambiguous_assoc_item_path(
608            span,
609            &type_names,
610            &[path_str],
611            item_segment.ident,
612            assoc_tag,
613        )
614    }
615
616    pub(super) fn report_unresolved_type_relative_path(
617        &self,
618        self_ty: Ty<'tcx>,
619        hir_self_ty: &hir::Ty<'_>,
620        assoc_tag: ty::AssocTag,
621        ident: Ident,
622        qpath_hir_id: HirId,
623        span: Span,
624        variant_def_id: Option<DefId>,
625    ) -> ErrorGuaranteed {
626        let tcx = self.tcx();
627        let kind_str = assoc_tag_str(assoc_tag);
628        if variant_def_id.is_some() {
629            // Variant in type position
630            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected {0}, found variant `{1}`",
                kind_str, ident))
    })format!("expected {kind_str}, found variant `{ident}`");
631            self.dcx().span_err(span, msg)
632        } else if self_ty.is_enum() {
633            let mut err = self.dcx().create_err(diagnostics::NoVariantNamed {
634                span: ident.span,
635                ident,
636                ty: self_ty,
637            });
638
639            let adt_def = self_ty.ty_adt_def().expect("enum is not an ADT");
640            if let Some(variant_name) = find_best_match_for_name(
641                &adt_def.variants().iter().map(|variant| variant.name).collect::<Vec<Symbol>>(),
642                ident.name,
643                None,
644            ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == variant_name)
645            {
646                let mut suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span, variant_name.to_string())]))vec![(ident.span, variant_name.to_string())];
647                if let hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(expr), .. })
648                | hir::Node::Expr(expr) = tcx.parent_hir_node(qpath_hir_id)
649                    && let hir::ExprKind::Struct(..) = expr.kind
650                {
651                    match variant.ctor {
652                        None => {
653                            // struct
654                            suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span.with_hi(expr.span.hi()),
                    if variant.fields.is_empty() {
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("{0} {{}}", variant_name))
                            })
                    } else {
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("{1} {{ {0} }}",
                                        variant.fields.iter().map(|f|
                                                        ::alloc::__export::must_use({
                                                                ::alloc::fmt::format(format_args!("{0}: /* value */",
                                                                        f.name))
                                                            })).collect::<Vec<_>>().join(", "), variant_name))
                            })
                    })]))vec![(
655                                ident.span.with_hi(expr.span.hi()),
656                                if variant.fields.is_empty() {
657                                    format!("{variant_name} {{}}")
658                                } else {
659                                    format!(
660                                        "{variant_name} {{ {} }}",
661                                        variant
662                                            .fields
663                                            .iter()
664                                            .map(|f| format!("{}: /* value */", f.name))
665                                            .collect::<Vec<_>>()
666                                            .join(", ")
667                                    )
668                                },
669                            )];
670                        }
671                        Some((hir::def::CtorKind::Fn, def_id)) => {
672                            // tuple
673                            let fn_sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();
674                            let inputs = fn_sig.inputs().skip_binder();
675                            suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span.with_hi(expr.span.hi()),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{1}({0})",
                                    inputs.iter().map(|i|
                                                    ::alloc::__export::must_use({
                                                            ::alloc::fmt::format(format_args!("/* {0} */", i))
                                                        })).collect::<Vec<_>>().join(", "), variant_name))
                        }))]))vec![(
676                                ident.span.with_hi(expr.span.hi()),
677                                format!(
678                                    "{variant_name}({})",
679                                    inputs
680                                        .iter()
681                                        .map(|i| format!("/* {i} */"))
682                                        .collect::<Vec<_>>()
683                                        .join(", ")
684                                ),
685                            )];
686                        }
687                        Some((hir::def::CtorKind::Const, _)) => {
688                            // unit
689                            suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span.with_hi(expr.span.hi()), variant_name.to_string())]))vec![(
690                                ident.span.with_hi(expr.span.hi()),
691                                variant_name.to_string(),
692                            )];
693                        }
694                    }
695                }
696                err.multipart_suggestion(
697                    "there is a variant with a similar name",
698                    suggestion,
699                    Applicability::HasPlaceholders,
700                );
701            } else {
702                err.span_label(ident.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("variant not found in `{0}`",
                self_ty))
    })format!("variant not found in `{self_ty}`"));
703            }
704
705            if let Some(sp) = tcx.hir_span_if_local(adt_def.did()) {
706                err.span_label(sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("variant `{0}` not found here",
                ident))
    })format!("variant `{ident}` not found here"));
707            }
708
709            err.emit_err()
710        } else if let Err(reported) = self_ty.error_reported() {
711            reported
712        } else {
713            match self.maybe_report_similar_assoc_fn(span, self_ty, hir_self_ty) {
714                Ok(()) => {}
715                Err(reported) => return reported,
716            }
717
718            let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(self_ty, ident);
719
720            self.report_ambiguous_assoc_item_path(
721                span,
722                &[self_ty.to_string()],
723                &traits,
724                ident,
725                assoc_tag,
726            )
727        }
728    }
729
730    fn report_ambiguous_assoc_item_path(
731        &self,
732        span: Span,
733        types: &[String],
734        traits: &[String],
735        ident: Ident,
736        assoc_tag: ty::AssocTag,
737    ) -> ErrorGuaranteed {
738        let kind_str = assoc_tag_str(assoc_tag);
739        let mut err =
740            {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("ambiguous associated {0}",
                            kind_str))
                })).with_code(E0223)
}struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
741        if self
742            .tcx()
743            .resolutions(())
744            .confused_type_with_std_module
745            .keys()
746            .any(|full_span| full_span.contains(span))
747        {
748            err.span_suggestion_verbose(
749                span.shrink_to_lo(),
750                "you are looking for the module in `std`, not the primitive type",
751                "std::",
752                Applicability::MachineApplicable,
753            );
754        } else {
755            let sugg_sp = span.until(ident.span);
756
757            let mut types = types.to_vec();
758            types.sort();
759            let mut traits = traits.to_vec();
760            traits.sort();
761            match (&types[..], &traits[..]) {
762                ([], []) => {
763                    err.span_suggestion_verbose(
764                        sugg_sp,
765                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if there were a type named `Type` that implements a trait named `Trait` with associated {0} `{1}`, you could use the fully-qualified path",
                kind_str, ident))
    })format!(
766                            "if there were a type named `Type` that implements a trait named \
767                             `Trait` with associated {kind_str} `{ident}`, you could use the \
768                             fully-qualified path",
769                        ),
770                        "<Type as Trait>::",
771                        Applicability::HasPlaceholders,
772                    );
773                }
774                ([], [trait_str]) => {
775                    err.span_suggestion_verbose(
776                        sugg_sp,
777                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if there were a type named `Example` that implemented `{0}`, you could use the fully-qualified path",
                trait_str))
    })format!(
778                            "if there were a type named `Example` that implemented `{trait_str}`, \
779                             you could use the fully-qualified path",
780                        ),
781                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<Example as {0}>::", trait_str))
    })format!("<Example as {trait_str}>::"),
782                        Applicability::HasPlaceholders,
783                    );
784                }
785                ([], traits) => {
786                    err.span_suggestions_with_style(
787                        sugg_sp,
788                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if there were a type named `Example` that implemented one of the traits with associated {0} `{1}`, you could use the fully-qualified path",
                kind_str, ident))
    })format!(
789                            "if there were a type named `Example` that implemented one of the \
790                             traits with associated {kind_str} `{ident}`, you could use the \
791                             fully-qualified path",
792                        ),
793                        traits.iter().map(|trait_str| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<Example as {0}>::", trait_str))
    })format!("<Example as {trait_str}>::")),
794                        Applicability::HasPlaceholders,
795                        SuggestionStyle::ShowAlways,
796                    );
797                }
798                ([type_str], []) => {
799                    err.span_suggestion_verbose(
800                        sugg_sp,
801                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if there were a trait named `Example` with associated {0} `{1}` implemented for `{2}`, you could use the fully-qualified path",
                kind_str, ident, type_str))
    })format!(
802                            "if there were a trait named `Example` with associated {kind_str} `{ident}` \
803                             implemented for `{type_str}`, you could use the fully-qualified path",
804                        ),
805                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0} as Example>::", type_str))
    })format!("<{type_str} as Example>::"),
806                        Applicability::HasPlaceholders,
807                    );
808                }
809                (types, []) => {
810                    err.span_suggestions_with_style(
811                        sugg_sp,
812                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if there were a trait named `Example` with associated {0} `{1}` implemented for one of the types, you could use the fully-qualified path",
                kind_str, ident))
    })format!(
813                            "if there were a trait named `Example` with associated {kind_str} `{ident}` \
814                             implemented for one of the types, you could use the fully-qualified \
815                             path",
816                        ),
817                        types
818                            .into_iter()
819                            .map(|type_str| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0} as Example>::", type_str))
    })format!("<{type_str} as Example>::")),
820                        Applicability::HasPlaceholders,
821                        SuggestionStyle::ShowAlways,
822                    );
823                }
824                (types, traits) => {
825                    let mut suggestions = ::alloc::vec::Vec::new()vec![];
826                    for type_str in types {
827                        for trait_str in traits {
828                            suggestions.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0} as {1}>::", type_str,
                trait_str))
    })format!("<{type_str} as {trait_str}>::"));
829                        }
830                    }
831                    err.span_suggestions_with_style(
832                        sugg_sp,
833                        "use fully-qualified syntax",
834                        suggestions,
835                        Applicability::MachineApplicable,
836                        SuggestionStyle::ShowAlways,
837                    );
838                }
839            }
840        }
841        err.emit_err()
842    }
843
844    pub(crate) fn report_ambiguous_inherent_assoc_item(
845        &self,
846        name: Ident,
847        candidates: Vec<DefId>,
848        span: Span,
849    ) -> ErrorGuaranteed {
850        let mut err = {
    self.dcx().struct_span_err(name.span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("multiple applicable items in scope"))
                })).with_code(E0034)
}struct_span_code_err!(
851            self.dcx(),
852            name.span,
853            E0034,
854            "multiple applicable items in scope"
855        );
856        err.span_label(name.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("multiple `{0}` found", name))
    })format!("multiple `{name}` found"));
857        self.note_ambiguous_inherent_assoc_item(&mut err, candidates, span);
858        err.emit_err()
859    }
860
861    // FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate.
862    fn note_ambiguous_inherent_assoc_item(
863        &self,
864        err: &mut Diag<'_>,
865        candidates: Vec<DefId>,
866        span: Span,
867    ) {
868        let tcx = self.tcx();
869
870        // Dynamic limit to avoid hiding just one candidate, which is silly.
871        let limit = if candidates.len() == 5 { 5 } else { 4 };
872
873        for (index, &item) in candidates.iter().take(limit).enumerate() {
874            let impl_ = tcx.parent(item);
875
876            let note_span = if item.is_local() {
877                Some(tcx.def_span(item))
878            } else if impl_.is_local() {
879                Some(tcx.def_span(impl_))
880            } else {
881                None
882            };
883
884            let title = if candidates.len() > 1 {
885                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("candidate #{0}", index + 1))
    })format!("candidate #{}", index + 1)
886            } else {
887                "the candidate".into()
888            };
889
890            let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity().skip_norm_wip();
891            let note = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} is defined in an impl for the type `{1}`",
                title, impl_ty))
    })format!("{title} is defined in an impl for the type `{impl_ty}`");
892
893            if let Some(span) = note_span {
894                err.span_note(span, note);
895            } else {
896                err.note(note);
897            }
898        }
899        if candidates.len() > limit {
900            err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("and {0} others",
                candidates.len() - limit))
    })format!("and {} others", candidates.len() - limit));
901        }
902    }
903
904    // FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
905    pub(crate) fn report_unresolved_inherent_assoc_item(
906        &self,
907        name: Ident,
908        self_ty: Ty<'tcx>,
909        candidates: Vec<InherentAssocCandidate>,
910        fulfillment_errors: ThinVec<FulfillmentError<'tcx>>,
911        span: Span,
912        assoc_tag: ty::AssocTag,
913    ) -> ErrorGuaranteed {
914        // FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`.
915        // Either
916        // * update this code by applying changes similar to #106702 or by taking a
917        //   Vec<(DefId, (DefId, DefId), Option<Vec<FulfillmentError<'tcx>>>)> or
918        // * deduplicate this code across the two crates.
919
920        let tcx = self.tcx();
921
922        let assoc_tag_str = assoc_tag_str(assoc_tag);
923        let adt_did = self_ty.ty_adt_def().map(|def| def.did());
924        let add_def_label = |err: &mut Diag<'_>| {
925            if let Some(did) = adt_did {
926                err.span_label(
927                    tcx.def_span(did),
928                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("associated {1} `{2}` not found for this {0}",
                tcx.def_descr(did), assoc_tag_str, name))
    })format!(
929                        "associated {assoc_tag_str} `{name}` not found for this {}",
930                        tcx.def_descr(did)
931                    ),
932                );
933            }
934        };
935
936        if fulfillment_errors.is_empty() {
937            // FIXME(fmease): Copied from `rustc_hir_typeck::method::probe`. Deduplicate.
938
939            let limit = if candidates.len() == 5 { 5 } else { 4 };
940            let type_candidates = candidates
941                .iter()
942                .take(limit)
943                .map(|cand| {
944                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("- `{0}`",
                tcx.at(span).type_of(cand.impl_).instantiate_identity().skip_norm_wip()))
    })format!(
945                        "- `{}`",
946                        tcx.at(span).type_of(cand.impl_).instantiate_identity().skip_norm_wip()
947                    )
948                })
949                .collect::<Vec<_>>()
950                .join("\n");
951            let additional_types = if candidates.len() > limit {
952                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\nand {0} more types",
                candidates.len() - limit))
    })format!("\nand {} more types", candidates.len() - limit)
953            } else {
954                String::new()
955            };
956
957            let mut err = {
    self.dcx().struct_span_err(name.span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("associated {0} `{1}` not found for `{2}` in the current scope",
                            assoc_tag_str, name, self_ty))
                })).with_code(E0220)
}struct_span_code_err!(
958                self.dcx(),
959                name.span,
960                E0220,
961                "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
962            );
963            err.span_label(name.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("associated item not found in `{0}`",
                self_ty))
    })format!("associated item not found in `{self_ty}`"));
964            err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the associated {0} was found for\n{1}{2}",
                assoc_tag_str, type_candidates, additional_types))
    })format!(
965                "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
966            ));
967            add_def_label(&mut err);
968            return err.emit_err();
969        }
970
971        let mut bound_spans: SortedMap<OrdSpan, Vec<String>> = Default::default();
972
973        let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
974            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`",
                if obligation.len() > 50 { quiet } else { obligation }))
    })format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
975            match self_ty.kind() {
976                // Point at the type that couldn't satisfy the bound.
977                ty::Adt(def, _) => bound_spans
978                    .get_mut_or_insert_default(OrdSpan(tcx.def_span(def.did())))
979                    .push(msg),
980                // Point at the trait object that couldn't satisfy the bound.
981                ty::Dynamic(preds, _) => {
982                    for pred in preds.iter() {
983                        match pred.skip_binder() {
984                            ty::ExistentialPredicate::Trait(tr) => {
985                                bound_spans
986                                    .get_mut_or_insert_default(OrdSpan(tcx.def_span(tr.def_id)))
987                                    .push(msg.clone());
988                            }
989                            ty::ExistentialPredicate::Projection(_)
990                            | ty::ExistentialPredicate::AutoTrait(_) => {}
991                        }
992                    }
993                }
994                // Point at the closure that couldn't satisfy the bound.
995                ty::Closure(def_id, _) => {
996                    bound_spans
997                        .get_mut_or_insert_default(OrdSpan(tcx.def_span(*def_id)))
998                        .push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", quiet))
    })format!("`{quiet}`"));
999                }
1000                _ => {}
1001            }
1002        };
1003
1004        let format_pred = |pred: ty::Predicate<'tcx>| {
1005            let bound_predicate = pred.kind();
1006            match bound_predicate.skip_binder() {
1007                ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
1008                    // `<Foo as Iterator>::Item = String`.
1009                    let projection_term = pred.projection_term;
1010                    let term = pred.term;
1011                    let self_ty = projection_term.args.get(0).and_then(|arg| arg.as_type())?;
1012
1013                    let obligation = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} = {1}", projection_term, term))
    })format!("{projection_term} = {term}");
1014                    let quiet_projection_term = projection_term
1015                        .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
1016                    let quiet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} = {1}", quiet_projection_term,
                term))
    })format!("{quiet_projection_term} = {term}");
1017
1018                    bound_span_label(self_ty, &obligation, &quiet);
1019
1020                    Some(obligation)
1021                }
1022                ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
1023                    let p = poly_trait_ref.trait_ref;
1024                    let self_ty = p.self_ty();
1025                    let path = p.print_only_trait_path();
1026                    let obligation = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: {1}", self_ty, path))
    })format!("{self_ty}: {path}");
1027                    let quiet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("_: {0}", path))
    })format!("_: {path}");
1028                    bound_span_label(self_ty, &obligation, &quiet);
1029                    Some(obligation)
1030                }
1031                _ => None,
1032            }
1033        };
1034
1035        // FIXME(fmease): `rustc_hir_typeck::method::suggest` uses a `skip_list` to filter out some bounds.
1036        // I would do the same here if it didn't mean more code duplication.
1037        let mut bounds: Vec<_> = fulfillment_errors
1038            .into_iter()
1039            .map(|error| error.root_obligation.predicate)
1040            .filter_map(format_pred)
1041            .map(|p| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", p))
    })format!("`{p}`"))
1042            .collect();
1043        bounds.sort();
1044        bounds.dedup();
1045
1046        let mut err = self.dcx().struct_span_err(
1047            name.span,
1048            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the associated {0} `{1}` exists for `{2}`, but its trait bounds were not satisfied",
                assoc_tag_str, name, self_ty))
    })format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
1049        );
1050        if !bounds.is_empty() {
1051            err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the following trait bounds were not satisfied:\n{0}",
                bounds.join("\n")))
    })format!(
1052                "the following trait bounds were not satisfied:\n{}",
1053                bounds.join("\n")
1054            ));
1055        }
1056        err.span_label(
1057            name.span,
1058            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("associated {0} cannot be referenced on `{1}` due to unsatisfied trait bounds",
                assoc_tag_str, self_ty))
    })format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
1059        );
1060
1061        for (span, mut bounds) in bound_spans {
1062            if !tcx.sess.source_map().is_span_accessible(span.0) {
1063                continue;
1064            }
1065            bounds.sort();
1066            bounds.dedup();
1067            let msg = match &bounds[..] {
1068                [bound] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("doesn\'t satisfy {0}", bound))
    })format!("doesn't satisfy {bound}"),
1069                bounds if bounds.len() > 4 => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("doesn\'t satisfy {0} bounds",
                bounds.len()))
    })format!("doesn't satisfy {} bounds", bounds.len()),
1070                [bounds @ .., last] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("doesn\'t satisfy {0} or {1}",
                bounds.join(", "), last))
    })format!("doesn't satisfy {} or {last}", bounds.join(", ")),
1071                [] => ::core::panicking::unreachable_default_msg()unreachable!(),
1072            };
1073            err.span_label(span.0, msg);
1074        }
1075        add_def_label(&mut err);
1076        err.emit_err()
1077    }
1078
1079    /// If there are any missing associated items, emit an error instructing the user to provide
1080    /// them unless that's impossible due to shadowing. Moreover, if any corresponding trait refs
1081    /// are dyn incompatible due to associated items we emit an dyn incompatibility error instead.
1082    pub(crate) fn check_for_required_assoc_items(
1083        &self,
1084        spans: SmallVec<[Span; 1]>,
1085        missing_assoc_items: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
1086        potential_assoc_items: Vec<usize>,
1087        trait_bounds: &[hir::PolyTraitRef<'_>],
1088    ) -> Result<(), ErrorGuaranteed> {
1089        if missing_assoc_items.is_empty() {
1090            return Ok(());
1091        }
1092
1093        let tcx = self.tcx();
1094        let principal_span = *spans.first().unwrap();
1095
1096        // FIXME: This logic needs some more care w.r.t handling of conflicts
1097        let missing_assoc_items: Vec<_> = missing_assoc_items
1098            .into_iter()
1099            .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
1100            .collect();
1101        let mut names: FxIndexMap<_, Vec<_>> = Default::default();
1102        let mut names_len = 0;
1103        let mut descr = None;
1104
1105        enum Descr {
1106            Item,
1107            Tag(ty::AssocTag),
1108        }
1109
1110        for &(assoc_item, trait_ref) in &missing_assoc_items {
1111            // We don't want to suggest specifying associated items if there's something wrong with
1112            // any of them that renders the trait dyn incompatible; providing them certainly won't
1113            // fix the issue and we could also risk suggesting invalid code.
1114            //
1115            // Note that this check is only truly necessary in item ctxts where we merely perform
1116            // *minimal* dyn compatibility checks. In fn ctxts we would've already bailed out with
1117            // an error by this point if the trait was dyn incompatible.
1118            let violations =
1119                dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), assoc_item);
1120            if !violations.is_empty() {
1121                return Err(report_dyn_incompatibility(
1122                    tcx,
1123                    principal_span,
1124                    None,
1125                    trait_ref.def_id(),
1126                    &violations,
1127                )
1128                .emit_err());
1129            }
1130
1131            names.entry(trait_ref).or_default().push(assoc_item.name());
1132            names_len += 1;
1133
1134            descr = match descr {
1135                None => Some(Descr::Tag(assoc_item.tag())),
1136                Some(Descr::Tag(tag)) if tag != assoc_item.tag() => Some(Descr::Item),
1137                _ => continue,
1138            };
1139        }
1140
1141        // related to issue #91997, turbofishes added only when in an expr or pat
1142        let mut in_expr_or_pat = false;
1143        if let ([], [bound]) = (&potential_assoc_items[..], &trait_bounds) {
1144            let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
1145            in_expr_or_pat = match grandparent {
1146                hir::Node::Expr(_) | hir::Node::Pat(_) => true,
1147                _ => false,
1148            };
1149        }
1150
1151        // We get all the associated items that *are* set, so that we can check if any of
1152        // their names match one of the ones we are missing.
1153        // This would mean that they are shadowing the associated item we are missing, and
1154        // we can then use their span to indicate this to the user.
1155        //
1156        // FIXME: This does not account for trait aliases. I think we should just make
1157        //        `lower_trait_object_ty` compute the list of all specified items or give us the
1158        //        necessary ingredients if it's too expensive to compute in the happy path.
1159        let bound_names: UnordMap<_, _> =
1160            trait_bounds
1161                .iter()
1162                .filter_map(|poly_trait_ref| {
1163                    let path = poly_trait_ref.trait_ref.path.segments.last()?;
1164                    let args = path.args?;
1165                    let Res::Def(DefKind::Trait, trait_def_id) = path.res else { return None };
1166
1167                    Some(args.constraints.iter().filter_map(move |constraint| {
1168                        let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
1169                        else {
1170                            return None;
1171                        };
1172                        let tag = match term {
1173                            hir::Term::Ty(_) => ty::AssocTag::Type,
1174                            hir::Term::Const(_) => ty::AssocTag::Const,
1175                        };
1176                        let assoc_item = tcx
1177                            .associated_items(trait_def_id)
1178                            .find_by_ident_and_kind(tcx, constraint.ident, tag, trait_def_id)?;
1179                        Some(((constraint.ident.name, tag), assoc_item.def_id))
1180                    }))
1181                })
1182                .flatten()
1183                .collect();
1184
1185        let mut names: Vec<_> = names
1186            .into_iter()
1187            .map(|(trait_, mut assocs)| {
1188                assocs.sort();
1189                let trait_ = trait_.print_trait_sugared();
1190                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} in `{1}`",
                listify(&assocs[..],
                        |a|
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", a))
                                })).unwrap_or_default(), trait_))
    })format!(
1191                    "{} in `{trait_}`",
1192                    listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
1193                )
1194            })
1195            .collect();
1196        names.sort();
1197        let names = names.join(", ");
1198
1199        let descr = match descr.unwrap() {
1200            Descr::Item => "associated item",
1201            Descr::Tag(tag) => tag.descr(),
1202        };
1203        let mut err = {
    self.dcx().struct_span_err(principal_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("the value of the {1}{0} {2} must be specified",
                            if names_len == 1 { "" } else { "s" }, descr, names))
                })).with_code(E0191)
}struct_span_code_err!(
1204            self.dcx(),
1205            principal_span,
1206            E0191,
1207            "the value of the {descr}{s} {names} must be specified",
1208            s = pluralize!(names_len),
1209        );
1210        let mut suggestions = ::alloc::vec::Vec::new()vec![];
1211        let mut items_count = 0;
1212        let mut where_constraints = ::alloc::vec::Vec::new()vec![];
1213        let mut already_has_generics_args_suggestion = false;
1214
1215        let mut names: UnordMap<_, usize> = Default::default();
1216        for (item, _) in &missing_assoc_items {
1217            items_count += 1;
1218            *names.entry((item.name(), item.tag())).or_insert(0) += 1;
1219        }
1220        let mut dupes = false;
1221        let mut shadows = false;
1222        for (item, trait_ref) in &missing_assoc_items {
1223            let name = item.name();
1224            let key = (name, item.tag());
1225
1226            if names[&key] > 1 {
1227                dupes = true;
1228            } else if bound_names.get(&key).is_some_and(|&def_id| def_id != item.def_id) {
1229                shadows = true;
1230            }
1231
1232            let prefix = if dupes || shadows {
1233                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::",
                tcx.def_path_str(trait_ref.def_id())))
    })format!("{}::", tcx.def_path_str(trait_ref.def_id()))
1234            } else {
1235                String::new()
1236            };
1237            let mut is_shadowed = false;
1238
1239            if let Some(&def_id) = bound_names.get(&key)
1240                && def_id != item.def_id
1241            {
1242                is_shadowed = true;
1243
1244                let rename_message = if def_id.is_local() { ", consider renaming it" } else { "" };
1245                err.span_label(
1246                    tcx.def_span(def_id),
1247                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}{1}` shadowed here{2}", prefix,
                name, rename_message))
    })format!("`{prefix}{name}` shadowed here{rename_message}"),
1248                );
1249            }
1250
1251            let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
1252
1253            if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
1254                err.span_label(sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}{1}` defined here{2}", prefix,
                name, rename_message))
    })format!("`{prefix}{name}` defined here{rename_message}"));
1255            }
1256        }
1257        if potential_assoc_items.len() == missing_assoc_items.len() {
1258            // When the amount of missing associated types equals the number of
1259            // extra type arguments present. A suggesting to replace the generic args with
1260            // associated types is already emitted.
1261            already_has_generics_args_suggestion = true;
1262        } else if let (Ok(snippet), false, false) =
1263            (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
1264        {
1265            let bindings: Vec<_> = missing_assoc_items
1266                .iter()
1267                .map(|(item, _)| {
1268                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} = /* {1} */", item.name(),
                match item.kind {
                    ty::AssocKind::Const { .. } => "CONST",
                    ty::AssocKind::Type { .. } => "Type",
                    ty::AssocKind::Fn { .. } =>
                        ::core::panicking::unreachable_default_msg(),
                }))
    })format!(
1269                        "{} = /* {} */",
1270                        item.name(),
1271                        match item.kind {
1272                            ty::AssocKind::Const { .. } => "CONST",
1273                            ty::AssocKind::Type { .. } => "Type",
1274                            ty::AssocKind::Fn { .. } => unreachable!(),
1275                        }
1276                    )
1277                })
1278                .collect();
1279            let code = if let Some(snippet) = snippet.strip_suffix("<>") {
1280                // Empty generics
1281                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1}<{0}>", bindings.join(", "),
                snippet))
    })format!("{snippet}<{}>", bindings.join(", "))
1282            } else if let Some(snippet) = snippet.strip_suffix('>') {
1283                // Non-empty generics
1284                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1}, {0}>", bindings.join(", "),
                snippet))
    })format!("{snippet}, {}>", bindings.join(", "))
1285            } else if in_expr_or_pat {
1286                // The user wrote `Trait`, so we don't have a term we can suggest, but at least we
1287                // can clue them to the correct syntax `Trait::<Item = /* ... */>`.
1288                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::<{1}>", snippet,
                bindings.join(", ")))
    })format!("{}::<{}>", snippet, bindings.join(", "))
1289            } else {
1290                // The user wrote `Trait`, so we don't have a term we can suggest, but at least we
1291                // can clue them to the correct syntax `Trait<Item = /* ... */>`.
1292                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}<{1}>", snippet,
                bindings.join(", ")))
    })format!("{}<{}>", snippet, bindings.join(", "))
1293            };
1294            suggestions.push((principal_span, code));
1295        } else if dupes {
1296            where_constraints.push(principal_span);
1297        }
1298
1299        // FIXME: This note doesn't make sense, get rid of this outright.
1300        //        I don't see how adding a type param (to the trait?) would help.
1301        //        If the user can modify the trait, they should just rename one of the assoc tys.
1302        //        What does it mean with the rest of the message?
1303        //        Does it suggest adding equality predicates (unimplemented) to the trait object
1304        //        type? (pseudo) "dyn B + <Self as B>::X = T + <Self as A>::X = U"?
1305        //        Instead, maybe mention shadowing if applicable (yes, even when no "relevant"
1306        //        bindings were provided).
1307        let where_msg = "consider introducing a new type parameter, adding `where` constraints \
1308                         using the fully-qualified path to the associated types";
1309        if !where_constraints.is_empty() && suggestions.is_empty() {
1310            // If there are duplicates associated type names and a single trait bound do not
1311            // use structured suggestion, it means that there are multiple supertraits with
1312            // the same associated type name.
1313            err.help(where_msg);
1314        }
1315        if suggestions.len() != 1 || already_has_generics_args_suggestion {
1316            // We don't need this label if there's an inline suggestion, show otherwise.
1317            let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
1318            for (item, _) in &missing_assoc_items {
1319                items_count += 1;
1320                *names.entry(item.name()).or_insert(0) += 1;
1321            }
1322            let mut label = ::alloc::vec::Vec::new()vec![];
1323            for (item, trait_ref) in &missing_assoc_items {
1324                let name = item.name();
1325                let postfix = if names[&name] > 1 {
1326                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" (from trait `{0}`)",
                trait_ref.print_trait_sugared()))
    })format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
1327                } else {
1328                    String::new()
1329                };
1330                label.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`{1}", name, postfix))
    })format!("`{}`{}", name, postfix));
1331            }
1332            if !label.is_empty() {
1333                err.span_label(
1334                    principal_span,
1335                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{2}{0} {1} must be specified",
                if label.len() == 1 { "" } else { "s" }, label.join(", "),
                descr))
    })format!(
1336                        "{descr}{s} {names} must be specified",
1337                        s = pluralize!(label.len()),
1338                        names = label.join(", "),
1339                    ),
1340                );
1341            }
1342        }
1343        suggestions.sort_by_key(|&(span, _)| span.lo_hi());
1344        // There are cases where one bound points to a span within another bound's span, like when
1345        // you have code like the following (#115019), so we skip providing a suggestion in those
1346        // cases to avoid having a malformed suggestion.
1347        //
1348        // pub struct Flatten<I> {
1349        //     inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::core,
1350        //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1351        //             |                  ^^^^^^^^^^^^^^^^^^^^^
1352        //             |                  |
1353        //             |                  associated types `Item`, `IntoIter` must be specified
1354        //             associated types `Item`, `IntoIter` must be specified
1355        // }
1356        let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
1357        if !suggestions.is_empty() && !overlaps {
1358            err.multipart_suggestion(
1359                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("specify the {1}{0}",
                if items_count == 1 { "" } else { "s" }, descr))
    })format!("specify the {descr}{s}", s = pluralize!(items_count)),
1360                suggestions,
1361                Applicability::HasPlaceholders,
1362            );
1363            if !where_constraints.is_empty() {
1364                err.span_help(where_constraints, where_msg);
1365            }
1366        }
1367
1368        Err(err.emit_err())
1369    }
1370
1371    /// On ambiguous associated type, look for an associated function whose name matches the
1372    /// extended path and, if found, emit an E0223 error with a structured suggestion.
1373    /// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195)
1374    pub(crate) fn maybe_report_similar_assoc_fn(
1375        &self,
1376        span: Span,
1377        qself_ty: Ty<'tcx>,
1378        qself: &hir::Ty<'_>,
1379    ) -> Result<(), ErrorGuaranteed> {
1380        let tcx = self.tcx();
1381        if let Some((_, node)) = tcx.hir_parent_iter(qself.hir_id).skip(1).next()
1382            && let hir::Node::Expr(hir::Expr {
1383                kind:
1384                    hir::ExprKind::Path(hir::QPath::TypeRelative(
1385                        hir::Ty {
1386                            kind:
1387                                hir::TyKind::Path(hir::QPath::TypeRelative(
1388                                    _,
1389                                    hir::PathSegment { ident: ident2, .. },
1390                                )),
1391                            ..
1392                        },
1393                        hir::PathSegment { ident: ident3, .. },
1394                    )),
1395                ..
1396            }) = node
1397            && let Some(inherent_impls) = qself_ty
1398                .ty_adt_def()
1399                .map(|adt_def| tcx.inherent_impls(adt_def.did()))
1400                .or_else(|| {
1401                    simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer)
1402                        .map(|simple_ty| tcx.incoherent_impls(simple_ty))
1403                })
1404            && let name = Symbol::intern(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}_{1}", ident2, ident3))
    })format!("{ident2}_{ident3}"))
1405            && let Some(item) = inherent_impls
1406                .iter()
1407                .flat_map(|&inherent_impl| {
1408                    tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
1409                })
1410                .next()
1411            && item.is_fn()
1412        {
1413            Err({
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("ambiguous associated type"))
                })).with_code(E0223)
}struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")
1414                .with_span_suggestion_verbose(
1415                    ident2.span.to(ident3.span),
1416                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("there is an associated function with a similar name: `{0}`",
                name))
    })format!("there is an associated function with a similar name: `{name}`"),
1417                    name,
1418                    Applicability::MaybeIncorrect,
1419                )
1420                .emit_err())
1421        } else {
1422            Ok(())
1423        }
1424    }
1425
1426    pub fn report_prohibited_generic_args<'a>(
1427        &self,
1428        segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1429        args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1430        err_extend: GenericsArgsErrExtend<'a>,
1431    ) -> ErrorGuaranteed {
1432        #[derive(#[automatically_derived]impl ::core::marker::StructuralPartialEq for
    ProhibitGenericsArg {
}
#[automatically_derived]impl ::core::cmp::PartialEq for ProhibitGenericsArg {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for ProhibitGenericsArg { }Eq, #[automatically_derived]impl ::core::hash::Hash for ProhibitGenericsArg {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state)
    }
}Hash)]
1433        enum ProhibitGenericsArg {
1434            Lifetime,
1435            Type,
1436            Const,
1437            Infer,
1438        }
1439
1440        let mut prohibit_args = FxIndexSet::default();
1441        args_visitors.for_each(|arg| {
1442            match arg {
1443                hir::GenericArg::Lifetime(_) => prohibit_args.insert(ProhibitGenericsArg::Lifetime),
1444                hir::GenericArg::Type(_) => prohibit_args.insert(ProhibitGenericsArg::Type),
1445                hir::GenericArg::Const(_) => prohibit_args.insert(ProhibitGenericsArg::Const),
1446                hir::GenericArg::Infer(_) => prohibit_args.insert(ProhibitGenericsArg::Infer),
1447            };
1448        });
1449
1450        let segments: Vec<_> = segments.collect();
1451        let types_and_spans: Vec<_> = segments
1452            .iter()
1453            .flat_map(|segment| {
1454                if segment.args().args.is_empty() {
1455                    None
1456                } else {
1457                    Some((
1458                        match segment.res {
1459                            Res::PrimTy(ty) => {
1460                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}`", segment.res.descr(),
                ty.name()))
    })format!("{} `{}`", segment.res.descr(), ty.name())
1461                            }
1462                            Res::Def(_, def_id)
1463                                if let Some(name) = self.tcx().opt_item_name(def_id) =>
1464                            {
1465                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}`", segment.res.descr(),
                name))
    })format!("{} `{name}`", segment.res.descr())
1466                            }
1467                            Res::Err => "this type".to_string(),
1468                            _ => segment.res.descr().to_string(),
1469                        },
1470                        segment.ident.span,
1471                    ))
1472                }
1473            })
1474            .collect();
1475        let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
1476            .expect("expected one segment to deny");
1477
1478        let arg_spans: Vec<Span> =
1479            segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
1480
1481        let mut kinds = Vec::with_capacity(4);
1482        prohibit_args.iter().for_each(|arg| match arg {
1483            ProhibitGenericsArg::Lifetime => kinds.push("lifetime"),
1484            ProhibitGenericsArg::Type => kinds.push("type"),
1485            ProhibitGenericsArg::Const => kinds.push("const"),
1486            ProhibitGenericsArg::Infer => kinds.push("generic"),
1487        });
1488
1489        let s = if kinds.len() == 1 { "" } else { "s" }pluralize!(kinds.len());
1490        let kind =
1491            listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit");
1492        let last_span = *arg_spans.last().unwrap();
1493        let span: MultiSpan = arg_spans.into();
1494        let mut err = {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0} arguments are not allowed on {1}",
                            kind, this_type))
                })).with_code(E0109)
}struct_span_code_err!(
1495            self.dcx(),
1496            span,
1497            E0109,
1498            "{kind} arguments are not allowed on {this_type}",
1499        );
1500        err.span_label(last_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} argument{1} not allowed", kind,
                s))
    })format!("{kind} argument{s} not allowed"));
1501        for (what, span) in types_and_spans {
1502            err.span_label(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("not allowed on {0}", what))
    })format!("not allowed on {what}"));
1503        }
1504        generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
1505        err.emit_err()
1506    }
1507
1508    pub fn report_trait_object_addition_traits(
1509        &self,
1510        regular_traits: &Vec<(ty::PolyTraitClause<'tcx>, SmallVec<[Span; 1]>)>,
1511    ) -> ErrorGuaranteed {
1512        // we use the last span to point at the traits themselves,
1513        // and all other preceding spans are trait alias expansions.
1514        let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap();
1515        let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap();
1516        let mut err = {
    self.dcx().struct_span_err(*regular_traits[1].1.first().unwrap(),
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("only auto traits can be used as additional traits in a trait object"))
                })).with_code(E0225)
}struct_span_code_err!(
1517            self.dcx(),
1518            *regular_traits[1].1.first().unwrap(),
1519            E0225,
1520            "only auto traits can be used as additional traits in a trait object"
1521        );
1522        err.span_label(first_span, "first non-auto trait");
1523        for &alias_span in first_alias_spans {
1524            err.span_label(alias_span, "first non-auto trait comes from this alias");
1525        }
1526        err.span_label(second_span, "additional non-auto trait");
1527        for &alias_span in second_alias_spans {
1528            err.span_label(alias_span, "second non-auto trait comes from this alias");
1529        }
1530        err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: {0} {{}}`",
                regular_traits.iter().map(|(pred, _)|
                                pred.map_bound(|pred|
                                                pred.trait_ref).print_only_trait_path().to_string()).collect::<Vec<_>>().join(" + ")))
    })format!(
1531            "consider creating a new trait with all of these as supertraits and using that \
1532             trait here instead: `trait NewTrait: {} {{}}`",
1533            regular_traits
1534                .iter()
1535                // FIXME: This should `print_sugared`, but also needs to integrate projection bounds...
1536                .map(|(pred, _)| pred
1537                    .map_bound(|pred| pred.trait_ref)
1538                    .print_only_trait_path()
1539                    .to_string())
1540                .collect::<Vec<_>>()
1541                .join(" + "),
1542        ));
1543        err.note(
1544            "auto-traits like `Send` and `Sync` are traits that have special properties; \
1545             for more information on them, visit \
1546             <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1547        );
1548        err.emit_err()
1549    }
1550
1551    pub fn report_trait_object_with_no_traits(
1552        &self,
1553        span: Span,
1554        user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
1555    ) -> ErrorGuaranteed {
1556        let tcx = self.tcx();
1557        let trait_alias_span = user_written_clauses
1558            .into_iter()
1559            .filter_map(|(clause, _)| clause.as_trait_clause())
1560            .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id()))
1561            .map(|trait_ref| tcx.def_span(trait_ref.def_id()));
1562
1563        self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
1564    }
1565}
1566
1567/// Emit an error for the given associated item constraint.
1568pub fn prohibit_assoc_item_constraint(
1569    cx: &dyn HirTyLowerer<'_>,
1570    constraint: &hir::AssocItemConstraint<'_>,
1571    segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
1572) -> ErrorGuaranteed {
1573    let tcx = cx.tcx();
1574    let mut err = cx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
1575        span: constraint.span,
1576        fn_trait_expansion: if let Some((_, segment, span)) = segment
1577            && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
1578        {
1579            Some(ParenthesizedFnTraitExpansion {
1580                span,
1581                expanded_type: fn_trait_to_string(tcx, segment, false),
1582            })
1583        } else {
1584            None
1585        },
1586    });
1587
1588    if let hir::AssocItemConstraintKind::Bound {
1589        bounds: [hir::GenericBound::Trait(poly_trait_ref)],
1590    } = constraint.kind
1591        && let Res::Err = poly_trait_ref.trait_ref.path.res
1592    {
1593        // This was likely a `Vec<foo::Bar>` to `Vec<foo:Bar>` typo. A prior error will have been
1594        // emitted during resolve, with better context.
1595        err.downgrade_to_delayed_bug();
1596    }
1597
1598    // Emit a suggestion to turn the assoc item binding into a generic arg
1599    // if the relevant item has a generic param whose name matches the binding name;
1600    // otherwise suggest the removal of the binding.
1601    if let Some((def_id, segment, _)) = segment
1602        && segment.args().parenthesized == hir::GenericArgsParentheses::No
1603    {
1604        // Suggests removal of the offending binding
1605        let suggest_removal = |e: &mut Diag<'_>| {
1606            let constraints = segment.args().constraints;
1607            let args = segment.args().args;
1608
1609            // Compute the span to remove based on the position
1610            // of the binding. We do that as follows:
1611            //  1. Find the index of the binding in the list of bindings
1612            //  2. Locate the spans preceding and following the binding.
1613            //     If it's the first binding the preceding span would be
1614            //     that of the last arg
1615            //  3. Using this information work out whether the span
1616            //     to remove will start from the end of the preceding span,
1617            //     the start of the next span or will simply be the
1618            //     span encomassing everything within the generics brackets
1619
1620            let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
1621                ::rustc_span::macros::bug_impl(None,
    format_args!("a type binding exists but its HIR ID not found in generics"),
    Location::caller());bug!("a type binding exists but its HIR ID not found in generics");
1622            };
1623
1624            let preceding_span = if index > 0 {
1625                Some(constraints[index - 1].span)
1626            } else {
1627                args.last().map(|a| a.span())
1628            };
1629
1630            let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
1631
1632            let removal_span = match (preceding_span, next_span) {
1633                (Some(prec), _) => constraint.span.with_lo(prec.hi()),
1634                (None, Some(next)) => constraint.span.with_hi(next.lo()),
1635                (None, None) => {
1636                    let Some(generics_span) = segment.args().span_ext() else {
1637                        ::rustc_span::macros::bug_impl(None,
    format_args!("a type binding exists but generic span is empty"),
    Location::caller());bug!("a type binding exists but generic span is empty");
1638                    };
1639
1640                    generics_span
1641                }
1642            };
1643
1644            // Now emit the suggestion
1645            e.span_suggestion_verbose(
1646                removal_span,
1647                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider removing this associated item {0}",
                constraint.kind.descr()))
    })format!("consider removing this associated item {}", constraint.kind.descr()),
1648                "",
1649                Applicability::MaybeIncorrect,
1650            );
1651        };
1652
1653        // Suggest replacing the associated item binding with a generic argument.
1654        // i.e., replacing `<..., T = A, ...>` with `<..., A, ...>`.
1655        let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
1656            if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
1657                e.span_suggestion_verbose(
1658                    constraint.span,
1659                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("to use `{0}` as a generic argument specify it directly",
                snippet))
    })format!("to use `{snippet}` as a generic argument specify it directly"),
1660                    snippet,
1661                    Applicability::MaybeIncorrect,
1662                );
1663            }
1664        };
1665
1666        // Check if the type has a generic param with the same name
1667        // as the assoc type name in the associated item binding.
1668        let generics = tcx.generics_of(def_id);
1669        let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
1670
1671        // Now emit the appropriate suggestion
1672        if let Some(matching_param) = matching_param {
1673            match (constraint.kind, &matching_param.kind) {
1674                (
1675                    hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
1676                    GenericParamDefKind::Type { .. },
1677                ) => suggest_direct_use(&mut err, ty.span),
1678                (
1679                    hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
1680                    GenericParamDefKind::Const { .. },
1681                ) => {
1682                    suggest_direct_use(&mut err, c.span);
1683                }
1684                (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
1685                    // Suggest `impl<T: Bound> Trait<T> for Foo` when finding
1686                    // `impl Trait<T: Bound> for Foo`
1687
1688                    // Get the parent impl block based on the binding we have
1689                    // and the trait DefId
1690                    let impl_block = tcx
1691                        .hir_parent_iter(constraint.hir_id)
1692                        .find_map(|(_, node)| node.impl_block_of_trait(def_id));
1693
1694                    let type_with_constraints =
1695                        tcx.sess.source_map().span_to_snippet(constraint.span);
1696
1697                    if let Some(impl_block) = impl_block
1698                        && let Ok(type_with_constraints) = type_with_constraints
1699                    {
1700                        // Filter out the lifetime parameters because
1701                        // they should be declared before the type parameter
1702                        let lifetimes: String = bounds
1703                            .iter()
1704                            .filter_map(|bound| {
1705                                if let hir::GenericBound::Outlives(lifetime) = bound {
1706                                    Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", lifetime))
    })format!("{lifetime}, "))
1707                                } else {
1708                                    None
1709                                }
1710                            })
1711                            .collect();
1712                        // Figure out a span and suggestion string based on
1713                        // whether there are any existing parameters
1714                        let param_decl = if let Some(param_span) =
1715                            impl_block.generics.span_for_param_suggestion()
1716                        {
1717                            (param_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}{1}", lifetimes,
                type_with_constraints))
    })format!(", {lifetimes}{type_with_constraints}"))
1718                        } else {
1719                            (
1720                                impl_block.generics.span.shrink_to_lo(),
1721                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}{1}>", lifetimes,
                type_with_constraints))
    })format!("<{lifetimes}{type_with_constraints}>"),
1722                            )
1723                        };
1724                        let suggestions = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [param_decl,
                (constraint.span.with_lo(constraint.ident.span.hi()),
                    String::new())]))vec![
1725                            param_decl,
1726                            (constraint.span.with_lo(constraint.ident.span.hi()), String::new()),
1727                        ];
1728
1729                        err.multipart_suggestion(
1730                            "declare the type parameter right after the `impl` keyword",
1731                            suggestions,
1732                            Applicability::MaybeIncorrect,
1733                        );
1734                    }
1735                }
1736                _ => suggest_removal(&mut err),
1737            }
1738        } else {
1739            suggest_removal(&mut err);
1740        }
1741    }
1742
1743    err.emit_err()
1744}
1745
1746pub(crate) fn fn_trait_to_string(
1747    tcx: TyCtxt<'_>,
1748    trait_segment: &hir::PathSegment<'_>,
1749    parenthesized: bool,
1750) -> String {
1751    let args = trait_segment
1752        .args
1753        .and_then(|args| args.args.first())
1754        .and_then(|arg| match arg {
1755            hir::GenericArg::Type(ty) => match ty.kind {
1756                hir::TyKind::Tup(t) => t
1757                    .iter()
1758                    .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
1759                    .collect::<Result<Vec<_>, _>>()
1760                    .map(|a| a.join(", ")),
1761                _ => tcx.sess.source_map().span_to_snippet(ty.span),
1762            }
1763            .map(|s| {
1764                // `is_empty()` checks to see if the type is the unit tuple, if so we don't want a comma
1765                if parenthesized || s.is_empty() { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("({0})", s))
    })format!("({s})") } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("({0},)", s))
    })format!("({s},)") }
1766            })
1767            .ok(),
1768            _ => None,
1769        })
1770        .unwrap_or_else(|| "()".to_string());
1771
1772    let ret = trait_segment
1773        .args()
1774        .constraints
1775        .iter()
1776        .find_map(|c| {
1777            if c.ident.name == sym::Output
1778                && let Some(ty) = c.ty()
1779                && ty.span != tcx.hir_span(trait_segment.hir_id)
1780            {
1781                tcx.sess.source_map().span_to_snippet(ty.span).ok()
1782            } else {
1783                None
1784            }
1785        })
1786        .unwrap_or_else(|| "()".to_string());
1787
1788    if parenthesized {
1789        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1} -> {2}",
                trait_segment.ident, args, ret))
    })format!("{}{} -> {}", trait_segment.ident, args, ret)
1790    } else {
1791        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}<{1}, Output={2}>",
                trait_segment.ident, args, ret))
    })format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
1792    }
1793}
1794
1795/// Used for generics args error extend.
1796pub enum GenericsArgsErrExtend<'tcx> {
1797    EnumVariant {
1798        qself: &'tcx hir::Ty<'tcx>,
1799        assoc_segment: &'tcx hir::PathSegment<'tcx>,
1800        adt_def: AdtDef<'tcx>,
1801    },
1802    OpaqueTy,
1803    PrimTy(hir::PrimTy),
1804    SelfTyAlias {
1805        def_id: DefId,
1806        span: Span,
1807    },
1808    SelfTyParam(Span),
1809    Param(DefId),
1810    DefVariant(&'tcx [hir::PathSegment<'tcx>]),
1811    None,
1812}
1813
1814fn generics_args_err_extend<'a>(
1815    tcx: TyCtxt<'_>,
1816    segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1817    err: &mut Diag<'_>,
1818    err_extend: GenericsArgsErrExtend<'a>,
1819) {
1820    match err_extend {
1821        GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
1822            err.note("enum variants can't have type parameters");
1823            let type_name = tcx.item_name(adt_def.did());
1824            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might have meant to specify type parameters on enum `{0}`",
                type_name))
    })format!(
1825                "you might have meant to specify type parameters on enum \
1826                `{type_name}`"
1827            );
1828            let Some(args) = assoc_segment.args else {
1829                return;
1830            };
1831            // Get the span of the generics args *including* the leading `::`.
1832            // We do so by stretching args.span_ext to the left by 2. Earlier
1833            // it was done based on the end of assoc segment but that sometimes
1834            // led to impossible spans and caused issues like #116473
1835            let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2));
1836            if tcx.generics_of(adt_def.did()).is_empty() {
1837                // FIXME(estebank): we could also verify that the arguments being
1838                // work for the `enum`, instead of just looking if it takes *any*.
1839                err.span_suggestion_verbose(
1840                    args_span,
1841                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} doesn\'t have generic parameters",
                type_name))
    })format!("{type_name} doesn't have generic parameters"),
1842                    "",
1843                    Applicability::MachineApplicable,
1844                );
1845                return;
1846            }
1847            let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
1848                err.note(msg);
1849                return;
1850            };
1851            let (qself_sugg_span, is_self) =
1852                if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1853                    // If the path segment already has type params, we want to overwrite
1854                    // them.
1855                    match &path.segments {
1856                        // `segment` is the previous to last element on the path,
1857                        // which would normally be the `enum` itself, while the last
1858                        // `_` `PathSegment` corresponds to the variant.
1859                        [
1860                            ..,
1861                            hir::PathSegment {
1862                                ident, args, res: Res::Def(DefKind::Enum, _), ..
1863                            },
1864                            _,
1865                        ] => (
1866                            // We need to include the `::` in `Type::Variant::<Args>`
1867                            // to point the span to `::<Args>`, not just `<Args>`.
1868                            ident
1869                                .span
1870                                .shrink_to_hi()
1871                                .to(args.map_or(ident.span.shrink_to_hi(), |a| a.span_ext)),
1872                            false,
1873                        ),
1874                        [segment] => {
1875                            (
1876                                // We need to include the `::` in `Type::Variant::<Args>`
1877                                // to point the span to `::<Args>`, not just `<Args>`.
1878                                segment.ident.span.shrink_to_hi().to(segment
1879                                    .args
1880                                    .map_or(segment.ident.span.shrink_to_hi(), |a| a.span_ext)),
1881                                kw::SelfUpper == segment.ident.name,
1882                            )
1883                        }
1884                        _ => {
1885                            err.note(msg);
1886                            return;
1887                        }
1888                    }
1889                } else {
1890                    err.note(msg);
1891                    return;
1892                };
1893            let suggestion = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [if is_self {
                    (qself.span,
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("{0}{1}", type_name,
                                        snippet))
                            }))
                } else { (qself_sugg_span, snippet) },
                (args_span, String::new())]))vec![
1894                if is_self {
1895                    // Account for people writing `Self::Variant::<Args>`, where
1896                    // `Self` is the enum, and suggest replacing `Self` with the
1897                    // appropriate type: `Type::<Args>::Variant`.
1898                    (qself.span, format!("{type_name}{snippet}"))
1899                } else {
1900                    (qself_sugg_span, snippet)
1901                },
1902                (args_span, String::new()),
1903            ];
1904            err.multipart_suggestion(msg, suggestion, Applicability::MaybeIncorrect);
1905        }
1906        GenericsArgsErrExtend::DefVariant(segments) => {
1907            let args: Vec<Span> = segments
1908                .iter()
1909                .filter_map(|segment| match segment.res {
1910                    Res::Def(
1911                        DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1912                        _,
1913                    ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1914                    _ => None,
1915                })
1916                .collect();
1917            if args.len() > 1
1918                && let Some(span) = args.into_iter().next_back()
1919            {
1920                err.note(
1921                    "generic arguments are not allowed on both an enum and its variant's path \
1922                     segments simultaneously; they are only valid in one place or the other",
1923                );
1924                err.span_suggestion_verbose(
1925                    span,
1926                    "remove the generics arguments from one of the path segments",
1927                    String::new(),
1928                    Applicability::MaybeIncorrect,
1929                );
1930            }
1931        }
1932        GenericsArgsErrExtend::PrimTy(prim_ty) => {
1933            let name = prim_ty.name_str();
1934            for segment in segments {
1935                if let Some(args) = segment.args {
1936                    err.span_suggestion_verbose(
1937                        segment.ident.span.shrink_to_hi().to(args.span_ext),
1938                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("primitive type `{0}` doesn\'t have generic parameters",
                name))
    })format!("primitive type `{name}` doesn't have generic parameters"),
1939                        "",
1940                        Applicability::MaybeIncorrect,
1941                    );
1942                }
1943            }
1944        }
1945        GenericsArgsErrExtend::OpaqueTy => {
1946            err.note("`impl Trait` types can't have type parameters");
1947        }
1948        GenericsArgsErrExtend::Param(def_id) => {
1949            let span = tcx.def_ident_span(def_id).unwrap();
1950            let kind = tcx.def_descr(def_id);
1951            let name = tcx.item_name(def_id);
1952            err.span_note(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}` defined here", kind,
                name))
    })format!("{kind} `{name}` defined here"));
1953        }
1954        GenericsArgsErrExtend::SelfTyParam(span) => {
1955            err.span_suggestion_verbose(
1956                span,
1957                "the `Self` type doesn't accept type parameters",
1958                "",
1959                Applicability::MaybeIncorrect,
1960            );
1961        }
1962        GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
1963            let ty = tcx.at(span).type_of(def_id).instantiate_identity().skip_norm_wip();
1964            let span_of_impl = tcx.span_of_impl(def_id);
1965            let ty::Adt(self_def, _) = *ty.kind() else { return };
1966            let def_id = self_def.did();
1967
1968            let type_name = tcx.item_name(def_id);
1969            let span_of_ty = tcx.def_ident_span(def_id);
1970            let generics = tcx.generics_of(def_id).count();
1971
1972            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`Self` is of type `{0}`", ty))
    })format!("`Self` is of type `{ty}`");
1973            if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
1974                let mut span: MultiSpan = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [t_sp]))vec![t_sp].into();
1975                span.push_span_label(
1976                    i_sp,
1977                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`Self` is on type `{0}` in this `impl`",
                type_name))
    })format!("`Self` is on type `{type_name}` in this `impl`"),
1978                );
1979                let mut postfix = "";
1980                if generics == 0 {
1981                    postfix = ", which doesn't have generic parameters";
1982                }
1983                span.push_span_label(t_sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`Self` corresponds to this type{0}",
                postfix))
    })format!("`Self` corresponds to this type{postfix}"));
1984                err.span_note(span, msg);
1985            } else {
1986                err.note(msg);
1987            }
1988            for segment in segments {
1989                if let Some(args) = segment.args
1990                    && segment.ident.name == kw::SelfUpper
1991                {
1992                    if generics == 0 {
1993                        // FIXME(estebank): we could also verify that the arguments being
1994                        // work for the `enum`, instead of just looking if it takes *any*.
1995                        err.span_suggestion_verbose(
1996                            segment.ident.span.shrink_to_hi().to(args.span_ext),
1997                            "the `Self` type doesn't accept type parameters",
1998                            "",
1999                            Applicability::MachineApplicable,
2000                        );
2001                        return;
2002                    } else {
2003                        err.span_suggestion_verbose(
2004                            segment.ident.span,
2005                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the `Self` type doesn\'t accept type parameters, use the concrete type\'s name `{0}` instead if you want to specify its type parameters",
                type_name))
    })format!(
2006                                "the `Self` type doesn't accept type parameters, use the \
2007                                concrete type's name `{type_name}` instead if you want to \
2008                                specify its type parameters"
2009                            ),
2010                            type_name,
2011                            Applicability::MaybeIncorrect,
2012                        );
2013                    }
2014                }
2015            }
2016        }
2017        _ => {}
2018    }
2019}
2020
2021pub(super) struct AmbiguityBetweenVariantAndAssocItem<'tcx> {
2022    pub(super) variant_def_id: DefId,
2023    pub(super) item_def_id: DefId,
2024    pub(super) span: Span,
2025    pub(super) segment_ident: Ident,
2026    pub(super) bound_def_id: DefId,
2027    pub(super) self_ty: Ty<'tcx>,
2028    pub(super) tcx: TyCtxt<'tcx>,
2029    pub(super) mode: super::LowerTypeRelativePathMode,
2030}
2031
2032impl<'a, 'tcx> rustc_errors::Diagnostic<'a> for AmbiguityBetweenVariantAndAssocItem<'tcx> {
2033    fn into_diag(
2034        self,
2035        dcx: rustc_errors::DiagCtxtHandle<'a>,
2036        level: rustc_errors::Level,
2037    ) -> Diag<'a> {
2038        let Self {
2039            variant_def_id,
2040            item_def_id,
2041            span,
2042            segment_ident,
2043            bound_def_id,
2044            self_ty,
2045            tcx,
2046            mode,
2047        } = self;
2048        let mut lint = Diag::new(dcx, level, "ambiguous associated item");
2049
2050        let mut could_refer_to = |kind: DefKind, def_id, also| {
2051            let note_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` could{1} refer to the {2} defined here",
                segment_ident, also, tcx.def_kind_descr(kind, def_id)))
    })format!(
2052                "`{}` could{} refer to the {} defined here",
2053                segment_ident,
2054                also,
2055                tcx.def_kind_descr(kind, def_id)
2056            );
2057            lint.span_note(tcx.def_span(def_id), note_msg);
2058        };
2059
2060        could_refer_to(DefKind::Variant, variant_def_id, "");
2061        could_refer_to(mode.def_kind_for_diagnostics(), item_def_id, " also");
2062
2063        lint.span_suggestion_verbose(
2064            span,
2065            "use fully-qualified syntax",
2066            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0} as {1}>::{2}", self_ty,
                tcx.item_name(bound_def_id), segment_ident))
    })format!("<{} as {}>::{}", self_ty, tcx.item_name(bound_def_id), segment_ident),
2067            Applicability::MachineApplicable,
2068        );
2069        lint
2070    }
2071}
2072
2073fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
2074    match assoc_tag {
2075        ty::AssocTag::Fn => "function",
2076        ty::AssocTag::Const => "constant",
2077        ty::AssocTag::Type => "type",
2078    }
2079}
2080
2081/// Computes the `pat.between(ty)` span for the "use `=`" suggestion on `let pat: ty`.
2082/// Returns `None` if `pat` and `ty` are in incompatible macro contexts (e.g. `pat` is a
2083/// metavariable from the call site while `ty` lives in the macro body), in which case no
2084/// suggestion is emitted.
2085pub(crate) fn eq_ctxt_suggestion_span(pat: Span, ty: Span) -> Option<Span> {
2086    if let Some(ty2) = ty.find_ancestor_in_same_ctxt(pat)
2087        && pat.hi() <= ty2.lo()
2088    {
2089        return Some(pat.between(ty2));
2090    }
2091    if let Some(pat2) = pat.find_ancestor_in_same_ctxt(ty)
2092        && pat2.hi() <= ty.lo()
2093    {
2094        return Some(pat2.between(ty));
2095    }
2096    None
2097}