1use derive_where::derive_where;
5use rustc_type_ir::data_structures::HashMap;
6use rustc_type_ir::inherent::*;
7use rustc_type_ir::lang_items::{SolverProjectionLangItem, SolverTraitLangItem};
8use rustc_type_ir::solve::SizedTraitKind;
9use rustc_type_ir::solve::inspect::ProbeKind;
10use rustc_type_ir::{
11 self as ty, Binder, FallibleTypeFolder, Interner, Movability, Mutability, Region, TypeFoldable,
12 TypeSuperFoldable, Unnormalized, Upcast as _, elaborate,
13};
14use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
15use tracing::instrument;
16
17use crate::delegate::SolverDelegate;
18use crate::solve::{
19 AdtDestructorKind, EvalCtxt, Goal, NoSolution, NoSolutionOrRerunNonErased, RerunNonErased,
20};
21
22x;#[instrument(level = "trace", skip(ecx), ret)]
24pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<D, I>(
25 ecx: &EvalCtxt<'_, D>,
26 ty: I::Ty,
27) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
28where
29 D: SolverDelegate<Interner = I>,
30 I: Interner,
31{
32 let cx = ecx.cx();
33 match ty.kind() {
34 ty::Uint(_)
35 | ty::Int(_)
36 | ty::Bool
37 | ty::Float(_)
38 | ty::FnDef(..)
39 | ty::FnPtr(..)
40 | ty::Error(_)
41 | ty::Never
42 | ty::Char => Ok(ty::Binder::dummy(vec![])),
43
44 ty::Foreign(..) => Ok(ty::Binder::dummy(vec![])),
48
49 ty::Str => Ok(ty::Binder::dummy(vec![Ty::new_slice(cx, Ty::new_u8(cx))])),
51
52 ty::Dynamic(..)
53 | ty::Param(..)
54 | ty::Alias(
55 ty::IsRigid::Yes,
56 ty::AliasTy {
57 kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, ..
58 },
59 )
60 | ty::Placeholder(..)
61 | ty::Alias(ty::IsRigid::No, _)
62 | ty::Bound(..)
63 | ty::Infer(_) => {
64 panic!("unexpected type `{ty:?}`")
65 }
66
67 ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
68 Ok(ty::Binder::dummy(vec![element_ty]))
69 }
70
71 ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
72 Ok(ty::Binder::dummy(vec![element_ty]))
73 }
74
75 ty::Tuple(tys) => {
76 Ok(ty::Binder::dummy(tys.to_vec()))
78 }
79
80 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
81
82 ty::CoroutineClosure(_, args) => {
83 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
84 }
85
86 ty::Coroutine(def_id, args) => Ok(ty::Binder::dummy(vec![
87 args.as_coroutine().tupled_upvars_ty(),
88 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
89 ])),
90
91 ty::CoroutineWitness(def_id, args) => Ok(ecx
92 .cx()
93 .coroutine_hidden_types(def_id)
94 .instantiate(cx, args)
95 .skip_norm_wip()
96 .map_bound(|bound| bound.types.to_vec())),
97
98 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
99
100 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
102
103 ty::Adt(def, args) => Ok(ty::Binder::dummy(
104 def.all_field_tys(cx)
105 .iter_instantiated(cx, args)
106 .map(Unnormalized::skip_norm_wip)
107 .collect(),
108 )),
109
110 ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
111 Ok(ty::Binder::dummy(vec![
115 cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip(),
116 ]))
117 }
118 }
119}
120
121x;#[instrument(level = "trace", skip(ecx), ret)]
122pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
123 ecx: &EvalCtxt<'_, D>,
124 sizedness: SizedTraitKind,
125 ty: I::Ty,
126) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
127where
128 D: SolverDelegate<Interner = I>,
129 I: Interner,
130{
131 match ty.kind() {
132 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
136 | ty::Uint(_)
137 | ty::Int(_)
138 | ty::Bool
139 | ty::Float(_)
140 | ty::FnDef(..)
141 | ty::FnPtr(..)
142 | ty::RawPtr(..)
143 | ty::Char
144 | ty::Ref(..)
145 | ty::Coroutine(..)
146 | ty::CoroutineWitness(..)
147 | ty::Array(..)
148 | ty::Pat(..)
149 | ty::Closure(..)
150 | ty::CoroutineClosure(..)
151 | ty::Never
152 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
153
154 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
156 SizedTraitKind::Sized => Err(NoSolution),
157 SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
158 },
159
160 ty::Foreign(..) => Err(NoSolution),
162
163 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
164
165 ty::Bound(..)
166 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
167 panic!("unexpected type `{ty:?}`")
168 }
169
170 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
171
172 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
175
176 ty::Adt(def, args) => {
191 if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
192 Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args).skip_norm_wip()]))
193 } else {
194 Ok(ty::Binder::dummy(vec![]))
195 }
196 }
197 }
198}
199
200x;#[instrument(level = "trace", skip(ecx), ret)]
201pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
202 ecx: &EvalCtxt<'_, D>,
203 ty: I::Ty,
204) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
205where
206 D: SolverDelegate<Interner = I>,
207 I: Interner,
208{
209 match ty.kind() {
210 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
212
213 ty::Uint(_)
215 | ty::Int(_)
216 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
217 | ty::Bool
218 | ty::Float(_)
219 | ty::Char
220 | ty::RawPtr(..)
221 | ty::Never
222 | ty::Ref(_, _, Mutability::Not)
223 | ty::Array(..) => Err(NoSolution),
224
225 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
228
229 ty::Dynamic(..)
230 | ty::Str
231 | ty::Slice(_)
232 | ty::Foreign(..)
233 | ty::Ref(_, _, Mutability::Mut)
234 | ty::Adt(_, _)
235 | ty::Alias(ty::IsRigid::Yes, _)
236 | ty::Param(_)
237 | ty::Placeholder(..) => Err(NoSolution),
238
239 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
241
242 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
244
245 ty::CoroutineClosure(_, args) => {
247 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
248 }
249
250 ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
253 Movability::Static => Err(NoSolution),
254 Movability::Movable => {
255 if ecx.cx().features().coroutine_clone() {
256 Ok(ty::Binder::dummy(vec![
257 args.as_coroutine().tupled_upvars_ty(),
258 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
259 ]))
260 } else {
261 Err(NoSolution)
262 }
263 }
264 },
265
266 ty::UnsafeBinder(_) => Err(NoSolution),
267
268 ty::CoroutineWitness(def_id, args) => Ok(ecx
270 .cx()
271 .coroutine_hidden_types(def_id)
272 .instantiate(ecx.cx(), args)
273 .skip_norm_wip()
274 .map_bound(|bound| bound.types.to_vec())),
275
276 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
277 | ty::Alias(ty::IsRigid::No, _)
278 | ty::Bound(..) => {
279 panic!("unexpected type `{ty:?}`")
280 }
281 }
282}
283
284pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
286 cx: I,
287 self_ty: I::Ty,
288 goal_kind: ty::ClosureKind,
289) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
290 match self_ty.kind() {
291 ty::FnDef(def_id, args) => {
293 let sig = cx.fn_sig(def_id);
294 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
295 Ok(Some(
296 sig.instantiate(cx, args.no_bound_vars().unwrap())
297 .skip_norm_wip()
298 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
299 ))
300 } else {
301 Err(NoSolution)
302 }
303 }
304 ty::FnPtr(sig_tys, hdr) => {
306 let sig = sig_tys.with(hdr);
307 if sig.is_fn_trait_compatible() {
308 Ok(Some(
309 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
310 ))
311 } else {
312 Err(NoSolution)
313 }
314 }
315 ty::Closure(_, args) => {
316 let closure_args = args.as_closure();
317 match closure_args.kind_ty().to_opt_closure_kind() {
318 Some(closure_kind) => {
321 if !closure_kind.extends(goal_kind) {
322 return Err(NoSolution);
323 }
324 }
325 None => {
328 if goal_kind != ty::ClosureKind::FnOnce {
329 return Ok(None);
330 }
331 }
332 }
333 Ok(Some(
334 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
335 ))
336 }
337
338 ty::CoroutineClosure(def_id, args) => {
343 let args = args.as_coroutine_closure();
344 let kind_ty = args.kind_ty();
345 let sig = args.coroutine_closure_sig().skip_binder();
346
347 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
348 && !args.tupled_upvars_ty().is_ty_var()
349 {
350 if !kind.extends(goal_kind) {
351 return Err(NoSolution);
352 }
353
354 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
359 return Err(NoSolution);
360 }
361
362 coroutine_closure_to_certain_coroutine(
363 cx,
364 goal_kind,
365 Region::new_static(cx),
367 def_id,
368 args,
369 sig,
370 )
371 } else {
372 if goal_kind != ty::ClosureKind::FnOnce {
375 return Ok(None);
376 }
377
378 coroutine_closure_to_ambiguous_coroutine(
379 cx,
380 goal_kind, Region::new_static(cx),
382 def_id,
383 args,
384 sig,
385 )
386 };
387
388 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
389 }
390
391 ty::Bool
392 | ty::Char
393 | ty::Int(_)
394 | ty::Uint(_)
395 | ty::Float(_)
396 | ty::Adt(_, _)
397 | ty::Foreign(_)
398 | ty::Str
399 | ty::Array(_, _)
400 | ty::Slice(_)
401 | ty::RawPtr(_, _)
402 | ty::Ref(_, _, _)
403 | ty::Dynamic(_, _)
404 | ty::Coroutine(_, _)
405 | ty::CoroutineWitness(..)
406 | ty::Never
407 | ty::Tuple(_)
408 | ty::Pat(_, _)
409 | ty::UnsafeBinder(_)
410 | ty::Alias(ty::IsRigid::Yes, _)
411 | ty::Param(_)
412 | ty::Placeholder(..)
413 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
414 | ty::Error(_) => Err(NoSolution),
415
416 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
417 | ty::Alias(ty::IsRigid::No, _)
418 | ty::Bound(..) => {
419 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
420 }
421 }
422}
423
424#[automatically_derived]
impl<I: Interner> ::core::fmt::Debug for AsyncCallableRelevantTypes<I> where
I: Interner {
fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
match self {
AsyncCallableRelevantTypes {
tupled_inputs_ty: ref __field_tupled_inputs_ty,
output_coroutine_ty: ref __field_output_coroutine_ty,
coroutine_return_ty: ref __field_coroutine_return_ty } => {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f,
"AsyncCallableRelevantTypes");
::core::fmt::DebugStruct::field(&mut __builder,
"tupled_inputs_ty", __field_tupled_inputs_ty);
::core::fmt::DebugStruct::field(&mut __builder,
"output_coroutine_ty", __field_output_coroutine_ty);
::core::fmt::DebugStruct::field(&mut __builder,
"coroutine_return_ty", __field_coroutine_return_ty);
::core::fmt::DebugStruct::finish(&mut __builder)
}
}
}
}#[derive_where(Clone, Copy, Debug; I: Interner)]
427#[derive(const _: () =
{
impl<I: Interner> ::rustc_type_ir::TypeVisitable<I> for
AsyncCallableRelevantTypes<I> where I: Interner,
I::Ty: ::rustc_type_ir::TypeVisitable<I> {
fn visit_with<__V: ::rustc_type_ir::TypeVisitor<I>>(&self,
__visitor: &mut __V) -> __V::Result {
match *self {
AsyncCallableRelevantTypes {
tupled_inputs_ty: ref __binding_0,
output_coroutine_ty: ref __binding_1,
coroutine_return_ty: ref __binding_2 } => {
{
match ::rustc_type_ir::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(__binding_0,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_type_ir::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_type_ir::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(__binding_1,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_type_ir::VisitorResult::from_residual(r);
}
}
}
{
match ::rustc_type_ir::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(__binding_2,
__visitor)) {
::core::ops::ControlFlow::Continue(()) => {}
::core::ops::ControlFlow::Break(r) => {
return ::rustc_type_ir::VisitorResult::from_residual(r);
}
}
}
}
}
<__V::Result as ::rustc_type_ir::VisitorResult>::output()
}
}
};TypeVisitable_Generic, const _: () =
{
impl<I: Interner> ::rustc_type_ir::TypeFoldable<I> for
AsyncCallableRelevantTypes<I> where I: Interner,
I::Ty: ::rustc_type_ir::TypeFoldable<I> {
fn try_fold_with<__F: ::rustc_type_ir::FallibleTypeFolder<I>>(self,
__folder: &mut __F) -> Result<Self, __F::Error> {
Ok(match self {
AsyncCallableRelevantTypes {
tupled_inputs_ty: __binding_0,
output_coroutine_ty: __binding_1,
coroutine_return_ty: __binding_2 } => {
AsyncCallableRelevantTypes {
tupled_inputs_ty: ::rustc_type_ir::TypeFoldable::try_fold_with(__binding_0,
__folder)?,
output_coroutine_ty: ::rustc_type_ir::TypeFoldable::try_fold_with(__binding_1,
__folder)?,
coroutine_return_ty: ::rustc_type_ir::TypeFoldable::try_fold_with(__binding_2,
__folder)?,
}
}
})
}
fn fold_with<__F: ::rustc_type_ir::TypeFolder<I>>(self,
__folder: &mut __F) -> Self {
match self {
AsyncCallableRelevantTypes {
tupled_inputs_ty: __binding_0,
output_coroutine_ty: __binding_1,
coroutine_return_ty: __binding_2 } => {
AsyncCallableRelevantTypes {
tupled_inputs_ty: ::rustc_type_ir::TypeFoldable::fold_with(__binding_0,
__folder),
output_coroutine_ty: ::rustc_type_ir::TypeFoldable::fold_with(__binding_1,
__folder),
coroutine_return_ty: ::rustc_type_ir::TypeFoldable::fold_with(__binding_2,
__folder),
}
}
}
}
}
};TypeFoldable_Generic)]
428pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
429 pub tupled_inputs_ty: I::Ty,
430 pub output_coroutine_ty: I::Ty,
433 pub coroutine_return_ty: I::Ty,
436}
437
438pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
444 cx: I,
445 self_ty: I::Ty,
446 goal_kind: ty::ClosureKind,
447 env_region: Region<I>,
448) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
449 match self_ty.kind() {
450 ty::CoroutineClosure(def_id, args) => {
451 let args = args.as_coroutine_closure();
452 let kind_ty = args.kind_ty();
453 let sig = args.coroutine_closure_sig().skip_binder();
454 let mut nested = ::alloc::vec::Vec::new()vec![];
455
456 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
457 && !args.tupled_upvars_ty().is_ty_var()
458 {
459 if !kind.extends(goal_kind) {
460 return Err(NoSolution);
461 }
462
463 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
464 } else {
465 nested.push(
473 ty::TraitRef::new(
474 cx,
475 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
476 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
477 )
478 .upcast(cx),
479 );
480
481 coroutine_closure_to_ambiguous_coroutine(
482 cx, goal_kind, env_region, def_id, args, sig,
483 )
484 };
485
486 Ok((
487 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
488 tupled_inputs_ty: sig.tupled_inputs_ty,
489 output_coroutine_ty: coroutine_ty,
490 coroutine_return_ty: sig.return_ty,
491 }),
492 nested,
493 ))
494 }
495
496 ty::FnDef(def_id, _) => {
497 let sig = self_ty.fn_sig(cx);
498 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
499 fn_item_to_async_callable(cx, sig)
500 } else {
501 Err(NoSolution)
502 }
503 }
504 ty::FnPtr(..) => {
505 let sig = self_ty.fn_sig(cx);
506 if sig.is_fn_trait_compatible() {
507 fn_item_to_async_callable(cx, sig)
508 } else {
509 Err(NoSolution)
510 }
511 }
512
513 ty::Closure(_, args) => {
514 let args = args.as_closure();
515 let bound_sig = args.sig();
516 let sig = bound_sig.skip_binder();
517 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
518 let mut nested = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id,
[sig.output()])).upcast(cx)]))vec![
521 bound_sig
522 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
523 .upcast(cx),
524 ];
525
526 let kind_ty = args.kind_ty();
529 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
530 if !closure_kind.extends(goal_kind) {
531 return Err(NoSolution);
532 }
533 } else {
534 let async_fn_kind_trait_def_id =
535 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
536 nested.push(
544 ty::TraitRef::new(
545 cx,
546 async_fn_kind_trait_def_id,
547 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
548 )
549 .upcast(cx),
550 );
551 }
552
553 let future_output_def_id =
554 cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
555 let future_output_ty =
556 Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]);
557 Ok((
558 bound_sig.rebind(AsyncCallableRelevantTypes {
559 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
560 output_coroutine_ty: sig.output(),
561 coroutine_return_ty: future_output_ty,
562 }),
563 nested,
564 ))
565 }
566
567 ty::Bool
568 | ty::Char
569 | ty::Int(_)
570 | ty::Uint(_)
571 | ty::Float(_)
572 | ty::Adt(_, _)
573 | ty::Foreign(_)
574 | ty::Str
575 | ty::Array(_, _)
576 | ty::Pat(_, _)
577 | ty::Slice(_)
578 | ty::RawPtr(_, _)
579 | ty::Ref(_, _, _)
580 | ty::Dynamic(_, _)
581 | ty::Coroutine(_, _)
582 | ty::CoroutineWitness(..)
583 | ty::Never
584 | ty::UnsafeBinder(_)
585 | ty::Tuple(_)
586 | ty::Alias(ty::IsRigid::Yes, _)
587 | ty::Param(_)
588 | ty::Placeholder(..)
589 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
590 | ty::Error(_) => Err(NoSolution),
591
592 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
593 | ty::Alias(ty::IsRigid::No, _)
594 | ty::Bound(..) => {
595 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
596 }
597 }
598}
599
600fn fn_item_to_async_callable<I: Interner>(
601 cx: I,
602 bound_sig: ty::Binder<I, ty::FnSig<I>>,
603) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
604 let sig = bound_sig.skip_binder();
605 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
606 let nested = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id,
[sig.output()])).upcast(cx)]))vec![
609 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
610 ];
611 let future_output_def_id =
612 cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
613 let future_output_ty =
614 Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]);
615 Ok((
616 bound_sig.rebind(AsyncCallableRelevantTypes {
617 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
618 output_coroutine_ty: sig.output(),
619 coroutine_return_ty: future_output_ty,
620 }),
621 nested,
622 ))
623}
624
625fn coroutine_closure_to_certain_coroutine<I: Interner>(
628 cx: I,
629 goal_kind: ty::ClosureKind,
630 goal_region: Region<I>,
631 def_id: I::CoroutineClosureId,
632 args: ty::CoroutineClosureArgs<I>,
633 sig: ty::CoroutineClosureSignature<I>,
634) -> I::Ty {
635 sig.to_coroutine_given_kind_and_upvars(
636 cx,
637 args.parent_args(),
638 cx.coroutine_for_closure(def_id),
639 goal_kind,
640 goal_region,
641 args.tupled_upvars_ty(),
642 args.coroutine_captures_by_ref_ty(),
643 )
644}
645
646fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
652 cx: I,
653 goal_kind: ty::ClosureKind,
654 goal_region: Region<I>,
655 def_id: I::CoroutineClosureId,
656 args: ty::CoroutineClosureArgs<I>,
657 sig: ty::CoroutineClosureSignature<I>,
658) -> I::Ty {
659 let upvars_projection_def_id =
660 cx.require_projection_lang_item(SolverProjectionLangItem::AsyncFnKindUpvars);
661 let tupled_upvars_ty = Ty::new_projection(
662 cx,
663 ty::IsRigid::No,
664 upvars_projection_def_id,
665 [
666 I::GenericArg::from(args.kind_ty()),
667 Ty::from_closure_kind(cx, goal_kind).into(),
668 goal_region.into(),
669 sig.tupled_inputs_ty.into(),
670 args.tupled_upvars_ty().into(),
671 args.coroutine_captures_by_ref_ty().into(),
672 ],
673 );
674 sig.to_coroutine(
675 cx,
676 args.parent_args(),
677 Ty::from_closure_kind(cx, goal_kind),
678 cx.coroutine_for_closure(def_id),
679 tupled_upvars_ty,
680 )
681}
682
683x;#[instrument(level = "trace", skip(cx), ret)]
690pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
691 cx: I,
692 self_ty: I::Ty,
693) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
694 match self_ty.kind() {
695 ty::FnDef(def_id, args) => {
696 let args = args.no_bound_vars().unwrap();
698
699 let sig = cx.fn_sig(def_id);
700 if sig.skip_binder().is_fn_trait_compatible()
701 && !cx.has_target_features(def_id)
702 && cx.fn_is_const(def_id)
703 {
704 Ok((
705 sig.instantiate(cx, args)
706 .skip_norm_wip()
707 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
708 def_id.into(),
709 args,
710 ))
711 } else {
712 return Err(NoSolution);
713 }
714 }
715 ty::FnPtr(..) => {
717 return Err(NoSolution);
718 }
719 ty::Closure(def, args) => {
720 if cx.closure_is_const(def) {
721 let closure_args = args.as_closure();
722 Ok((
723 closure_args
724 .sig()
725 .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
726 def.into(),
727 args,
728 ))
729 } else {
730 return Err(NoSolution);
731 }
732 }
733 ty::CoroutineClosure(..) => {
735 return Err(NoSolution);
736 }
737
738 ty::Bool
739 | ty::Char
740 | ty::Int(_)
741 | ty::Uint(_)
742 | ty::Float(_)
743 | ty::Adt(_, _)
744 | ty::Foreign(_)
745 | ty::Str
746 | ty::Array(_, _)
747 | ty::Slice(_)
748 | ty::RawPtr(_, _)
749 | ty::Ref(_, _, _)
750 | ty::Dynamic(_, _)
751 | ty::Coroutine(_, _)
752 | ty::CoroutineWitness(..)
753 | ty::Never
754 | ty::Tuple(_)
755 | ty::Pat(_, _)
756 | ty::Alias(ty::IsRigid::Yes, _)
757 | ty::Param(_)
758 | ty::Placeholder(..)
759 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
760 | ty::Error(_)
761 | ty::UnsafeBinder(_) => return Err(NoSolution),
762
763 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
764 | ty::Alias(ty::IsRigid::No, _)
765 | ty::Bound(..) => {
766 panic!("unexpected type `{self_ty:?}`")
767 }
768 }
769}
770
771pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
774 cx: I,
775 self_ty: I::Ty,
776) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
777 let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
778
779 match self_ty.kind() {
780 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()vec![]),
782
783 ty::Adt(adt_def, args) => {
786 let mut const_conditions: Vec<_> = adt_def
787 .all_field_tys(cx)
788 .iter_instantiated(cx, args)
789 .map(Unnormalized::skip_norm_wip)
790 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
791 .collect();
792 match adt_def.destructor(cx) {
793 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
795 Some(AdtDestructorKind::Const) => {
797 let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
798 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
799 const_conditions.push(drop_trait_ref);
800 }
801 None => {}
803 }
804 Ok(const_conditions)
805 }
806
807 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
808 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ty::TraitRef::new(cx, destruct_def_id, [ty])]))vec![ty::TraitRef::new(cx, destruct_def_id, [ty])])
809 }
810
811 ty::Tuple(tys) => Ok(tys
812 .iter()
813 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
814 .collect()),
815
816 ty::Bool
818 | ty::Char
819 | ty::Int(..)
820 | ty::Uint(..)
821 | ty::Float(..)
822 | ty::Str
823 | ty::RawPtr(..)
824 | ty::Ref(..)
825 | ty::FnDef(..)
826 | ty::FnPtr(..)
827 | ty::Never
828 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
829 | ty::Error(_) => Ok(::alloc::vec::Vec::new()vec![]),
830
831 ty::Closure(_, args) => {
833 let closure_args = args.as_closure();
834 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ty::TraitRef::new(cx, destruct_def_id,
[closure_args.tupled_upvars_ty()])]))vec![ty::TraitRef::new(cx, destruct_def_id, [closure_args.tupled_upvars_ty()])])
835 }
836 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
839 Err(NoSolution)
840 }
841
842 ty::UnsafeBinder(_) => Err(NoSolution),
845
846 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
847 Err(NoSolution)
848 }
849
850 ty::Bound(..)
851 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
852 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
853 }
854 }
855}
856
857pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
892 ecx: &mut EvalCtxt<'_, D>,
893 param_env: I::ParamEnv,
894 trait_ref: Binder<I, ty::TraitRef<I>>,
895 object_bounds: I::BoundExistentialPredicates,
896) -> Result<Vec<Goal<I, I::Predicate>>, AmbiguousOrRerunNonErased>
897where
898 D: SolverDelegate<Interner = I>,
899 I: Interner,
900{
901 let cx = ecx.cx();
902 let trait_ref = ecx.instantiate_binder_with_infer(trait_ref);
903 let mut requirements = ::alloc::vec::Vec::new()vec![];
904 requirements.extend(elaborate::elaborate(
912 cx,
913 cx.explicit_super_clauses_of(trait_ref.def_id)
914 .iter_instantiated(cx, trait_ref.args)
915 .map(Unnormalized::skip_norm_wip)
916 .map(|(pred, _)| pred),
917 ));
918
919 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
922 if cx.generics_require_sized_self(associated_type_def_id) {
925 continue;
926 }
927
928 requirements.extend(
929 cx.item_bounds(associated_type_def_id)
930 .iter_instantiated(cx, trait_ref.args)
931 .map(Unnormalized::skip_norm_wip),
932 );
933 }
934
935 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
936 for bound in object_bounds.iter() {
937 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
938 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
943 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
944 }
945 }
946
947 let mut folder = ReplaceProjectionWith {
948 ecx,
949 param_env,
950 self_ty: trait_ref.self_ty(),
951 mapping: &replace_projection_with,
952 nested: ::alloc::vec::Vec::new()vec![],
953 };
954
955 let requirements = requirements.try_fold_with(&mut folder)?;
956 Ok(folder
957 .nested
958 .into_iter()
959 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
960 .collect())
961}
962
963struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
964 ecx: &'a mut EvalCtxt<'b, D>,
965 param_env: I::ParamEnv,
966 self_ty: I::Ty,
967 mapping: &'a HashMap<I::TraitAssocTermId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
968 nested: Vec<Goal<I, I::Predicate>>,
969}
970
971impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
972where
973 D: SolverDelegate<Interner = I>,
974 I: Interner,
975{
976 fn projection_may_match(
977 &mut self,
978 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
979 target_projection: ty::AliasTerm<I>,
980 ) -> Result<bool, RerunNonErased> {
981 if source_projection.item_def_id() != target_projection.expect_projection_def_id() {
982 return Ok(false);
983 }
984 match self
985 .ecx
986 .probe(|_| ProbeKind::ProjectionCompatibility)
987 .enter_without_propagated_nested_goals(|ecx| {
988 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
989 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
990 ecx.try_evaluate_added_goals()
991 }) {
992 Ok(_) => Ok(true),
993 Err(NoSolutionOrRerunNonErased::NoSolution(_)) => Ok(false),
994 Err(NoSolutionOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun),
995 }
996 }
997
998 fn try_eagerly_replace_alias(
1004 &mut self,
1005 alias_term: ty::AliasTerm<I>,
1006 ) -> Result<Option<I::Term>, AmbiguousOrRerunNonErased> {
1007 if alias_term.self_ty() != self.self_ty {
1008 return Ok(None);
1009 }
1010
1011 let Some(replacements) = self.mapping.get(&alias_term.expect_projection_def_id()) else {
1012 return Ok(None);
1013 };
1014
1015 let mut matching_projection = None;
1019 for source_projection in replacements {
1020 if self.projection_may_match(*source_projection, alias_term)? {
1021 if matching_projection.is_some() {
1023 return Err(AmbiguousOrRerunNonErased::Ambiguous);
1027 }
1028 matching_projection = Some(source_projection)
1029 }
1030 }
1031
1032 let Some(matching) = matching_projection else {
1033 {
::core::panicking::panic_fmt(format_args!("could not replace {1:?} with term from from {0:?}",
self.self_ty, alias_term));
};panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty);
1035 };
1036
1037 let replacement = self.ecx.instantiate_binder_with_infer(*matching);
1038 self.nested.extend(
1039 self.ecx
1040 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
1041 .expect("expected to be able to unify goal projection with dyn's projection"),
1042 );
1043
1044 Ok(Some(replacement.term))
1045 }
1046}
1047
1048pub(crate) enum AmbiguousOrRerunNonErased {
1049 Ambiguous,
1051 RerunNonErased(RerunNonErased),
1052}
1053
1054impl From<RerunNonErased> for AmbiguousOrRerunNonErased {
1055 fn from(rerun: RerunNonErased) -> Self {
1056 AmbiguousOrRerunNonErased::RerunNonErased(rerun)
1057 }
1058}
1059
1060impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1061where
1062 D: SolverDelegate<Interner = I>,
1063 I: Interner,
1064{
1065 type Error = AmbiguousOrRerunNonErased;
1066
1067 fn cx(&self) -> I {
1068 self.ecx.cx()
1069 }
1070
1071 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Self::Error> {
1072 if let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind()
1073 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1074 {
1075 Ok(term.expect_ty())
1076 } else {
1077 ty.try_super_fold_with(self)
1078 }
1079 }
1080}