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