1use derive_where::derive_where;
5use rustc_type_ir::data_structures::HashMap;
6use rustc_type_ir::inherent::*;
7use rustc_type_ir::lang_items::{SolverLangItem, 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, 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
20x;#[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::AliasTy {
53 kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. },
54 ..
55 })
56 | ty::Placeholder(..)
57 | ty::Bound(..)
58 | ty::Infer(_) => {
59 panic!("unexpected type `{ty:?}`")
60 }
61
62 ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
63 Ok(ty::Binder::dummy(vec![element_ty]))
64 }
65
66 ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
67 Ok(ty::Binder::dummy(vec![element_ty]))
68 }
69
70 ty::Tuple(tys) => {
71 Ok(ty::Binder::dummy(tys.to_vec()))
73 }
74
75 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
76
77 ty::CoroutineClosure(_, args) => {
78 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
79 }
80
81 ty::Coroutine(def_id, args) => Ok(ty::Binder::dummy(vec![
82 args.as_coroutine().tupled_upvars_ty(),
83 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
84 ])),
85
86 ty::CoroutineWitness(def_id, args) => Ok(ecx
87 .cx()
88 .coroutine_hidden_types(def_id)
89 .instantiate(cx, args)
90 .map_bound(|bound| bound.types.to_vec())),
91
92 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
93
94 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
96
97 ty::Adt(def, args) => {
98 Ok(ty::Binder::dummy(def.all_field_tys(cx).iter_instantiated(cx, args).collect()))
99 }
100
101 ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
102 Ok(ty::Binder::dummy(vec![cx.type_of(def_id).instantiate(cx, args)]))
106 }
107 }
108}
109
110x;#[instrument(level = "trace", skip(ecx), ret)]
111pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
112 ecx: &EvalCtxt<'_, D>,
113 sizedness: SizedTraitKind,
114 ty: I::Ty,
115) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
116where
117 D: SolverDelegate<Interner = I>,
118 I: Interner,
119{
120 match ty.kind() {
121 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
125 | ty::Uint(_)
126 | ty::Int(_)
127 | ty::Bool
128 | ty::Float(_)
129 | ty::FnDef(..)
130 | ty::FnPtr(..)
131 | ty::RawPtr(..)
132 | ty::Char
133 | ty::Ref(..)
134 | ty::Coroutine(..)
135 | ty::CoroutineWitness(..)
136 | ty::Array(..)
137 | ty::Pat(..)
138 | ty::Closure(..)
139 | ty::CoroutineClosure(..)
140 | ty::Never
141 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
142
143 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
145 SizedTraitKind::Sized => Err(NoSolution),
146 SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
147 },
148
149 ty::Foreign(..) => Err(NoSolution),
151
152 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
153
154 ty::Bound(..)
155 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
156 panic!("unexpected type `{ty:?}`")
157 }
158
159 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
160
161 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
164
165 ty::Adt(def, args) => {
180 if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
181 Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
182 } else {
183 Ok(ty::Binder::dummy(vec![]))
184 }
185 }
186 }
187}
188
189x;#[instrument(level = "trace", skip(ecx), ret)]
190pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
191 ecx: &EvalCtxt<'_, D>,
192 ty: I::Ty,
193) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
194where
195 D: SolverDelegate<Interner = I>,
196 I: Interner,
197{
198 match ty.kind() {
199 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
201
202 ty::Uint(_)
204 | ty::Int(_)
205 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
206 | ty::Bool
207 | ty::Float(_)
208 | ty::Char
209 | ty::RawPtr(..)
210 | ty::Never
211 | ty::Ref(_, _, Mutability::Not)
212 | ty::Array(..) => Err(NoSolution),
213
214 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
217
218 ty::Dynamic(..)
219 | ty::Str
220 | ty::Slice(_)
221 | ty::Foreign(..)
222 | ty::Ref(_, _, Mutability::Mut)
223 | ty::Adt(_, _)
224 | ty::Alias(_)
225 | ty::Param(_)
226 | ty::Placeholder(..) => Err(NoSolution),
227
228 ty::Bound(..)
229 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
230 panic!("unexpected type `{ty:?}`")
231 }
232
233 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
235
236 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
238
239 ty::CoroutineClosure(_, args) => {
241 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
242 }
243
244 ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
247 Movability::Static => Err(NoSolution),
248 Movability::Movable => {
249 if ecx.cx().features().coroutine_clone() {
250 Ok(ty::Binder::dummy(vec![
251 args.as_coroutine().tupled_upvars_ty(),
252 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
253 ]))
254 } else {
255 Err(NoSolution)
256 }
257 }
258 },
259
260 ty::UnsafeBinder(_) => Err(NoSolution),
261
262 ty::CoroutineWitness(def_id, args) => Ok(ecx
264 .cx()
265 .coroutine_hidden_types(def_id)
266 .instantiate(ecx.cx(), args)
267 .map_bound(|bound| bound.types.to_vec())),
268 }
269}
270
271pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
273 cx: I,
274 self_ty: I::Ty,
275 goal_kind: ty::ClosureKind,
276) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
277 match self_ty.kind() {
278 ty::FnDef(def_id, args) => {
280 let sig = cx.fn_sig(def_id);
281 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
282 Ok(Some(
283 sig.instantiate(cx, args)
284 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
285 ))
286 } else {
287 Err(NoSolution)
288 }
289 }
290 ty::FnPtr(sig_tys, hdr) => {
292 let sig = sig_tys.with(hdr);
293 if sig.is_fn_trait_compatible() {
294 Ok(Some(
295 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
296 ))
297 } else {
298 Err(NoSolution)
299 }
300 }
301 ty::Closure(_, args) => {
302 let closure_args = args.as_closure();
303 match closure_args.kind_ty().to_opt_closure_kind() {
304 Some(closure_kind) => {
307 if !closure_kind.extends(goal_kind) {
308 return Err(NoSolution);
309 }
310 }
311 None => {
314 if goal_kind != ty::ClosureKind::FnOnce {
315 return Ok(None);
316 }
317 }
318 }
319 Ok(Some(
320 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
321 ))
322 }
323
324 ty::CoroutineClosure(def_id, args) => {
329 let args = args.as_coroutine_closure();
330 let kind_ty = args.kind_ty();
331 let sig = args.coroutine_closure_sig().skip_binder();
332
333 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
334 && !args.tupled_upvars_ty().is_ty_var()
335 {
336 if !kind.extends(goal_kind) {
337 return Err(NoSolution);
338 }
339
340 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
345 return Err(NoSolution);
346 }
347
348 coroutine_closure_to_certain_coroutine(
349 cx,
350 goal_kind,
351 Region::new_static(cx),
353 def_id,
354 args,
355 sig,
356 )
357 } else {
358 if goal_kind != ty::ClosureKind::FnOnce {
361 return Ok(None);
362 }
363
364 coroutine_closure_to_ambiguous_coroutine(
365 cx,
366 goal_kind, Region::new_static(cx),
368 def_id,
369 args,
370 sig,
371 )
372 };
373
374 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
375 }
376
377 ty::Bool
378 | ty::Char
379 | ty::Int(_)
380 | ty::Uint(_)
381 | ty::Float(_)
382 | ty::Adt(_, _)
383 | ty::Foreign(_)
384 | ty::Str
385 | ty::Array(_, _)
386 | ty::Slice(_)
387 | ty::RawPtr(_, _)
388 | ty::Ref(_, _, _)
389 | ty::Dynamic(_, _)
390 | ty::Coroutine(_, _)
391 | ty::CoroutineWitness(..)
392 | ty::Never
393 | ty::Tuple(_)
394 | ty::Pat(_, _)
395 | ty::UnsafeBinder(_)
396 | ty::Alias(_)
397 | ty::Param(_)
398 | ty::Placeholder(..)
399 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
400 | ty::Error(_) => Err(NoSolution),
401
402 ty::Bound(..)
403 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
404 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
405 }
406 }
407}
408
409#[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)]
412#[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)]
413pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
414 pub tupled_inputs_ty: I::Ty,
415 pub output_coroutine_ty: I::Ty,
418 pub coroutine_return_ty: I::Ty,
421}
422
423pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
429 cx: I,
430 self_ty: I::Ty,
431 goal_kind: ty::ClosureKind,
432 env_region: I::Region,
433) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
434 match self_ty.kind() {
435 ty::CoroutineClosure(def_id, args) => {
436 let args = args.as_coroutine_closure();
437 let kind_ty = args.kind_ty();
438 let sig = args.coroutine_closure_sig().skip_binder();
439 let mut nested = ::alloc::vec::Vec::new()vec![];
440
441 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
442 && !args.tupled_upvars_ty().is_ty_var()
443 {
444 if !kind.extends(goal_kind) {
445 return Err(NoSolution);
446 }
447
448 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
449 } else {
450 nested.push(
458 ty::TraitRef::new(
459 cx,
460 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
461 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
462 )
463 .upcast(cx),
464 );
465
466 coroutine_closure_to_ambiguous_coroutine(
467 cx, goal_kind, env_region, def_id, args, sig,
468 )
469 };
470
471 Ok((
472 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
473 tupled_inputs_ty: sig.tupled_inputs_ty,
474 output_coroutine_ty: coroutine_ty,
475 coroutine_return_ty: sig.return_ty,
476 }),
477 nested,
478 ))
479 }
480
481 ty::FnDef(def_id, _) => {
482 let sig = self_ty.fn_sig(cx);
483 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
484 fn_item_to_async_callable(cx, sig)
485 } else {
486 Err(NoSolution)
487 }
488 }
489 ty::FnPtr(..) => {
490 let sig = self_ty.fn_sig(cx);
491 if sig.is_fn_trait_compatible() {
492 fn_item_to_async_callable(cx, sig)
493 } else {
494 Err(NoSolution)
495 }
496 }
497
498 ty::Closure(_, args) => {
499 let args = args.as_closure();
500 let bound_sig = args.sig();
501 let sig = bound_sig.skip_binder();
502 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
503 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![
506 bound_sig
507 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
508 .upcast(cx),
509 ];
510
511 let kind_ty = args.kind_ty();
514 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
515 if !closure_kind.extends(goal_kind) {
516 return Err(NoSolution);
517 }
518 } else {
519 let async_fn_kind_trait_def_id =
520 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
521 nested.push(
529 ty::TraitRef::new(
530 cx,
531 async_fn_kind_trait_def_id,
532 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
533 )
534 .upcast(cx),
535 );
536 }
537
538 let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
539 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
540 Ok((
541 bound_sig.rebind(AsyncCallableRelevantTypes {
542 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
543 output_coroutine_ty: sig.output(),
544 coroutine_return_ty: future_output_ty,
545 }),
546 nested,
547 ))
548 }
549
550 ty::Bool
551 | ty::Char
552 | ty::Int(_)
553 | ty::Uint(_)
554 | ty::Float(_)
555 | ty::Adt(_, _)
556 | ty::Foreign(_)
557 | ty::Str
558 | ty::Array(_, _)
559 | ty::Pat(_, _)
560 | ty::Slice(_)
561 | ty::RawPtr(_, _)
562 | ty::Ref(_, _, _)
563 | ty::Dynamic(_, _)
564 | ty::Coroutine(_, _)
565 | ty::CoroutineWitness(..)
566 | ty::Never
567 | ty::UnsafeBinder(_)
568 | ty::Tuple(_)
569 | ty::Alias(_)
570 | ty::Param(_)
571 | ty::Placeholder(..)
572 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
573 | ty::Error(_) => Err(NoSolution),
574
575 ty::Bound(..)
576 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
577 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
578 }
579 }
580}
581
582fn fn_item_to_async_callable<I: Interner>(
583 cx: I,
584 bound_sig: ty::Binder<I, ty::FnSig<I>>,
585) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
586 let sig = bound_sig.skip_binder();
587 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
588 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![
591 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
592 ];
593 let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
594 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
595 Ok((
596 bound_sig.rebind(AsyncCallableRelevantTypes {
597 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
598 output_coroutine_ty: sig.output(),
599 coroutine_return_ty: future_output_ty,
600 }),
601 nested,
602 ))
603}
604
605fn coroutine_closure_to_certain_coroutine<I: Interner>(
608 cx: I,
609 goal_kind: ty::ClosureKind,
610 goal_region: I::Region,
611 def_id: I::CoroutineClosureId,
612 args: ty::CoroutineClosureArgs<I>,
613 sig: ty::CoroutineClosureSignature<I>,
614) -> I::Ty {
615 sig.to_coroutine_given_kind_and_upvars(
616 cx,
617 args.parent_args(),
618 cx.coroutine_for_closure(def_id),
619 goal_kind,
620 goal_region,
621 args.tupled_upvars_ty(),
622 args.coroutine_captures_by_ref_ty(),
623 )
624}
625
626fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
632 cx: I,
633 goal_kind: ty::ClosureKind,
634 goal_region: I::Region,
635 def_id: I::CoroutineClosureId,
636 args: ty::CoroutineClosureArgs<I>,
637 sig: ty::CoroutineClosureSignature<I>,
638) -> I::Ty {
639 let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars);
640 let tupled_upvars_ty = Ty::new_projection(
641 cx,
642 upvars_projection_def_id,
643 [
644 I::GenericArg::from(args.kind_ty()),
645 Ty::from_closure_kind(cx, goal_kind).into(),
646 goal_region.into(),
647 sig.tupled_inputs_ty.into(),
648 args.tupled_upvars_ty().into(),
649 args.coroutine_captures_by_ref_ty().into(),
650 ],
651 );
652 sig.to_coroutine(
653 cx,
654 args.parent_args(),
655 Ty::from_closure_kind(cx, goal_kind),
656 cx.coroutine_for_closure(def_id),
657 tupled_upvars_ty,
658 )
659}
660
661x;#[instrument(level = "trace", skip(cx), ret)]
668pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
669 cx: I,
670 self_ty: I::Ty,
671) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
672 match self_ty.kind() {
673 ty::FnDef(def_id, args) => {
674 let sig = cx.fn_sig(def_id);
675 if sig.skip_binder().is_fn_trait_compatible()
676 && !cx.has_target_features(def_id)
677 && cx.fn_is_const(def_id)
678 {
679 Ok((
680 sig.instantiate(cx, args)
681 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
682 def_id.into(),
683 args,
684 ))
685 } else {
686 return Err(NoSolution);
687 }
688 }
689 ty::FnPtr(..) => {
691 return Err(NoSolution);
692 }
693 ty::Closure(def, args) => {
694 if cx.closure_is_const(def) {
695 let closure_args = args.as_closure();
696 Ok((
697 closure_args
698 .sig()
699 .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
700 def.into(),
701 args,
702 ))
703 } else {
704 return Err(NoSolution);
705 }
706 }
707 ty::CoroutineClosure(..) => {
709 return Err(NoSolution);
710 }
711
712 ty::Bool
713 | ty::Char
714 | ty::Int(_)
715 | ty::Uint(_)
716 | ty::Float(_)
717 | ty::Adt(_, _)
718 | ty::Foreign(_)
719 | ty::Str
720 | ty::Array(_, _)
721 | ty::Slice(_)
722 | ty::RawPtr(_, _)
723 | ty::Ref(_, _, _)
724 | ty::Dynamic(_, _)
725 | ty::Coroutine(_, _)
726 | ty::CoroutineWitness(..)
727 | ty::Never
728 | ty::Tuple(_)
729 | ty::Pat(_, _)
730 | ty::Alias(_)
731 | ty::Param(_)
732 | ty::Placeholder(..)
733 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
734 | ty::Error(_)
735 | ty::UnsafeBinder(_) => return Err(NoSolution),
736
737 ty::Bound(..)
738 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
739 panic!("unexpected type `{self_ty:?}`")
740 }
741 }
742}
743
744pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
747 cx: I,
748 self_ty: I::Ty,
749) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
750 let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
751
752 match self_ty.kind() {
753 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()vec![]),
755
756 ty::Adt(adt_def, args) => {
759 let mut const_conditions: Vec<_> = adt_def
760 .all_field_tys(cx)
761 .iter_instantiated(cx, args)
762 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
763 .collect();
764 match adt_def.destructor(cx) {
765 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
767 Some(AdtDestructorKind::Const) => {
769 let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
770 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
771 const_conditions.push(drop_trait_ref);
772 }
773 None => {}
775 }
776 Ok(const_conditions)
777 }
778
779 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
780 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])])
781 }
782
783 ty::Tuple(tys) => Ok(tys
784 .iter()
785 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
786 .collect()),
787
788 ty::Bool
790 | ty::Char
791 | ty::Int(..)
792 | ty::Uint(..)
793 | ty::Float(..)
794 | ty::Str
795 | ty::RawPtr(..)
796 | ty::Ref(..)
797 | ty::FnDef(..)
798 | ty::FnPtr(..)
799 | ty::Never
800 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
801 | ty::Error(_) => Ok(::alloc::vec::Vec::new()vec![]),
802
803 ty::Closure(_, args) => {
805 let closure_args = args.as_closure();
806 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()])])
807 }
808 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
811 Err(NoSolution)
812 }
813
814 ty::UnsafeBinder(_) => Err(NoSolution),
817
818 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
819 Err(NoSolution)
820 }
821
822 ty::Bound(..)
823 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
824 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
825 }
826 }
827}
828
829pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
864 ecx: &mut EvalCtxt<'_, D>,
865 param_env: I::ParamEnv,
866 trait_ref: Binder<I, ty::TraitRef<I>>,
867 object_bounds: I::BoundExistentialPredicates,
868) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
869where
870 D: SolverDelegate<Interner = I>,
871 I: Interner,
872{
873 let cx = ecx.cx();
874 let trait_ref = ecx.instantiate_binder_with_infer(trait_ref);
875 let mut requirements = ::alloc::vec::Vec::new()vec![];
876 requirements.extend(elaborate::elaborate(
884 cx,
885 cx.explicit_super_predicates_of(trait_ref.def_id)
886 .iter_instantiated(cx, trait_ref.args)
887 .map(|(pred, _)| pred),
888 ));
889
890 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
893 if cx.generics_require_sized_self(associated_type_def_id) {
896 continue;
897 }
898
899 requirements
900 .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
901 }
902
903 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
904 for bound in object_bounds.iter() {
905 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
906 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
911 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
912 }
913 }
914
915 let mut folder = ReplaceProjectionWith {
916 ecx,
917 param_env,
918 self_ty: trait_ref.self_ty(),
919 mapping: &replace_projection_with,
920 nested: ::alloc::vec::Vec::new()vec![],
921 };
922
923 let requirements = requirements.try_fold_with(&mut folder)?;
924 Ok(folder
925 .nested
926 .into_iter()
927 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
928 .collect())
929}
930
931struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
932 ecx: &'a mut EvalCtxt<'b, D>,
933 param_env: I::ParamEnv,
934 self_ty: I::Ty,
935 mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
936 nested: Vec<Goal<I, I::Predicate>>,
937}
938
939impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
940where
941 D: SolverDelegate<Interner = I>,
942 I: Interner,
943{
944 fn projection_may_match(
945 &mut self,
946 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
947 target_projection: ty::AliasTerm<I>,
948 ) -> bool {
949 source_projection.item_def_id() == target_projection.def_id
950 && self
951 .ecx
952 .probe(|_| ProbeKind::ProjectionCompatibility)
953 .enter_without_propagated_nested_goals(|ecx| -> Result<_, NoSolution> {
954 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
955 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
956 ecx.try_evaluate_added_goals()
957 })
958 .is_ok()
959 }
960
961 fn try_eagerly_replace_alias(
966 &mut self,
967 alias_term: ty::AliasTerm<I>,
968 ) -> Result<Option<I::Term>, Ambiguous> {
969 if alias_term.self_ty() != self.self_ty {
970 return Ok(None);
971 }
972
973 let Some(replacements) = self.mapping.get(&alias_term.def_id) else {
974 return Ok(None);
975 };
976
977 let mut matching_projections = replacements
981 .iter()
982 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
983 let Some(replacement) = matching_projections.next() else {
984 {
::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);
986 };
987 if matching_projections.next().is_some() {
989 return Err(Ambiguous);
993 }
994
995 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
996 self.nested.extend(
997 self.ecx
998 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
999 .expect("expected to be able to unify goal projection with dyn's projection"),
1000 );
1001
1002 Ok(Some(replacement.term))
1003 }
1004}
1005
1006pub(crate) struct Ambiguous;
1008
1009impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1010where
1011 D: SolverDelegate<Interner = I>,
1012 I: Interner,
1013{
1014 type Error = Ambiguous;
1015
1016 fn cx(&self) -> I {
1017 self.ecx.cx()
1018 }
1019
1020 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
1021 if let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind()
1022 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1023 {
1024 Ok(term.expect_ty())
1025 } else {
1026 ty.try_super_fold_with(self)
1027 }
1028 }
1029}