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