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, 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::{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 .skip_norm_wip()
91 .map_bound(|bound| bound.types.to_vec())),
92
93 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
94
95 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
97
98 ty::Adt(def, args) => Ok(ty::Binder::dummy(
99 def.all_field_tys(cx)
100 .iter_instantiated(cx, args)
101 .map(Unnormalized::skip_norm_wip)
102 .collect(),
103 )),
104
105 ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
106 Ok(ty::Binder::dummy(vec![cx.type_of(def_id).instantiate(cx, args).skip_norm_wip()]))
110 }
111 }
112}
113
114x;#[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).skip_norm_wip()]))
186 } else {
187 Ok(ty::Binder::dummy(vec![]))
188 }
189 }
190 }
191}
192
193x;#[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 Ok(ty::Binder::dummy(vec![
255 args.as_coroutine().tupled_upvars_ty(),
256 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
257 ]))
258 } else {
259 Err(NoSolution)
260 }
261 }
262 },
263
264 ty::UnsafeBinder(_) => Err(NoSolution),
265
266 ty::CoroutineWitness(def_id, args) => Ok(ecx
268 .cx()
269 .coroutine_hidden_types(def_id)
270 .instantiate(ecx.cx(), args)
271 .skip_norm_wip()
272 .map_bound(|bound| bound.types.to_vec())),
273 }
274}
275
276pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
278 cx: I,
279 self_ty: I::Ty,
280 goal_kind: ty::ClosureKind,
281) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
282 match self_ty.kind() {
283 ty::FnDef(def_id, args) => {
285 let sig = cx.fn_sig(def_id);
286 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
287 Ok(Some(
288 sig.instantiate(cx, args)
289 .skip_norm_wip()
290 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
291 ))
292 } else {
293 Err(NoSolution)
294 }
295 }
296 ty::FnPtr(sig_tys, hdr) => {
298 let sig = sig_tys.with(hdr);
299 if sig.is_fn_trait_compatible() {
300 Ok(Some(
301 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
302 ))
303 } else {
304 Err(NoSolution)
305 }
306 }
307 ty::Closure(_, args) => {
308 let closure_args = args.as_closure();
309 match closure_args.kind_ty().to_opt_closure_kind() {
310 Some(closure_kind) => {
313 if !closure_kind.extends(goal_kind) {
314 return Err(NoSolution);
315 }
316 }
317 None => {
320 if goal_kind != ty::ClosureKind::FnOnce {
321 return Ok(None);
322 }
323 }
324 }
325 Ok(Some(
326 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
327 ))
328 }
329
330 ty::CoroutineClosure(def_id, args) => {
335 let args = args.as_coroutine_closure();
336 let kind_ty = args.kind_ty();
337 let sig = args.coroutine_closure_sig().skip_binder();
338
339 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
340 && !args.tupled_upvars_ty().is_ty_var()
341 {
342 if !kind.extends(goal_kind) {
343 return Err(NoSolution);
344 }
345
346 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
351 return Err(NoSolution);
352 }
353
354 coroutine_closure_to_certain_coroutine(
355 cx,
356 goal_kind,
357 Region::new_static(cx),
359 def_id,
360 args,
361 sig,
362 )
363 } else {
364 if goal_kind != ty::ClosureKind::FnOnce {
367 return Ok(None);
368 }
369
370 coroutine_closure_to_ambiguous_coroutine(
371 cx,
372 goal_kind, Region::new_static(cx),
374 def_id,
375 args,
376 sig,
377 )
378 };
379
380 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
381 }
382
383 ty::Bool
384 | ty::Char
385 | ty::Int(_)
386 | ty::Uint(_)
387 | ty::Float(_)
388 | ty::Adt(_, _)
389 | ty::Foreign(_)
390 | ty::Str
391 | ty::Array(_, _)
392 | ty::Slice(_)
393 | ty::RawPtr(_, _)
394 | ty::Ref(_, _, _)
395 | ty::Dynamic(_, _)
396 | ty::Coroutine(_, _)
397 | ty::CoroutineWitness(..)
398 | ty::Never
399 | ty::Tuple(_)
400 | ty::Pat(_, _)
401 | ty::UnsafeBinder(_)
402 | ty::Alias(_)
403 | ty::Param(_)
404 | ty::Placeholder(..)
405 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
406 | ty::Error(_) => Err(NoSolution),
407
408 ty::Bound(..)
409 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
410 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
411 }
412 }
413}
414
415#[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)]
418#[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)]
419pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
420 pub tupled_inputs_ty: I::Ty,
421 pub output_coroutine_ty: I::Ty,
424 pub coroutine_return_ty: I::Ty,
427}
428
429pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
435 cx: I,
436 self_ty: I::Ty,
437 goal_kind: ty::ClosureKind,
438 env_region: I::Region,
439) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
440 match self_ty.kind() {
441 ty::CoroutineClosure(def_id, args) => {
442 let args = args.as_coroutine_closure();
443 let kind_ty = args.kind_ty();
444 let sig = args.coroutine_closure_sig().skip_binder();
445 let mut nested = ::alloc::vec::Vec::new()vec![];
446
447 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
448 && !args.tupled_upvars_ty().is_ty_var()
449 {
450 if !kind.extends(goal_kind) {
451 return Err(NoSolution);
452 }
453
454 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
455 } else {
456 nested.push(
464 ty::TraitRef::new(
465 cx,
466 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
467 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
468 )
469 .upcast(cx),
470 );
471
472 coroutine_closure_to_ambiguous_coroutine(
473 cx, goal_kind, env_region, def_id, args, sig,
474 )
475 };
476
477 Ok((
478 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
479 tupled_inputs_ty: sig.tupled_inputs_ty,
480 output_coroutine_ty: coroutine_ty,
481 coroutine_return_ty: sig.return_ty,
482 }),
483 nested,
484 ))
485 }
486
487 ty::FnDef(def_id, _) => {
488 let sig = self_ty.fn_sig(cx);
489 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
490 fn_item_to_async_callable(cx, sig)
491 } else {
492 Err(NoSolution)
493 }
494 }
495 ty::FnPtr(..) => {
496 let sig = self_ty.fn_sig(cx);
497 if sig.is_fn_trait_compatible() {
498 fn_item_to_async_callable(cx, sig)
499 } else {
500 Err(NoSolution)
501 }
502 }
503
504 ty::Closure(_, args) => {
505 let args = args.as_closure();
506 let bound_sig = args.sig();
507 let sig = bound_sig.skip_binder();
508 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
509 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![
512 bound_sig
513 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
514 .upcast(cx),
515 ];
516
517 let kind_ty = args.kind_ty();
520 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
521 if !closure_kind.extends(goal_kind) {
522 return Err(NoSolution);
523 }
524 } else {
525 let async_fn_kind_trait_def_id =
526 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
527 nested.push(
535 ty::TraitRef::new(
536 cx,
537 async_fn_kind_trait_def_id,
538 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
539 )
540 .upcast(cx),
541 );
542 }
543
544 let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
545 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
546 Ok((
547 bound_sig.rebind(AsyncCallableRelevantTypes {
548 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
549 output_coroutine_ty: sig.output(),
550 coroutine_return_ty: future_output_ty,
551 }),
552 nested,
553 ))
554 }
555
556 ty::Bool
557 | ty::Char
558 | ty::Int(_)
559 | ty::Uint(_)
560 | ty::Float(_)
561 | ty::Adt(_, _)
562 | ty::Foreign(_)
563 | ty::Str
564 | ty::Array(_, _)
565 | ty::Pat(_, _)
566 | ty::Slice(_)
567 | ty::RawPtr(_, _)
568 | ty::Ref(_, _, _)
569 | ty::Dynamic(_, _)
570 | ty::Coroutine(_, _)
571 | ty::CoroutineWitness(..)
572 | ty::Never
573 | ty::UnsafeBinder(_)
574 | ty::Tuple(_)
575 | ty::Alias(_)
576 | ty::Param(_)
577 | ty::Placeholder(..)
578 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
579 | ty::Error(_) => Err(NoSolution),
580
581 ty::Bound(..)
582 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
583 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
584 }
585 }
586}
587
588fn fn_item_to_async_callable<I: Interner>(
589 cx: I,
590 bound_sig: ty::Binder<I, ty::FnSig<I>>,
591) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
592 let sig = bound_sig.skip_binder();
593 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
594 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![
597 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
598 ];
599 let future_output_def_id = cx.require_lang_item(SolverLangItem::FutureOutput);
600 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
601 Ok((
602 bound_sig.rebind(AsyncCallableRelevantTypes {
603 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
604 output_coroutine_ty: sig.output(),
605 coroutine_return_ty: future_output_ty,
606 }),
607 nested,
608 ))
609}
610
611fn coroutine_closure_to_certain_coroutine<I: Interner>(
614 cx: I,
615 goal_kind: ty::ClosureKind,
616 goal_region: I::Region,
617 def_id: I::CoroutineClosureId,
618 args: ty::CoroutineClosureArgs<I>,
619 sig: ty::CoroutineClosureSignature<I>,
620) -> I::Ty {
621 sig.to_coroutine_given_kind_and_upvars(
622 cx,
623 args.parent_args(),
624 cx.coroutine_for_closure(def_id),
625 goal_kind,
626 goal_region,
627 args.tupled_upvars_ty(),
628 args.coroutine_captures_by_ref_ty(),
629 )
630}
631
632fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
638 cx: I,
639 goal_kind: ty::ClosureKind,
640 goal_region: I::Region,
641 def_id: I::CoroutineClosureId,
642 args: ty::CoroutineClosureArgs<I>,
643 sig: ty::CoroutineClosureSignature<I>,
644) -> I::Ty {
645 let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars);
646 let tupled_upvars_ty = Ty::new_projection(
647 cx,
648 upvars_projection_def_id,
649 [
650 I::GenericArg::from(args.kind_ty()),
651 Ty::from_closure_kind(cx, goal_kind).into(),
652 goal_region.into(),
653 sig.tupled_inputs_ty.into(),
654 args.tupled_upvars_ty().into(),
655 args.coroutine_captures_by_ref_ty().into(),
656 ],
657 );
658 sig.to_coroutine(
659 cx,
660 args.parent_args(),
661 Ty::from_closure_kind(cx, goal_kind),
662 cx.coroutine_for_closure(def_id),
663 tupled_upvars_ty,
664 )
665}
666
667x;#[instrument(level = "trace", skip(cx), ret)]
674pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
675 cx: I,
676 self_ty: I::Ty,
677) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
678 match self_ty.kind() {
679 ty::FnDef(def_id, args) => {
680 let sig = cx.fn_sig(def_id);
681 if sig.skip_binder().is_fn_trait_compatible()
682 && !cx.has_target_features(def_id)
683 && cx.fn_is_const(def_id)
684 {
685 Ok((
686 sig.instantiate(cx, args)
687 .skip_norm_wip()
688 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
689 def_id.into(),
690 args,
691 ))
692 } else {
693 return Err(NoSolution);
694 }
695 }
696 ty::FnPtr(..) => {
698 return Err(NoSolution);
699 }
700 ty::Closure(def, args) => {
701 if cx.closure_is_const(def) {
702 let closure_args = args.as_closure();
703 Ok((
704 closure_args
705 .sig()
706 .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
707 def.into(),
708 args,
709 ))
710 } else {
711 return Err(NoSolution);
712 }
713 }
714 ty::CoroutineClosure(..) => {
716 return Err(NoSolution);
717 }
718
719 ty::Bool
720 | ty::Char
721 | ty::Int(_)
722 | ty::Uint(_)
723 | ty::Float(_)
724 | ty::Adt(_, _)
725 | ty::Foreign(_)
726 | ty::Str
727 | ty::Array(_, _)
728 | ty::Slice(_)
729 | ty::RawPtr(_, _)
730 | ty::Ref(_, _, _)
731 | ty::Dynamic(_, _)
732 | ty::Coroutine(_, _)
733 | ty::CoroutineWitness(..)
734 | ty::Never
735 | ty::Tuple(_)
736 | ty::Pat(_, _)
737 | ty::Alias(_)
738 | ty::Param(_)
739 | ty::Placeholder(..)
740 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
741 | ty::Error(_)
742 | ty::UnsafeBinder(_) => return Err(NoSolution),
743
744 ty::Bound(..)
745 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
746 panic!("unexpected type `{self_ty:?}`")
747 }
748 }
749}
750
751pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
754 cx: I,
755 self_ty: I::Ty,
756) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
757 let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
758
759 match self_ty.kind() {
760 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()vec![]),
762
763 ty::Adt(adt_def, args) => {
766 let mut const_conditions: Vec<_> = adt_def
767 .all_field_tys(cx)
768 .iter_instantiated(cx, args)
769 .map(Unnormalized::skip_norm_wip)
770 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
771 .collect();
772 match adt_def.destructor(cx) {
773 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
775 Some(AdtDestructorKind::Const) => {
777 let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
778 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
779 const_conditions.push(drop_trait_ref);
780 }
781 None => {}
783 }
784 Ok(const_conditions)
785 }
786
787 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
788 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])])
789 }
790
791 ty::Tuple(tys) => Ok(tys
792 .iter()
793 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
794 .collect()),
795
796 ty::Bool
798 | ty::Char
799 | ty::Int(..)
800 | ty::Uint(..)
801 | ty::Float(..)
802 | ty::Str
803 | ty::RawPtr(..)
804 | ty::Ref(..)
805 | ty::FnDef(..)
806 | ty::FnPtr(..)
807 | ty::Never
808 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
809 | ty::Error(_) => Ok(::alloc::vec::Vec::new()vec![]),
810
811 ty::Closure(_, args) => {
813 let closure_args = args.as_closure();
814 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()])])
815 }
816 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
819 Err(NoSolution)
820 }
821
822 ty::UnsafeBinder(_) => Err(NoSolution),
825
826 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
827 Err(NoSolution)
828 }
829
830 ty::Bound(..)
831 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
832 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
833 }
834 }
835}
836
837pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
872 ecx: &mut EvalCtxt<'_, D>,
873 param_env: I::ParamEnv,
874 trait_ref: Binder<I, ty::TraitRef<I>>,
875 object_bounds: I::BoundExistentialPredicates,
876) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
877where
878 D: SolverDelegate<Interner = I>,
879 I: Interner,
880{
881 let cx = ecx.cx();
882 let trait_ref = ecx.instantiate_binder_with_infer(trait_ref);
883 let mut requirements = ::alloc::vec::Vec::new()vec![];
884 requirements.extend(elaborate::elaborate(
892 cx,
893 cx.explicit_super_predicates_of(trait_ref.def_id)
894 .iter_instantiated(cx, trait_ref.args)
895 .map(Unnormalized::skip_norm_wip)
896 .map(|(pred, _)| pred),
897 ));
898
899 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
902 if cx.generics_require_sized_self(associated_type_def_id) {
905 continue;
906 }
907
908 requirements.extend(
909 cx.item_bounds(associated_type_def_id)
910 .iter_instantiated(cx, trait_ref.args)
911 .map(Unnormalized::skip_norm_wip),
912 );
913 }
914
915 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
916 for bound in object_bounds.iter() {
917 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
918 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
923 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
924 }
925 }
926
927 let mut folder = ReplaceProjectionWith {
928 ecx,
929 param_env,
930 self_ty: trait_ref.self_ty(),
931 mapping: &replace_projection_with,
932 nested: ::alloc::vec::Vec::new()vec![],
933 };
934
935 let requirements = requirements.try_fold_with(&mut folder)?;
936 Ok(folder
937 .nested
938 .into_iter()
939 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
940 .collect())
941}
942
943struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
944 ecx: &'a mut EvalCtxt<'b, D>,
945 param_env: I::ParamEnv,
946 self_ty: I::Ty,
947 mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
948 nested: Vec<Goal<I, I::Predicate>>,
949}
950
951impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
952where
953 D: SolverDelegate<Interner = I>,
954 I: Interner,
955{
956 fn projection_may_match(
957 &mut self,
958 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
959 target_projection: ty::AliasTerm<I>,
960 ) -> bool {
961 source_projection.item_def_id() == target_projection.def_id()
962 && self
963 .ecx
964 .probe(|_| ProbeKind::ProjectionCompatibility)
965 .enter_without_propagated_nested_goals(|ecx| -> Result<_, NoSolution> {
966 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
967 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
968 ecx.try_evaluate_added_goals()
969 })
970 .is_ok()
971 }
972
973 fn try_eagerly_replace_alias(
978 &mut self,
979 alias_term: ty::AliasTerm<I>,
980 ) -> Result<Option<I::Term>, Ambiguous> {
981 if alias_term.self_ty() != self.self_ty {
982 return Ok(None);
983 }
984
985 let Some(replacements) = self.mapping.get(&alias_term.def_id()) else {
986 return Ok(None);
987 };
988
989 let mut matching_projections = replacements
993 .iter()
994 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
995 let Some(replacement) = matching_projections.next() else {
996 {
::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);
998 };
999 if matching_projections.next().is_some() {
1001 return Err(Ambiguous);
1005 }
1006
1007 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
1008 self.nested.extend(
1009 self.ecx
1010 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
1011 .expect("expected to be able to unify goal projection with dyn's projection"),
1012 );
1013
1014 Ok(Some(replacement.term))
1015 }
1016}
1017
1018pub(crate) struct Ambiguous;
1020
1021impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1022where
1023 D: SolverDelegate<Interner = I>,
1024 I: Interner,
1025{
1026 type Error = Ambiguous;
1027
1028 fn cx(&self) -> I {
1029 self.ecx.cx()
1030 }
1031
1032 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
1033 if let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind()
1034 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1035 {
1036 Ok(term.expect_ty())
1037 } else {
1038 ty.try_super_fold_with(self)
1039 }
1040 }
1041}