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