Skip to main content

rustc_next_trait_solver/solve/assembly/
structural_traits.rs

1//! Code which is used by built-in goals that match "structurally", such a auto
2//! traits, `Copy`/`Clone`.
3
4use derive_where::derive_where;
5use rustc_type_ir::data_structures::HashMap;
6use rustc_type_ir::inherent::*;
7use rustc_type_ir::lang_items::{SolverProjectionLangItem, SolverTraitLangItem};
8use rustc_type_ir::solve::SizedTraitKind;
9use rustc_type_ir::solve::inspect::ProbeKind;
10use rustc_type_ir::{
11    self as ty, FallibleTypeFolder, Interner, Movability, Mutability, Region, TypeFoldable,
12    TypeSuperFoldable, Unnormalized, Upcast as _, elaborate,
13};
14use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
15use tracing::instrument;
16
17use crate::delegate::SolverDelegate;
18use crate::solve::{
19    AdtDestructorKind, EvalCtxt, Goal, NoSolution, NoSolutionOrRerunNonErased, RerunNonErased,
20};
21
22// Calculates the constituent types of a type for `auto trait` purposes.
23{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::TRACE <=
                ::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("instantiate_constituent_tys_for_auto_trait",
                                "rustc_next_trait_solver::solve::assembly::structural_traits",
                                ::tracing::Level::TRACE,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                                ::tracing_core::__macro_support::Option::Some(23u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("ty")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("ty");
                                                    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::TRACE <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::TRACE <=
                                ::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(&ty)
                                                        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:
                                Result<ty::Binder<I, Vec<I::Ty>>, NoSolution> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let cx = ecx.cx();
                        match ty.kind() {
                            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
                                ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) | ty::Never |
                                ty::Char => Ok(ty::Binder::dummy(::alloc::vec::Vec::new())),
                            ty::Foreign(..) =>
                                Ok(ty::Binder::dummy(::alloc::vec::Vec::new())),
                            ty::Str =>
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [Ty::new_slice(cx, Ty::new_u8(cx))])))),
                            ty::Dynamic(..) | ty::Param(..) |
                                ty::Alias(ty::IsRigid::Yes, ty::AliasTy {
                                kind: ty::Projection { .. } | ty::Inherent { .. } |
                                    ty::Free { .. }, .. }) | ty::Placeholder(..) |
                                ty::Alias(ty::IsRigid::No, _) | ty::Bound(..) | ty::Infer(_)
                                |
                                ty::Alias(ty::IsRigid::Yes, ty::AliasTy {
                                kind: ty::Opaque { .. }, .. }) => {
                                {
                                    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
                                            ty));
                                }
                            }
                            ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [element_ty]))))
                            }
                            ty::Pat(element_ty, _) | ty::Array(element_ty, _) |
                                ty::Slice(element_ty) => {
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [element_ty]))))
                            }
                            ty::Tuple(tys) => { Ok(ty::Binder::dummy(tys.to_vec())) }
                            ty::Closure(_, args) =>
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [args.as_closure().tupled_upvars_ty()])))),
                            ty::CoroutineClosure(_, args) => {
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [args.as_coroutine_closure().tupled_upvars_ty()]))))
                            }
                            ty::Coroutine(def_id, args) =>
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [args.as_coroutine().tupled_upvars_ty(),
                                                        Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id,
                                                            args)])))),
                            ty::CoroutineWitness(def_id, args) =>
                                Ok(ecx.cx().coroutine_hidden_types(def_id).instantiate(cx,
                                                args).skip_norm_wip().map_bound(|bound|
                                            bound.types.to_vec())),
                            ty::UnsafeBinder(bound_ty) =>
                                Ok(bound_ty.map_bound(|ty|
                                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                    [ty])))),
                            ty::Adt(def, args) if def.is_phantom_data() =>
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [args.type_at(0)])))),
                            ty::Adt(def, args) =>
                                Ok(ty::Binder::dummy(def.all_field_tys(cx).iter_instantiated(cx,
                                                    args).map(Unnormalized::skip_norm_wip).collect())),
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs:23",
                        "rustc_next_trait_solver::solve::assembly::structural_traits",
                        ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                        ::tracing_core::__macro_support::Option::Some(23u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                        ::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::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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 = "trace", skip(ecx), ret)]
24pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<D, I>(
25    ecx: &EvalCtxt<'_, D>,
26    ty: I::Ty,
27) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
28where
29    D: SolverDelegate<Interner = I>,
30    I: Interner,
31{
32    let cx = ecx.cx();
33    match ty.kind() {
34        ty::Uint(_)
35        | ty::Int(_)
36        | ty::Bool
37        | ty::Float(_)
38        | ty::FnDef(..)
39        | ty::FnPtr(..)
40        | ty::Error(_)
41        | ty::Never
42        | ty::Char => Ok(ty::Binder::dummy(vec![])),
43
44        // This branch is only for `experimental_default_bounds`.
45        // Other foreign types were rejected earlier in
46        // `disqualify_auto_trait_candidate_due_to_possible_impl`.
47        ty::Foreign(..) => Ok(ty::Binder::dummy(vec![])),
48
49        // Treat `str` like it's defined as `struct str([u8]);`
50        ty::Str => Ok(ty::Binder::dummy(vec![Ty::new_slice(cx, Ty::new_u8(cx))])),
51
52        ty::Dynamic(..)
53        | ty::Param(..)
54        | ty::Alias(
55            ty::IsRigid::Yes,
56            ty::AliasTy {
57                kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, ..
58            },
59        )
60        | ty::Placeholder(..)
61        | ty::Alias(ty::IsRigid::No, _)
62        | ty::Bound(..)
63        | ty::Infer(_)
64        | ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => {
65            panic!("unexpected type `{ty:?}`")
66        }
67
68        ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
69            Ok(ty::Binder::dummy(vec![element_ty]))
70        }
71
72        ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
73            Ok(ty::Binder::dummy(vec![element_ty]))
74        }
75
76        ty::Tuple(tys) => {
77            // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
78            Ok(ty::Binder::dummy(tys.to_vec()))
79        }
80
81        ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
82
83        ty::CoroutineClosure(_, args) => {
84            Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
85        }
86
87        ty::Coroutine(def_id, args) => Ok(ty::Binder::dummy(vec![
88            args.as_coroutine().tupled_upvars_ty(),
89            Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
90        ])),
91
92        ty::CoroutineWitness(def_id, args) => Ok(ecx
93            .cx()
94            .coroutine_hidden_types(def_id)
95            .instantiate(cx, args)
96            .skip_norm_wip()
97            .map_bound(|bound| bound.types.to_vec())),
98
99        ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
100
101        // For `PhantomData<T>`, we pass `T`.
102        ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
103
104        ty::Adt(def, args) => Ok(ty::Binder::dummy(
105            def.all_field_tys(cx)
106                .iter_instantiated(cx, args)
107                .map(Unnormalized::skip_norm_wip)
108                .collect(),
109        )),
110    }
111}
112
113{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::TRACE <=
                ::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("instantiate_constituent_tys_for_sizedness_trait",
                                "rustc_next_trait_solver::solve::assembly::structural_traits",
                                ::tracing::Level::TRACE,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                                ::tracing_core::__macro_support::Option::Some(113u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("sizedness")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("sizedness");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("ty")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("ty");
                                                    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::TRACE <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::TRACE <=
                                ::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(&sizedness)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
                                                        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:
                                Result<ty::Binder<I, Vec<I::Ty>>, NoSolution> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        match ty.kind() {
                            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Uint(_) |
                                ty::Int(_) | ty::Bool | ty::Float(_) | ty::FnDef(..) |
                                ty::FnPtr(..) | ty::RawPtr(..) | ty::Char | ty::Ref(..) |
                                ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Array(..)
                                | ty::Pat(..) | ty::Closure(..) | ty::CoroutineClosure(..) |
                                ty::Never | ty::Error(_) =>
                                Ok(ty::Binder::dummy(::alloc::vec::Vec::new())),
                            ty::Str | ty::Slice(_) | ty::Dynamic(..) =>
                                match sizedness {
                                    SizedTraitKind::Sized => Err(NoSolution),
                                    SizedTraitKind::MetaSized =>
                                        Ok(ty::Binder::dummy(::alloc::vec::Vec::new())),
                                },
                            ty::Foreign(..) => Err(NoSolution),
                            ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) =>
                                Err(NoSolution),
                            ty::Bound(..) |
                                ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_)
                                | ty::FreshFloatTy(_)) => {
                                {
                                    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
                                            ty));
                                }
                            }
                            ty::UnsafeBinder(bound_ty) =>
                                Ok(bound_ty.map_bound(|ty|
                                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                    [ty])))),
                            ty::Tuple(tys) =>
                                Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new,
                                            |ty|
                                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                        [ty]))))),
                            ty::Adt(def, args) => {
                                if let Some(crit) =
                                        def.sizedness_constraint(ecx.cx(), sizedness) {
                                    Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                    [crit.instantiate(ecx.cx(), args).skip_norm_wip()]))))
                                } else { Ok(ty::Binder::dummy(::alloc::vec::Vec::new())) }
                            }
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs:113",
                        "rustc_next_trait_solver::solve::assembly::structural_traits",
                        ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                        ::tracing_core::__macro_support::Option::Some(113u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                        ::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::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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 = "trace", skip(ecx), ret)]
114pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
115    ecx: &EvalCtxt<'_, D>,
116    sizedness: SizedTraitKind,
117    ty: I::Ty,
118) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
119where
120    D: SolverDelegate<Interner = I>,
121    I: Interner,
122{
123    match ty.kind() {
124        // impl {Meta,}Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char
125        // impl {Meta,}Sized for &mut? T, [T; N], dyn* Trait, !, Coroutine, CoroutineWitness
126        // impl {Meta,}Sized for Closure, CoroutineClosure
127        ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
128        | ty::Uint(_)
129        | ty::Int(_)
130        | ty::Bool
131        | ty::Float(_)
132        | ty::FnDef(..)
133        | ty::FnPtr(..)
134        | ty::RawPtr(..)
135        | ty::Char
136        | ty::Ref(..)
137        | ty::Coroutine(..)
138        | ty::CoroutineWitness(..)
139        | ty::Array(..)
140        | ty::Pat(..)
141        | ty::Closure(..)
142        | ty::CoroutineClosure(..)
143        | ty::Never
144        | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
145
146        // impl {Meta,}Sized for str, [T], dyn Trait
147        ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
148            SizedTraitKind::Sized => Err(NoSolution),
149            SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
150        },
151
152        // impl {} for extern type
153        ty::Foreign(..) => Err(NoSolution),
154
155        ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
156
157        ty::Bound(..)
158        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
159            panic!("unexpected type `{ty:?}`")
160        }
161
162        ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
163
164        // impl {Meta,}Sized for ()
165        // impl {Meta,}Sized for (T1, T2, .., Tn) where Tn: {Meta,}Sized if n >= 1
166        ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
167
168        // impl {Meta,}Sized for Adt<Args...>
169        //   where {meta,pointee,}sized_constraint(Adt)<Args...>: {Meta,}Sized
170        //
171        //   `{meta,pointee,}sized_constraint(Adt)` is the deepest struct trail that can be
172        //   determined by the definition of `Adt`, independent of the generic args.
173        //
174        // impl {Meta,}Sized for Adt<Args...>
175        //   if {meta,pointee,}sized_constraint(Adt) == None
176        //
177        //   As a performance optimization, `{meta,pointee,}sized_constraint(Adt)` can return `None`
178        //   if the ADTs definition implies that it is {meta,}sized by for all possible args.
179        //   In this case, the builtin impl will have no nested subgoals. This is a
180        //   "best effort" optimization and `{meta,pointee,}sized_constraint` may return `Some`,
181        //   even if the ADT is {meta,pointee,}sized for all possible args.
182        ty::Adt(def, args) => {
183            if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
184                Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args).skip_norm_wip()]))
185            } else {
186                Ok(ty::Binder::dummy(vec![]))
187            }
188        }
189    }
190}
191
192{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::TRACE <=
                ::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("instantiate_constituent_tys_for_copy_clone_trait",
                                "rustc_next_trait_solver::solve::assembly::structural_traits",
                                ::tracing::Level::TRACE,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                                ::tracing_core::__macro_support::Option::Some(192u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("ty")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("ty");
                                                    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::TRACE <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::TRACE <=
                                ::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(&ty)
                                                        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:
                                Result<ty::Binder<I, Vec<I::Ty>>, NoSolution> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        match ty.kind() {
                            ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) =>
                                Ok(ty::Binder::dummy(::alloc::vec::Vec::new())),
                            ty::Uint(_) | ty::Int(_) |
                                ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Bool |
                                ty::Float(_) | ty::Char | ty::RawPtr(..) | ty::Never |
                                ty::Ref(_, _, Mutability::Not) | ty::Array(..) =>
                                Err(NoSolution),
                            ty::Pat(ty, ..) =>
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [ty])))),
                            ty::Dynamic(..) | ty::Str | ty::Slice(_) | ty::Foreign(..) |
                                ty::Ref(_, _, Mutability::Mut) | ty::Adt(_, _) |
                                ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) |
                                ty::Placeholder(..) => Err(NoSolution),
                            ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
                            ty::Closure(_, args) =>
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [args.as_closure().tupled_upvars_ty()])))),
                            ty::CoroutineClosure(_, args) => {
                                Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                [args.as_coroutine_closure().tupled_upvars_ty()]))))
                            }
                            ty::Coroutine(def_id, args) =>
                                match ecx.cx().coroutine_movability(def_id) {
                                    Movability::Static => Err(NoSolution),
                                    Movability::Movable => {
                                        if ecx.cx().features().coroutine_clone() {
                                            Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                            [args.as_coroutine().tupled_upvars_ty(),
                                                                    Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id,
                                                                        args)]))))
                                        } else { Err(NoSolution) }
                                    }
                                },
                            ty::UnsafeBinder(_) => Err(NoSolution),
                            ty::CoroutineWitness(def_id, args) =>
                                Ok(ecx.cx().coroutine_hidden_types(def_id).instantiate(ecx.cx(),
                                                args).skip_norm_wip().map_bound(|bound|
                                            bound.types.to_vec())),
                            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_)
                                | ty::FreshFloatTy(_)) | ty::Alias(ty::IsRigid::No, _) |
                                ty::Bound(..) => {
                                {
                                    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
                                            ty));
                                }
                            }
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs:192",
                        "rustc_next_trait_solver::solve::assembly::structural_traits",
                        ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                        ::tracing_core::__macro_support::Option::Some(192u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                        ::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::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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 = "trace", skip(ecx), ret)]
193pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
194    ecx: &EvalCtxt<'_, D>,
195    ty: I::Ty,
196) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
197where
198    D: SolverDelegate<Interner = I>,
199    I: Interner,
200{
201    match ty.kind() {
202        // impl Copy/Clone for FnDef, FnPtr
203        ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
204
205        // Implementations are provided in core
206        ty::Uint(_)
207        | ty::Int(_)
208        | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
209        | ty::Bool
210        | ty::Float(_)
211        | ty::Char
212        | ty::RawPtr(..)
213        | ty::Never
214        | ty::Ref(_, _, Mutability::Not)
215        | ty::Array(..) => Err(NoSolution),
216
217        // Cannot implement in core, as we can't be generic over patterns yet,
218        // so we'd have to list all patterns and type combinations.
219        ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
220
221        ty::Dynamic(..)
222        | ty::Str
223        | ty::Slice(_)
224        | ty::Foreign(..)
225        | ty::Ref(_, _, Mutability::Mut)
226        | ty::Adt(_, _)
227        | ty::Alias(ty::IsRigid::Yes, _)
228        | ty::Param(_)
229        | ty::Placeholder(..) => Err(NoSolution),
230
231        // impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
232        ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
233
234        // impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
235        ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
236
237        // impl Copy/Clone for CoroutineClosure where Self::TupledUpvars: Copy/Clone
238        ty::CoroutineClosure(_, args) => {
239            Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
240        }
241
242        // only when `coroutine_clone` is enabled and the coroutine is movable
243        // impl Copy/Clone for Coroutine where T: Copy/Clone forall T in (upvars, witnesses)
244        ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
245            Movability::Static => Err(NoSolution),
246            Movability::Movable => {
247                if ecx.cx().features().coroutine_clone() {
248                    Ok(ty::Binder::dummy(vec![
249                        args.as_coroutine().tupled_upvars_ty(),
250                        Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
251                    ]))
252                } else {
253                    Err(NoSolution)
254                }
255            }
256        },
257
258        ty::UnsafeBinder(_) => Err(NoSolution),
259
260        // impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types
261        ty::CoroutineWitness(def_id, args) => Ok(ecx
262            .cx()
263            .coroutine_hidden_types(def_id)
264            .instantiate(ecx.cx(), args)
265            .skip_norm_wip()
266            .map_bound(|bound| bound.types.to_vec())),
267
268        ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
269        | ty::Alias(ty::IsRigid::No, _)
270        | ty::Bound(..) => {
271            panic!("unexpected type `{ty:?}`")
272        }
273    }
274}
275
276// Returns a binder of the tupled inputs types and output type from a builtin callable type.
277pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
278    cx: I,
279    self_ty: I::Ty,
280    goal_kind: ty::ClosureKind,
281) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
282    match self_ty.kind() {
283        // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
284        ty::FnDef(def_id, args) => {
285            let sig = cx.fn_sig(def_id);
286            if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
287                Ok(Some(
288                    sig.instantiate(cx, args.no_bound_vars().unwrap())
289                        .skip_norm_wip()
290                        .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
291                ))
292            } else {
293                Err(NoSolution)
294            }
295        }
296        // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
297        ty::FnPtr(sig_tys, hdr) => {
298            let sig = sig_tys.with(hdr);
299            if sig.is_fn_trait_compatible() {
300                Ok(Some(
301                    sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
302                ))
303            } else {
304                Err(NoSolution)
305            }
306        }
307        ty::Closure(_, args) => {
308            let closure_args = args.as_closure();
309            match closure_args.kind_ty().to_opt_closure_kind() {
310                // If the closure's kind doesn't extend the goal kind,
311                // then the closure doesn't implement the trait.
312                Some(closure_kind) => {
313                    if !closure_kind.extends(goal_kind) {
314                        return Err(NoSolution);
315                    }
316                }
317                // Closure kind is not yet determined, so we return ambiguity unless
318                // the expected kind is `FnOnce` as that is always implemented.
319                None => {
320                    if goal_kind != ty::ClosureKind::FnOnce {
321                        return Ok(None);
322                    }
323                }
324            }
325            Ok(Some(
326                closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
327            ))
328        }
329
330        // Coroutine-closures don't implement `Fn` traits the normal way.
331        // Instead, they always implement `FnOnce`, but only implement
332        // `FnMut`/`Fn` if they capture no upvars, since those may borrow
333        // from the closure.
334        ty::CoroutineClosure(def_id, args) => {
335            let args = args.as_coroutine_closure();
336            let kind_ty = args.kind_ty();
337            let sig = args.coroutine_closure_sig().skip_binder();
338
339            let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
340                && !args.tupled_upvars_ty().is_ty_var()
341            {
342                if !kind.extends(goal_kind) {
343                    return Err(NoSolution);
344                }
345
346                // A coroutine-closure implements `FnOnce` *always*, since it may
347                // always be called once. It additionally implements `Fn`/`FnMut`
348                // only if it has no upvars referencing the closure-env lifetime,
349                // and if the closure kind permits it.
350                if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
351                    return Err(NoSolution);
352                }
353
354                coroutine_closure_to_certain_coroutine(
355                    cx,
356                    goal_kind,
357                    // No captures by ref, so this doesn't matter.
358                    Region::new_static(cx),
359                    def_id,
360                    args,
361                    sig,
362                )
363            } else {
364                // Closure kind is not yet determined, so we return ambiguity unless
365                // the expected kind is `FnOnce` as that is always implemented.
366                if goal_kind != ty::ClosureKind::FnOnce {
367                    return Ok(None);
368                }
369
370                coroutine_closure_to_ambiguous_coroutine(
371                    cx,
372                    goal_kind, // No captures by ref, so this doesn't matter.
373                    Region::new_static(cx),
374                    def_id,
375                    args,
376                    sig,
377                )
378            };
379
380            Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
381        }
382
383        ty::Bool
384        | ty::Char
385        | ty::Int(_)
386        | ty::Uint(_)
387        | ty::Float(_)
388        | ty::Adt(_, _)
389        | ty::Foreign(_)
390        | ty::Str
391        | ty::Array(_, _)
392        | ty::Slice(_)
393        | ty::RawPtr(_, _)
394        | ty::Ref(_, _, _)
395        | ty::Dynamic(_, _)
396        | ty::Coroutine(_, _)
397        | ty::CoroutineWitness(..)
398        | ty::Never
399        | ty::Tuple(_)
400        | ty::Pat(_, _)
401        | ty::UnsafeBinder(_)
402        | ty::Alias(ty::IsRigid::Yes, _)
403        | ty::Param(_)
404        | ty::Placeholder(..)
405        | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
406        | ty::Error(_) => Err(NoSolution),
407
408        ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
409        | ty::Alias(ty::IsRigid::No, _)
410        | ty::Bound(..) => {
411            {
    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
            self_ty));
}panic!("unexpected type `{self_ty:?}`")
412        }
413    }
414}
415
416/// Relevant types for an async callable, including its inputs, output,
417/// and the return type you get from awaiting the output.
418#[automatically_derived]
impl<I: Interner> ::core::clone::Clone for AsyncCallableRelevantTypes<I> where
    I: Interner {
    #[inline]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]
impl<I: Interner> ::core::marker::Copy for AsyncCallableRelevantTypes<I> where
    I: Interner {
}
#[automatically_derived]
impl<I: Interner> ::core::fmt::Debug for AsyncCallableRelevantTypes<I> where
    I: Interner {
    fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
        -> ::core::fmt::Result {
        match self {
            AsyncCallableRelevantTypes {
                tupled_inputs_ty: ref __field_tupled_inputs_ty,
                output_coroutine_ty: ref __field_output_coroutine_ty,
                coroutine_return_ty: ref __field_coroutine_return_ty } => {
                let mut __builder =
                    ::core::fmt::Formatter::debug_struct(__f,
                        "AsyncCallableRelevantTypes");
                ::core::fmt::DebugStruct::field(&mut __builder,
                    "tupled_inputs_ty", __field_tupled_inputs_ty);
                ::core::fmt::DebugStruct::field(&mut __builder,
                    "output_coroutine_ty", __field_output_coroutine_ty);
                ::core::fmt::DebugStruct::field(&mut __builder,
                    "coroutine_return_ty", __field_coroutine_return_ty);
                ::core::fmt::DebugStruct::finish(&mut __builder)
            }
        }
    }
}#[derive_where(Clone, Copy, Debug; I: Interner)]
419#[derive(const _: () =
    {
        impl<I: Interner> ::rustc_type_ir::TypeVisitable<I> for
            AsyncCallableRelevantTypes<I> where I: Interner,
            I::Ty: ::rustc_type_ir::TypeVisitable<I> {
            fn visit_with<__V: ::rustc_type_ir::TypeVisitor<I>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    AsyncCallableRelevantTypes {
                        tupled_inputs_ty: ref __binding_0,
                        output_coroutine_ty: ref __binding_1,
                        coroutine_return_ty: ref __binding_2 } => {
                        {
                            match ::rustc_type_ir::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_type_ir::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_type_ir::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_type_ir::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_type_ir::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(__binding_2,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_type_ir::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_type_ir::VisitorResult>::output()
            }
        }
    };TypeVisitable_Generic, const _: () =
    {
        impl<I: Interner> ::rustc_type_ir::TypeFoldable<I> for
            AsyncCallableRelevantTypes<I> where I: Interner,
            I::Ty: ::rustc_type_ir::TypeFoldable<I> {
            fn try_fold_with<__F: ::rustc_type_ir::FallibleTypeFolder<I>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        AsyncCallableRelevantTypes {
                            tupled_inputs_ty: __binding_0,
                            output_coroutine_ty: __binding_1,
                            coroutine_return_ty: __binding_2 } => {
                            AsyncCallableRelevantTypes {
                                tupled_inputs_ty: ::rustc_type_ir::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                                output_coroutine_ty: ::rustc_type_ir::TypeFoldable::try_fold_with(__binding_1,
                                        __folder)?,
                                coroutine_return_ty: ::rustc_type_ir::TypeFoldable::try_fold_with(__binding_2,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_type_ir::TypeFolder<I>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    AsyncCallableRelevantTypes {
                        tupled_inputs_ty: __binding_0,
                        output_coroutine_ty: __binding_1,
                        coroutine_return_ty: __binding_2 } => {
                        AsyncCallableRelevantTypes {
                            tupled_inputs_ty: ::rustc_type_ir::TypeFoldable::fold_with(__binding_0,
                                __folder),
                            output_coroutine_ty: ::rustc_type_ir::TypeFoldable::fold_with(__binding_1,
                                __folder),
                            coroutine_return_ty: ::rustc_type_ir::TypeFoldable::fold_with(__binding_2,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable_Generic)]
420pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
421    pub tupled_inputs_ty: I::Ty,
422    /// Type returned by calling the closure
423    /// i.e. `f()`.
424    pub output_coroutine_ty: I::Ty,
425    /// Type returned by `await`ing the output
426    /// i.e. `f().await`.
427    pub coroutine_return_ty: I::Ty,
428}
429
430// Returns a binder of the tupled inputs types, output type, and coroutine type
431// from a builtin coroutine-closure type. If we don't yet know the closure kind of
432// the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper`
433// which enforces the closure is actually callable with the given trait. When we
434// know the kind already, we can short-circuit this check.
435pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
436    cx: I,
437    self_ty: I::Ty,
438    goal_kind: ty::ClosureKind,
439    env_region: Region<I>,
440) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
441    match self_ty.kind() {
442        ty::CoroutineClosure(def_id, args) => {
443            if !cx.coroutine_is_async(cx.coroutine_for_closure(def_id)) {
444                return Err(NoSolution);
445            }
446
447            let args = args.as_coroutine_closure();
448            let kind_ty = args.kind_ty();
449            let sig = args.coroutine_closure_sig().skip_binder();
450            let mut nested = ::alloc::vec::Vec::new()vec![];
451
452            let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
453                && !args.tupled_upvars_ty().is_ty_var()
454            {
455                if !kind.extends(goal_kind) {
456                    return Err(NoSolution);
457                }
458
459                coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
460            } else {
461                // When we don't know the closure kind (and therefore also the closure's upvars,
462                // which are computed at the same time), we must delay the computation of the
463                // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
464                // goal functions similarly to the old `ClosureKind` predicate, and ensures that
465                // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
466                // will project to the right upvars for the generator, appending the inputs and
467                // coroutine upvars respecting the closure kind.
468                nested.push(
469                    ty::TraitRef::new(
470                        cx,
471                        cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
472                        [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
473                    )
474                    .upcast(cx),
475                );
476
477                coroutine_closure_to_ambiguous_coroutine(
478                    cx, goal_kind, env_region, def_id, args, sig,
479                )
480            };
481
482            Ok((
483                args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
484                    tupled_inputs_ty: sig.tupled_inputs_ty,
485                    output_coroutine_ty: coroutine_ty,
486                    coroutine_return_ty: sig.return_ty,
487                }),
488                nested,
489            ))
490        }
491
492        ty::FnDef(def_id, _) => {
493            let sig = self_ty.fn_sig(cx);
494            if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
495                fn_item_to_async_callable(cx, sig)
496            } else {
497                Err(NoSolution)
498            }
499        }
500        ty::FnPtr(..) => {
501            let sig = self_ty.fn_sig(cx);
502            if sig.is_fn_trait_compatible() {
503                fn_item_to_async_callable(cx, sig)
504            } else {
505                Err(NoSolution)
506            }
507        }
508
509        ty::Closure(_, args) => {
510            let args = args.as_closure();
511            let bound_sig = args.sig();
512            let sig = bound_sig.skip_binder();
513            let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
514            // `Closure`s only implement `AsyncFn*` when their return type
515            // implements `Future`.
516            let mut nested = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id,
                            [sig.output()])).upcast(cx)]))vec![
517                bound_sig
518                    .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
519                    .upcast(cx),
520            ];
521
522            // Additionally, we need to check that the closure kind
523            // is still compatible.
524            let kind_ty = args.kind_ty();
525            if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
526                if !closure_kind.extends(goal_kind) {
527                    return Err(NoSolution);
528                }
529            } else {
530                let async_fn_kind_trait_def_id =
531                    cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
532                // When we don't know the closure kind (and therefore also the closure's upvars,
533                // which are computed at the same time), we must delay the computation of the
534                // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
535                // goal functions similarly to the old `ClosureKind` predicate, and ensures that
536                // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
537                // will project to the right upvars for the generator, appending the inputs and
538                // coroutine upvars respecting the closure kind.
539                nested.push(
540                    ty::TraitRef::new(
541                        cx,
542                        async_fn_kind_trait_def_id,
543                        [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
544                    )
545                    .upcast(cx),
546                );
547            }
548
549            let future_output_def_id =
550                cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
551            let future_output_ty =
552                Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]);
553            Ok((
554                bound_sig.rebind(AsyncCallableRelevantTypes {
555                    tupled_inputs_ty: sig.inputs().get(0).unwrap(),
556                    output_coroutine_ty: sig.output(),
557                    coroutine_return_ty: future_output_ty,
558                }),
559                nested,
560            ))
561        }
562
563        ty::Bool
564        | ty::Char
565        | ty::Int(_)
566        | ty::Uint(_)
567        | ty::Float(_)
568        | ty::Adt(_, _)
569        | ty::Foreign(_)
570        | ty::Str
571        | ty::Array(_, _)
572        | ty::Pat(_, _)
573        | ty::Slice(_)
574        | ty::RawPtr(_, _)
575        | ty::Ref(_, _, _)
576        | ty::Dynamic(_, _)
577        | ty::Coroutine(_, _)
578        | ty::CoroutineWitness(..)
579        | ty::Never
580        | ty::UnsafeBinder(_)
581        | ty::Tuple(_)
582        | ty::Alias(ty::IsRigid::Yes, _)
583        | ty::Param(_)
584        | ty::Placeholder(..)
585        | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
586        | ty::Error(_) => Err(NoSolution),
587
588        ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
589        | ty::Alias(ty::IsRigid::No, _)
590        | ty::Bound(..) => {
591            {
    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
            self_ty));
}panic!("unexpected type `{self_ty:?}`")
592        }
593    }
594}
595
596fn fn_item_to_async_callable<I: Interner>(
597    cx: I,
598    bound_sig: ty::Binder<I, ty::FnSig<I>>,
599) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
600    let sig = bound_sig.skip_binder();
601    let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
602    // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
603    // return type implements `Future`.
604    let nested = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id,
                            [sig.output()])).upcast(cx)]))vec![
605        bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
606    ];
607    let future_output_def_id =
608        cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
609    let future_output_ty =
610        Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]);
611    Ok((
612        bound_sig.rebind(AsyncCallableRelevantTypes {
613            tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
614            output_coroutine_ty: sig.output(),
615            coroutine_return_ty: future_output_ty,
616        }),
617        nested,
618    ))
619}
620
621/// Given a coroutine-closure, project to its returned coroutine when we are *certain*
622/// that the closure's kind is compatible with the goal.
623fn coroutine_closure_to_certain_coroutine<I: Interner>(
624    cx: I,
625    goal_kind: ty::ClosureKind,
626    goal_region: Region<I>,
627    def_id: I::CoroutineClosureId,
628    args: ty::CoroutineClosureArgs<I>,
629    sig: ty::CoroutineClosureSignature<I>,
630) -> I::Ty {
631    sig.to_coroutine_given_kind_and_upvars(
632        cx,
633        args.parent_args(),
634        cx.coroutine_for_closure(def_id),
635        goal_kind,
636        goal_region,
637        args.tupled_upvars_ty(),
638        args.coroutine_captures_by_ref_ty(),
639    )
640}
641
642/// Given a coroutine-closure, project to its returned coroutine when we are *not certain*
643/// that the closure's kind is compatible with the goal, and therefore also don't know
644/// yet what the closure's upvars are.
645///
646/// Note that we do not also push a `AsyncFnKindHelper` goal here.
647fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
648    cx: I,
649    goal_kind: ty::ClosureKind,
650    goal_region: Region<I>,
651    def_id: I::CoroutineClosureId,
652    args: ty::CoroutineClosureArgs<I>,
653    sig: ty::CoroutineClosureSignature<I>,
654) -> I::Ty {
655    let upvars_projection_def_id =
656        cx.require_projection_lang_item(SolverProjectionLangItem::AsyncFnKindUpvars);
657    let tupled_upvars_ty = Ty::new_projection(
658        cx,
659        ty::IsRigid::No,
660        upvars_projection_def_id,
661        [
662            I::GenericArg::from(args.kind_ty()),
663            Ty::from_closure_kind(cx, goal_kind).into(),
664            goal_region.into(),
665            sig.tupled_inputs_ty.into(),
666            args.tupled_upvars_ty().into(),
667            args.coroutine_captures_by_ref_ty().into(),
668        ],
669    );
670    sig.to_coroutine(
671        cx,
672        args.parent_args(),
673        Ty::from_closure_kind(cx, goal_kind),
674        cx.coroutine_for_closure(def_id),
675        tupled_upvars_ty,
676    )
677}
678
679/// This duplicates `extract_tupled_inputs_and_output_from_callable` but needs
680/// to return different information (namely, the def id and args) so that we can
681/// create const conditions.
682///
683/// Doing so on all calls to `extract_tupled_inputs_and_output_from_callable`
684/// would be wasteful.
685{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::TRACE <=
                ::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("extract_fn_def_from_const_callable",
                                "rustc_next_trait_solver::solve::assembly::structural_traits",
                                ::tracing::Level::TRACE,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                                ::tracing_core::__macro_support::Option::Some(685u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("self_ty")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("self_ty");
                                                    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::TRACE <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::TRACE <=
                                ::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(&self_ty)
                                                        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:
                                Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId,
                                I::GenericArgs), NoSolution> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        match self_ty.kind() {
                            ty::FnDef(def_id, args) => {
                                let args = args.no_bound_vars().unwrap();
                                let sig = cx.fn_sig(def_id);
                                if sig.skip_binder().is_fn_trait_compatible() &&
                                            !cx.has_target_features(def_id) && cx.fn_is_const(def_id) {
                                    Ok((sig.instantiate(cx,
                                                        args).skip_norm_wip().map_bound(|sig|
                                                    (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
                                            def_id.into(), args))
                                } else { return Err(NoSolution); }
                            }
                            ty::FnPtr(..) => { return Err(NoSolution); }
                            ty::Closure(def, args) => {
                                if cx.closure_is_const(def) {
                                    let closure_args = args.as_closure();
                                    Ok((closure_args.sig().map_bound(|sig|
                                                    (sig.inputs().get(0).unwrap(), sig.output())), def.into(),
                                            args))
                                } else { return Err(NoSolution); }
                            }
                            ty::CoroutineClosure(..) => { return Err(NoSolution); }
                            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) |
                                ty::Float(_) | ty::Adt(_, _) | ty::Foreign(_) | ty::Str |
                                ty::Array(_, _) | ty::Slice(_) | ty::RawPtr(_, _) |
                                ty::Ref(_, _, _) | ty::Dynamic(_, _) | ty::Coroutine(_, _) |
                                ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) |
                                ty::Pat(_, _) | ty::Alias(ty::IsRigid::Yes, _) |
                                ty::Param(_) | ty::Placeholder(..) |
                                ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Error(_) |
                                ty::UnsafeBinder(_) => return Err(NoSolution),
                            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_)
                                | ty::FreshFloatTy(_)) | ty::Alias(ty::IsRigid::No, _) |
                                ty::Bound(..) => {
                                {
                                    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
                                            self_ty));
                                }
                            }
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs:685",
                        "rustc_next_trait_solver::solve::assembly::structural_traits",
                        ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/12433c307b5a497388ffe2f4e49dbf1ab8c71fa0/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs"),
                        ::tracing_core::__macro_support::Option::Some(685u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::assembly::structural_traits"),
                        ::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::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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 = "trace", skip(cx), ret)]
686pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
687    cx: I,
688    self_ty: I::Ty,
689) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
690    match self_ty.kind() {
691        ty::FnDef(def_id, args) => {
692            // FIXME
693            let args = args.no_bound_vars().unwrap();
694
695            let sig = cx.fn_sig(def_id);
696            if sig.skip_binder().is_fn_trait_compatible()
697                && !cx.has_target_features(def_id)
698                && cx.fn_is_const(def_id)
699            {
700                Ok((
701                    sig.instantiate(cx, args)
702                        .skip_norm_wip()
703                        .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
704                    def_id.into(),
705                    args,
706                ))
707            } else {
708                return Err(NoSolution);
709            }
710        }
711        // `FnPtr`s are not const for now.
712        ty::FnPtr(..) => {
713            return Err(NoSolution);
714        }
715        ty::Closure(def, args) => {
716            if cx.closure_is_const(def) {
717                let closure_args = args.as_closure();
718                Ok((
719                    closure_args
720                        .sig()
721                        .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
722                    def.into(),
723                    args,
724                ))
725            } else {
726                return Err(NoSolution);
727            }
728        }
729        // `CoroutineClosure`s are not const for now.
730        ty::CoroutineClosure(..) => {
731            return Err(NoSolution);
732        }
733
734        ty::Bool
735        | ty::Char
736        | ty::Int(_)
737        | ty::Uint(_)
738        | ty::Float(_)
739        | ty::Adt(_, _)
740        | ty::Foreign(_)
741        | ty::Str
742        | ty::Array(_, _)
743        | ty::Slice(_)
744        | ty::RawPtr(_, _)
745        | ty::Ref(_, _, _)
746        | ty::Dynamic(_, _)
747        | ty::Coroutine(_, _)
748        | ty::CoroutineWitness(..)
749        | ty::Never
750        | ty::Tuple(_)
751        | ty::Pat(_, _)
752        | ty::Alias(ty::IsRigid::Yes, _)
753        | ty::Param(_)
754        | ty::Placeholder(..)
755        | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
756        | ty::Error(_)
757        | ty::UnsafeBinder(_) => return Err(NoSolution),
758
759        ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
760        | ty::Alias(ty::IsRigid::No, _)
761        | ty::Bound(..) => {
762            panic!("unexpected type `{self_ty:?}`")
763        }
764    }
765}
766
767// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
768// the old solver, for as long as that exists.
769pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
770    cx: I,
771    self_ty: I::Ty,
772) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
773    let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
774
775    match self_ty.kind() {
776        // `ManuallyDrop` is trivially `[const] Destruct` as we do not run any drop glue on it.
777        ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()vec![]),
778
779        // An ADT is `[const] Destruct` only if all of the fields are,
780        // *and* if there is a `Drop` impl, that `Drop` impl is also `[const]`.
781        ty::Adt(adt_def, args) => {
782            let mut const_conditions: Vec<_> = adt_def
783                .all_field_tys(cx)
784                .iter_instantiated(cx, args)
785                .map(Unnormalized::skip_norm_wip)
786                .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
787                .collect();
788            match adt_def.destructor(cx) {
789                // `Drop` impl exists, but it's not const. Type cannot be `[const] Destruct`.
790                Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
791                // `Drop` impl exists, and it's const. Require `Ty: [const] Drop` to hold.
792                Some(AdtDestructorKind::Const) => {
793                    let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
794                    let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
795                    const_conditions.push(drop_trait_ref);
796                }
797                // No `Drop` impl, no need to require anything else.
798                None => {}
799            }
800            Ok(const_conditions)
801        }
802
803        ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
804            Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ty::TraitRef::new(cx, destruct_def_id, [ty])]))vec![ty::TraitRef::new(cx, destruct_def_id, [ty])])
805        }
806
807        ty::Tuple(tys) => Ok(tys
808            .iter()
809            .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
810            .collect()),
811
812        // Trivially implement `[const] Destruct`
813        ty::Bool
814        | ty::Char
815        | ty::Int(..)
816        | ty::Uint(..)
817        | ty::Float(..)
818        | ty::Str
819        | ty::RawPtr(..)
820        | ty::Ref(..)
821        | ty::FnDef(..)
822        | ty::FnPtr(..)
823        | ty::Never
824        | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
825        | ty::Error(_) => Ok(::alloc::vec::Vec::new()vec![]),
826
827        // Closures are [const] Destruct when all of their upvars (captures) are [const] Destruct.
828        ty::Closure(_, args) => {
829            let closure_args = args.as_closure();
830            Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ty::TraitRef::new(cx, destruct_def_id,
                    [closure_args.tupled_upvars_ty()])]))vec![ty::TraitRef::new(cx, destruct_def_id, [closure_args.tupled_upvars_ty()])])
831        }
832        // Coroutines could implement `[const] Drop`,
833        // but they don't really need to right now.
834        ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
835            Err(NoSolution)
836        }
837
838        // FIXME(unsafe_binders): Unsafe binders could implement `[const] Drop`
839        // if their inner type implements it.
840        ty::UnsafeBinder(_) => Err(NoSolution),
841
842        ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
843            Err(NoSolution)
844        }
845
846        ty::Bound(..)
847        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
848            {
    ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
            self_ty));
}panic!("unexpected type `{self_ty:?}`")
849        }
850    }
851}
852
853/// Assemble a list of predicates that would be present on a theoretical
854/// user impl for an object type. These predicates must be checked any time
855/// we assemble a built-in object candidate for an object type, since they
856/// are not implied by the well-formedness of the type.
857///
858/// For example, given the following traits:
859///
860/// ```rust,ignore (theoretical code)
861/// trait Foo: Baz {
862///     type Bar: Copy;
863/// }
864///
865/// trait Baz {}
866/// ```
867///
868/// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
869/// pair of theoretical impls:
870///
871/// ```rust,ignore (theoretical code)
872/// impl Foo for dyn Foo<Item = Ty>
873/// where
874///     Self: Baz,
875///     <Self as Foo>::Bar: Copy,
876/// {
877///     type Bar = Ty;
878/// }
879///
880/// impl Baz for dyn Foo<Item = Ty> {}
881/// ```
882///
883/// However, in order to make such impls non-cyclical, we need to do an
884/// additional step of eagerly folding the associated types in the where
885/// clauses of the impl. In this example, that means replacing
886/// `<Self as Foo>::Bar` with `Ty` in the first impl.
887pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
888    ecx: &mut EvalCtxt<'_, D>,
889    param_env: I::ParamEnv,
890    trait_ref: ty::TraitRef<I>,
891    object_bounds: I::BoundExistentialPredicates,
892) -> Result<Vec<Goal<I, I::Predicate>>, AmbiguousOrRerunNonErased>
893where
894    D: SolverDelegate<Interner = I>,
895    I: Interner,
896{
897    let cx = ecx.cx();
898    let mut requirements = ::alloc::vec::Vec::new()vec![];
899    // Elaborating all supertrait outlives obligations here is not soundness critical,
900    // since if we just used the unelaborated set, then the transitive supertraits would
901    // be reachable when proving the former. However, since we elaborate all supertrait
902    // outlives obligations when confirming impls, we would end up with a different set
903    // of outlives obligations here if we didn't do the same, leading to ambiguity.
904    // FIXME(-Znext-solver=coinductive): Adding supertraits here can be removed once we
905    // make impls coinductive always, since they'll always need to prove their supertraits.
906    requirements.extend(elaborate::elaborate(
907        cx,
908        cx.explicit_super_clauses_of(trait_ref.def_id)
909            .iter_instantiated(cx, trait_ref.args)
910            .map(Unnormalized::skip_norm_wip)
911            .map(|(pred, _)| pred),
912    ));
913
914    // FIXME(mgca): Also add associated consts to
915    // the requirements here.
916    for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
917        // associated types that require `Self: Sized` do not show up in the built-in
918        // implementation of `Trait for dyn Trait`, and can be dropped here.
919        if cx.generics_require_sized_self(associated_type_def_id) {
920            continue;
921        }
922
923        requirements.extend(
924            cx.item_bounds(associated_type_def_id)
925                .iter_instantiated(cx, trait_ref.args)
926                .map(Unnormalized::skip_norm_wip),
927        );
928    }
929
930    let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
931    for bound in object_bounds.iter() {
932        if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
933            // FIXME: We *probably* should replace this with a dummy placeholder,
934            // b/c don't want to replace literal instances of this dyn type that
935            // show up in the bounds, but just ones that come from substituting
936            // `Self` with the dyn type.
937            let proj = proj.with_self_ty(cx, trait_ref.self_ty());
938            replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
939        }
940    }
941
942    let mut folder = ReplaceProjectionWith {
943        ecx,
944        param_env,
945        self_ty: trait_ref.self_ty(),
946        mapping: &replace_projection_with,
947        nested: ::alloc::vec::Vec::new()vec![],
948    };
949
950    let requirements = requirements.try_fold_with(&mut folder)?;
951    Ok(folder
952        .nested
953        .into_iter()
954        .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
955        .collect())
956}
957
958struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
959    ecx: &'a mut EvalCtxt<'b, D>,
960    param_env: I::ParamEnv,
961    self_ty: I::Ty,
962    mapping: &'a HashMap<I::TraitAssocTermId, Vec<ty::Binder<I, ty::ProjectionClause<I>>>>,
963    nested: Vec<Goal<I, I::Predicate>>,
964}
965
966impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
967where
968    D: SolverDelegate<Interner = I>,
969    I: Interner,
970{
971    fn projection_may_match(
972        &mut self,
973        source_projection: ty::Binder<I, ty::ProjectionClause<I>>,
974        target_projection: ty::AliasTerm<I>,
975    ) -> Result<bool, RerunNonErased> {
976        if source_projection.item_def_id() != target_projection.expect_projection_def_id() {
977            return Ok(false);
978        }
979        match self
980            .ecx
981            .probe(|_| ProbeKind::ProjectionCompatibility)
982            .enter_without_propagated_nested_goals(|ecx| {
983                let source_projection = ecx.instantiate_binder_with_infer(source_projection);
984                ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
985                ecx.try_evaluate_added_goals()
986            }) {
987            Ok(_) => Ok(true),
988            Err(NoSolutionOrRerunNonErased::NoSolution(_)) => Ok(false),
989            Err(NoSolutionOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun),
990        }
991    }
992
993    /// Try to replace an alias with the term present in the projection bounds of the self type.
994    /// Returns `Ok<None>` if this alias is not eligible to be replaced, or bail with
995    /// `Err(Ambiguous)` if it's uncertain which projection bound to replace the term with due
996    /// to multiple bounds applying, or with `Err(RerunNonErased)` if we have to rerun the
997    /// goal in original `TypingMode`.
998    fn try_eagerly_replace_alias(
999        &mut self,
1000        alias_term: ty::AliasTerm<I>,
1001    ) -> Result<Option<I::Term>, AmbiguousOrRerunNonErased> {
1002        if alias_term.self_ty() != self.self_ty {
1003            return Ok(None);
1004        }
1005
1006        let Some(replacements) = self.mapping.get(&alias_term.expect_projection_def_id()) else {
1007            return Ok(None);
1008        };
1009
1010        // This is quite similar to the `projection_may_match` we use in unsizing,
1011        // but here we want to unify a projection predicate against an alias term
1012        // so we can replace it with the projection predicate's term.
1013        let mut matching_projection = None;
1014        for source_projection in replacements {
1015            if self.projection_may_match(*source_projection, alias_term)? {
1016                // FIXME: This *may* have issues with duplicated projections.
1017                if matching_projection.is_some() {
1018                    // If there's more than one projection that we can unify here, then we
1019                    // need to stall until inference constrains things so that there's only
1020                    // one choice.
1021                    return Err(AmbiguousOrRerunNonErased::Ambiguous);
1022                }
1023                matching_projection = Some(source_projection)
1024            }
1025        }
1026
1027        let Some(matching) = matching_projection else {
1028            // This shouldn't happen.
1029            {
    ::core::panicking::panic_fmt(format_args!("could not replace {1:?} with term from from {0:?}",
            self.self_ty, alias_term));
};panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty);
1030        };
1031
1032        let replacement = self.ecx.instantiate_binder_with_infer(*matching);
1033        self.nested.extend(
1034            self.ecx
1035                .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
1036                .expect("expected to be able to unify goal projection with dyn's projection"),
1037        );
1038
1039        Ok(Some(replacement.term))
1040    }
1041}
1042
1043pub(crate) enum AmbiguousOrRerunNonErased {
1044    /// Marker for bailing with ambiguity.
1045    Ambiguous,
1046    RerunNonErased(RerunNonErased),
1047}
1048
1049impl From<RerunNonErased> for AmbiguousOrRerunNonErased {
1050    fn from(rerun: RerunNonErased) -> Self {
1051        AmbiguousOrRerunNonErased::RerunNonErased(rerun)
1052    }
1053}
1054
1055impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1056where
1057    D: SolverDelegate<Interner = I>,
1058    I: Interner,
1059{
1060    type Error = AmbiguousOrRerunNonErased;
1061
1062    fn cx(&self) -> I {
1063        self.ecx.cx()
1064    }
1065
1066    fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Self::Error> {
1067        if let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind()
1068            && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1069        {
1070            Ok(term.expect_ty())
1071        } else {
1072            ty.try_super_fold_with(self)
1073        }
1074    }
1075}