1use 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#[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 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 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 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 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 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 ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |ty| vec![ty::Binder::dummy(ty)])),
154
155 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 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(vec![]),
186
187 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 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 ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
220
221 ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
223
224 ty::CoroutineClosure(_, args) => {
226 Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())])
227 }
228
229 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 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
258pub(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 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 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 Some(closure_kind) => {
294 if !closure_kind.extends(goal_kind) {
295 return Err(NoSolution);
296 }
297 }
298 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 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 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 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 Region::new_static(cx),
341 def_id,
342 args,
343 sig,
344 )
345 } else {
346 if goal_kind != ty::ClosureKind::FnOnce {
349 return Ok(None);
350 }
351
352 coroutine_closure_to_ambiguous_coroutine(
353 cx,
354 goal_kind, 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#[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 pub output_coroutine_ty: I::Ty,
406 pub coroutine_return_ty: I::Ty,
409}
410
411pub(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 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 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 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 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 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 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
593fn 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
614fn 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
649pub(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 ty::FnPtr(..) => {
677 return Err(NoSolution);
678 }
679 ty::Closure(..) => {
681 return Err(NoSolution);
682 }
683 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
720pub(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 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 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
740 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 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 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 ty::Closure(_, _)
779 | ty::CoroutineClosure(_, _)
780 | ty::Coroutine(_, _)
781 | ty::CoroutineWitness(_, _) => Err(NoSolution),
782
783 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
798pub(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 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 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
867 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 let proj = self.ecx.instantiate_binder_with_infer(*replacement);
925 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}