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(def_id, args) => {
79 let coroutine_args = args.as_coroutine();
80 Ok(ty::Binder::dummy(vec![
81 coroutine_args.tupled_upvars_ty(),
82 Ty::new_coroutine_witness(
83 ecx.cx(),
84 def_id,
85 ecx.cx().mk_args(coroutine_args.parent_args().as_slice()),
86 ),
87 ]))
88 }
89
90 ty::CoroutineWitness(def_id, args) => Ok(ecx
91 .cx()
92 .coroutine_hidden_types(def_id)
93 .instantiate(cx, args)
94 .map_bound(|bound| bound.types.to_vec())),
95
96 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
97
98 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
100
101 ty::Adt(def, args) => {
102 Ok(ty::Binder::dummy(def.all_field_tys(cx).iter_instantiated(cx, args).collect()))
103 }
104
105 ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
106 Ok(ty::Binder::dummy(vec![cx.type_of(def_id).instantiate(cx, args)]))
110 }
111 }
112}
113
114#[instrument(level = "trace", skip(ecx), ret)]
115pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
116 ecx: &EvalCtxt<'_, D>,
117 sizedness: SizedTraitKind,
118 ty: I::Ty,
119) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
120where
121 D: SolverDelegate<Interner = I>,
122 I: Interner,
123{
124 match ty.kind() {
125 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
129 | ty::Uint(_)
130 | ty::Int(_)
131 | ty::Bool
132 | ty::Float(_)
133 | ty::FnDef(..)
134 | ty::FnPtr(..)
135 | ty::RawPtr(..)
136 | ty::Char
137 | ty::Ref(..)
138 | ty::Coroutine(..)
139 | ty::CoroutineWitness(..)
140 | ty::Array(..)
141 | ty::Pat(..)
142 | ty::Closure(..)
143 | ty::CoroutineClosure(..)
144 | ty::Never
145 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
146
147 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
149 SizedTraitKind::Sized => Err(NoSolution),
150 SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
151 },
152
153 ty::Foreign(..) => Err(NoSolution),
155
156 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
157
158 ty::Bound(..)
159 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
160 panic!("unexpected type `{ty:?}`")
161 }
162
163 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
164
165 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
168
169 ty::Adt(def, args) => {
184 if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
185 Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
186 } else {
187 Ok(ty::Binder::dummy(vec![]))
188 }
189 }
190 }
191}
192
193#[instrument(level = "trace", skip(ecx), ret)]
194pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
195 ecx: &EvalCtxt<'_, D>,
196 ty: I::Ty,
197) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
198where
199 D: SolverDelegate<Interner = I>,
200 I: Interner,
201{
202 match ty.kind() {
203 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
205
206 ty::Uint(_)
208 | ty::Int(_)
209 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
210 | ty::Bool
211 | ty::Float(_)
212 | ty::Char
213 | ty::RawPtr(..)
214 | ty::Never
215 | ty::Ref(_, _, Mutability::Not)
216 | ty::Array(..) => Err(NoSolution),
217
218 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
221
222 ty::Dynamic(..)
223 | ty::Str
224 | ty::Slice(_)
225 | ty::Foreign(..)
226 | ty::Ref(_, _, Mutability::Mut)
227 | ty::Adt(_, _)
228 | ty::Alias(_, _)
229 | ty::Param(_)
230 | ty::Placeholder(..) => Err(NoSolution),
231
232 ty::Bound(..)
233 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
234 panic!("unexpected type `{ty:?}`")
235 }
236
237 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
239
240 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
242
243 ty::CoroutineClosure(_, args) => {
245 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
246 }
247
248 ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
251 Movability::Static => Err(NoSolution),
252 Movability::Movable => {
253 if ecx.cx().features().coroutine_clone() {
254 let coroutine = args.as_coroutine();
255 Ok(ty::Binder::dummy(vec![
256 coroutine.tupled_upvars_ty(),
257 Ty::new_coroutine_witness(
258 ecx.cx(),
259 def_id,
260 ecx.cx().mk_args(coroutine.parent_args().as_slice()),
261 ),
262 ]))
263 } else {
264 Err(NoSolution)
265 }
266 }
267 },
268
269 ty::UnsafeBinder(_) => Err(NoSolution),
270
271 ty::CoroutineWitness(def_id, args) => Ok(ecx
273 .cx()
274 .coroutine_hidden_types(def_id)
275 .instantiate(ecx.cx(), args)
276 .map_bound(|bound| bound.types.to_vec())),
277 }
278}
279
280pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
282 cx: I,
283 self_ty: I::Ty,
284 goal_kind: ty::ClosureKind,
285) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
286 match self_ty.kind() {
287 ty::FnDef(def_id, args) => {
289 let sig = cx.fn_sig(def_id);
290 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
291 Ok(Some(
292 sig.instantiate(cx, args)
293 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
294 ))
295 } else {
296 Err(NoSolution)
297 }
298 }
299 ty::FnPtr(sig_tys, hdr) => {
301 let sig = sig_tys.with(hdr);
302 if sig.is_fn_trait_compatible() {
303 Ok(Some(
304 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
305 ))
306 } else {
307 Err(NoSolution)
308 }
309 }
310 ty::Closure(_, args) => {
311 let closure_args = args.as_closure();
312 match closure_args.kind_ty().to_opt_closure_kind() {
313 Some(closure_kind) => {
316 if !closure_kind.extends(goal_kind) {
317 return Err(NoSolution);
318 }
319 }
320 None => {
323 if goal_kind != ty::ClosureKind::FnOnce {
324 return Ok(None);
325 }
326 }
327 }
328 Ok(Some(
329 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
330 ))
331 }
332
333 ty::CoroutineClosure(def_id, args) => {
338 let args = args.as_coroutine_closure();
339 let kind_ty = args.kind_ty();
340 let sig = args.coroutine_closure_sig().skip_binder();
341
342 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
343 && !args.tupled_upvars_ty().is_ty_var()
344 {
345 if !kind.extends(goal_kind) {
346 return Err(NoSolution);
347 }
348
349 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
354 return Err(NoSolution);
355 }
356
357 coroutine_closure_to_certain_coroutine(
358 cx,
359 goal_kind,
360 Region::new_static(cx),
362 def_id,
363 args,
364 sig,
365 )
366 } else {
367 if goal_kind != ty::ClosureKind::FnOnce {
370 return Ok(None);
371 }
372
373 coroutine_closure_to_ambiguous_coroutine(
374 cx,
375 goal_kind, Region::new_static(cx),
377 def_id,
378 args,
379 sig,
380 )
381 };
382
383 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
384 }
385
386 ty::Bool
387 | ty::Char
388 | ty::Int(_)
389 | ty::Uint(_)
390 | ty::Float(_)
391 | ty::Adt(_, _)
392 | ty::Foreign(_)
393 | ty::Str
394 | ty::Array(_, _)
395 | ty::Slice(_)
396 | ty::RawPtr(_, _)
397 | ty::Ref(_, _, _)
398 | ty::Dynamic(_, _, _)
399 | ty::Coroutine(_, _)
400 | ty::CoroutineWitness(..)
401 | ty::Never
402 | ty::Tuple(_)
403 | ty::Pat(_, _)
404 | ty::UnsafeBinder(_)
405 | ty::Alias(_, _)
406 | ty::Param(_)
407 | ty::Placeholder(..)
408 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
409 | ty::Error(_) => Err(NoSolution),
410
411 ty::Bound(..)
412 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
413 panic!("unexpected type `{self_ty:?}`")
414 }
415 }
416}
417
418#[derive_where(Clone, Copy, Debug; I: Interner)]
421#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
422pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
423 pub tupled_inputs_ty: I::Ty,
424 pub output_coroutine_ty: I::Ty,
427 pub coroutine_return_ty: I::Ty,
430}
431
432pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
438 cx: I,
439 self_ty: I::Ty,
440 goal_kind: ty::ClosureKind,
441 env_region: I::Region,
442) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
443 match self_ty.kind() {
444 ty::CoroutineClosure(def_id, args) => {
445 let args = args.as_coroutine_closure();
446 let kind_ty = args.kind_ty();
447 let sig = args.coroutine_closure_sig().skip_binder();
448 let mut nested = vec![];
449
450 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
451 && !args.tupled_upvars_ty().is_ty_var()
452 {
453 if !kind.extends(goal_kind) {
454 return Err(NoSolution);
455 }
456
457 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
458 } else {
459 nested.push(
467 ty::TraitRef::new(
468 cx,
469 cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
470 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
471 )
472 .upcast(cx),
473 );
474
475 coroutine_closure_to_ambiguous_coroutine(
476 cx, goal_kind, env_region, def_id, args, sig,
477 )
478 };
479
480 Ok((
481 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
482 tupled_inputs_ty: sig.tupled_inputs_ty,
483 output_coroutine_ty: coroutine_ty,
484 coroutine_return_ty: sig.return_ty,
485 }),
486 nested,
487 ))
488 }
489
490 ty::FnDef(def_id, _) => {
491 let sig = self_ty.fn_sig(cx);
492 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
493 fn_item_to_async_callable(cx, sig)
494 } else {
495 Err(NoSolution)
496 }
497 }
498 ty::FnPtr(..) => {
499 let sig = self_ty.fn_sig(cx);
500 if sig.is_fn_trait_compatible() {
501 fn_item_to_async_callable(cx, sig)
502 } else {
503 Err(NoSolution)
504 }
505 }
506
507 ty::Closure(_, args) => {
508 let args = args.as_closure();
509 let bound_sig = args.sig();
510 let sig = bound_sig.skip_binder();
511 let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
512 let mut nested = vec![
515 bound_sig
516 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
517 .upcast(cx),
518 ];
519
520 let kind_ty = args.kind_ty();
523 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
524 if !closure_kind.extends(goal_kind) {
525 return Err(NoSolution);
526 }
527 } else {
528 let async_fn_kind_trait_def_id =
529 cx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
530 nested.push(
538 ty::TraitRef::new(
539 cx,
540 async_fn_kind_trait_def_id,
541 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
542 )
543 .upcast(cx),
544 );
545 }
546
547 let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
548 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
549 Ok((
550 bound_sig.rebind(AsyncCallableRelevantTypes {
551 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
552 output_coroutine_ty: sig.output(),
553 coroutine_return_ty: future_output_ty,
554 }),
555 nested,
556 ))
557 }
558
559 ty::Bool
560 | ty::Char
561 | ty::Int(_)
562 | ty::Uint(_)
563 | ty::Float(_)
564 | ty::Adt(_, _)
565 | ty::Foreign(_)
566 | ty::Str
567 | ty::Array(_, _)
568 | ty::Pat(_, _)
569 | ty::Slice(_)
570 | ty::RawPtr(_, _)
571 | ty::Ref(_, _, _)
572 | ty::Dynamic(_, _, _)
573 | ty::Coroutine(_, _)
574 | ty::CoroutineWitness(..)
575 | ty::Never
576 | ty::UnsafeBinder(_)
577 | ty::Tuple(_)
578 | ty::Alias(_, _)
579 | ty::Param(_)
580 | ty::Placeholder(..)
581 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
582 | ty::Error(_) => Err(NoSolution),
583
584 ty::Bound(..)
585 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
586 panic!("unexpected type `{self_ty:?}`")
587 }
588 }
589}
590
591fn fn_item_to_async_callable<I: Interner>(
592 cx: I,
593 bound_sig: ty::Binder<I, ty::FnSig<I>>,
594) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
595 let sig = bound_sig.skip_binder();
596 let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
597 let nested = vec![
600 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
601 ];
602 let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
603 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
604 Ok((
605 bound_sig.rebind(AsyncCallableRelevantTypes {
606 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
607 output_coroutine_ty: sig.output(),
608 coroutine_return_ty: future_output_ty,
609 }),
610 nested,
611 ))
612}
613
614fn coroutine_closure_to_certain_coroutine<I: Interner>(
617 cx: I,
618 goal_kind: ty::ClosureKind,
619 goal_region: I::Region,
620 def_id: I::DefId,
621 args: ty::CoroutineClosureArgs<I>,
622 sig: ty::CoroutineClosureSignature<I>,
623) -> I::Ty {
624 sig.to_coroutine_given_kind_and_upvars(
625 cx,
626 args.parent_args(),
627 cx.coroutine_for_closure(def_id),
628 goal_kind,
629 goal_region,
630 args.tupled_upvars_ty(),
631 args.coroutine_captures_by_ref_ty(),
632 )
633}
634
635fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
641 cx: I,
642 goal_kind: ty::ClosureKind,
643 goal_region: I::Region,
644 def_id: I::DefId,
645 args: ty::CoroutineClosureArgs<I>,
646 sig: ty::CoroutineClosureSignature<I>,
647) -> I::Ty {
648 let upvars_projection_def_id = cx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
649 let tupled_upvars_ty = Ty::new_projection(
650 cx,
651 upvars_projection_def_id,
652 [
653 I::GenericArg::from(args.kind_ty()),
654 Ty::from_closure_kind(cx, goal_kind).into(),
655 goal_region.into(),
656 sig.tupled_inputs_ty.into(),
657 args.tupled_upvars_ty().into(),
658 args.coroutine_captures_by_ref_ty().into(),
659 ],
660 );
661 sig.to_coroutine(
662 cx,
663 args.parent_args(),
664 Ty::from_closure_kind(cx, goal_kind),
665 cx.coroutine_for_closure(def_id),
666 tupled_upvars_ty,
667 )
668}
669
670pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
677 cx: I,
678 self_ty: I::Ty,
679) -> Result<(ty::Binder<I, (I::FnInputTys, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
680 match self_ty.kind() {
681 ty::FnDef(def_id, args) => {
682 let sig = cx.fn_sig(def_id);
683 if sig.skip_binder().is_fn_trait_compatible()
684 && !cx.has_target_features(def_id)
685 && cx.fn_is_const(def_id)
686 {
687 Ok((
688 sig.instantiate(cx, args).map_bound(|sig| (sig.inputs(), sig.output())),
689 def_id,
690 args,
691 ))
692 } else {
693 return Err(NoSolution);
694 }
695 }
696 ty::FnPtr(..) => {
698 return Err(NoSolution);
699 }
700 ty::Closure(..) => {
702 return Err(NoSolution);
703 }
704 ty::CoroutineClosure(..) => {
706 return Err(NoSolution);
707 }
708
709 ty::Bool
710 | ty::Char
711 | ty::Int(_)
712 | ty::Uint(_)
713 | ty::Float(_)
714 | ty::Adt(_, _)
715 | ty::Foreign(_)
716 | ty::Str
717 | ty::Array(_, _)
718 | ty::Slice(_)
719 | ty::RawPtr(_, _)
720 | ty::Ref(_, _, _)
721 | ty::Dynamic(_, _, _)
722 | ty::Coroutine(_, _)
723 | ty::CoroutineWitness(..)
724 | ty::Never
725 | ty::Tuple(_)
726 | ty::Pat(_, _)
727 | ty::Alias(_, _)
728 | ty::Param(_)
729 | ty::Placeholder(..)
730 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
731 | ty::Error(_)
732 | ty::UnsafeBinder(_) => return Err(NoSolution),
733
734 ty::Bound(..)
735 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
736 panic!("unexpected type `{self_ty:?}`")
737 }
738 }
739}
740
741pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
744 cx: I,
745 self_ty: I::Ty,
746) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
747 let destruct_def_id = cx.require_lang_item(TraitSolverLangItem::Destruct);
748
749 match self_ty.kind() {
750 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(vec![]),
752
753 ty::Adt(adt_def, args) => {
756 let mut const_conditions: Vec<_> = adt_def
757 .all_field_tys(cx)
758 .iter_instantiated(cx, args)
759 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
760 .collect();
761 match adt_def.destructor(cx) {
762 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
764 Some(AdtDestructorKind::Const) => {
766 let drop_def_id = cx.require_lang_item(TraitSolverLangItem::Drop);
767 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
768 const_conditions.push(drop_trait_ref);
769 }
770 None => {}
772 }
773 Ok(const_conditions)
774 }
775
776 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
777 Ok(vec![ty::TraitRef::new(cx, destruct_def_id, [ty])])
778 }
779
780 ty::Tuple(tys) => Ok(tys
781 .iter()
782 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
783 .collect()),
784
785 ty::Bool
787 | ty::Char
788 | ty::Int(..)
789 | ty::Uint(..)
790 | ty::Float(..)
791 | ty::Str
792 | ty::RawPtr(..)
793 | ty::Ref(..)
794 | ty::FnDef(..)
795 | ty::FnPtr(..)
796 | ty::Never
797 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
798 | ty::Error(_) => Ok(vec![]),
799
800 ty::Closure(_, _)
803 | ty::CoroutineClosure(_, _)
804 | ty::Coroutine(_, _)
805 | ty::CoroutineWitness(_, _) => Err(NoSolution),
806
807 ty::UnsafeBinder(_) => Err(NoSolution),
810
811 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
812 Err(NoSolution)
813 }
814
815 ty::Bound(..)
816 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
817 panic!("unexpected type `{self_ty:?}`")
818 }
819 }
820}
821
822pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
857 ecx: &mut EvalCtxt<'_, D>,
858 param_env: I::ParamEnv,
859 trait_ref: ty::TraitRef<I>,
860 object_bounds: I::BoundExistentialPredicates,
861) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
862where
863 D: SolverDelegate<Interner = I>,
864 I: Interner,
865{
866 let cx = ecx.cx();
867 let mut requirements = vec![];
868 requirements.extend(elaborate::elaborate(
876 cx,
877 cx.explicit_super_predicates_of(trait_ref.def_id)
878 .iter_instantiated(cx, trait_ref.args)
879 .map(|(pred, _)| pred),
880 ));
881
882 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
885 if cx.generics_require_sized_self(associated_type_def_id) {
888 continue;
889 }
890
891 requirements
892 .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
893 }
894
895 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
896 for bound in object_bounds.iter() {
897 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
898 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
903 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
904 }
905 }
906
907 let mut folder = ReplaceProjectionWith {
908 ecx,
909 param_env,
910 self_ty: trait_ref.self_ty(),
911 mapping: &replace_projection_with,
912 nested: vec![],
913 };
914
915 let requirements = requirements.try_fold_with(&mut folder)?;
916 Ok(folder
917 .nested
918 .into_iter()
919 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
920 .collect())
921}
922
923struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
924 ecx: &'a mut EvalCtxt<'b, D>,
925 param_env: I::ParamEnv,
926 self_ty: I::Ty,
927 mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
928 nested: Vec<Goal<I, I::Predicate>>,
929}
930
931impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
932where
933 D: SolverDelegate<Interner = I>,
934 I: Interner,
935{
936 fn projection_may_match(
937 &mut self,
938 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
939 target_projection: ty::AliasTerm<I>,
940 ) -> bool {
941 source_projection.item_def_id() == target_projection.def_id
942 && self
943 .ecx
944 .probe(|_| ProbeKind::ProjectionCompatibility)
945 .enter(|ecx| -> Result<_, NoSolution> {
946 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
947 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
948 ecx.try_evaluate_added_goals()
949 })
950 .is_ok()
951 }
952
953 fn try_eagerly_replace_alias(
958 &mut self,
959 alias_term: ty::AliasTerm<I>,
960 ) -> Result<Option<I::Term>, Ambiguous> {
961 if alias_term.self_ty() != self.self_ty {
962 return Ok(None);
963 }
964
965 let Some(replacements) = self.mapping.get(&alias_term.def_id) else {
966 return Ok(None);
967 };
968
969 let mut matching_projections = replacements
973 .iter()
974 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
975 let Some(replacement) = matching_projections.next() else {
976 panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty);
978 };
979 if matching_projections.next().is_some() {
981 return Err(Ambiguous);
985 }
986
987 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
988 self.nested.extend(
989 self.ecx
990 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
991 .expect("expected to be able to unify goal projection with dyn's projection"),
992 );
993
994 Ok(Some(replacement.term))
995 }
996}
997
998pub(crate) struct Ambiguous;
1000
1001impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1002where
1003 D: SolverDelegate<Interner = I>,
1004 I: Interner,
1005{
1006 type Error = Ambiguous;
1007
1008 fn cx(&self) -> I {
1009 self.ecx.cx()
1010 }
1011
1012 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
1013 if let ty::Alias(ty::Projection, alias_ty) = ty.kind()
1014 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1015 {
1016 Ok(term.expect_ty())
1017 } else {
1018 ty.try_super_fold_with(self)
1019 }
1020 }
1021}