1use 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::{
9 self as ty, Interner, Movability, Mutability, TypeFoldable, TypeFolder, TypeSuperFoldable,
10 Upcast as _, elaborate,
11};
12use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
13use tracing::instrument;
14
15use crate::delegate::SolverDelegate;
16use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution};
17
18#[instrument(level = "trace", skip(ecx), ret)]
20pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<D, I>(
21 ecx: &EvalCtxt<'_, D>,
22 ty: I::Ty,
23) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
24where
25 D: SolverDelegate<Interner = I>,
26 I: Interner,
27{
28 let cx = ecx.cx();
29 match ty.kind() {
30 ty::Uint(_)
31 | ty::Int(_)
32 | ty::Bool
33 | ty::Float(_)
34 | ty::FnDef(..)
35 | ty::FnPtr(..)
36 | ty::Error(_)
37 | ty::Never
38 | ty::Char => Ok(ty::Binder::dummy(vec![])),
39
40 ty::Str => Ok(ty::Binder::dummy(vec![Ty::new_slice(cx, Ty::new_u8(cx))])),
42
43 ty::Dynamic(..)
44 | ty::Param(..)
45 | ty::Foreign(..)
46 | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
47 | ty::Placeholder(..)
48 | ty::Bound(..)
49 | ty::Infer(_) => {
50 panic!("unexpected type `{ty:?}`")
51 }
52
53 ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
54 Ok(ty::Binder::dummy(vec![element_ty]))
55 }
56
57 ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
58 Ok(ty::Binder::dummy(vec![element_ty]))
59 }
60
61 ty::Tuple(tys) => {
62 Ok(ty::Binder::dummy(tys.to_vec()))
64 }
65
66 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
67
68 ty::CoroutineClosure(_, args) => {
69 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
70 }
71
72 ty::Coroutine(_, args) => {
73 let coroutine_args = args.as_coroutine();
74 Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]))
75 }
76
77 ty::CoroutineWitness(def_id, args) => Ok(ecx
78 .cx()
79 .coroutine_hidden_types(def_id)
80 .instantiate(cx, args)
81 .map_bound(|tys| tys.to_vec())),
82
83 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
84
85 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
87
88 ty::Adt(def, args) => {
89 Ok(ty::Binder::dummy(def.all_field_tys(cx).iter_instantiated(cx, args).collect()))
90 }
91
92 ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
93 Ok(ty::Binder::dummy(vec![cx.type_of(def_id).instantiate(cx, args)]))
97 }
98 }
99}
100
101#[instrument(level = "trace", skip(ecx), ret)]
102pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
103 ecx: &EvalCtxt<'_, D>,
104 ty: I::Ty,
105) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
106where
107 D: SolverDelegate<Interner = I>,
108 I: Interner,
109{
110 match ty.kind() {
111 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
114 | ty::Uint(_)
115 | ty::Int(_)
116 | ty::Bool
117 | ty::Float(_)
118 | ty::FnDef(..)
119 | ty::FnPtr(..)
120 | ty::RawPtr(..)
121 | ty::Char
122 | ty::Ref(..)
123 | ty::Coroutine(..)
124 | ty::CoroutineWitness(..)
125 | ty::Array(..)
126 | ty::Pat(..)
127 | ty::Closure(..)
128 | ty::CoroutineClosure(..)
129 | ty::Never
130 | ty::Dynamic(_, _, ty::DynStar)
131 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
132
133 ty::Str
134 | ty::Slice(_)
135 | ty::Dynamic(..)
136 | ty::Foreign(..)
137 | ty::Alias(..)
138 | ty::Param(_)
139 | ty::Placeholder(..) => Err(NoSolution),
140
141 ty::Bound(..)
142 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
143 panic!("unexpected type `{ty:?}`")
144 }
145
146 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
147
148 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
151
152 ty::Adt(def, args) => {
162 if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
163 Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
164 } else {
165 Ok(ty::Binder::dummy(vec![]))
166 }
167 }
168 }
169}
170
171#[instrument(level = "trace", skip(ecx), ret)]
172pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
173 ecx: &EvalCtxt<'_, D>,
174 ty: I::Ty,
175) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
176where
177 D: SolverDelegate<Interner = I>,
178 I: Interner,
179{
180 match ty.kind() {
181 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
183
184 ty::Uint(_)
186 | ty::Int(_)
187 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
188 | ty::Bool
189 | ty::Float(_)
190 | ty::Char
191 | ty::RawPtr(..)
192 | ty::Never
193 | ty::Ref(_, _, Mutability::Not)
194 | ty::Array(..) => Err(NoSolution),
195
196 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
199
200 ty::Dynamic(..)
201 | ty::Str
202 | ty::Slice(_)
203 | ty::Foreign(..)
204 | ty::Ref(_, _, Mutability::Mut)
205 | ty::Adt(_, _)
206 | ty::Alias(_, _)
207 | ty::Param(_)
208 | ty::Placeholder(..) => Err(NoSolution),
209
210 ty::Bound(..)
211 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
212 panic!("unexpected type `{ty:?}`")
213 }
214
215 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
217
218 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
220
221 ty::CoroutineClosure(_, args) => {
223 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
224 }
225
226 ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
229 Movability::Static => Err(NoSolution),
230 Movability::Movable => {
231 if ecx.cx().features().coroutine_clone() {
232 let coroutine = args.as_coroutine();
233 Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]))
234 } else {
235 Err(NoSolution)
236 }
237 }
238 },
239
240 ty::UnsafeBinder(_) => Err(NoSolution),
241
242 ty::CoroutineWitness(def_id, args) => Ok(ecx
244 .cx()
245 .coroutine_hidden_types(def_id)
246 .instantiate(ecx.cx(), args)
247 .map_bound(|tys| tys.to_vec())),
248 }
249}
250
251pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
253 cx: I,
254 self_ty: I::Ty,
255 goal_kind: ty::ClosureKind,
256) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
257 match self_ty.kind() {
258 ty::FnDef(def_id, args) => {
260 let sig = cx.fn_sig(def_id);
261 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
262 Ok(Some(
263 sig.instantiate(cx, args)
264 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
265 ))
266 } else {
267 Err(NoSolution)
268 }
269 }
270 ty::FnPtr(sig_tys, hdr) => {
272 let sig = sig_tys.with(hdr);
273 if sig.is_fn_trait_compatible() {
274 Ok(Some(
275 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
276 ))
277 } else {
278 Err(NoSolution)
279 }
280 }
281 ty::Closure(_, args) => {
282 let closure_args = args.as_closure();
283 match closure_args.kind_ty().to_opt_closure_kind() {
284 Some(closure_kind) => {
287 if !closure_kind.extends(goal_kind) {
288 return Err(NoSolution);
289 }
290 }
291 None => {
294 if goal_kind != ty::ClosureKind::FnOnce {
295 return Ok(None);
296 }
297 }
298 }
299 Ok(Some(
300 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
301 ))
302 }
303
304 ty::CoroutineClosure(def_id, args) => {
309 let args = args.as_coroutine_closure();
310 let kind_ty = args.kind_ty();
311 let sig = args.coroutine_closure_sig().skip_binder();
312
313 let kind = kind_ty.to_opt_closure_kind();
315 let coroutine_ty = if kind.is_some() && !args.tupled_upvars_ty().is_ty_var() {
316 let closure_kind = kind.unwrap();
317 if !closure_kind.extends(goal_kind) {
318 return Err(NoSolution);
319 }
320
321 if closure_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
326 return Err(NoSolution);
327 }
328
329 coroutine_closure_to_certain_coroutine(
330 cx,
331 goal_kind,
332 Region::new_static(cx),
334 def_id,
335 args,
336 sig,
337 )
338 } else {
339 if goal_kind != ty::ClosureKind::FnOnce {
342 return Ok(None);
343 }
344
345 coroutine_closure_to_ambiguous_coroutine(
346 cx,
347 goal_kind, Region::new_static(cx),
349 def_id,
350 args,
351 sig,
352 )
353 };
354
355 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
356 }
357
358 ty::Bool
359 | ty::Char
360 | ty::Int(_)
361 | ty::Uint(_)
362 | ty::Float(_)
363 | ty::Adt(_, _)
364 | ty::Foreign(_)
365 | ty::Str
366 | ty::Array(_, _)
367 | ty::Slice(_)
368 | ty::RawPtr(_, _)
369 | ty::Ref(_, _, _)
370 | ty::Dynamic(_, _, _)
371 | ty::Coroutine(_, _)
372 | ty::CoroutineWitness(..)
373 | ty::Never
374 | ty::Tuple(_)
375 | ty::Pat(_, _)
376 | ty::UnsafeBinder(_)
377 | ty::Alias(_, _)
378 | ty::Param(_)
379 | ty::Placeholder(..)
380 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
381 | ty::Error(_) => Err(NoSolution),
382
383 ty::Bound(..)
384 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
385 panic!("unexpected type `{self_ty:?}`")
386 }
387 }
388}
389
390#[derive_where(Clone, Copy, Debug; I: Interner)]
393#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
394pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
395 pub tupled_inputs_ty: I::Ty,
396 pub output_coroutine_ty: I::Ty,
399 pub coroutine_return_ty: I::Ty,
402}
403
404pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
410 cx: I,
411 self_ty: I::Ty,
412 goal_kind: ty::ClosureKind,
413 env_region: I::Region,
414) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
415 match self_ty.kind() {
416 ty::CoroutineClosure(def_id, args) => {
417 let args = args.as_coroutine_closure();
418 let kind_ty = args.kind_ty();
419 let sig = args.coroutine_closure_sig().skip_binder();
420 let mut nested = vec![];
421
422 let kind = kind_ty.to_opt_closure_kind();
424 let coroutine_ty = if kind.is_some() && !args.tupled_upvars_ty().is_ty_var() {
425 if !kind.unwrap().extends(goal_kind) {
426 return Err(NoSolution);
427 }
428
429 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
430 } else {
431 nested.push(
439 ty::TraitRef::new(
440 cx,
441 cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
442 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
443 )
444 .upcast(cx),
445 );
446
447 coroutine_closure_to_ambiguous_coroutine(
448 cx, goal_kind, env_region, def_id, args, sig,
449 )
450 };
451
452 Ok((
453 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
454 tupled_inputs_ty: sig.tupled_inputs_ty,
455 output_coroutine_ty: coroutine_ty,
456 coroutine_return_ty: sig.return_ty,
457 }),
458 nested,
459 ))
460 }
461
462 ty::FnDef(def_id, _) => {
463 let sig = self_ty.fn_sig(cx);
464 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
465 fn_item_to_async_callable(cx, sig)
466 } else {
467 Err(NoSolution)
468 }
469 }
470 ty::FnPtr(..) => {
471 let sig = self_ty.fn_sig(cx);
472 if sig.is_fn_trait_compatible() {
473 fn_item_to_async_callable(cx, sig)
474 } else {
475 Err(NoSolution)
476 }
477 }
478
479 ty::Closure(_, args) => {
480 let args = args.as_closure();
481 let bound_sig = args.sig();
482 let sig = bound_sig.skip_binder();
483 let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
484 let mut nested = vec![
487 bound_sig
488 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
489 .upcast(cx),
490 ];
491
492 let kind_ty = args.kind_ty();
495 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
496 if !closure_kind.extends(goal_kind) {
497 return Err(NoSolution);
498 }
499 } else {
500 let async_fn_kind_trait_def_id =
501 cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
502 nested.push(
510 ty::TraitRef::new(
511 cx,
512 async_fn_kind_trait_def_id,
513 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
514 )
515 .upcast(cx),
516 );
517 }
518
519 let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
520 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
521 Ok((
522 bound_sig.rebind(AsyncCallableRelevantTypes {
523 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
524 output_coroutine_ty: sig.output(),
525 coroutine_return_ty: future_output_ty,
526 }),
527 nested,
528 ))
529 }
530
531 ty::Bool
532 | ty::Char
533 | ty::Int(_)
534 | ty::Uint(_)
535 | ty::Float(_)
536 | ty::Adt(_, _)
537 | ty::Foreign(_)
538 | ty::Str
539 | ty::Array(_, _)
540 | ty::Pat(_, _)
541 | ty::Slice(_)
542 | ty::RawPtr(_, _)
543 | ty::Ref(_, _, _)
544 | ty::Dynamic(_, _, _)
545 | ty::Coroutine(_, _)
546 | ty::CoroutineWitness(..)
547 | ty::Never
548 | ty::UnsafeBinder(_)
549 | ty::Tuple(_)
550 | ty::Alias(_, _)
551 | ty::Param(_)
552 | ty::Placeholder(..)
553 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
554 | ty::Error(_) => Err(NoSolution),
555
556 ty::Bound(..)
557 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
558 panic!("unexpected type `{self_ty:?}`")
559 }
560 }
561}
562
563fn fn_item_to_async_callable<I: Interner>(
564 cx: I,
565 bound_sig: ty::Binder<I, ty::FnSig<I>>,
566) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
567 let sig = bound_sig.skip_binder();
568 let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
569 let nested = vec![
572 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
573 ];
574 let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
575 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
576 Ok((
577 bound_sig.rebind(AsyncCallableRelevantTypes {
578 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
579 output_coroutine_ty: sig.output(),
580 coroutine_return_ty: future_output_ty,
581 }),
582 nested,
583 ))
584}
585
586fn coroutine_closure_to_certain_coroutine<I: Interner>(
589 cx: I,
590 goal_kind: ty::ClosureKind,
591 goal_region: I::Region,
592 def_id: I::DefId,
593 args: ty::CoroutineClosureArgs<I>,
594 sig: ty::CoroutineClosureSignature<I>,
595) -> I::Ty {
596 sig.to_coroutine_given_kind_and_upvars(
597 cx,
598 args.parent_args(),
599 cx.coroutine_for_closure(def_id),
600 goal_kind,
601 goal_region,
602 args.tupled_upvars_ty(),
603 args.coroutine_captures_by_ref_ty(),
604 )
605}
606
607fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
613 cx: I,
614 goal_kind: ty::ClosureKind,
615 goal_region: I::Region,
616 def_id: I::DefId,
617 args: ty::CoroutineClosureArgs<I>,
618 sig: ty::CoroutineClosureSignature<I>,
619) -> I::Ty {
620 let upvars_projection_def_id = cx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
621 let tupled_upvars_ty = Ty::new_projection(
622 cx,
623 upvars_projection_def_id,
624 [
625 I::GenericArg::from(args.kind_ty()),
626 Ty::from_closure_kind(cx, goal_kind).into(),
627 goal_region.into(),
628 sig.tupled_inputs_ty.into(),
629 args.tupled_upvars_ty().into(),
630 args.coroutine_captures_by_ref_ty().into(),
631 ],
632 );
633 sig.to_coroutine(
634 cx,
635 args.parent_args(),
636 Ty::from_closure_kind(cx, goal_kind),
637 cx.coroutine_for_closure(def_id),
638 tupled_upvars_ty,
639 )
640}
641
642pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
649 cx: I,
650 self_ty: I::Ty,
651) -> Result<(ty::Binder<I, (I::FnInputTys, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
652 match self_ty.kind() {
653 ty::FnDef(def_id, args) => {
654 let sig = cx.fn_sig(def_id);
655 if sig.skip_binder().is_fn_trait_compatible()
656 && !cx.has_target_features(def_id)
657 && cx.fn_is_const(def_id)
658 {
659 Ok((
660 sig.instantiate(cx, args).map_bound(|sig| (sig.inputs(), sig.output())),
661 def_id,
662 args,
663 ))
664 } else {
665 return Err(NoSolution);
666 }
667 }
668 ty::FnPtr(..) => {
670 return Err(NoSolution);
671 }
672 ty::Closure(..) => {
674 return Err(NoSolution);
675 }
676 ty::CoroutineClosure(..) => {
678 return Err(NoSolution);
679 }
680
681 ty::Bool
682 | ty::Char
683 | ty::Int(_)
684 | ty::Uint(_)
685 | ty::Float(_)
686 | ty::Adt(_, _)
687 | ty::Foreign(_)
688 | ty::Str
689 | ty::Array(_, _)
690 | ty::Slice(_)
691 | ty::RawPtr(_, _)
692 | ty::Ref(_, _, _)
693 | ty::Dynamic(_, _, _)
694 | ty::Coroutine(_, _)
695 | ty::CoroutineWitness(..)
696 | ty::Never
697 | ty::Tuple(_)
698 | ty::Pat(_, _)
699 | ty::Alias(_, _)
700 | ty::Param(_)
701 | ty::Placeholder(..)
702 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
703 | ty::Error(_)
704 | ty::UnsafeBinder(_) => return Err(NoSolution),
705
706 ty::Bound(..)
707 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
708 panic!("unexpected type `{self_ty:?}`")
709 }
710 }
711}
712
713pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
716 cx: I,
717 self_ty: I::Ty,
718) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
719 let destruct_def_id = cx.require_lang_item(TraitSolverLangItem::Destruct);
720
721 match self_ty.kind() {
722 ty::Adt(adt_def, args) => {
725 let mut const_conditions: Vec<_> = adt_def
726 .all_field_tys(cx)
727 .iter_instantiated(cx, args)
728 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
729 .collect();
730 match adt_def.destructor(cx) {
731 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
733 Some(AdtDestructorKind::Const) => {
735 let drop_def_id = cx.require_lang_item(TraitSolverLangItem::Drop);
736 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
737 const_conditions.push(drop_trait_ref);
738 }
739 None => {}
741 }
742 Ok(const_conditions)
743 }
744
745 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
746 Ok(vec![ty::TraitRef::new(cx, destruct_def_id, [ty])])
747 }
748
749 ty::Tuple(tys) => Ok(tys
750 .iter()
751 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
752 .collect()),
753
754 ty::Bool
756 | ty::Char
757 | ty::Int(..)
758 | ty::Uint(..)
759 | ty::Float(..)
760 | ty::Str
761 | ty::RawPtr(..)
762 | ty::Ref(..)
763 | ty::FnDef(..)
764 | ty::FnPtr(..)
765 | ty::Never
766 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
767 | ty::Error(_) => Ok(vec![]),
768
769 ty::Closure(_, _)
772 | ty::CoroutineClosure(_, _)
773 | ty::Coroutine(_, _)
774 | ty::CoroutineWitness(_, _) => Err(NoSolution),
775
776 ty::UnsafeBinder(_) => Err(NoSolution),
779
780 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
781 Err(NoSolution)
782 }
783
784 ty::Bound(..)
785 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
786 panic!("unexpected type `{self_ty:?}`")
787 }
788 }
789}
790
791pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
832 ecx: &EvalCtxt<'_, D>,
833 param_env: I::ParamEnv,
834 trait_ref: ty::TraitRef<I>,
835 object_bounds: I::BoundExistentialPredicates,
836) -> Vec<Goal<I, I::Predicate>>
837where
838 D: SolverDelegate<Interner = I>,
839 I: Interner,
840{
841 let cx = ecx.cx();
842 let mut requirements = vec![];
843 requirements.extend(elaborate::elaborate(
851 cx,
852 cx.explicit_super_predicates_of(trait_ref.def_id)
853 .iter_instantiated(cx, trait_ref.args)
854 .map(|(pred, _)| pred),
855 ));
856
857 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
860 if cx.generics_require_sized_self(associated_type_def_id) {
863 continue;
864 }
865
866 requirements
867 .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
868 }
869
870 let mut replace_projection_with = HashMap::default();
871 for bound in object_bounds.iter() {
872 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
873 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
874 let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
875 assert_eq!(
876 old_ty,
877 None,
878 "{:?} has two generic parameters: {:?} and {:?}",
879 proj.projection_term,
880 proj.term,
881 old_ty.unwrap()
882 );
883 }
884 }
885
886 let mut folder =
887 ReplaceProjectionWith { ecx, param_env, mapping: replace_projection_with, nested: vec![] };
888 let folded_requirements = requirements.fold_with(&mut folder);
889
890 folder
891 .nested
892 .into_iter()
893 .chain(folded_requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
894 .collect()
895}
896
897struct ReplaceProjectionWith<'a, D: SolverDelegate<Interner = I>, I: Interner> {
898 ecx: &'a EvalCtxt<'a, D>,
899 param_env: I::ParamEnv,
900 mapping: HashMap<I::DefId, ty::Binder<I, ty::ProjectionPredicate<I>>>,
901 nested: Vec<Goal<I, I::Predicate>>,
902}
903
904impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I>
905 for ReplaceProjectionWith<'_, D, I>
906{
907 fn cx(&self) -> I {
908 self.ecx.cx()
909 }
910
911 fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
912 if let ty::Alias(ty::Projection, alias_ty) = ty.kind() {
913 if let Some(replacement) = self.mapping.get(&alias_ty.def_id) {
914 let proj = self.ecx.instantiate_binder_with_infer(*replacement);
918 self.nested.extend(
920 self.ecx
921 .eq_and_get_goals(
922 self.param_env,
923 alias_ty,
924 proj.projection_term.expect_ty(self.ecx.cx()),
925 )
926 .expect(
927 "expected to be able to unify goal projection with dyn's projection",
928 ),
929 );
930 proj.term.expect_ty()
931 } else {
932 ty.super_fold_with(self)
933 }
934 } else {
935 ty.super_fold_with(self)
936 }
937 }
938}