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