Skip to main content

rustc_hir_analysis/hir_ty_lowering/
dyn_trait.rs

1use rustc_ast::TraitObjectSyntax;
2use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
3use rustc_errors::codes::*;
4use rustc_errors::{
5    Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, StashKey,
6    Suggestions, struct_span_code_err,
7};
8use rustc_hir::def::{DefKind, Res};
9use rustc_hir::def_id::DefId;
10use rustc_hir::{self as hir, HirId, LangItem};
11use rustc_lint_defs::builtin::{BARE_TRAIT_OBJECTS, UNUSED_ASSOCIATED_TYPE_BOUNDS};
12use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
13use rustc_middle::ty::{
14    self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
15    TypeVisitableExt, Upcast,
16};
17use rustc_span::edit_distance::find_best_match_for_name;
18use rustc_span::{ErrorGuaranteed, Span};
19use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
20use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
21use rustc_trait_selection::traits;
22use smallvec::{SmallVec, smallvec};
23use tracing::{debug, instrument};
24
25use super::HirTyLowerer;
26use crate::diagnostics::DynTraitAssocItemBindingMentionsSelf;
27use crate::hir_ty_lowering::{
28    GenericArgCountMismatch, ImpliedBoundsContext, OverlappingAsssocItemConstraints,
29    PredicateFilter, RegionInferReason,
30};
31
32impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
33    /// Lower a trait object type from the HIR to our internal notion of a type.
34    x;#[instrument(level = "debug", skip_all, ret)]
35    pub(super) fn lower_trait_object_ty(
36        &self,
37        span: Span,
38        hir_id: hir::HirId,
39        hir_bounds: &[hir::PolyTraitRef<'tcx>],
40        lifetime: &hir::Lifetime,
41        syntax: TraitObjectSyntax,
42    ) -> Ty<'tcx> {
43        let tcx = self.tcx();
44        let dummy_self = tcx.types.trait_object_dummy_self;
45
46        match syntax {
47            TraitObjectSyntax::Dyn => {}
48            TraitObjectSyntax::None => {
49                match self.prohibit_or_lint_bare_trait_object_ty(span, hir_id, hir_bounds) {
50                    // Don't continue with type analysis if the `dyn` keyword is missing.
51                    // It generates confusing errors, especially if the user meant to use
52                    // another keyword like `impl`.
53                    Some(guar) => return Ty::new_error(tcx, guar),
54                    None => {}
55                }
56            }
57        }
58
59        let mut user_written_bounds = Vec::new();
60        let mut potential_assoc_items = Vec::new();
61        for poly_trait_ref in hir_bounds.iter() {
62            // FIXME(mgca): We actually leak `trait_object_dummy_self` if the type of any assoc
63            //              const mentions `Self` (in "Self projections" which we intentionally
64            //              allow). That's because we query feed the instantiated type to `type_of`.
65            //              That's really bad, dummy self should never escape lowering! It leads us
66            //              to accept less code we'd like to support and can lead to ICEs later.
67            let result = self.lower_poly_trait_ref(
68                poly_trait_ref,
69                dummy_self,
70                &mut user_written_bounds,
71                PredicateFilter::SelfOnly,
72                OverlappingAsssocItemConstraints::Forbidden,
73            );
74            if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
75                potential_assoc_items.extend(invalid_args);
76            }
77        }
78
79        self.add_default_traits(
80            &mut user_written_bounds,
81            dummy_self,
82            &hir_bounds
83                .iter()
84                .map(|&trait_ref| hir::GenericBound::Trait(trait_ref))
85                .collect::<Vec<_>>(),
86            &[],
87            ImpliedBoundsContext::TraitObject,
88            span,
89        );
90
91        let (mut elaborated_trait_bounds, elaborated_projection_bounds) =
92            traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
93
94        // FIXME(sized-hierarchy): https://github.com/rust-lang/rust/pull/142712#issuecomment-3013231794
95        debug!(?user_written_bounds, ?elaborated_trait_bounds);
96        let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
97        // Don't strip out `MetaSized` when the user wrote it explicitly, only when it was
98        // elaborated
99        if user_written_bounds
100            .iter()
101            .all(|(clause, _)| clause.as_trait_clause().map(|p| p.def_id()) != Some(meta_sized_did))
102        {
103            elaborated_trait_bounds.retain(|(pred, _)| pred.def_id() != meta_sized_did);
104        }
105        debug!(?user_written_bounds, ?elaborated_trait_bounds);
106
107        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
108            .into_iter()
109            .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
110
111        // We don't support empty trait objects.
112        if regular_traits.is_empty() && auto_traits.is_empty() {
113            let guar =
114                self.report_trait_object_with_no_traits(span, user_written_bounds.iter().copied());
115            return Ty::new_error(tcx, guar);
116        }
117        // We don't support >1 principal
118        if regular_traits.len() > 1 {
119            let guar = self.report_trait_object_addition_traits(&regular_traits);
120            return Ty::new_error(tcx, guar);
121        }
122        // Don't create a dyn trait if we have errors in the principal.
123        if let Err(guar) = regular_traits.error_reported() {
124            return Ty::new_error(tcx, guar);
125        }
126
127        // Check that there are no gross dyn-compatibility violations;
128        // most importantly, that the supertraits don't contain `Self`,
129        // to avoid ICEs.
130        for (clause, span) in user_written_bounds {
131            if let Some(trait_pred) = clause.as_trait_clause() {
132                let violations = self.dyn_compatibility_violations(trait_pred.def_id());
133                if !violations.is_empty() {
134                    let reported = report_dyn_incompatibility(
135                        tcx,
136                        span,
137                        Some(hir_id),
138                        trait_pred.def_id(),
139                        &violations,
140                    )
141                    .emit();
142                    return Ty::new_error(tcx, reported);
143                }
144            }
145        }
146
147        // Map the projection bounds onto a key that makes it easy to remove redundant
148        // bounds that are constrained by supertraits of the principal trait.
149        //
150        // Also make sure we detect conflicting bounds from expanding trait aliases.
151        //
152        // FIXME(#150936): Since the elaborated projection bounds also include the user-written ones
153        //                 and we're separately rejecting duplicate+conflicting bindings for trait
154        //                 object types when lowering assoc item bindings, there are basic cases
155        //                 where we're emitting two distinct but very similar diagnostics.
156        let mut projection_bounds = FxIndexMap::default();
157        for (proj, proj_span) in elaborated_projection_bounds {
158            let item_def_id = proj.item_def_id();
159
160            let proj = proj.map_bound(|mut proj| {
161                let references_self = proj.term.walk().any(|arg| arg == dummy_self.into());
162                if references_self {
163                    let guar = self.dcx().emit_err(DynTraitAssocItemBindingMentionsSelf {
164                        span,
165                        kind: tcx.def_descr(item_def_id),
166                        binding: proj_span,
167                    });
168                    proj.term = replace_dummy_self_with_error(tcx, proj.term, guar);
169                }
170                proj
171            });
172
173            let key = (
174                item_def_id,
175                tcx.anonymize_bound_vars(
176                    proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
177                ),
178            );
179            if let Some((old_proj, old_proj_span)) =
180                projection_bounds.insert(key, (proj, proj_span))
181                && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
182            {
183                let kind = tcx.def_descr(item_def_id);
184                let name = tcx.item_name(item_def_id);
185                self.dcx()
186                    .struct_span_err(span, format!("conflicting {kind} bindings for `{name}`"))
187                    .with_span_label(
188                        old_proj_span,
189                        format!("`{name}` is specified to be `{}` here", old_proj.term()),
190                    )
191                    .with_span_label(
192                        proj_span,
193                        format!("`{name}` is specified to be `{}` here", proj.term()),
194                    )
195                    .emit();
196            }
197        }
198
199        let principal_trait = regular_traits.into_iter().next();
200
201        // A stable ordering of associated types & consts from the principal trait and all its
202        // supertraits. We use this to ensure that different substitutions of a trait don't
203        // result in `dyn Trait` types with different projections lists, which can be unsound:
204        // <https://github.com/rust-lang/rust/pull/136458>.
205        // We achieve a stable ordering by walking over the unsubstituted principal trait ref.
206        let mut ordered_associated_items = vec![];
207
208        if let Some((principal_trait, ref spans)) = principal_trait {
209            let principal_trait = principal_trait.map_bound(|trait_pred| {
210                assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
211                trait_pred.trait_ref
212            });
213
214            for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
215                tcx,
216                [ClauseWithSupertraitSpan::new(
217                    ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
218                    *spans.last().unwrap(),
219                )],
220            )
221            .filter_only_self()
222            {
223                let clause = clause.instantiate_supertrait(tcx, principal_trait);
224                debug!("observing object predicate `{clause:?}`");
225
226                let bound_predicate = clause.kind();
227                match bound_predicate.skip_binder() {
228                    ty::ClauseKind::Trait(pred) => {
229                        // FIXME(negative_bounds): Handle this correctly...
230                        let trait_ref =
231                            tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
232                        ordered_associated_items.extend(
233                            tcx.associated_items(pred.trait_ref.def_id)
234                                .in_definition_order()
235                                // Only associated types & type consts can possibly be
236                                // constrained in a trait object type via a binding.
237                                .filter(|item| item.is_type() || item.is_type_const())
238                                // Traits with RPITITs are simply not dyn compatible (for now).
239                                .filter(|item| !item.is_impl_trait_in_trait())
240                                .map(|item| (item.def_id, trait_ref)),
241                        );
242                    }
243                    ty::ClauseKind::Projection(pred) => {
244                        let pred = bound_predicate.rebind(pred);
245                        // A `Self` within the original bound will be instantiated with a
246                        // `trait_object_dummy_self`, so check for that.
247                        let references_self =
248                            pred.skip_binder().term.walk().any(|arg| arg == dummy_self.into());
249
250                        // If the projection output contains `Self`, force the user to
251                        // elaborate it explicitly to avoid a lot of complexity.
252                        //
253                        // The "classically useful" case is the following:
254                        // ```
255                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
256                        //         type MyOutput;
257                        //     }
258                        // ```
259                        //
260                        // Here, the user could theoretically write `dyn MyTrait<MyOutput = X>`,
261                        // but actually supporting that would "expand" to an infinitely-long type
262                        // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
263                        //
264                        // Instead, we force the user to write
265                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
266                        // the discussion in #56288 for alternatives.
267                        if !references_self {
268                            let key = (
269                                pred.item_def_id(),
270                                tcx.anonymize_bound_vars(
271                                    pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
272                                ),
273                            );
274                            if !projection_bounds.contains_key(&key) {
275                                projection_bounds.insert(key, (pred, supertrait_span));
276                            }
277                        }
278
279                        self.check_elaborated_projection_mentions_input_lifetimes(
280                            pred,
281                            *spans.first().unwrap(),
282                            supertrait_span,
283                        );
284                    }
285                    _ => (),
286                }
287            }
288        }
289
290        // Flag assoc item bindings that didn't really need to be specified.
291        for &(projection_bound, span) in projection_bounds.values() {
292            let def_id = projection_bound.item_def_id();
293            if tcx.generics_require_sized_self(def_id) {
294                // FIXME(mgca): Ideally we would generalize the name of this lint to sth. like
295                // `unused_associated_item_bindings` since this can now also trigger on *const*
296                // projections / assoc *const* bindings.
297                tcx.emit_node_span_lint(
298                    UNUSED_ASSOCIATED_TYPE_BOUNDS,
299                    hir_id,
300                    span,
301                    crate::diagnostics::UnusedAssociatedTypeBounds { span },
302                );
303            }
304        }
305
306        // The user has to constrain all associated types & consts via bindings unless the
307        // corresponding associated item has a `where Self: Sized` clause. This can be done
308        // in the `dyn Trait` directly, in the supertrait bounds or behind trait aliases.
309        //
310        // Collect all associated items that weren't specified and compute the list of
311        // projection bounds which we'll later turn into existential ones.
312        //
313        // We intentionally keep around projections whose associated item has a `Self: Sized`
314        // bound in order to be able to wfcheck the RHS, allow the RHS to constrain generic
315        // parameters and to imply bounds.
316        // See also <https://github.com/rust-lang/rust/pull/140684>.
317        let mut missing_assoc_items = FxIndexSet::default();
318        let projection_bounds: Vec<_> = ordered_associated_items
319            .into_iter()
320            .filter_map(|key @ (def_id, _)| {
321                if let Some(&assoc) = projection_bounds.get(&key) {
322                    return Some(assoc);
323                }
324                if !tcx.generics_require_sized_self(def_id) {
325                    missing_assoc_items.insert(key);
326                }
327                None
328            })
329            .collect();
330
331        // If there are any associated items whose value wasn't provided, bail out with an error.
332        if let Err(guar) = self.check_for_required_assoc_items(
333            principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
334            missing_assoc_items,
335            potential_assoc_items,
336            hir_bounds,
337        ) {
338            return Ty::new_error(tcx, guar);
339        }
340
341        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
342        // `dyn Trait + Send`.
343        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
344        // the bounds
345        let mut duplicates = FxHashSet::default();
346        auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id()));
347
348        debug!(?principal_trait);
349        debug!(?auto_traits);
350
351        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
352        let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| {
353            trait_pred.map_bound(|trait_pred| {
354                let trait_ref = trait_pred.trait_ref;
355                assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
356                assert_eq!(trait_ref.self_ty(), dummy_self);
357
358                let span = *spans.first().unwrap();
359
360                // Verify that `dummy_self` did not leak inside generic parameter defaults. This
361                // could not be done at path creation, since we need to see through trait aliases.
362                let mut missing_generic_params = Vec::new();
363                let generics = tcx.generics_of(trait_ref.def_id);
364                let args: Vec<_> = trait_ref
365                    .args
366                    .iter()
367                    .enumerate()
368                    // Skip `Self`
369                    .skip(1)
370                    .map(|(index, arg)| {
371                        if arg.walk().any(|arg| arg == dummy_self.into()) {
372                            let param = &generics.own_params[index];
373                            missing_generic_params.push((param.name, param.kind.clone()));
374                            param.to_error(tcx)
375                        } else {
376                            arg
377                        }
378                    })
379                    .collect();
380
381                let empty_generic_args = hir_bounds.iter().any(|hir_bound| {
382                    hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
383                        && hir_bound.span.contains(span)
384                });
385                self.report_missing_generic_params(
386                    missing_generic_params,
387                    trait_ref.def_id,
388                    span,
389                    empty_generic_args,
390                );
391
392                ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(
393                    tcx,
394                    trait_ref.def_id,
395                    args,
396                ))
397            })
398        });
399
400        let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
401            bound.map_bound(|mut b| {
402                assert_eq!(b.projection_term.self_ty(), dummy_self);
403
404                // Like for trait refs, verify that `dummy_self` did not leak inside default type
405                // parameters.
406                let references_self = b.projection_term.args.iter().skip(1).any(|arg| {
407                    if arg.walk().any(|arg| arg == dummy_self.into()) {
408                        return true;
409                    }
410                    false
411                });
412                if references_self {
413                    let guar = tcx
414                        .dcx()
415                        .span_delayed_bug(span, "trait object projection bounds reference `Self`");
416                    b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
417                }
418
419                ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
420                    tcx, b,
421                ))
422            })
423        });
424
425        let mut auto_trait_predicates: Vec<_> = auto_traits
426            .into_iter()
427            .map(|(trait_pred, _)| {
428                assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
429                assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
430
431                ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
432            })
433            .collect();
434        auto_trait_predicates.dedup();
435
436        // N.b. principal, projections, auto traits
437        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
438        let mut predicates = principal_trait_ref
439            .into_iter()
440            .chain(existential_projections)
441            .chain(auto_trait_predicates)
442            .collect::<SmallVec<[_; 8]>>();
443        predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
444        let predicates = tcx.mk_poly_existential_predicates(&predicates);
445
446        let region_bound = self.lower_trait_object_lifetime(lifetime, predicates, span);
447
448        Ty::new_dynamic(tcx, predicates, region_bound)
449    }
450
451    fn lower_trait_object_lifetime(
452        &self,
453        lifetime: &hir::Lifetime,
454        predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
455        span: Span,
456    ) -> ty::Region<'tcx> {
457        // Curiously, we also use the *object region bound* for `Infer` (`'_`)
458        // while we obviously don't use the *object lifetime default* for it...
459        if let hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer =
460            lifetime.kind
461            && let Some(region) = self.compute_object_lifetime_bound(span, predicates)
462        {
463            return region;
464        }
465
466        let reason = if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind {
467            RegionInferReason::ObjectLifetimeDefault(span.shrink_to_hi())
468        } else {
469            RegionInferReason::ExplicitObjectLifetime
470        };
471
472        self.lower_lifetime(lifetime, reason)
473    }
474
475    /// Check that elaborating the principal of a trait ref doesn't lead to projections
476    /// that are unconstrained. This can happen because an otherwise unconstrained
477    /// *type variable* can be substituted with a type that has late-bound regions. See
478    /// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
479    fn check_elaborated_projection_mentions_input_lifetimes(
480        &self,
481        pred: ty::PolyProjectionPredicate<'tcx>,
482        span: Span,
483        supertrait_span: Span,
484    ) {
485        let tcx = self.tcx();
486
487        // Find any late-bound regions declared in `ty` that are not
488        // declared in the trait-ref or assoc_item. These are not well-formed.
489        //
490        // Example:
491        //
492        //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
493        //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
494        let late_bound_in_projection_term =
495            tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
496        let late_bound_in_term =
497            tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
498        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:498",
                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(498u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                        ::tracing_core::field::FieldSet::new(&["late_bound_in_projection_term"],
                            ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&late_bound_in_projection_term)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(?late_bound_in_projection_term);
499        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:499",
                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(499u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                        ::tracing_core::field::FieldSet::new(&["late_bound_in_term"],
                            ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&late_bound_in_term)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(?late_bound_in_term);
500
501        // FIXME: point at the type params that don't have appropriate lifetimes:
502        // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
503        //                         ----  ----     ^^^^^^^
504        // NOTE(mgca): This error should be impossible to trigger with assoc const bindings.
505        self.validate_late_bound_regions(
506            late_bound_in_projection_term,
507            late_bound_in_term,
508            |br_name| {
509                let item_name = tcx.item_name(pred.item_def_id());
510                {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("binding for associated type `{0}` references {1}, which does not appear in the trait input types",
                            item_name, br_name))
                })).with_code(E0582)
}struct_span_code_err!(
511                    self.dcx(),
512                    span,
513                    E0582,
514                    "binding for associated type `{}` references {}, \
515                             which does not appear in the trait input types",
516                    item_name,
517                    br_name
518                )
519                .with_span_label(supertrait_span, "due to this supertrait")
520            },
521        );
522    }
523
524    /// Given the bounds on an object, determines what single region bound (if any) we can
525    /// use to summarize this type.
526    ///
527    /// The basic idea is that we will use the bound the user
528    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
529    /// for region bounds. It may be that we can derive no bound at all, in which case
530    /// we return `None`.
531    x;#[instrument(level = "debug", skip(self, span), ret)]
532    fn compute_object_lifetime_bound(
533        &self,
534        span: Span,
535        existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
536    ) -> Option<ty::Region<'tcx>> // if None, use the default
537    {
538        let tcx = self.tcx();
539
540        // No explicit region bound specified. Therefore, examine trait
541        // bounds and see if we can derive region bounds from those.
542        let derived_region_bounds = traits::wf::object_region_bounds(tcx, existential_predicates);
543
544        // If there are no derived region bounds, then report back that we
545        // can find no region bound. The caller will use the default.
546        if derived_region_bounds.is_empty() {
547            return None;
548        }
549
550        // If any of the derived region bounds are 'static, that is always
551        // the best choice.
552        if derived_region_bounds.iter().any(|r| r.is_static()) {
553            return Some(tcx.lifetimes.re_static);
554        }
555
556        // Determine whether there is exactly one unique region in the set
557        // of derived region bounds. If so, use that. Otherwise, report an
558        // error.
559        let r = derived_region_bounds[0];
560        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
561            self.dcx().emit_err(crate::diagnostics::AmbiguousLifetimeBound { span });
562        }
563        Some(r)
564    }
565
566    /// Prohibit or lint against *bare* trait object types depending on the edition.
567    ///
568    /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
569    /// In edition 2021 and onward we emit a hard error for them.
570    fn prohibit_or_lint_bare_trait_object_ty(
571        &self,
572        span: Span,
573        hir_id: hir::HirId,
574        hir_bounds: &[hir::PolyTraitRef<'tcx>],
575    ) -> Option<ErrorGuaranteed> {
576        struct TraitObjectWithoutDyn<'a, 'tcx> {
577            span: Span,
578            hir_id: HirId,
579            sugg: Vec<(Span, String)>,
580            this: &'a dyn HirTyLowerer<'tcx>,
581        }
582
583        impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for TraitObjectWithoutDyn<'b, 'tcx> {
584            fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
585                let Self { span, hir_id, sugg, this } = self;
586                let mut lint =
587                    Diag::new(dcx, level, "trait objects without an explicit `dyn` are deprecated");
588                if span.can_be_used_for_suggestions() {
589                    lint.multipart_suggestion(
590                        "if this is a dyn-compatible trait, use `dyn`",
591                        sugg,
592                        Applicability::MachineApplicable,
593                    );
594                }
595                this.maybe_suggest_blanket_trait_impl(span, hir_id, &mut lint);
596                lint
597            }
598        }
599
600        let tcx = self.tcx();
601        let [poly_trait_ref, ..] = hir_bounds else { return None };
602
603        let in_path = match tcx.parent_hir_node(hir_id) {
604            hir::Node::Ty(hir::Ty {
605                kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)),
606                ..
607            })
608            | hir::Node::Expr(hir::Expr {
609                kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)),
610                ..
611            })
612            | hir::Node::PatExpr(hir::PatExpr {
613                kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)),
614                ..
615            }) if qself.hir_id == hir_id => true,
616            _ => false,
617        };
618        let needs_bracket = in_path
619            && !tcx
620                .sess
621                .source_map()
622                .span_to_prev_source(span)
623                .ok()
624                .is_some_and(|s| s.trim_end().ends_with('<'));
625
626        let is_global = poly_trait_ref.trait_ref.path.is_global();
627
628        let mut sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}dyn {1}",
                                    if needs_bracket { "<" } else { "" },
                                    if is_global { "(" } else { "" }))
                        }))]))vec![(
629            span.shrink_to_lo(),
630            format!(
631                "{}dyn {}",
632                if needs_bracket { "<" } else { "" },
633                if is_global { "(" } else { "" },
634            ),
635        )];
636
637        if is_global || needs_bracket {
638            sugg.push((
639                span.shrink_to_hi(),
640                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}",
                if is_global { ")" } else { "" },
                if needs_bracket { ">" } else { "" }))
    })format!(
641                    "{}{}",
642                    if is_global { ")" } else { "" },
643                    if needs_bracket { ">" } else { "" },
644                ),
645            ));
646        }
647
648        if span.edition().at_least_rust_2021() {
649            let mut diag = {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}",
                            "expected a type, found a trait"))
                })).with_code(E0782)
}rustc_errors::struct_span_code_err!(
650                self.dcx(),
651                span,
652                E0782,
653                "{}",
654                "expected a type, found a trait"
655            );
656            if span.can_be_used_for_suggestions()
657                && poly_trait_ref.trait_ref.trait_def_id().is_some()
658                && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag)
659                && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag)
660            {
661                self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag);
662            }
663            // Check if the impl trait that we are considering is an impl of a local trait.
664            self.maybe_suggest_blanket_trait_impl(span, hir_id, &mut diag);
665            self.maybe_suggest_assoc_ty_bound(hir_id, &mut diag);
666            self.maybe_suggest_typoed_method(
667                hir_id,
668                poly_trait_ref.trait_ref.trait_def_id(),
669                &mut diag,
670            );
671            // In case there is an associated type with the same name
672            // Add the suggestion to this error
673            if let Some(mut sugg) =
674                self.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion)
675                && let Suggestions::Enabled(ref mut s1) = diag.suggestions
676                && let Suggestions::Enabled(ref mut s2) = sugg.suggestions
677            {
678                s1.append(s2);
679                sugg.cancel();
680            }
681            Some(diag.emit())
682        } else {
683            tcx.emit_node_span_lint(
684                BARE_TRAIT_OBJECTS,
685                hir_id,
686                span,
687                TraitObjectWithoutDyn { span, hir_id, sugg, this: self },
688            );
689            None
690        }
691    }
692
693    /// For a struct or enum with an invalid bare trait object field, suggest turning
694    /// it into a generic type bound.
695    fn maybe_suggest_add_generic_impl_trait(
696        &self,
697        span: Span,
698        hir_id: hir::HirId,
699        diag: &mut Diag<'_>,
700    ) -> bool {
701        let tcx = self.tcx();
702
703        let parent_hir_id = tcx.parent_hir_id(hir_id);
704        let parent_item = tcx.hir_get_parent_item(hir_id).def_id;
705
706        let generics = match tcx.hir_node_by_def_id(parent_item) {
707            hir::Node::Item(hir::Item {
708                kind: hir::ItemKind::Struct(_, generics, variant),
709                ..
710            }) => {
711                if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
712                    return false;
713                }
714                generics
715            }
716            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => {
717                if !def
718                    .variants
719                    .iter()
720                    .flat_map(|variant| variant.data.fields().iter())
721                    .any(|field| field.hir_id == parent_hir_id)
722                {
723                    return false;
724                }
725                generics
726            }
727            _ => return false,
728        };
729
730        let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(span) else {
731            return false;
732        };
733
734        let param = "TUV"
735            .chars()
736            .map(|c| c.to_string())
737            .chain((0..).map(|i| ::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("P{0}", i)) })format!("P{i}")))
738            .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
739            .expect("we definitely can find at least one param name to generate");
740        let mut sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span, param.to_string())]))vec![(span, param.to_string())];
741        if let Some(insertion_span) = generics.span_for_param_suggestion() {
742            sugg.push((insertion_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {1}: {0}", rendered_ty, param))
    })format!(", {param}: {}", rendered_ty)));
743        } else {
744            sugg.push((generics.where_clause_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{1}: {0}>", rendered_ty, param))
    })format!("<{param}: {}>", rendered_ty)));
745        }
746        diag.multipart_suggestion(
747            "you might be missing a type parameter",
748            sugg,
749            Applicability::MachineApplicable,
750        );
751        true
752    }
753
754    /// Make sure that we are in the condition to suggest the blanket implementation.
755    fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
756        &self,
757        span: Span,
758        hir_id: hir::HirId,
759        diag: &mut Diag<'_, G>,
760    ) {
761        let tcx = self.tcx();
762        let parent_id = tcx.hir_get_parent_item(hir_id).def_id;
763        if let hir::Node::Item(hir::Item {
764            kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
765            ..
766        }) = tcx.hir_node_by_def_id(parent_id)
767            && hir_id == impl_self_ty.hir_id
768        {
769            let Some(of_trait) = of_trait else {
770                diag.span_suggestion_verbose(
771                    impl_self_ty.span.shrink_to_hi(),
772                    "you might have intended to implement this trait for a given type",
773                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for /* Type */"))
    })format!(" for /* Type */"),
774                    Applicability::HasPlaceholders,
775                );
776                return;
777            };
778            if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
779                return;
780            }
781            let of_trait_span = of_trait.trait_ref.path.span;
782            // make sure that we are not calling unwrap to abort during the compilation
783            let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else {
784                return;
785            };
786
787            let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(span) else {
788                return;
789            };
790            let sugg = self.add_generic_param_suggestion(generics, span, &impl_trait_name);
791            diag.multipart_suggestion(
792                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("alternatively use a blanket implementation to implement `{0}` for all types that also implement `{1}`",
                of_trait_name, impl_trait_name))
    })format!(
793                    "alternatively use a blanket implementation to implement `{of_trait_name}` for \
794                     all types that also implement `{impl_trait_name}`"
795                ),
796                sugg,
797                Applicability::MaybeIncorrect,
798            );
799        }
800    }
801
802    /// Try our best to approximate when adding `dyn` would be helpful for a bare
803    /// trait object.
804    ///
805    /// Right now, this is if the type is either directly nested in another ty,
806    /// or if it's in the tail field within a struct. This approximates what the
807    /// user would've gotten on edition 2015, except for the case where we have
808    /// an *obvious* knock-on `Sized` error.
809    fn maybe_suggest_dyn_trait(
810        &self,
811        hir_id: hir::HirId,
812        span: Span,
813        sugg: Vec<(Span, String)>,
814        diag: &mut Diag<'_>,
815    ) -> bool {
816        let tcx = self.tcx();
817        if span.in_derive_expansion() {
818            return false;
819        }
820
821        // Look at the direct HIR parent, since we care about the relationship between
822        // the type and the thing that directly encloses it.
823        match tcx.parent_hir_node(hir_id) {
824            // These are all generally ok. Namely, when a trait object is nested
825            // into another expression or ty, it's either very certain that they
826            // missed the ty (e.g. `&Trait`) or it's not really possible to tell
827            // what their intention is, so let's not give confusing suggestions and
828            // just mention `dyn`. The user can make up their mind what to do here.
829            hir::Node::Ty(_)
830            | hir::Node::Expr(_)
831            | hir::Node::PatExpr(_)
832            | hir::Node::PathSegment(_)
833            | hir::Node::AssocItemConstraint(_)
834            | hir::Node::TraitRef(_)
835            | hir::Node::Item(_)
836            | hir::Node::WherePredicate(_) => {}
837
838            hir::Node::Field(field) => {
839                // Enums can't have unsized fields, fields can only have an unsized tail field.
840                if let hir::Node::Item(hir::Item {
841                    kind: hir::ItemKind::Struct(_, _, variant), ..
842                }) = tcx.parent_hir_node(field.hir_id)
843                    && variant
844                        .fields()
845                        .last()
846                        .is_some_and(|tail_field| tail_field.hir_id == field.hir_id)
847                {
848                    // Ok
849                } else {
850                    return false;
851                }
852            }
853            _ => return false,
854        }
855
856        // FIXME: Only emit this suggestion if the trait is dyn-compatible.
857        diag.multipart_suggestion(
858            "you can add the `dyn` keyword if you want a trait object",
859            sugg,
860            Applicability::MachineApplicable,
861        );
862        true
863    }
864
865    fn add_generic_param_suggestion(
866        &self,
867        generics: &hir::Generics<'_>,
868        self_ty_span: Span,
869        impl_trait_name: &str,
870    ) -> Vec<(Span, String)> {
871        // check if the trait has generics, to make a correct suggestion
872        let param_name = generics.params.next_type_param_name(None);
873
874        let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
875            (span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}: {1}", param_name,
                impl_trait_name))
    })format!(", {param_name}: {impl_trait_name}"))
876        } else {
877            (generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}: {1}>", param_name,
                impl_trait_name))
    })format!("<{param_name}: {impl_trait_name}>"))
878        };
879        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(self_ty_span, param_name), add_generic_sugg]))vec![(self_ty_span, param_name), add_generic_sugg]
880    }
881
882    /// Make sure that we are in the condition to suggest `impl Trait`.
883    fn maybe_suggest_impl_trait(
884        &self,
885        span: Span,
886        hir_id: hir::HirId,
887        hir_bounds: &[hir::PolyTraitRef<'tcx>],
888        diag: &mut Diag<'_>,
889    ) -> bool {
890        let tcx = self.tcx();
891        let parent_id = tcx.hir_get_parent_item(hir_id).def_id;
892        // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
893        //        and suggest `Trait0<Ty = impl Trait1>`.
894        // Functions are found in three different contexts.
895        // 1. Independent functions
896        // 2. Functions inside trait blocks
897        // 3. Functions inside impl blocks
898        let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
899            hir::Node::Item(hir::Item {
900                kind: hir::ItemKind::Fn { sig, generics, .. }, ..
901            }) => (sig, generics),
902            hir::Node::TraitItem(hir::TraitItem {
903                kind: hir::TraitItemKind::Fn(sig, _),
904                generics,
905                ..
906            }) => (sig, generics),
907            hir::Node::ImplItem(hir::ImplItem {
908                kind: hir::ImplItemKind::Fn(sig, _),
909                generics,
910                ..
911            }) => (sig, generics),
912            _ => return false,
913        };
914        let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(span) else {
915            return false;
916        };
917        let impl_sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), "impl ".to_string())]))vec![(span.shrink_to_lo(), "impl ".to_string())];
918        // Check if trait object is safe for suggesting dynamic dispatch.
919        let is_dyn_compatible = hir_bounds.iter().all(|bound| match bound.trait_ref.path.res {
920            Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id),
921            _ => false,
922        });
923
924        let borrowed = #[allow(non_exhaustive_omitted_patterns)] match tcx.parent_hir_node(hir_id) {
    hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. }) => true,
    _ => false,
}matches!(
925            tcx.parent_hir_node(hir_id),
926            hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. })
927        );
928
929        // Suggestions for function return type.
930        if let hir::FnRetTy::Return(ty) = sig.decl.output
931            && ty.peel_refs().hir_id == hir_id
932        {
933            let pre = if !is_dyn_compatible {
934                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is dyn-incompatible, ",
                trait_name))
    })format!("`{trait_name}` is dyn-incompatible, ")
935            } else {
936                String::new()
937            };
938            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}use `impl {1}` to return an opaque type, as long as you return a single underlying type",
                pre, trait_name))
    })format!(
939                "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \
940                 single underlying type",
941            );
942
943            diag.multipart_suggestion(msg, impl_sugg, Applicability::MachineApplicable);
944
945            // Suggest `Box<dyn Trait>` for return type
946            if is_dyn_compatible {
947                // If the return type is `&Trait`, we don't want
948                // the ampersand to be displayed in the `Box<dyn Trait>`
949                // suggestion.
950                let suggestion = if borrowed {
951                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ty.span,
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("Box<dyn {0}>",
                                    trait_name))
                        }))]))vec![(ty.span, format!("Box<dyn {trait_name}>"))]
952                } else {
953                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
                (ty.span.shrink_to_hi(), ">".to_string())]))vec![
954                        (ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
955                        (ty.span.shrink_to_hi(), ">".to_string()),
956                    ]
957                };
958
959                diag.multipart_suggestion(
960                    "alternatively, you can return an owned trait object",
961                    suggestion,
962                    Applicability::MachineApplicable,
963                );
964            }
965            return true;
966        }
967
968        // Suggestions for function parameters.
969        for ty in sig.decl.inputs {
970            if ty.peel_refs().hir_id != hir_id {
971                continue;
972            }
973            let sugg = self.add_generic_param_suggestion(generics, span, &trait_name);
974            diag.multipart_suggestion(
975                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use a new generic type parameter, constrained by `{0}`",
                trait_name))
    })format!("use a new generic type parameter, constrained by `{trait_name}`"),
976                sugg,
977                Applicability::MachineApplicable,
978            );
979            diag.multipart_suggestion(
980                "you can also use an opaque type, but users won't be able to specify the type \
981                 parameter when calling the `fn`, having to rely exclusively on type inference",
982                impl_sugg,
983                Applicability::MachineApplicable,
984            );
985            if !is_dyn_compatible {
986                diag.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is dyn-incompatible, otherwise a trait object could be used",
                trait_name))
    })format!(
987                    "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used"
988                ));
989            } else {
990                // No ampersand in suggestion if it's borrowed already
991                let (dyn_str, paren_dyn_str) =
992                    if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };
993
994                let sugg = if let [_, _, ..] = hir_bounds {
995                    // There is more than one trait bound, we need surrounding parentheses.
996                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), paren_dyn_str.to_string()),
                (span.shrink_to_hi(), ")".to_string())]))vec![
997                        (span.shrink_to_lo(), paren_dyn_str.to_string()),
998                        (span.shrink_to_hi(), ")".to_string()),
999                    ]
1000                } else {
1001                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_lo(), dyn_str.to_string())]))vec![(span.shrink_to_lo(), dyn_str.to_string())]
1002                };
1003                diag.multipart_suggestion(
1004                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("alternatively, use a trait object to accept any type that implements `{0}`, accessing its methods at runtime using dynamic dispatch",
                trait_name))
    })format!(
1005                        "alternatively, use a trait object to accept any type that implements \
1006                         `{trait_name}`, accessing its methods at runtime using dynamic dispatch",
1007                    ),
1008                    sugg,
1009                    Applicability::MachineApplicable,
1010                );
1011            }
1012            return true;
1013        }
1014        false
1015    }
1016
1017    fn maybe_suggest_assoc_ty_bound(&self, hir_id: hir::HirId, diag: &mut Diag<'_>) {
1018        let mut parents = self.tcx().hir_parent_iter(hir_id);
1019
1020        if let Some((c_hir_id, hir::Node::AssocItemConstraint(constraint))) = parents.next()
1021            && let Some(obj_ty) = constraint.ty()
1022            && let Some((_, hir::Node::TraitRef(trait_ref))) = parents.next()
1023        {
1024            if let Some((_, hir::Node::Ty(ty))) = parents.next()
1025                && let hir::TyKind::TraitObject(..) = ty.kind
1026            {
1027                // Assoc ty bounds aren't permitted inside trait object types.
1028                return;
1029            }
1030
1031            if trait_ref
1032                .path
1033                .segments
1034                .iter()
1035                .find_map(|seg| {
1036                    seg.args.filter(|args| args.constraints.iter().any(|c| c.hir_id == c_hir_id))
1037                })
1038                .is_none_or(|args| args.parenthesized != hir::GenericArgsParentheses::No)
1039            {
1040                // Only consider angle-bracketed args (where we have a `=` to replace with `:`).
1041                return;
1042            }
1043
1044            let lo = if constraint.gen_args.span_ext.is_dummy() {
1045                constraint.ident.span
1046            } else {
1047                constraint.gen_args.span_ext
1048            };
1049            let hi = obj_ty.span;
1050
1051            if !lo.eq_ctxt(hi) {
1052                return;
1053            }
1054
1055            diag.span_suggestion_verbose(
1056                lo.between(hi),
1057                "you might have meant to write a bound here",
1058                ": ",
1059                Applicability::MaybeIncorrect,
1060            );
1061        }
1062    }
1063
1064    fn maybe_suggest_typoed_method(
1065        &self,
1066        hir_id: hir::HirId,
1067        trait_def_id: Option<DefId>,
1068        diag: &mut Diag<'_>,
1069    ) {
1070        let tcx = self.tcx();
1071        let Some(trait_def_id) = trait_def_id else {
1072            return;
1073        };
1074        let hir::Node::Expr(hir::Expr {
1075            kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
1076            ..
1077        }) = tcx.parent_hir_node(hir_id)
1078        else {
1079            return;
1080        };
1081        if path_ty.hir_id != hir_id {
1082            return;
1083        }
1084        let names: Vec<_> = tcx
1085            .associated_items(trait_def_id)
1086            .in_definition_order()
1087            .filter(|assoc| assoc.namespace() == hir::def::Namespace::ValueNS)
1088            .map(|cand| cand.name())
1089            .collect();
1090        if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
1091            diag.span_suggestion_verbose(
1092                segment.ident.span,
1093                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you may have misspelled this associated item, causing `{0}` to be interpreted as a type rather than a trait",
                tcx.item_name(trait_def_id)))
    })format!(
1094                    "you may have misspelled this associated item, causing `{}` \
1095                    to be interpreted as a type rather than a trait",
1096                    tcx.item_name(trait_def_id),
1097                ),
1098                typo,
1099                Applicability::MaybeIncorrect,
1100            );
1101        }
1102    }
1103}
1104
1105fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
1106    tcx: TyCtxt<'tcx>,
1107    t: T,
1108    guar: ErrorGuaranteed,
1109) -> T {
1110    t.fold_with(&mut BottomUpFolder {
1111        tcx,
1112        ty_op: |ty| {
1113            if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty }
1114        },
1115        lt_op: |lt| lt,
1116        ct_op: |ct| ct,
1117    })
1118}