Skip to main content

rustc_hir_analysis/hir_ty_lowering/
dyn_trait.rs

1use rustc_ast::TraitObjectSyntax;
2use rustc_attr_ir::lang_items::LangItem;
3use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
4use rustc_errors::codes::*;
5use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, struct_span_code_err};
6use rustc_hir::def::{DefKind, Res};
7use rustc_hir::def_id::DefId;
8use rustc_hir::{self as hir, HirId};
9use rustc_lint_defs::builtin::{BARE_TRAIT_OBJECTS, UNUSED_ASSOCIATED_TYPE_BOUNDS};
10use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
11use rustc_middle::ty::{
12    self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
13    TypeVisitableExt, Upcast,
14};
15use rustc_span::edit_distance::find_best_match_for_name;
16use rustc_span::{ErrorGuaranteed, Span};
17use rustc_trait_selection::diagnostics::AssocTypeWithSameName;
18use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
19use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
20use rustc_trait_selection::traits;
21use smallvec::{SmallVec, smallvec};
22use tracing::{debug, instrument};
23
24use super::HirTyLowerer;
25use crate::diagnostics::DynTraitAssocItemBindingMentionsSelf;
26use crate::hir_ty_lowering::{
27    GenericArgCountMismatch, ImpliedBoundsContext, OverlappingAsssocItemConstraints,
28    PredicateFilter, RegionInferReason,
29};
30
31impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
32    /// Lower a trait object type from the HIR to our internal notion of a type.
33    {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("lower_trait_object_ty",
                                "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                ::tracing_core::__macro_support::Option::Some(33u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                ::tracing_core::field::FieldSet::new(&[],
                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{ meta.fields().value_set_all(&[]) })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return: Ty<'tcx> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let tcx = self.tcx();
                        let dummy_self = tcx.types.trait_object_dummy_self;
                        match syntax {
                            TraitObjectSyntax::Dyn => {}
                            TraitObjectSyntax::None => {
                                match self.prohibit_or_lint_bare_trait_object_ty(span,
                                        hir_id, hir_bounds) {
                                    Some(guar) => return Ty::new_error(tcx, guar),
                                    None => {}
                                }
                            }
                        }
                        let mut user_written_bounds = Vec::new();
                        let mut potential_assoc_items = Vec::new();
                        for poly_trait_ref in hir_bounds.iter() {
                            let result =
                                self.lower_poly_trait_ref(poly_trait_ref, dummy_self,
                                    &mut user_written_bounds, PredicateFilter::SelfOnly,
                                    OverlappingAsssocItemConstraints::Forbidden);
                            if let Err(GenericArgCountMismatch { invalid_args, .. }) =
                                    result.correct {
                                potential_assoc_items.extend(invalid_args);
                            }
                        }
                        self.add_default_traits(&mut user_written_bounds,
                            dummy_self,
                            &hir_bounds.iter().map(|&trait_ref|
                                            hir::GenericBound::Trait(trait_ref)).collect::<Vec<_>>(),
                            ImpliedBoundsContext::AssociatedTypeOrImplTrait, span);
                        let (mut elaborated_trait_bounds,
                                elaborated_projection_bounds) =
                            traits::expand_trait_aliases(tcx,
                                user_written_bounds.iter().copied());
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:93",
                                                "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                                ::tracing_core::__macro_support::Option::Some(93u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("user_written_bounds")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("user_written_bounds");
                                                                    NAME.as_str()
                                                                },
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("elaborated_trait_bounds")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("elaborated_trait_bounds");
                                                                    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(&user_written_bounds)
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&elaborated_trait_bounds)
                                                                    as &dyn ::tracing::field::Value))])
                                    });
                            } else { ; }
                        };
                        let meta_sized_did =
                            tcx.require_lang_item(LangItem::MetaSized, span);
                        if user_written_bounds.iter().all(|(clause, _)|
                                    clause.as_trait_clause().map(|p| p.def_id()) !=
                                        Some(meta_sized_did)) {
                            elaborated_trait_bounds.retain(|(pred, _)|
                                    pred.def_id() != meta_sized_did);
                        }
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:103",
                                                "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                                ::tracing_core::__macro_support::Option::Some(103u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("user_written_bounds")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("user_written_bounds");
                                                                    NAME.as_str()
                                                                },
                                                                {
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("elaborated_trait_bounds")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("elaborated_trait_bounds");
                                                                    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(&user_written_bounds)
                                                                    as &dyn ::tracing::field::Value)),
                                                        (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&elaborated_trait_bounds)
                                                                    as &dyn ::tracing::field::Value))])
                                    });
                            } else { ; }
                        };
                        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) =
                            elaborated_trait_bounds.into_iter().partition(|(trait_ref,
                                        _)| !tcx.trait_is_auto(trait_ref.def_id()));
                        if regular_traits.is_empty() && auto_traits.is_empty() {
                            let guar =
                                self.report_trait_object_with_no_traits(span,
                                    user_written_bounds.iter().copied());
                            return Ty::new_error(tcx, guar);
                        }
                        if regular_traits.len() > 1 {
                            let guar =
                                self.report_trait_object_addition_traits(&regular_traits);
                            return Ty::new_error(tcx, guar);
                        }
                        if let Err(guar) = regular_traits.error_reported() {
                            return Ty::new_error(tcx, guar);
                        }
                        for (clause, span) in user_written_bounds {
                            if let Some(trait_pred) = clause.as_trait_clause() {
                                let violations =
                                    self.dyn_compatibility_violations(trait_pred.def_id());
                                if !violations.is_empty() {
                                    let reported =
                                        report_dyn_incompatibility(tcx, span, Some(hir_id),
                                                trait_pred.def_id(), &violations).emit_err();
                                    return Ty::new_error(tcx, reported);
                                }
                            }
                        }
                        let mut projection_bounds = FxIndexMap::default();
                        for (proj, proj_span) in elaborated_projection_bounds {
                            let item_def_id = proj.item_def_id();
                            let proj =
                                proj.map_bound(|mut proj|
                                        {
                                            let references_self =
                                                proj.term.walk().any(|arg| arg == dummy_self.into());
                                            if references_self {
                                                let guar =
                                                    self.dcx().emit_err(DynTraitAssocItemBindingMentionsSelf {
                                                            span,
                                                            kind: tcx.def_descr(item_def_id),
                                                            binding: proj_span,
                                                        });
                                                proj.term =
                                                    replace_dummy_self_with_error(tcx, proj.term, guar);
                                            }
                                            proj
                                        });
                            let key =
                                (item_def_id,
                                    tcx.anonymize_bound_vars(proj.map_bound(|proj|
                                                proj.projection_term.trait_ref(tcx))));
                            if let Some((old_proj, old_proj_span)) =
                                        projection_bounds.insert(key, (proj, proj_span)) &&
                                    tcx.anonymize_bound_vars(proj) !=
                                        tcx.anonymize_bound_vars(old_proj) {
                                let kind = tcx.def_descr(item_def_id);
                                let name = tcx.item_name(item_def_id);
                                self.dcx().struct_span_err(span,
                                                ::alloc::__export::must_use({
                                                        ::alloc::fmt::format(format_args!("conflicting {0} bindings for `{1}`",
                                                                kind, name))
                                                    })).with_span_label(old_proj_span,
                                            ::alloc::__export::must_use({
                                                    ::alloc::fmt::format(format_args!("`{1}` is specified to be `{0}` here",
                                                            old_proj.term(), name))
                                                })).with_span_label(proj_span,
                                        ::alloc::__export::must_use({
                                                ::alloc::fmt::format(format_args!("`{1}` is specified to be `{0}` here",
                                                        proj.term(), name))
                                            })).emit();
                            }
                        }
                        let principal_trait = regular_traits.into_iter().next();
                        let mut ordered_associated_items = ::alloc::vec::Vec::new();
                        if let Some((principal_trait, ref spans)) = principal_trait
                            {
                            let principal_trait =
                                principal_trait.map_bound(|trait_pred|
                                        {
                                            {
                                                match (&trait_pred.polarity, &ty::ClausePolarity::Positive)
                                                    {
                                                    (left_val, right_val) => {
                                                        if !(*left_val == *right_val) {
                                                            let kind = ::core::panicking::AssertKind::Eq;
                                                            ::core::panicking::assert_failed(kind, &*left_val,
                                                                &*right_val, ::core::option::Option::None);
                                                        }
                                                    }
                                                }
                                            };
                                            trait_pred.trait_ref
                                        });
                            for ClauseWithSupertraitSpan { clause, supertrait_span } in
                                traits::elaborate(tcx,
                                        [ClauseWithSupertraitSpan::new(ty::TraitRef::identity(tcx,
                                                            principal_trait.def_id()).upcast(tcx),
                                                    *spans.last().unwrap())]).filter_only_self() {
                                let clause =
                                    clause.instantiate_supertrait(tcx, principal_trait);
                                {
                                    use ::tracing::__macro_support::Callsite as _;
                                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                        {
                                            static META: ::tracing::Metadata<'static> =
                                                {
                                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:222",
                                                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                                        ::tracing::Level::DEBUG,
                                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                                        ::tracing_core::__macro_support::Option::Some(222u32),
                                                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                                        ::tracing_core::field::FieldSet::new(&["message"],
                                                            ::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(&format_args!("observing object predicate `{0:?}`",
                                                                                    clause) as &dyn ::tracing::field::Value))])
                                            });
                                    } else { ; }
                                };
                                let bound_predicate = clause.kind();
                                match bound_predicate.skip_binder() {
                                    ty::ClauseKind::Trait(pred) => {
                                        let trait_ref =
                                            tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
                                        ordered_associated_items.extend(tcx.associated_items(pred.trait_ref.def_id).in_definition_order().filter(|item|
                                                            item.can_have_equality_constraint(tcx)).filter(|item|
                                                        !item.is_impl_trait_in_trait()).map(|item|
                                                    (item.def_id, trait_ref)));
                                    }
                                    ty::ClauseKind::Projection(pred) => {
                                        let pred = bound_predicate.rebind(pred);
                                        let references_self =
                                            pred.skip_binder().term.walk().any(|arg|
                                                    arg == dummy_self.into());
                                        if !references_self {
                                            let key =
                                                (pred.item_def_id(),
                                                    tcx.anonymize_bound_vars(pred.map_bound(|proj|
                                                                proj.projection_term.trait_ref(tcx))));
                                            if !projection_bounds.contains_key(&key) {
                                                projection_bounds.insert(key, (pred, supertrait_span));
                                            }
                                        }
                                        self.check_elaborated_projection_mentions_input_lifetimes(pred,
                                            *spans.first().unwrap(), supertrait_span);
                                    }
                                    _ => (),
                                }
                            }
                        }
                        for &(projection_bound, span) in projection_bounds.values()
                            {
                            let def_id = projection_bound.item_def_id();
                            if tcx.generics_require_sized_self(def_id) {
                                tcx.emit_node_span_lint(UNUSED_ASSOCIATED_TYPE_BOUNDS,
                                    hir_id, span,
                                    crate::diagnostics::UnusedAssociatedTypeBounds { span });
                            }
                        }
                        let mut missing_assoc_items = FxIndexSet::default();
                        let projection_bounds: Vec<_> =
                            ordered_associated_items.into_iter().filter_map(|key @
                                            (def_id, _)|
                                        {
                                            if let Some(&assoc) = projection_bounds.get(&key) {
                                                return Some(assoc);
                                            }
                                            if !tcx.generics_require_sized_self(def_id) {
                                                missing_assoc_items.insert(key);
                                            }
                                            None
                                        }).collect();
                        if let Err(guar) =
                                self.check_for_required_assoc_items(principal_trait.as_ref().map_or(::smallvec::SmallVec::new(),
                                        |(_, spans)| spans.clone()), missing_assoc_items,
                                    potential_assoc_items, hir_bounds) {
                            return Ty::new_error(tcx, guar);
                        }
                        let mut duplicates = FxHashSet::default();
                        auto_traits.retain(|(trait_pred, _)|
                                duplicates.insert(trait_pred.def_id()));
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:344",
                                                "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                                ::tracing_core::__macro_support::Option::Some(344u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("principal_trait")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("principal_trait");
                                                                    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(&principal_trait)
                                                                    as &dyn ::tracing::field::Value))])
                                    });
                            } else { ; }
                        };
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:345",
                                                "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                                ::tracing_core::__macro_support::Option::Some(345u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("auto_traits")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("auto_traits");
                                                                    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(&auto_traits)
                                                                    as &dyn ::tracing::field::Value))])
                                    });
                            } else { ; }
                        };
                        let principal_trait_ref =
                            principal_trait.map(|(trait_pred, spans)|
                                    {
                                        trait_pred.map_bound(|trait_pred|
                                                {
                                                    let trait_ref = trait_pred.trait_ref;
                                                    {
                                                        match (&trait_pred.polarity, &ty::ClausePolarity::Positive)
                                                            {
                                                            (left_val, right_val) => {
                                                                if !(*left_val == *right_val) {
                                                                    let kind = ::core::panicking::AssertKind::Eq;
                                                                    ::core::panicking::assert_failed(kind, &*left_val,
                                                                        &*right_val, ::core::option::Option::None);
                                                                }
                                                            }
                                                        }
                                                    };
                                                    {
                                                        match (&trait_ref.self_ty(), &dummy_self) {
                                                            (left_val, right_val) => {
                                                                if !(*left_val == *right_val) {
                                                                    let kind = ::core::panicking::AssertKind::Eq;
                                                                    ::core::panicking::assert_failed(kind, &*left_val,
                                                                        &*right_val, ::core::option::Option::None);
                                                                }
                                                            }
                                                        }
                                                    };
                                                    let span = *spans.first().unwrap();
                                                    let mut missing_generic_params = Vec::new();
                                                    let generics = tcx.generics_of(trait_ref.def_id);
                                                    let args: Vec<_> =
                                                        trait_ref.args.iter().enumerate().skip(1).map(|(index, arg)|
                                                                    {
                                                                        if arg.walk().any(|arg| arg == dummy_self.into()) {
                                                                            let param = &generics.own_params[index];
                                                                            missing_generic_params.push((param.name,
                                                                                    param.kind.clone()));
                                                                            param.to_error(tcx)
                                                                        } else { arg }
                                                                    }).collect();
                                                    let empty_generic_args =
                                                        hir_bounds.iter().any(|hir_bound|
                                                                {
                                                                    hir_bound.trait_ref.path.res ==
                                                                            Res::Def(DefKind::Trait, trait_ref.def_id) &&
                                                                        hir_bound.span.contains(span)
                                                                });
                                                    self.report_missing_generic_params(missing_generic_params,
                                                        trait_ref.def_id, span, empty_generic_args);
                                                    ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(tcx,
                                                            trait_ref.def_id, args))
                                                })
                                    });
                        let existential_projections =
                            projection_bounds.into_iter().map(|(bound, _)|
                                    {
                                        bound.map_bound(|mut b|
                                                {
                                                    {
                                                        match (&b.projection_term.self_ty(), &dummy_self) {
                                                            (left_val, right_val) => {
                                                                if !(*left_val == *right_val) {
                                                                    let kind = ::core::panicking::AssertKind::Eq;
                                                                    ::core::panicking::assert_failed(kind, &*left_val,
                                                                        &*right_val, ::core::option::Option::None);
                                                                }
                                                            }
                                                        }
                                                    };
                                                    let references_self =
                                                        b.projection_term.args.iter().skip(1).any(|arg|
                                                                arg.walk().any(|arg| arg == dummy_self.into()));
                                                    if references_self {
                                                        let guar =
                                                            tcx.dcx().span_delayed_bug(span,
                                                                "trait object projection bounds reference `Self`");
                                                        b.projection_term =
                                                            replace_dummy_self_with_error(tcx, b.projection_term, guar);
                                                    }
                                                    ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(tcx,
                                                            b))
                                                })
                                    });
                        let mut auto_trait_predicates: Vec<_> =
                            auto_traits.into_iter().map(|(trait_pred, _)|
                                        {
                                            {
                                                match (&trait_pred.polarity(),
                                                        &ty::ClausePolarity::Positive) {
                                                    (left_val, right_val) => {
                                                        if !(*left_val == *right_val) {
                                                            let kind = ::core::panicking::AssertKind::Eq;
                                                            ::core::panicking::assert_failed(kind, &*left_val,
                                                                &*right_val, ::core::option::Option::None);
                                                        }
                                                    }
                                                }
                                            };
                                            {
                                                match (&trait_pred.self_ty().skip_binder(), &dummy_self) {
                                                    (left_val, right_val) => {
                                                        if !(*left_val == *right_val) {
                                                            let kind = ::core::panicking::AssertKind::Eq;
                                                            ::core::panicking::assert_failed(kind, &*left_val,
                                                                &*right_val, ::core::option::Option::None);
                                                        }
                                                    }
                                                }
                                            };
                                            ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
                                        }).collect();
                        auto_trait_predicates.dedup();
                        let mut predicates =
                            principal_trait_ref.into_iter().chain(existential_projections).chain(auto_trait_predicates).collect::<SmallVec<[_; 8]>>();
                        predicates.sort_by(|a, b|
                                a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
                        let predicates =
                            tcx.mk_poly_existential_predicates(&predicates);
                        let region_bound =
                            self.lower_trait_object_lifetime(lifetime, predicates,
                                span);
                        Ty::new_dynamic(tcx, predicates, region_bound)
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:33",
                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(33u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            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(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip_all, ret)]
34    pub(super) fn lower_trait_object_ty(
35        &self,
36        span: Span,
37        hir_id: hir::HirId,
38        hir_bounds: &[hir::PolyTraitRef<'_>],
39        lifetime: &hir::Lifetime,
40        syntax: TraitObjectSyntax,
41    ) -> Ty<'tcx> {
42        let tcx = self.tcx();
43        let dummy_self = tcx.types.trait_object_dummy_self;
44
45        match syntax {
46            TraitObjectSyntax::Dyn => {}
47            TraitObjectSyntax::None => {
48                match self.prohibit_or_lint_bare_trait_object_ty(span, hir_id, hir_bounds) {
49                    // Don't continue with type analysis if the `dyn` keyword is missing.
50                    // It generates confusing errors, especially if the user meant to use
51                    // another keyword like `impl`.
52                    Some(guar) => return Ty::new_error(tcx, guar),
53                    None => {}
54                }
55            }
56        }
57
58        let mut user_written_bounds = Vec::new();
59        let mut potential_assoc_items = Vec::new();
60        for poly_trait_ref in hir_bounds.iter() {
61            // FIXME(mgca): We actually leak `trait_object_dummy_self` if the type of any assoc
62            //              const mentions `Self` (in "Self projections" which we intentionally
63            //              allow). That's because we query feed the instantiated type to `type_of`.
64            //              That's really bad, dummy self should never escape lowering! It leads us
65            //              to accept less code we'd like to support and can lead to ICEs later.
66            let result = self.lower_poly_trait_ref(
67                poly_trait_ref,
68                dummy_self,
69                &mut user_written_bounds,
70                PredicateFilter::SelfOnly,
71                OverlappingAsssocItemConstraints::Forbidden,
72            );
73            if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
74                potential_assoc_items.extend(invalid_args);
75            }
76        }
77
78        self.add_default_traits(
79            &mut user_written_bounds,
80            dummy_self,
81            &hir_bounds
82                .iter()
83                .map(|&trait_ref| hir::GenericBound::Trait(trait_ref))
84                .collect::<Vec<_>>(),
85            ImpliedBoundsContext::AssociatedTypeOrImplTrait,
86            span,
87        );
88
89        let (mut elaborated_trait_bounds, elaborated_projection_bounds) =
90            traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
91
92        // FIXME(sized-hierarchy): https://github.com/rust-lang/rust/pull/142712#issuecomment-3013231794
93        debug!(?user_written_bounds, ?elaborated_trait_bounds);
94        let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
95        // Don't strip out `MetaSized` when the user wrote it explicitly, only when it was
96        // elaborated
97        if user_written_bounds
98            .iter()
99            .all(|(clause, _)| clause.as_trait_clause().map(|p| p.def_id()) != Some(meta_sized_did))
100        {
101            elaborated_trait_bounds.retain(|(pred, _)| pred.def_id() != meta_sized_did);
102        }
103        debug!(?user_written_bounds, ?elaborated_trait_bounds);
104
105        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
106            .into_iter()
107            .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
108
109        // We don't support empty trait objects.
110        if regular_traits.is_empty() && auto_traits.is_empty() {
111            let guar =
112                self.report_trait_object_with_no_traits(span, user_written_bounds.iter().copied());
113            return Ty::new_error(tcx, guar);
114        }
115        // We don't support >1 principal
116        if regular_traits.len() > 1 {
117            let guar = self.report_trait_object_addition_traits(&regular_traits);
118            return Ty::new_error(tcx, guar);
119        }
120        // Don't create a dyn trait if we have errors in the principal.
121        if let Err(guar) = regular_traits.error_reported() {
122            return Ty::new_error(tcx, guar);
123        }
124
125        // Check that there are no gross dyn-compatibility violations;
126        // most importantly, that the supertraits don't contain `Self`,
127        // to avoid ICEs.
128        for (clause, span) in user_written_bounds {
129            if let Some(trait_pred) = clause.as_trait_clause() {
130                let violations = self.dyn_compatibility_violations(trait_pred.def_id());
131                if !violations.is_empty() {
132                    let reported = report_dyn_incompatibility(
133                        tcx,
134                        span,
135                        Some(hir_id),
136                        trait_pred.def_id(),
137                        &violations,
138                    )
139                    .emit_err();
140                    return Ty::new_error(tcx, reported);
141                }
142            }
143        }
144
145        // Map the projection bounds onto a key that makes it easy to remove redundant
146        // bounds that are constrained by supertraits of the principal trait.
147        //
148        // Also make sure we detect conflicting bounds from expanding trait aliases.
149        //
150        // FIXME(#150936): Since the elaborated projection bounds also include the user-written ones
151        //                 and we're separately rejecting duplicate+conflicting bindings for trait
152        //                 object types when lowering assoc item bindings, there are basic cases
153        //                 where we're emitting two distinct but very similar diagnostics.
154        let mut projection_bounds = FxIndexMap::default();
155        for (proj, proj_span) in elaborated_projection_bounds {
156            let item_def_id = proj.item_def_id();
157
158            let proj = proj.map_bound(|mut proj| {
159                let references_self = proj.term.walk().any(|arg| arg == dummy_self.into());
160                if references_self {
161                    let guar = self.dcx().emit_err(DynTraitAssocItemBindingMentionsSelf {
162                        span,
163                        kind: tcx.def_descr(item_def_id),
164                        binding: proj_span,
165                    });
166                    proj.term = replace_dummy_self_with_error(tcx, proj.term, guar);
167                }
168                proj
169            });
170
171            let key = (
172                item_def_id,
173                tcx.anonymize_bound_vars(
174                    proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
175                ),
176            );
177            if let Some((old_proj, old_proj_span)) =
178                projection_bounds.insert(key, (proj, proj_span))
179                && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
180            {
181                let kind = tcx.def_descr(item_def_id);
182                let name = tcx.item_name(item_def_id);
183                self.dcx()
184                    .struct_span_err(span, format!("conflicting {kind} bindings for `{name}`"))
185                    .with_span_label(
186                        old_proj_span,
187                        format!("`{name}` is specified to be `{}` here", old_proj.term()),
188                    )
189                    .with_span_label(
190                        proj_span,
191                        format!("`{name}` is specified to be `{}` here", proj.term()),
192                    )
193                    .emit();
194            }
195        }
196
197        let principal_trait = regular_traits.into_iter().next();
198
199        // A stable ordering of associated types & consts from the principal trait and all its
200        // supertraits. We use this to ensure that different substitutions of a trait don't
201        // result in `dyn Trait` types with different projections lists, which can be unsound:
202        // <https://github.com/rust-lang/rust/pull/136458>.
203        // We achieve a stable ordering by walking over the unsubstituted principal trait ref.
204        let mut ordered_associated_items = vec![];
205
206        if let Some((principal_trait, ref spans)) = principal_trait {
207            let principal_trait = principal_trait.map_bound(|trait_pred| {
208                assert_eq!(trait_pred.polarity, ty::ClausePolarity::Positive);
209                trait_pred.trait_ref
210            });
211
212            for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
213                tcx,
214                [ClauseWithSupertraitSpan::new(
215                    ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
216                    *spans.last().unwrap(),
217                )],
218            )
219            .filter_only_self()
220            {
221                let clause = clause.instantiate_supertrait(tcx, principal_trait);
222                debug!("observing object predicate `{clause:?}`");
223
224                let bound_predicate = clause.kind();
225                match bound_predicate.skip_binder() {
226                    ty::ClauseKind::Trait(pred) => {
227                        // FIXME(negative_bounds): Handle this correctly...
228                        let trait_ref =
229                            tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
230                        ordered_associated_items.extend(
231                            tcx.associated_items(pred.trait_ref.def_id)
232                                .in_definition_order()
233                                .filter(|item| item.can_have_equality_constraint(tcx))
234                                // Traits with RPITITs are simply not dyn compatible (for now).
235                                .filter(|item| !item.is_impl_trait_in_trait())
236                                .map(|item| (item.def_id, trait_ref)),
237                        );
238                    }
239                    ty::ClauseKind::Projection(pred) => {
240                        let pred = bound_predicate.rebind(pred);
241                        // A `Self` within the original bound will be instantiated with a
242                        // `trait_object_dummy_self`, so check for that.
243                        let references_self =
244                            pred.skip_binder().term.walk().any(|arg| arg == dummy_self.into());
245
246                        // If the projection output contains `Self`, force the user to
247                        // elaborate it explicitly to avoid a lot of complexity.
248                        //
249                        // The "classically useful" case is the following:
250                        // ```
251                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
252                        //         type MyOutput;
253                        //     }
254                        // ```
255                        //
256                        // Here, the user could theoretically write `dyn MyTrait<MyOutput = X>`,
257                        // but actually supporting that would "expand" to an infinitely-long type
258                        // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
259                        //
260                        // Instead, we force the user to write
261                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
262                        // the discussion in #56288 for alternatives.
263                        if !references_self {
264                            let key = (
265                                pred.item_def_id(),
266                                tcx.anonymize_bound_vars(
267                                    pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
268                                ),
269                            );
270                            if !projection_bounds.contains_key(&key) {
271                                projection_bounds.insert(key, (pred, supertrait_span));
272                            }
273                        }
274
275                        self.check_elaborated_projection_mentions_input_lifetimes(
276                            pred,
277                            *spans.first().unwrap(),
278                            supertrait_span,
279                        );
280                    }
281                    _ => (),
282                }
283            }
284        }
285
286        // Flag assoc item bindings that didn't really need to be specified.
287        for &(projection_bound, span) in projection_bounds.values() {
288            let def_id = projection_bound.item_def_id();
289            if tcx.generics_require_sized_self(def_id) {
290                // FIXME(mgca): Ideally we would generalize the name of this lint to sth. like
291                // `unused_associated_item_bindings` since this can now also trigger on *const*
292                // projections / assoc *const* bindings.
293                tcx.emit_node_span_lint(
294                    UNUSED_ASSOCIATED_TYPE_BOUNDS,
295                    hir_id,
296                    span,
297                    crate::diagnostics::UnusedAssociatedTypeBounds { span },
298                );
299            }
300        }
301
302        // The user has to constrain all associated types & consts via bindings unless the
303        // corresponding associated item has a `where Self: Sized` clause. This can be done
304        // in the `dyn Trait` directly, in the supertrait bounds or behind trait aliases.
305        //
306        // Collect all associated items that weren't specified and compute the list of
307        // projection bounds which we'll later turn into existential ones.
308        //
309        // We intentionally keep around projections whose associated item has a `Self: Sized`
310        // bound in order to be able to wfcheck the RHS, allow the RHS to constrain generic
311        // parameters and to imply bounds.
312        // See also <https://github.com/rust-lang/rust/pull/140684>.
313        let mut missing_assoc_items = FxIndexSet::default();
314        let projection_bounds: Vec<_> = ordered_associated_items
315            .into_iter()
316            .filter_map(|key @ (def_id, _)| {
317                if let Some(&assoc) = projection_bounds.get(&key) {
318                    return Some(assoc);
319                }
320                if !tcx.generics_require_sized_self(def_id) {
321                    missing_assoc_items.insert(key);
322                }
323                None
324            })
325            .collect();
326
327        // If there are any associated items whose value wasn't provided, bail out with an error.
328        if let Err(guar) = self.check_for_required_assoc_items(
329            principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
330            missing_assoc_items,
331            potential_assoc_items,
332            hir_bounds,
333        ) {
334            return Ty::new_error(tcx, guar);
335        }
336
337        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
338        // `dyn Trait + Send`.
339        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
340        // the bounds
341        let mut duplicates = FxHashSet::default();
342        auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id()));
343
344        debug!(?principal_trait);
345        debug!(?auto_traits);
346
347        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
348        let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| {
349            trait_pred.map_bound(|trait_pred| {
350                let trait_ref = trait_pred.trait_ref;
351                assert_eq!(trait_pred.polarity, ty::ClausePolarity::Positive);
352                assert_eq!(trait_ref.self_ty(), dummy_self);
353
354                let span = *spans.first().unwrap();
355
356                // Verify that `dummy_self` did not leak inside generic parameter defaults. This
357                // could not be done at path creation, since we need to see through trait aliases.
358                let mut missing_generic_params = Vec::new();
359                let generics = tcx.generics_of(trait_ref.def_id);
360                let args: Vec<_> = trait_ref
361                    .args
362                    .iter()
363                    .enumerate()
364                    // Skip `Self`
365                    .skip(1)
366                    .map(|(index, arg)| {
367                        if arg.walk().any(|arg| arg == dummy_self.into()) {
368                            let param = &generics.own_params[index];
369                            missing_generic_params.push((param.name, param.kind.clone()));
370                            param.to_error(tcx)
371                        } else {
372                            arg
373                        }
374                    })
375                    .collect();
376
377                let empty_generic_args = hir_bounds.iter().any(|hir_bound| {
378                    hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
379                        && hir_bound.span.contains(span)
380                });
381                self.report_missing_generic_params(
382                    missing_generic_params,
383                    trait_ref.def_id,
384                    span,
385                    empty_generic_args,
386                );
387
388                ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new(
389                    tcx,
390                    trait_ref.def_id,
391                    args,
392                ))
393            })
394        });
395
396        let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
397            bound.map_bound(|mut b| {
398                assert_eq!(b.projection_term.self_ty(), dummy_self);
399
400                // Like for trait refs, verify that `dummy_self` did not leak inside default type
401                // parameters.
402                let references_self = b
403                    .projection_term
404                    .args
405                    .iter()
406                    .skip(1)
407                    .any(|arg| arg.walk().any(|arg| arg == dummy_self.into()));
408                if references_self {
409                    let guar = tcx
410                        .dcx()
411                        .span_delayed_bug(span, "trait object projection bounds reference `Self`");
412                    b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar);
413                }
414
415                ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
416                    tcx, b,
417                ))
418            })
419        });
420
421        let mut auto_trait_predicates: Vec<_> = auto_traits
422            .into_iter()
423            .map(|(trait_pred, _)| {
424                assert_eq!(trait_pred.polarity(), ty::ClausePolarity::Positive);
425                assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
426
427                ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
428            })
429            .collect();
430        auto_trait_predicates.dedup();
431
432        // N.b. principal, projections, auto traits
433        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
434        let mut predicates = principal_trait_ref
435            .into_iter()
436            .chain(existential_projections)
437            .chain(auto_trait_predicates)
438            .collect::<SmallVec<[_; 8]>>();
439        predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
440        let predicates = tcx.mk_poly_existential_predicates(&predicates);
441
442        let region_bound = self.lower_trait_object_lifetime(lifetime, predicates, span);
443
444        Ty::new_dynamic(tcx, predicates, region_bound)
445    }
446
447    fn lower_trait_object_lifetime(
448        &self,
449        lifetime: &hir::Lifetime,
450        predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
451        span: Span,
452    ) -> ty::Region<'tcx> {
453        // Curiously, we also use the *object region bound* for `Infer` (`'_`)
454        // while we obviously don't use the *object lifetime default* for it...
455        if let hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer =
456            lifetime.kind
457            && let Some(region) = self.compute_object_lifetime_bound(span, predicates)
458        {
459            return region;
460        }
461
462        let reason = if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind {
463            RegionInferReason::ObjectLifetimeDefault(span.shrink_to_hi())
464        } else {
465            RegionInferReason::ExplicitObjectLifetime
466        };
467
468        self.lower_lifetime(lifetime, reason)
469    }
470
471    /// Check that elaborating the principal of a trait ref doesn't lead to projections
472    /// that are unconstrained. This can happen because an otherwise unconstrained
473    /// *type variable* can be substituted with a type that has late-bound regions. See
474    /// `elaborated-predicates-unconstrained-late-bound.rs` for a test.
475    fn check_elaborated_projection_mentions_input_lifetimes(
476        &self,
477        pred: ty::PolyProjectionClause<'tcx>,
478        span: Span,
479        supertrait_span: Span,
480    ) {
481        let tcx = self.tcx();
482
483        // Find any late-bound regions declared in `ty` that are not
484        // declared in the trait-ref or assoc_item. These are not well-formed.
485        //
486        // Example:
487        //
488        //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
489        //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
490        let late_bound_in_projection_term =
491            tcx.collect_constrained_late_bound_regions(pred.map_bound(|pred| pred.projection_term));
492        let late_bound_in_term =
493            tcx.collect_referenced_late_bound_regions(pred.map_bound(|pred| pred.term));
494        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:494",
                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(494u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("late_bound_in_projection_term")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("late_bound_in_projection_term");
                                            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(&late_bound_in_projection_term)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?late_bound_in_projection_term);
495        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:495",
                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(495u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("late_bound_in_term")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("late_bound_in_term");
                                            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(&late_bound_in_term)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?late_bound_in_term);
496
497        // FIXME: point at the type params that don't have appropriate lifetimes:
498        // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
499        //                         ----  ----     ^^^^^^^
500        // NOTE(mgca): This error should be impossible to trigger with assoc const bindings.
501        self.validate_late_bound_regions(
502            late_bound_in_projection_term,
503            late_bound_in_term,
504            |br_name| {
505                let item_name = tcx.item_name(pred.item_def_id());
506                {
    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!(
507                    self.dcx(),
508                    span,
509                    E0582,
510                    "binding for associated type `{}` references {}, \
511                             which does not appear in the trait input types",
512                    item_name,
513                    br_name
514                )
515                .with_span_label(supertrait_span, "due to this supertrait")
516            },
517        );
518    }
519
520    /// Given the bounds on an object, determines what single region bound (if any) we can
521    /// use to summarize this type.
522    ///
523    /// The basic idea is that we will use the bound the user
524    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
525    /// for region bounds. It may be that we can derive no bound at all, in which case
526    /// we return `None`.
527    {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("compute_object_lifetime_bound",
                                "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                                ::tracing_core::__macro_support::Option::Some(527u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("existential_predicates")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("existential_predicates");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&existential_predicates)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return: Option<ty::Region<'tcx>> =
                            loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let tcx = self.tcx();
                        let derived_region_bounds =
                            traits::wf::object_region_bounds(tcx,
                                existential_predicates);
                        if derived_region_bounds.is_empty() { return None; }
                        if derived_region_bounds.iter().any(|r| r.is_static()) {
                            return Some(tcx.lifetimes.re_static);
                        }
                        let r = derived_region_bounds[0];
                        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
                            self.dcx().emit_err(crate::diagnostics::AmbiguousLifetimeBound {
                                    span,
                                });
                        }
                        Some(r)
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs:527",
                        "rustc_hir_analysis::hir_ty_lowering::dyn_trait",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c36f1457196e315bc204b9564a6a5a7fe7f5a51f/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs"),
                        ::tracing_core::__macro_support::Option::Some(527u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::dyn_trait"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            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(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(self, span), ret)]
528    fn compute_object_lifetime_bound(
529        &self,
530        span: Span,
531        existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
532    ) -> Option<ty::Region<'tcx>> // if None, use the default
533    {
534        let tcx = self.tcx();
535
536        // No explicit region bound specified. Therefore, examine trait
537        // bounds and see if we can derive region bounds from those.
538        let derived_region_bounds = traits::wf::object_region_bounds(tcx, existential_predicates);
539
540        // If there are no derived region bounds, then report back that we
541        // can find no region bound. The caller will use the default.
542        if derived_region_bounds.is_empty() {
543            return None;
544        }
545
546        // If any of the derived region bounds are 'static, that is always
547        // the best choice.
548        if derived_region_bounds.iter().any(|r| r.is_static()) {
549            return Some(tcx.lifetimes.re_static);
550        }
551
552        // Determine whether there is exactly one unique region in the set
553        // of derived region bounds. If so, use that. Otherwise, report an
554        // error.
555        let r = derived_region_bounds[0];
556        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
557            self.dcx().emit_err(crate::diagnostics::AmbiguousLifetimeBound { span });
558        }
559        Some(r)
560    }
561
562    /// Prohibit or lint against *bare* trait object types depending on the edition.
563    ///
564    /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
565    /// In edition 2021 and onward we emit a hard error for them.
566    fn prohibit_or_lint_bare_trait_object_ty(
567        &self,
568        span: Span,
569        hir_id: hir::HirId,
570        hir_bounds: &[hir::PolyTraitRef<'_>],
571    ) -> Option<ErrorGuaranteed> {
572        struct TraitObjectWithoutDyn<'a, 'tcx> {
573            span: Span,
574            hir_id: HirId,
575            sugg: Vec<(Span, String)>,
576            this: &'a dyn HirTyLowerer<'tcx>,
577        }
578
579        impl<'a, 'b, 'tcx> Diagnostic<'a> for TraitObjectWithoutDyn<'b, 'tcx> {
580            fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> {
581                let Self { span, hir_id, sugg, this } = self;
582                let mut lint =
583                    Diag::new(dcx, level, "trait objects without an explicit `dyn` are deprecated");
584                if span.can_be_used_for_suggestions() {
585                    lint.multipart_suggestion(
586                        "if this is a dyn-compatible trait, use `dyn`",
587                        sugg,
588                        Applicability::MachineApplicable,
589                    );
590                }
591                this.maybe_suggest_blanket_trait_impl(span, hir_id, &mut lint);
592                lint
593            }
594        }
595
596        let tcx = self.tcx();
597        let [poly_trait_ref, ..] = hir_bounds else { return None };
598
599        let in_path = match tcx.parent_hir_node(hir_id).path() {
600            Some(hir::QPath::TypeRelative(qself, _)) if qself.hir_id == hir_id => true,
601            _ => false,
602        };
603        let needs_bracket = in_path
604            && !tcx
605                .sess
606                .source_map()
607                .span_to_prev_source(span)
608                .ok()
609                .is_some_and(|s| s.trim_end().ends_with('<'));
610
611        let is_global = poly_trait_ref.trait_ref.path.is_global();
612
613        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![(
614            span.shrink_to_lo(),
615            format!(
616                "{}dyn {}",
617                if needs_bracket { "<" } else { "" },
618                if is_global { "(" } else { "" },
619            ),
620        )];
621
622        if is_global || needs_bracket {
623            sugg.push((
624                span.shrink_to_hi(),
625                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}",
                if is_global { ")" } else { "" },
                if needs_bracket { ">" } else { "" }))
    })format!(
626                    "{}{}",
627                    if is_global { ")" } else { "" },
628                    if needs_bracket { ">" } else { "" },
629                ),
630            ));
631        }
632
633        if span.edition().at_least_rust_2021() {
634            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!(
635                self.dcx(),
636                span,
637                E0782,
638                "{}",
639                "expected a type, found a trait"
640            );
641            if span.can_be_used_for_suggestions()
642                && poly_trait_ref.trait_ref.trait_def_id().is_some()
643                && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag)
644                && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag)
645            {
646                self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag);
647            }
648            // Check if the impl trait that we are considering is an impl of a local trait.
649            self.maybe_suggest_blanket_trait_impl(span, hir_id, &mut diag);
650            self.maybe_suggest_assoc_ty_bound(hir_id, &mut diag);
651            self.maybe_suggest_typoed_method(
652                hir_id,
653                poly_trait_ref.trait_ref.trait_def_id(),
654                &mut diag,
655            );
656            // If there is an associated type with the same name, add the suggestion to this error.
657            if self
658                .tcx()
659                .resolutions(())
660                .paths_matching_assoc_types
661                .contains(&span.with_parent(None))
662            {
663                diag.subdiagnostic(AssocTypeWithSameName { span: span.shrink_to_lo() });
664            }
665            Some(diag.emit_err())
666        } else {
667            tcx.emit_node_span_lint(
668                BARE_TRAIT_OBJECTS,
669                hir_id,
670                span,
671                TraitObjectWithoutDyn { span, hir_id, sugg, this: self },
672            );
673            None
674        }
675    }
676
677    /// For a struct or enum with an invalid bare trait object field, suggest turning
678    /// it into a generic type bound.
679    fn maybe_suggest_add_generic_impl_trait(
680        &self,
681        span: Span,
682        hir_id: hir::HirId,
683        diag: &mut Diag<'_>,
684    ) -> bool {
685        let tcx = self.tcx();
686
687        let parent_hir_id = tcx.parent_hir_id(hir_id);
688        let parent_item = tcx.hir_get_parent_item(hir_id).def_id;
689
690        let generics = match tcx.hir_node_by_def_id(parent_item) {
691            hir::Node::Item(hir::Item {
692                kind: hir::ItemKind::Struct(_, generics, variant),
693                ..
694            }) => {
695                if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
696                    return false;
697                }
698                generics
699            }
700            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => {
701                if !def
702                    .variants
703                    .iter()
704                    .flat_map(|variant| variant.data.fields().iter())
705                    .any(|field| field.hir_id == parent_hir_id)
706                {
707                    return false;
708                }
709                generics
710            }
711            _ => return false,
712        };
713
714        let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(span) else {
715            return false;
716        };
717
718        let param = "TUV"
719            .chars()
720            .map(|c| c.to_string())
721            .chain((0..).map(|i| ::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("P{0}", i)) })format!("P{i}")))
722            .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
723            .expect("we definitely can find at least one param name to generate");
724        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())];
725        if let Some(insertion_span) = generics.span_for_param_suggestion() {
726            sugg.push((insertion_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {1}: {0}", rendered_ty, param))
    })format!(", {param}: {}", rendered_ty)));
727        } else {
728            sugg.push((generics.where_clause_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{1}: {0}>", rendered_ty, param))
    })format!("<{param}: {}>", rendered_ty)));
729        }
730        diag.multipart_suggestion(
731            "you might be missing a type parameter",
732            sugg,
733            Applicability::MachineApplicable,
734        );
735        true
736    }
737
738    /// Make sure that we are in the condition to suggest the blanket implementation.
739    fn maybe_suggest_blanket_trait_impl(
740        &self,
741        span: Span,
742        hir_id: hir::HirId,
743        diag: &mut Diag<'_>,
744    ) {
745        let tcx = self.tcx();
746        let parent_id = tcx.hir_get_parent_item(hir_id).def_id;
747        if let hir::Node::Item(hir::Item {
748            kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
749            ..
750        }) = tcx.hir_node_by_def_id(parent_id)
751            && hir_id == impl_self_ty.hir_id
752        {
753            let Some(of_trait) = of_trait else {
754                diag.span_suggestion_verbose(
755                    impl_self_ty.span.shrink_to_hi(),
756                    "you might have intended to implement this trait for a given type",
757                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" for /* Type */"))
    })format!(" for /* Type */"),
758                    Applicability::HasPlaceholders,
759                );
760                return;
761            };
762            if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
763                return;
764            }
765            let of_trait_span = of_trait.trait_ref.path.span;
766            // make sure that we are not calling unwrap to abort during the compilation
767            let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else {
768                return;
769            };
770
771            let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(span) else {
772                return;
773            };
774            let sugg = self.add_generic_param_suggestion(generics, span, &impl_trait_name);
775            diag.multipart_suggestion(
776                ::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!(
777                    "alternatively use a blanket implementation to implement `{of_trait_name}` for \
778                     all types that also implement `{impl_trait_name}`"
779                ),
780                sugg,
781                Applicability::MaybeIncorrect,
782            );
783        }
784    }
785
786    /// Try our best to approximate when adding `dyn` would be helpful for a bare
787    /// trait object.
788    ///
789    /// Right now, this is if the type is either directly nested in another ty,
790    /// or if it's in the tail field within a struct. This approximates what the
791    /// user would've gotten on edition 2015, except for the case where we have
792    /// an *obvious* knock-on `Sized` error.
793    fn maybe_suggest_dyn_trait(
794        &self,
795        hir_id: hir::HirId,
796        span: Span,
797        sugg: Vec<(Span, String)>,
798        diag: &mut Diag<'_>,
799    ) -> bool {
800        let tcx = self.tcx();
801        if span.in_derive_expansion() {
802            return false;
803        }
804
805        // Look at the direct HIR parent, since we care about the relationship between
806        // the type and the thing that directly encloses it.
807        match tcx.parent_hir_node(hir_id) {
808            // These are all generally ok. Namely, when a trait object is nested
809            // into another expression or ty, it's either very certain that they
810            // missed the ty (e.g. `&Trait`) or it's not really possible to tell
811            // what their intention is, so let's not give confusing suggestions and
812            // just mention `dyn`. The user can make up their mind what to do here.
813            hir::Node::Ty(_)
814            | hir::Node::Expr(_)
815            | hir::Node::PatExpr(_)
816            | hir::Node::PathSegment(_)
817            | hir::Node::AssocItemConstraint(_)
818            | hir::Node::TraitRef(_)
819            | hir::Node::Item(_)
820            | hir::Node::WherePredicate(_) => {}
821
822            hir::Node::Field(field) => {
823                // Enums can't have unsized fields, fields can only have an unsized tail field.
824                if let hir::Node::Item(hir::Item {
825                    kind: hir::ItemKind::Struct(_, _, variant), ..
826                }) = tcx.parent_hir_node(field.hir_id)
827                    && variant
828                        .fields()
829                        .last()
830                        .is_some_and(|tail_field| tail_field.hir_id == field.hir_id)
831                {
832                    // Ok
833                } else {
834                    return false;
835                }
836            }
837            _ => return false,
838        }
839
840        // FIXME: Only emit this suggestion if the trait is dyn-compatible.
841        diag.multipart_suggestion(
842            "you can add the `dyn` keyword if you want a trait object",
843            sugg,
844            Applicability::MachineApplicable,
845        );
846        true
847    }
848
849    fn add_generic_param_suggestion(
850        &self,
851        generics: &hir::Generics<'_>,
852        self_ty_span: Span,
853        impl_trait_name: &str,
854    ) -> Vec<(Span, String)> {
855        // check if the trait has generics, to make a correct suggestion
856        let param_name = generics.params.next_type_param_name(None);
857
858        let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
859            (span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}: {1}", param_name,
                impl_trait_name))
    })format!(", {param_name}: {impl_trait_name}"))
860        } else {
861            (generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}: {1}>", param_name,
                impl_trait_name))
    })format!("<{param_name}: {impl_trait_name}>"))
862        };
863        ::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]
864    }
865
866    /// Make sure that we are in the condition to suggest `impl Trait`.
867    fn maybe_suggest_impl_trait(
868        &self,
869        span: Span,
870        hir_id: hir::HirId,
871        hir_bounds: &[hir::PolyTraitRef<'_>],
872        diag: &mut Diag<'_>,
873    ) -> bool {
874        let tcx = self.tcx();
875        let parent_id = tcx.hir_get_parent_item(hir_id).def_id;
876        // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
877        //        and suggest `Trait0<Ty = impl Trait1>`.
878        // Functions are found in three different contexts.
879        // 1. Independent functions
880        // 2. Functions inside trait blocks
881        // 3. Functions inside impl blocks
882        let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
883            hir::Node::Item(hir::Item {
884                kind: hir::ItemKind::Fn { sig, generics, .. }, ..
885            }) => (sig, generics),
886            hir::Node::TraitItem(hir::TraitItem {
887                kind: hir::TraitItemKind::Fn(sig, _),
888                generics,
889                ..
890            }) => (sig, generics),
891            hir::Node::ImplItem(hir::ImplItem {
892                kind: hir::ImplItemKind::Fn(sig, _),
893                generics,
894                ..
895            }) => (sig, generics),
896            _ => return false,
897        };
898        let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(span) else {
899            return false;
900        };
901        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())];
902        // Check if trait object is safe for suggesting dynamic dispatch.
903        let is_dyn_compatible = hir_bounds.iter().all(|bound| match bound.trait_ref.path.res {
904            Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id),
905            _ => false,
906        });
907
908        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!(
909            tcx.parent_hir_node(hir_id),
910            hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. })
911        );
912
913        // Suggestions for function return type.
914        if let hir::FnRetTy::Return(ty) = sig.decl.output
915            && ty.peel_refs().hir_id == hir_id
916        {
917            let pre = if !is_dyn_compatible {
918                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is dyn-incompatible, ",
                trait_name))
    })format!("`{trait_name}` is dyn-incompatible, ")
919            } else {
920                String::new()
921            };
922            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!(
923                "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \
924                 single underlying type",
925            );
926
927            diag.multipart_suggestion(msg, impl_sugg, Applicability::MachineApplicable);
928
929            // Suggest `Box<dyn Trait>` for return type
930            if is_dyn_compatible {
931                // If the return type is `&Trait`, we don't want
932                // the ampersand to be displayed in the `Box<dyn Trait>`
933                // suggestion.
934                let suggestion = if borrowed {
935                    ::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}>"))]
936                } else {
937                    ::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![
938                        (ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
939                        (ty.span.shrink_to_hi(), ">".to_string()),
940                    ]
941                };
942
943                diag.multipart_suggestion(
944                    "alternatively, you can return an owned trait object",
945                    suggestion,
946                    Applicability::MachineApplicable,
947                );
948            }
949            return true;
950        }
951
952        // Suggestions for function parameters.
953        for ty in sig.decl.inputs {
954            if ty.peel_refs().hir_id != hir_id {
955                continue;
956            }
957            let sugg = self.add_generic_param_suggestion(generics, span, &trait_name);
958            diag.multipart_suggestion(
959                ::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}`"),
960                sugg,
961                Applicability::MachineApplicable,
962            );
963            diag.multipart_suggestion(
964                "you can also use an opaque type, but users won't be able to specify the type \
965                 parameter when calling the `fn`, having to rely exclusively on type inference",
966                impl_sugg,
967                Applicability::MachineApplicable,
968            );
969            if !is_dyn_compatible {
970                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!(
971                    "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used"
972                ));
973            } else {
974                // No ampersand in suggestion if it's borrowed already
975                let (dyn_str, paren_dyn_str) =
976                    if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };
977
978                let sugg = if let [_, _, ..] = hir_bounds {
979                    // There is more than one trait bound, we need surrounding parentheses.
980                    ::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![
981                        (span.shrink_to_lo(), paren_dyn_str.to_string()),
982                        (span.shrink_to_hi(), ")".to_string()),
983                    ]
984                } else {
985                    ::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())]
986                };
987                diag.multipart_suggestion(
988                    ::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!(
989                        "alternatively, use a trait object to accept any type that implements \
990                         `{trait_name}`, accessing its methods at runtime using dynamic dispatch",
991                    ),
992                    sugg,
993                    Applicability::MachineApplicable,
994                );
995            }
996            return true;
997        }
998        false
999    }
1000
1001    fn maybe_suggest_assoc_ty_bound(&self, hir_id: hir::HirId, diag: &mut Diag<'_>) {
1002        let mut parents = self.tcx().hir_parent_iter(hir_id);
1003
1004        if let Some((c_hir_id, hir::Node::AssocItemConstraint(constraint))) = parents.next()
1005            && let Some(obj_ty) = constraint.ty()
1006            && let Some((_, hir::Node::TraitRef(trait_ref))) = parents.next()
1007        {
1008            if let Some((_, hir::Node::Ty(ty))) = parents.next()
1009                && let hir::TyKind::TraitObject(..) = ty.kind
1010            {
1011                // Assoc ty bounds aren't permitted inside trait object types.
1012                return;
1013            }
1014
1015            if trait_ref
1016                .path
1017                .segments
1018                .iter()
1019                .find_map(|seg| {
1020                    seg.args.filter(|args| args.constraints.iter().any(|c| c.hir_id == c_hir_id))
1021                })
1022                .is_none_or(|args| args.parenthesized != hir::GenericArgsParentheses::No)
1023            {
1024                // Only consider angle-bracketed args (where we have a `=` to replace with `:`).
1025                return;
1026            }
1027
1028            let lo = if constraint.gen_args.span_ext.is_dummy() {
1029                constraint.ident.span
1030            } else {
1031                constraint.gen_args.span_ext
1032            };
1033            let hi = obj_ty.span;
1034
1035            if !lo.eq_ctxt(hi) {
1036                return;
1037            }
1038
1039            diag.span_suggestion_verbose(
1040                lo.between(hi),
1041                "you might have meant to write a bound here",
1042                ": ",
1043                Applicability::MaybeIncorrect,
1044            );
1045        }
1046    }
1047
1048    fn maybe_suggest_typoed_method(
1049        &self,
1050        hir_id: hir::HirId,
1051        trait_def_id: Option<DefId>,
1052        diag: &mut Diag<'_>,
1053    ) {
1054        let tcx = self.tcx();
1055        let Some(trait_def_id) = trait_def_id else {
1056            return;
1057        };
1058        let hir::Node::Expr(hir::Expr {
1059            kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
1060            ..
1061        }) = tcx.parent_hir_node(hir_id)
1062        else {
1063            return;
1064        };
1065        if path_ty.hir_id != hir_id {
1066            return;
1067        }
1068        let names: Vec<_> = tcx
1069            .associated_items(trait_def_id)
1070            .in_definition_order()
1071            .filter(|assoc| assoc.namespace() == hir::def::Namespace::ValueNS)
1072            .map(|cand| cand.name())
1073            .collect();
1074        if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
1075            diag.span_suggestion_verbose(
1076                segment.ident.span,
1077                ::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!(
1078                    "you may have misspelled this associated item, causing `{}` \
1079                    to be interpreted as a type rather than a trait",
1080                    tcx.item_name(trait_def_id),
1081                ),
1082                typo,
1083                Applicability::MaybeIncorrect,
1084            );
1085        } else {
1086            diag.span_label(
1087                segment.ident.span,
1088                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("not an associated item of trait `{0}`, so `{0}` is interpreted as a type",
                tcx.item_name(trait_def_id)))
    })format!(
1089                    "not an associated item of trait `{trait_name}`, so `{trait_name}` is \
1090                    interpreted as a type",
1091                    trait_name = tcx.item_name(trait_def_id),
1092                ),
1093            );
1094        }
1095    }
1096}
1097
1098fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
1099    tcx: TyCtxt<'tcx>,
1100    t: T,
1101    guar: ErrorGuaranteed,
1102) -> T {
1103    t.fold_with(&mut BottomUpFolder {
1104        tcx,
1105        ty_op: |ty| {
1106            if ty == tcx.types.trait_object_dummy_self { Ty::new_error(tcx, guar) } else { ty }
1107        },
1108        lt_op: |lt| lt,
1109        ct_op: |ct| ct,
1110    })
1111}