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, 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::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) => Ok(ty::Binder::dummy(vec![
79 args.as_coroutine().tupled_upvars_ty(),
80 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
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
107x;#[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
186x;#[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 Ok(ty::Binder::dummy(vec![
248 args.as_coroutine().tupled_upvars_ty(),
249 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
250 ]))
251 } else {
252 Err(NoSolution)
253 }
254 }
255 },
256
257 ty::UnsafeBinder(_) => Err(NoSolution),
258
259 ty::CoroutineWitness(def_id, args) => Ok(ecx
261 .cx()
262 .coroutine_hidden_types(def_id)
263 .instantiate(ecx.cx(), args)
264 .map_bound(|bound| bound.types.to_vec())),
265 }
266}
267
268pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
270 cx: I,
271 self_ty: I::Ty,
272 goal_kind: ty::ClosureKind,
273) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
274 match self_ty.kind() {
275 ty::FnDef(def_id, args) => {
277 let sig = cx.fn_sig(def_id);
278 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
279 Ok(Some(
280 sig.instantiate(cx, args)
281 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
282 ))
283 } else {
284 Err(NoSolution)
285 }
286 }
287 ty::FnPtr(sig_tys, hdr) => {
289 let sig = sig_tys.with(hdr);
290 if sig.is_fn_trait_compatible() {
291 Ok(Some(
292 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
293 ))
294 } else {
295 Err(NoSolution)
296 }
297 }
298 ty::Closure(_, args) => {
299 let closure_args = args.as_closure();
300 match closure_args.kind_ty().to_opt_closure_kind() {
301 Some(closure_kind) => {
304 if !closure_kind.extends(goal_kind) {
305 return Err(NoSolution);
306 }
307 }
308 None => {
311 if goal_kind != ty::ClosureKind::FnOnce {
312 return Ok(None);
313 }
314 }
315 }
316 Ok(Some(
317 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
318 ))
319 }
320
321 ty::CoroutineClosure(def_id, args) => {
326 let args = args.as_coroutine_closure();
327 let kind_ty = args.kind_ty();
328 let sig = args.coroutine_closure_sig().skip_binder();
329
330 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
331 && !args.tupled_upvars_ty().is_ty_var()
332 {
333 if !kind.extends(goal_kind) {
334 return Err(NoSolution);
335 }
336
337 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
342 return Err(NoSolution);
343 }
344
345 coroutine_closure_to_certain_coroutine(
346 cx,
347 goal_kind,
348 Region::new_static(cx),
350 def_id,
351 args,
352 sig,
353 )
354 } else {
355 if goal_kind != ty::ClosureKind::FnOnce {
358 return Ok(None);
359 }
360
361 coroutine_closure_to_ambiguous_coroutine(
362 cx,
363 goal_kind, Region::new_static(cx),
365 def_id,
366 args,
367 sig,
368 )
369 };
370
371 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
372 }
373
374 ty::Bool
375 | ty::Char
376 | ty::Int(_)
377 | ty::Uint(_)
378 | ty::Float(_)
379 | ty::Adt(_, _)
380 | ty::Foreign(_)
381 | ty::Str
382 | ty::Array(_, _)
383 | ty::Slice(_)
384 | ty::RawPtr(_, _)
385 | ty::Ref(_, _, _)
386 | ty::Dynamic(_, _)
387 | ty::Coroutine(_, _)
388 | ty::CoroutineWitness(..)
389 | ty::Never
390 | ty::Tuple(_)
391 | ty::Pat(_, _)
392 | ty::UnsafeBinder(_)
393 | ty::Alias(_, _)
394 | ty::Param(_)
395 | ty::Placeholder(..)
396 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
397 | ty::Error(_) => Err(NoSolution),
398
399 ty::Bound(..)
400 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
401 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
402 }
403 }
404}
405
406#[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)]
409#[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)]
410pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
411 pub tupled_inputs_ty: I::Ty,
412 pub output_coroutine_ty: I::Ty,
415 pub coroutine_return_ty: I::Ty,
418}
419
420pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
426 cx: I,
427 self_ty: I::Ty,
428 goal_kind: ty::ClosureKind,
429 env_region: I::Region,
430) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
431 match self_ty.kind() {
432 ty::CoroutineClosure(def_id, args) => {
433 let args = args.as_coroutine_closure();
434 let kind_ty = args.kind_ty();
435 let sig = args.coroutine_closure_sig().skip_binder();
436 let mut nested = ::alloc::vec::Vec::new()vec![];
437
438 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
439 && !args.tupled_upvars_ty().is_ty_var()
440 {
441 if !kind.extends(goal_kind) {
442 return Err(NoSolution);
443 }
444
445 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
446 } else {
447 nested.push(
455 ty::TraitRef::new(
456 cx,
457 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
458 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
459 )
460 .upcast(cx),
461 );
462
463 coroutine_closure_to_ambiguous_coroutine(
464 cx, goal_kind, env_region, def_id, args, sig,
465 )
466 };
467
468 Ok((
469 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
470 tupled_inputs_ty: sig.tupled_inputs_ty,
471 output_coroutine_ty: coroutine_ty,
472 coroutine_return_ty: sig.return_ty,
473 }),
474 nested,
475 ))
476 }
477
478 ty::FnDef(def_id, _) => {
479 let sig = self_ty.fn_sig(cx);
480 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
481 fn_item_to_async_callable(cx, sig)
482 } else {
483 Err(NoSolution)
484 }
485 }
486 ty::FnPtr(..) => {
487 let sig = self_ty.fn_sig(cx);
488 if sig.is_fn_trait_compatible() {
489 fn_item_to_async_callable(cx, sig)
490 } else {
491 Err(NoSolution)
492 }
493 }
494
495 ty::Closure(_, args) => {
496 let args = args.as_closure();
497 let bound_sig = args.sig();
498 let sig = bound_sig.skip_binder();
499 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
500 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![
503 bound_sig
504 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
505 .upcast(cx),
506 ];
507
508 let kind_ty = args.kind_ty();
511 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
512 if !closure_kind.extends(goal_kind) {
513 return Err(NoSolution);
514 }
515 } else {
516 let async_fn_kind_trait_def_id =
517 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
518 nested.push(
526 ty::TraitRef::new(
527 cx,
528 async_fn_kind_trait_def_id,
529 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
530 )
531 .upcast(cx),
532 );
533 }
534
535 let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
536 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
537 Ok((
538 bound_sig.rebind(AsyncCallableRelevantTypes {
539 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
540 output_coroutine_ty: sig.output(),
541 coroutine_return_ty: future_output_ty,
542 }),
543 nested,
544 ))
545 }
546
547 ty::Bool
548 | ty::Char
549 | ty::Int(_)
550 | ty::Uint(_)
551 | ty::Float(_)
552 | ty::Adt(_, _)
553 | ty::Foreign(_)
554 | ty::Str
555 | ty::Array(_, _)
556 | ty::Pat(_, _)
557 | ty::Slice(_)
558 | ty::RawPtr(_, _)
559 | ty::Ref(_, _, _)
560 | ty::Dynamic(_, _)
561 | ty::Coroutine(_, _)
562 | ty::CoroutineWitness(..)
563 | ty::Never
564 | ty::UnsafeBinder(_)
565 | ty::Tuple(_)
566 | ty::Alias(_, _)
567 | ty::Param(_)
568 | ty::Placeholder(..)
569 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
570 | ty::Error(_) => Err(NoSolution),
571
572 ty::Bound(..)
573 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
574 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
575 }
576 }
577}
578
579fn fn_item_to_async_callable<I: Interner>(
580 cx: I,
581 bound_sig: ty::Binder<I, ty::FnSig<I>>,
582) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
583 let sig = bound_sig.skip_binder();
584 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
585 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![
588 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
589 ];
590 let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
591 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
592 Ok((
593 bound_sig.rebind(AsyncCallableRelevantTypes {
594 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
595 output_coroutine_ty: sig.output(),
596 coroutine_return_ty: future_output_ty,
597 }),
598 nested,
599 ))
600}
601
602fn coroutine_closure_to_certain_coroutine<I: Interner>(
605 cx: I,
606 goal_kind: ty::ClosureKind,
607 goal_region: I::Region,
608 def_id: I::CoroutineClosureId,
609 args: ty::CoroutineClosureArgs<I>,
610 sig: ty::CoroutineClosureSignature<I>,
611) -> I::Ty {
612 sig.to_coroutine_given_kind_and_upvars(
613 cx,
614 args.parent_args(),
615 cx.coroutine_for_closure(def_id),
616 goal_kind,
617 goal_region,
618 args.tupled_upvars_ty(),
619 args.coroutine_captures_by_ref_ty(),
620 )
621}
622
623fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
629 cx: I,
630 goal_kind: ty::ClosureKind,
631 goal_region: I::Region,
632 def_id: I::CoroutineClosureId,
633 args: ty::CoroutineClosureArgs<I>,
634 sig: ty::CoroutineClosureSignature<I>,
635) -> I::Ty {
636 let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars);
637 let tupled_upvars_ty = Ty::new_projection(
638 cx,
639 upvars_projection_def_id,
640 [
641 I::GenericArg::from(args.kind_ty()),
642 Ty::from_closure_kind(cx, goal_kind).into(),
643 goal_region.into(),
644 sig.tupled_inputs_ty.into(),
645 args.tupled_upvars_ty().into(),
646 args.coroutine_captures_by_ref_ty().into(),
647 ],
648 );
649 sig.to_coroutine(
650 cx,
651 args.parent_args(),
652 Ty::from_closure_kind(cx, goal_kind),
653 cx.coroutine_for_closure(def_id),
654 tupled_upvars_ty,
655 )
656}
657
658x;#[instrument(level = "trace", skip(cx), ret)]
665pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
666 cx: I,
667 self_ty: I::Ty,
668) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
669 match self_ty.kind() {
670 ty::FnDef(def_id, args) => {
671 let sig = cx.fn_sig(def_id);
672 if sig.skip_binder().is_fn_trait_compatible()
673 && !cx.has_target_features(def_id)
674 && cx.fn_is_const(def_id)
675 {
676 Ok((
677 sig.instantiate(cx, args)
678 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
679 def_id.into(),
680 args,
681 ))
682 } else {
683 return Err(NoSolution);
684 }
685 }
686 ty::FnPtr(..) => {
688 return Err(NoSolution);
689 }
690 ty::Closure(def, args) => {
691 if cx.closure_is_const(def) {
692 let closure_args = args.as_closure();
693 Ok((
694 closure_args
695 .sig()
696 .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
697 def.into(),
698 args,
699 ))
700 } else {
701 return Err(NoSolution);
702 }
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_trait_lang_item(SolverTraitLangItem::Destruct);
748
749 match self_ty.kind() {
750 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()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_trait_lang_item(SolverTraitLangItem::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(::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])])
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(::alloc::vec::Vec::new()vec![]),
799
800 ty::Closure(_, args) => {
802 let closure_args = args.as_closure();
803 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()])])
804 }
805 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
808 Err(NoSolution)
809 }
810
811 ty::UnsafeBinder(_) => Err(NoSolution),
814
815 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
816 Err(NoSolution)
817 }
818
819 ty::Bound(..)
820 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
821 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
822 }
823 }
824}
825
826pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
861 ecx: &mut EvalCtxt<'_, D>,
862 param_env: I::ParamEnv,
863 trait_ref: ty::TraitRef<I>,
864 object_bounds: I::BoundExistentialPredicates,
865) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
866where
867 D: SolverDelegate<Interner = I>,
868 I: Interner,
869{
870 let cx = ecx.cx();
871 let mut requirements = ::alloc::vec::Vec::new()vec![];
872 requirements.extend(elaborate::elaborate(
880 cx,
881 cx.explicit_super_predicates_of(trait_ref.def_id)
882 .iter_instantiated(cx, trait_ref.args)
883 .map(|(pred, _)| pred),
884 ));
885
886 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
889 if cx.generics_require_sized_self(associated_type_def_id) {
892 continue;
893 }
894
895 requirements
896 .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
897 }
898
899 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
900 for bound in object_bounds.iter() {
901 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
902 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
907 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
908 }
909 }
910
911 let mut folder = ReplaceProjectionWith {
912 ecx,
913 param_env,
914 self_ty: trait_ref.self_ty(),
915 mapping: &replace_projection_with,
916 nested: ::alloc::vec::Vec::new()vec![],
917 };
918
919 let requirements = requirements.try_fold_with(&mut folder)?;
920 Ok(folder
921 .nested
922 .into_iter()
923 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
924 .collect())
925}
926
927struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
928 ecx: &'a mut EvalCtxt<'b, D>,
929 param_env: I::ParamEnv,
930 self_ty: I::Ty,
931 mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
932 nested: Vec<Goal<I, I::Predicate>>,
933}
934
935impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
936where
937 D: SolverDelegate<Interner = I>,
938 I: Interner,
939{
940 fn projection_may_match(
941 &mut self,
942 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
943 target_projection: ty::AliasTerm<I>,
944 ) -> bool {
945 source_projection.item_def_id() == target_projection.def_id
946 && self
947 .ecx
948 .probe(|_| ProbeKind::ProjectionCompatibility)
949 .enter(|ecx| -> Result<_, NoSolution> {
950 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
951 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
952 ecx.try_evaluate_added_goals()
953 })
954 .is_ok()
955 }
956
957 fn try_eagerly_replace_alias(
962 &mut self,
963 alias_term: ty::AliasTerm<I>,
964 ) -> Result<Option<I::Term>, Ambiguous> {
965 if alias_term.self_ty() != self.self_ty {
966 return Ok(None);
967 }
968
969 let Some(replacements) = self.mapping.get(&alias_term.def_id) else {
970 return Ok(None);
971 };
972
973 let mut matching_projections = replacements
977 .iter()
978 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
979 let Some(replacement) = matching_projections.next() else {
980 {
::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);
982 };
983 if matching_projections.next().is_some() {
985 return Err(Ambiguous);
989 }
990
991 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
992 self.nested.extend(
993 self.ecx
994 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
995 .expect("expected to be able to unify goal projection with dyn's projection"),
996 );
997
998 Ok(Some(replacement.term))
999 }
1000}
1001
1002pub(crate) struct Ambiguous;
1004
1005impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1006where
1007 D: SolverDelegate<Interner = I>,
1008 I: Interner,
1009{
1010 type Error = Ambiguous;
1011
1012 fn cx(&self) -> I {
1013 self.ecx.cx()
1014 }
1015
1016 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
1017 if let ty::Alias(ty::Projection, alias_ty) = ty.kind()
1018 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1019 {
1020 Ok(term.expect_ty())
1021 } else {
1022 ty.try_super_fold_with(self)
1023 }
1024 }
1025}