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