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::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#[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 ty::Foreign(..) => Ok(ty::Binder::dummy(vec![])),
46
47 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 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(_, args) => {
79 let coroutine_args = args.as_coroutine();
80 Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]))
81 }
82
83 ty::CoroutineWitness(def_id, args) => Ok(ecx
84 .cx()
85 .coroutine_hidden_types(def_id)
86 .instantiate(cx, args)
87 .map_bound(|bound| bound.types.to_vec())),
88
89 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
90
91 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
93
94 ty::Adt(def, args) => {
95 Ok(ty::Binder::dummy(def.all_field_tys(cx).iter_instantiated(cx, args).collect()))
96 }
97
98 ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
99 Ok(ty::Binder::dummy(vec![cx.type_of(def_id).instantiate(cx, args)]))
103 }
104 }
105}
106
107#[instrument(level = "trace", skip(ecx), ret)]
108pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
109 ecx: &EvalCtxt<'_, D>,
110 sizedness: SizedTraitKind,
111 ty: I::Ty,
112) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
113where
114 D: SolverDelegate<Interner = I>,
115 I: Interner,
116{
117 match ty.kind() {
118 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
122 | ty::Uint(_)
123 | ty::Int(_)
124 | ty::Bool
125 | ty::Float(_)
126 | ty::FnDef(..)
127 | ty::FnPtr(..)
128 | ty::RawPtr(..)
129 | ty::Char
130 | ty::Ref(..)
131 | ty::Coroutine(..)
132 | ty::CoroutineWitness(..)
133 | ty::Array(..)
134 | ty::Pat(..)
135 | ty::Closure(..)
136 | ty::CoroutineClosure(..)
137 | ty::Never
138 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
139
140 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
142 SizedTraitKind::Sized => Err(NoSolution),
143 SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
144 },
145
146 ty::Foreign(..) => Err(NoSolution),
148
149 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
150
151 ty::Bound(..)
152 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
153 panic!("unexpected type `{ty:?}`")
154 }
155
156 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
157
158 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
161
162 ty::Adt(def, args) => {
177 if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
178 Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
179 } else {
180 Ok(ty::Binder::dummy(vec![]))
181 }
182 }
183 }
184}
185
186#[instrument(level = "trace", skip(ecx), ret)]
187pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
188 ecx: &EvalCtxt<'_, D>,
189 ty: I::Ty,
190) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
191where
192 D: SolverDelegate<Interner = I>,
193 I: Interner,
194{
195 match ty.kind() {
196 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
198
199 ty::Uint(_)
201 | ty::Int(_)
202 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
203 | ty::Bool
204 | ty::Float(_)
205 | ty::Char
206 | ty::RawPtr(..)
207 | ty::Never
208 | ty::Ref(_, _, Mutability::Not)
209 | ty::Array(..) => Err(NoSolution),
210
211 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
214
215 ty::Dynamic(..)
216 | ty::Str
217 | ty::Slice(_)
218 | ty::Foreign(..)
219 | ty::Ref(_, _, Mutability::Mut)
220 | ty::Adt(_, _)
221 | ty::Alias(_, _)
222 | ty::Param(_)
223 | ty::Placeholder(..) => Err(NoSolution),
224
225 ty::Bound(..)
226 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
227 panic!("unexpected type `{ty:?}`")
228 }
229
230 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
232
233 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
235
236 ty::CoroutineClosure(_, args) => {
238 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
239 }
240
241 ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
244 Movability::Static => Err(NoSolution),
245 Movability::Movable => {
246 if ecx.cx().features().coroutine_clone() {
247 let coroutine = args.as_coroutine();
248 Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]))
249 } else {
250 Err(NoSolution)
251 }
252 }
253 },
254
255 ty::UnsafeBinder(_) => Err(NoSolution),
256
257 ty::CoroutineWitness(def_id, args) => Ok(ecx
259 .cx()
260 .coroutine_hidden_types(def_id)
261 .instantiate(ecx.cx(), args)
262 .map_bound(|bound| bound.types.to_vec())),
263 }
264}
265
266pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
268 cx: I,
269 self_ty: I::Ty,
270 goal_kind: ty::ClosureKind,
271) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
272 match self_ty.kind() {
273 ty::FnDef(def_id, args) => {
275 let sig = cx.fn_sig(def_id);
276 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
277 Ok(Some(
278 sig.instantiate(cx, args)
279 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
280 ))
281 } else {
282 Err(NoSolution)
283 }
284 }
285 ty::FnPtr(sig_tys, hdr) => {
287 let sig = sig_tys.with(hdr);
288 if sig.is_fn_trait_compatible() {
289 Ok(Some(
290 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
291 ))
292 } else {
293 Err(NoSolution)
294 }
295 }
296 ty::Closure(_, args) => {
297 let closure_args = args.as_closure();
298 match closure_args.kind_ty().to_opt_closure_kind() {
299 Some(closure_kind) => {
302 if !closure_kind.extends(goal_kind) {
303 return Err(NoSolution);
304 }
305 }
306 None => {
309 if goal_kind != ty::ClosureKind::FnOnce {
310 return Ok(None);
311 }
312 }
313 }
314 Ok(Some(
315 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
316 ))
317 }
318
319 ty::CoroutineClosure(def_id, args) => {
324 let args = args.as_coroutine_closure();
325 let kind_ty = args.kind_ty();
326 let sig = args.coroutine_closure_sig().skip_binder();
327
328 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
329 && !args.tupled_upvars_ty().is_ty_var()
330 {
331 if !kind.extends(goal_kind) {
332 return Err(NoSolution);
333 }
334
335 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
340 return Err(NoSolution);
341 }
342
343 coroutine_closure_to_certain_coroutine(
344 cx,
345 goal_kind,
346 Region::new_static(cx),
348 def_id,
349 args,
350 sig,
351 )
352 } else {
353 if goal_kind != ty::ClosureKind::FnOnce {
356 return Ok(None);
357 }
358
359 coroutine_closure_to_ambiguous_coroutine(
360 cx,
361 goal_kind, Region::new_static(cx),
363 def_id,
364 args,
365 sig,
366 )
367 };
368
369 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
370 }
371
372 ty::Bool
373 | ty::Char
374 | ty::Int(_)
375 | ty::Uint(_)
376 | ty::Float(_)
377 | ty::Adt(_, _)
378 | ty::Foreign(_)
379 | ty::Str
380 | ty::Array(_, _)
381 | ty::Slice(_)
382 | ty::RawPtr(_, _)
383 | ty::Ref(_, _, _)
384 | ty::Dynamic(_, _, _)
385 | ty::Coroutine(_, _)
386 | ty::CoroutineWitness(..)
387 | ty::Never
388 | ty::Tuple(_)
389 | ty::Pat(_, _)
390 | ty::UnsafeBinder(_)
391 | ty::Alias(_, _)
392 | ty::Param(_)
393 | ty::Placeholder(..)
394 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
395 | ty::Error(_) => Err(NoSolution),
396
397 ty::Bound(..)
398 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
399 panic!("unexpected type `{self_ty:?}`")
400 }
401 }
402}
403
404#[derive_where(Clone, Copy, Debug; I: Interner)]
407#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
408pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
409 pub tupled_inputs_ty: I::Ty,
410 pub output_coroutine_ty: I::Ty,
413 pub coroutine_return_ty: I::Ty,
416}
417
418pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
424 cx: I,
425 self_ty: I::Ty,
426 goal_kind: ty::ClosureKind,
427 env_region: I::Region,
428) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
429 match self_ty.kind() {
430 ty::CoroutineClosure(def_id, args) => {
431 let args = args.as_coroutine_closure();
432 let kind_ty = args.kind_ty();
433 let sig = args.coroutine_closure_sig().skip_binder();
434 let mut nested = vec![];
435
436 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
437 && !args.tupled_upvars_ty().is_ty_var()
438 {
439 if !kind.extends(goal_kind) {
440 return Err(NoSolution);
441 }
442
443 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
444 } else {
445 nested.push(
453 ty::TraitRef::new(
454 cx,
455 cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
456 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
457 )
458 .upcast(cx),
459 );
460
461 coroutine_closure_to_ambiguous_coroutine(
462 cx, goal_kind, env_region, def_id, args, sig,
463 )
464 };
465
466 Ok((
467 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
468 tupled_inputs_ty: sig.tupled_inputs_ty,
469 output_coroutine_ty: coroutine_ty,
470 coroutine_return_ty: sig.return_ty,
471 }),
472 nested,
473 ))
474 }
475
476 ty::FnDef(def_id, _) => {
477 let sig = self_ty.fn_sig(cx);
478 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
479 fn_item_to_async_callable(cx, sig)
480 } else {
481 Err(NoSolution)
482 }
483 }
484 ty::FnPtr(..) => {
485 let sig = self_ty.fn_sig(cx);
486 if sig.is_fn_trait_compatible() {
487 fn_item_to_async_callable(cx, sig)
488 } else {
489 Err(NoSolution)
490 }
491 }
492
493 ty::Closure(_, args) => {
494 let args = args.as_closure();
495 let bound_sig = args.sig();
496 let sig = bound_sig.skip_binder();
497 let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
498 let mut nested = vec![
501 bound_sig
502 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
503 .upcast(cx),
504 ];
505
506 let kind_ty = args.kind_ty();
509 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
510 if !closure_kind.extends(goal_kind) {
511 return Err(NoSolution);
512 }
513 } else {
514 let async_fn_kind_trait_def_id =
515 cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
516 nested.push(
524 ty::TraitRef::new(
525 cx,
526 async_fn_kind_trait_def_id,
527 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
528 )
529 .upcast(cx),
530 );
531 }
532
533 let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
534 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
535 Ok((
536 bound_sig.rebind(AsyncCallableRelevantTypes {
537 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
538 output_coroutine_ty: sig.output(),
539 coroutine_return_ty: future_output_ty,
540 }),
541 nested,
542 ))
543 }
544
545 ty::Bool
546 | ty::Char
547 | ty::Int(_)
548 | ty::Uint(_)
549 | ty::Float(_)
550 | ty::Adt(_, _)
551 | ty::Foreign(_)
552 | ty::Str
553 | ty::Array(_, _)
554 | ty::Pat(_, _)
555 | ty::Slice(_)
556 | ty::RawPtr(_, _)
557 | ty::Ref(_, _, _)
558 | ty::Dynamic(_, _, _)
559 | ty::Coroutine(_, _)
560 | ty::CoroutineWitness(..)
561 | ty::Never
562 | ty::UnsafeBinder(_)
563 | ty::Tuple(_)
564 | ty::Alias(_, _)
565 | ty::Param(_)
566 | ty::Placeholder(..)
567 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
568 | ty::Error(_) => Err(NoSolution),
569
570 ty::Bound(..)
571 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
572 panic!("unexpected type `{self_ty:?}`")
573 }
574 }
575}
576
577fn fn_item_to_async_callable<I: Interner>(
578 cx: I,
579 bound_sig: ty::Binder<I, ty::FnSig<I>>,
580) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
581 let sig = bound_sig.skip_binder();
582 let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
583 let nested = vec![
586 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
587 ];
588 let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
589 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
590 Ok((
591 bound_sig.rebind(AsyncCallableRelevantTypes {
592 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
593 output_coroutine_ty: sig.output(),
594 coroutine_return_ty: future_output_ty,
595 }),
596 nested,
597 ))
598}
599
600fn coroutine_closure_to_certain_coroutine<I: Interner>(
603 cx: I,
604 goal_kind: ty::ClosureKind,
605 goal_region: I::Region,
606 def_id: I::DefId,
607 args: ty::CoroutineClosureArgs<I>,
608 sig: ty::CoroutineClosureSignature<I>,
609) -> I::Ty {
610 sig.to_coroutine_given_kind_and_upvars(
611 cx,
612 args.parent_args(),
613 cx.coroutine_for_closure(def_id),
614 goal_kind,
615 goal_region,
616 args.tupled_upvars_ty(),
617 args.coroutine_captures_by_ref_ty(),
618 )
619}
620
621fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
627 cx: I,
628 goal_kind: ty::ClosureKind,
629 goal_region: I::Region,
630 def_id: I::DefId,
631 args: ty::CoroutineClosureArgs<I>,
632 sig: ty::CoroutineClosureSignature<I>,
633) -> I::Ty {
634 let upvars_projection_def_id = cx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
635 let tupled_upvars_ty = Ty::new_projection(
636 cx,
637 upvars_projection_def_id,
638 [
639 I::GenericArg::from(args.kind_ty()),
640 Ty::from_closure_kind(cx, goal_kind).into(),
641 goal_region.into(),
642 sig.tupled_inputs_ty.into(),
643 args.tupled_upvars_ty().into(),
644 args.coroutine_captures_by_ref_ty().into(),
645 ],
646 );
647 sig.to_coroutine(
648 cx,
649 args.parent_args(),
650 Ty::from_closure_kind(cx, goal_kind),
651 cx.coroutine_for_closure(def_id),
652 tupled_upvars_ty,
653 )
654}
655
656pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
663 cx: I,
664 self_ty: I::Ty,
665) -> Result<(ty::Binder<I, (I::FnInputTys, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
666 match self_ty.kind() {
667 ty::FnDef(def_id, args) => {
668 let sig = cx.fn_sig(def_id);
669 if sig.skip_binder().is_fn_trait_compatible()
670 && !cx.has_target_features(def_id)
671 && cx.fn_is_const(def_id)
672 {
673 Ok((
674 sig.instantiate(cx, args).map_bound(|sig| (sig.inputs(), sig.output())),
675 def_id,
676 args,
677 ))
678 } else {
679 return Err(NoSolution);
680 }
681 }
682 ty::FnPtr(..) => {
684 return Err(NoSolution);
685 }
686 ty::Closure(..) => {
688 return Err(NoSolution);
689 }
690 ty::CoroutineClosure(..) => {
692 return Err(NoSolution);
693 }
694
695 ty::Bool
696 | ty::Char
697 | ty::Int(_)
698 | ty::Uint(_)
699 | ty::Float(_)
700 | ty::Adt(_, _)
701 | ty::Foreign(_)
702 | ty::Str
703 | ty::Array(_, _)
704 | ty::Slice(_)
705 | ty::RawPtr(_, _)
706 | ty::Ref(_, _, _)
707 | ty::Dynamic(_, _, _)
708 | ty::Coroutine(_, _)
709 | ty::CoroutineWitness(..)
710 | ty::Never
711 | ty::Tuple(_)
712 | ty::Pat(_, _)
713 | ty::Alias(_, _)
714 | ty::Param(_)
715 | ty::Placeholder(..)
716 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
717 | ty::Error(_)
718 | ty::UnsafeBinder(_) => return Err(NoSolution),
719
720 ty::Bound(..)
721 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
722 panic!("unexpected type `{self_ty:?}`")
723 }
724 }
725}
726
727pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
730 cx: I,
731 self_ty: I::Ty,
732) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
733 let destruct_def_id = cx.require_lang_item(TraitSolverLangItem::Destruct);
734
735 match self_ty.kind() {
736 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(vec![]),
738
739 ty::Adt(adt_def, args) => {
742 let mut const_conditions: Vec<_> = adt_def
743 .all_field_tys(cx)
744 .iter_instantiated(cx, args)
745 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
746 .collect();
747 match adt_def.destructor(cx) {
748 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
750 Some(AdtDestructorKind::Const) => {
752 let drop_def_id = cx.require_lang_item(TraitSolverLangItem::Drop);
753 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
754 const_conditions.push(drop_trait_ref);
755 }
756 None => {}
758 }
759 Ok(const_conditions)
760 }
761
762 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
763 Ok(vec![ty::TraitRef::new(cx, destruct_def_id, [ty])])
764 }
765
766 ty::Tuple(tys) => Ok(tys
767 .iter()
768 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
769 .collect()),
770
771 ty::Bool
773 | ty::Char
774 | ty::Int(..)
775 | ty::Uint(..)
776 | ty::Float(..)
777 | ty::Str
778 | ty::RawPtr(..)
779 | ty::Ref(..)
780 | ty::FnDef(..)
781 | ty::FnPtr(..)
782 | ty::Never
783 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
784 | ty::Error(_) => Ok(vec![]),
785
786 ty::Closure(_, _)
789 | ty::CoroutineClosure(_, _)
790 | ty::Coroutine(_, _)
791 | ty::CoroutineWitness(_, _) => Err(NoSolution),
792
793 ty::UnsafeBinder(_) => Err(NoSolution),
796
797 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
798 Err(NoSolution)
799 }
800
801 ty::Bound(..)
802 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
803 panic!("unexpected type `{self_ty:?}`")
804 }
805 }
806}
807
808pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
843 ecx: &mut EvalCtxt<'_, D>,
844 param_env: I::ParamEnv,
845 trait_ref: ty::TraitRef<I>,
846 object_bounds: I::BoundExistentialPredicates,
847) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
848where
849 D: SolverDelegate<Interner = I>,
850 I: Interner,
851{
852 let cx = ecx.cx();
853 let mut requirements = vec![];
854 requirements.extend(elaborate::elaborate(
862 cx,
863 cx.explicit_super_predicates_of(trait_ref.def_id)
864 .iter_instantiated(cx, trait_ref.args)
865 .map(|(pred, _)| pred),
866 ));
867
868 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
871 if cx.generics_require_sized_self(associated_type_def_id) {
874 continue;
875 }
876
877 requirements
878 .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
879 }
880
881 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
882 for bound in object_bounds.iter() {
883 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
884 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
889 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
890 }
891 }
892
893 let mut folder = ReplaceProjectionWith {
894 ecx,
895 param_env,
896 self_ty: trait_ref.self_ty(),
897 mapping: &replace_projection_with,
898 nested: vec![],
899 };
900
901 let requirements = requirements.try_fold_with(&mut folder)?;
902 Ok(folder
903 .nested
904 .into_iter()
905 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
906 .collect())
907}
908
909struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
910 ecx: &'a mut EvalCtxt<'b, D>,
911 param_env: I::ParamEnv,
912 self_ty: I::Ty,
913 mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
914 nested: Vec<Goal<I, I::Predicate>>,
915}
916
917impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
918where
919 D: SolverDelegate<Interner = I>,
920 I: Interner,
921{
922 fn projection_may_match(
923 &mut self,
924 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
925 target_projection: ty::AliasTerm<I>,
926 ) -> bool {
927 source_projection.item_def_id() == target_projection.def_id
928 && self
929 .ecx
930 .probe(|_| ProbeKind::ProjectionCompatibility)
931 .enter(|ecx| -> Result<_, NoSolution> {
932 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
933 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
934 ecx.try_evaluate_added_goals()
935 })
936 .is_ok()
937 }
938
939 fn try_eagerly_replace_alias(
944 &mut self,
945 alias_term: ty::AliasTerm<I>,
946 ) -> Result<Option<I::Term>, Ambiguous> {
947 if alias_term.self_ty() != self.self_ty {
948 return Ok(None);
949 }
950
951 let Some(replacements) = self.mapping.get(&alias_term.def_id) else {
952 return Ok(None);
953 };
954
955 let mut matching_projections = replacements
959 .iter()
960 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
961 let Some(replacement) = matching_projections.next() else {
962 panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty);
964 };
965 if matching_projections.next().is_some() {
967 return Err(Ambiguous);
971 }
972
973 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
974 self.nested.extend(
975 self.ecx
976 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
977 .expect("expected to be able to unify goal projection with dyn's projection"),
978 );
979
980 Ok(Some(replacement.term))
981 }
982}
983
984pub(crate) struct Ambiguous;
986
987impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
988where
989 D: SolverDelegate<Interner = I>,
990 I: Interner,
991{
992 type Error = Ambiguous;
993
994 fn cx(&self) -> I {
995 self.ecx.cx()
996 }
997
998 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
999 if let ty::Alias(ty::Projection, alias_ty) = ty.kind()
1000 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1001 {
1002 Ok(term.expect_ty())
1003 } else {
1004 ty.try_super_fold_with(self)
1005 }
1006 }
1007}