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, 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(
53 ty::IsRigid::Yes,
54 ty::AliasTy {
55 kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, ..
56 },
57 )
58 | ty::Placeholder(..)
59 | ty::Alias(ty::IsRigid::No, _)
60 | ty::Bound(..)
61 | ty::Infer(_) => {
62 panic!("unexpected type `{ty:?}`")
63 }
64
65 ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
66 Ok(ty::Binder::dummy(vec![element_ty]))
67 }
68
69 ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
70 Ok(ty::Binder::dummy(vec![element_ty]))
71 }
72
73 ty::Tuple(tys) => {
74 Ok(ty::Binder::dummy(tys.to_vec()))
76 }
77
78 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
79
80 ty::CoroutineClosure(_, args) => {
81 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
82 }
83
84 ty::Coroutine(def_id, args) => Ok(ty::Binder::dummy(vec![
85 args.as_coroutine().tupled_upvars_ty(),
86 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
87 ])),
88
89 ty::CoroutineWitness(def_id, args) => Ok(ecx
90 .cx()
91 .coroutine_hidden_types(def_id)
92 .instantiate(cx, args)
93 .skip_norm_wip()
94 .map_bound(|bound| bound.types.to_vec())),
95
96 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
97
98 ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
100
101 ty::Adt(def, args) => Ok(ty::Binder::dummy(
102 def.all_field_tys(cx)
103 .iter_instantiated(cx, args)
104 .map(Unnormalized::skip_norm_wip)
105 .collect(),
106 )),
107
108 ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
109 Ok(ty::Binder::dummy(vec![
113 cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip(),
114 ]))
115 }
116 }
117}
118
119x;#[instrument(level = "trace", skip(ecx), ret)]
120pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
121 ecx: &EvalCtxt<'_, D>,
122 sizedness: SizedTraitKind,
123 ty: I::Ty,
124) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
125where
126 D: SolverDelegate<Interner = I>,
127 I: Interner,
128{
129 match ty.kind() {
130 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
134 | ty::Uint(_)
135 | ty::Int(_)
136 | ty::Bool
137 | ty::Float(_)
138 | ty::FnDef(..)
139 | ty::FnPtr(..)
140 | ty::RawPtr(..)
141 | ty::Char
142 | ty::Ref(..)
143 | ty::Coroutine(..)
144 | ty::CoroutineWitness(..)
145 | ty::Array(..)
146 | ty::Pat(..)
147 | ty::Closure(..)
148 | ty::CoroutineClosure(..)
149 | ty::Never
150 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
151
152 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
154 SizedTraitKind::Sized => Err(NoSolution),
155 SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
156 },
157
158 ty::Foreign(..) => Err(NoSolution),
160
161 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
162
163 ty::Bound(..)
164 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
165 panic!("unexpected type `{ty:?}`")
166 }
167
168 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
169
170 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
173
174 ty::Adt(def, args) => {
189 if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
190 Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args).skip_norm_wip()]))
191 } else {
192 Ok(ty::Binder::dummy(vec![]))
193 }
194 }
195 }
196}
197
198x;#[instrument(level = "trace", skip(ecx), ret)]
199pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
200 ecx: &EvalCtxt<'_, D>,
201 ty: I::Ty,
202) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
203where
204 D: SolverDelegate<Interner = I>,
205 I: Interner,
206{
207 match ty.kind() {
208 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
210
211 ty::Uint(_)
213 | ty::Int(_)
214 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
215 | ty::Bool
216 | ty::Float(_)
217 | ty::Char
218 | ty::RawPtr(..)
219 | ty::Never
220 | ty::Ref(_, _, Mutability::Not)
221 | ty::Array(..) => Err(NoSolution),
222
223 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
226
227 ty::Dynamic(..)
228 | ty::Str
229 | ty::Slice(_)
230 | ty::Foreign(..)
231 | ty::Ref(_, _, Mutability::Mut)
232 | ty::Adt(_, _)
233 | ty::Alias(ty::IsRigid::Yes, _)
234 | ty::Param(_)
235 | ty::Placeholder(..) => Err(NoSolution),
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 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
275 | ty::Alias(ty::IsRigid::No, _)
276 | ty::Bound(..) => {
277 panic!("unexpected type `{ty:?}`")
278 }
279 }
280}
281
282pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
284 cx: I,
285 self_ty: I::Ty,
286 goal_kind: ty::ClosureKind,
287) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
288 match self_ty.kind() {
289 ty::FnDef(def_id, args) => {
291 let sig = cx.fn_sig(def_id);
292 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
293 Ok(Some(
294 sig.instantiate(cx, args.no_bound_vars().unwrap())
295 .skip_norm_wip()
296 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
297 ))
298 } else {
299 Err(NoSolution)
300 }
301 }
302 ty::FnPtr(sig_tys, hdr) => {
304 let sig = sig_tys.with(hdr);
305 if sig.is_fn_trait_compatible() {
306 Ok(Some(
307 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
308 ))
309 } else {
310 Err(NoSolution)
311 }
312 }
313 ty::Closure(_, args) => {
314 let closure_args = args.as_closure();
315 match closure_args.kind_ty().to_opt_closure_kind() {
316 Some(closure_kind) => {
319 if !closure_kind.extends(goal_kind) {
320 return Err(NoSolution);
321 }
322 }
323 None => {
326 if goal_kind != ty::ClosureKind::FnOnce {
327 return Ok(None);
328 }
329 }
330 }
331 Ok(Some(
332 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
333 ))
334 }
335
336 ty::CoroutineClosure(def_id, args) => {
341 let args = args.as_coroutine_closure();
342 let kind_ty = args.kind_ty();
343 let sig = args.coroutine_closure_sig().skip_binder();
344
345 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
346 && !args.tupled_upvars_ty().is_ty_var()
347 {
348 if !kind.extends(goal_kind) {
349 return Err(NoSolution);
350 }
351
352 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
357 return Err(NoSolution);
358 }
359
360 coroutine_closure_to_certain_coroutine(
361 cx,
362 goal_kind,
363 Region::new_static(cx),
365 def_id,
366 args,
367 sig,
368 )
369 } else {
370 if goal_kind != ty::ClosureKind::FnOnce {
373 return Ok(None);
374 }
375
376 coroutine_closure_to_ambiguous_coroutine(
377 cx,
378 goal_kind, Region::new_static(cx),
380 def_id,
381 args,
382 sig,
383 )
384 };
385
386 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
387 }
388
389 ty::Bool
390 | ty::Char
391 | ty::Int(_)
392 | ty::Uint(_)
393 | ty::Float(_)
394 | ty::Adt(_, _)
395 | ty::Foreign(_)
396 | ty::Str
397 | ty::Array(_, _)
398 | ty::Slice(_)
399 | ty::RawPtr(_, _)
400 | ty::Ref(_, _, _)
401 | ty::Dynamic(_, _)
402 | ty::Coroutine(_, _)
403 | ty::CoroutineWitness(..)
404 | ty::Never
405 | ty::Tuple(_)
406 | ty::Pat(_, _)
407 | ty::UnsafeBinder(_)
408 | ty::Alias(ty::IsRigid::Yes, _)
409 | ty::Param(_)
410 | ty::Placeholder(..)
411 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
412 | ty::Error(_) => Err(NoSolution),
413
414 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
415 | ty::Alias(ty::IsRigid::No, _)
416 | ty::Bound(..) => {
417 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
418 }
419 }
420}
421
422#[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)]
425#[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)]
426pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
427 pub tupled_inputs_ty: I::Ty,
428 pub output_coroutine_ty: I::Ty,
431 pub coroutine_return_ty: I::Ty,
434}
435
436pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
442 cx: I,
443 self_ty: I::Ty,
444 goal_kind: ty::ClosureKind,
445 env_region: I::Region,
446) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
447 match self_ty.kind() {
448 ty::CoroutineClosure(def_id, args) => {
449 let args = args.as_coroutine_closure();
450 let kind_ty = args.kind_ty();
451 let sig = args.coroutine_closure_sig().skip_binder();
452 let mut nested = ::alloc::vec::Vec::new()vec![];
453
454 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
455 && !args.tupled_upvars_ty().is_ty_var()
456 {
457 if !kind.extends(goal_kind) {
458 return Err(NoSolution);
459 }
460
461 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
462 } else {
463 nested.push(
471 ty::TraitRef::new(
472 cx,
473 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
474 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
475 )
476 .upcast(cx),
477 );
478
479 coroutine_closure_to_ambiguous_coroutine(
480 cx, goal_kind, env_region, def_id, args, sig,
481 )
482 };
483
484 Ok((
485 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
486 tupled_inputs_ty: sig.tupled_inputs_ty,
487 output_coroutine_ty: coroutine_ty,
488 coroutine_return_ty: sig.return_ty,
489 }),
490 nested,
491 ))
492 }
493
494 ty::FnDef(def_id, _) => {
495 let sig = self_ty.fn_sig(cx);
496 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
497 fn_item_to_async_callable(cx, sig)
498 } else {
499 Err(NoSolution)
500 }
501 }
502 ty::FnPtr(..) => {
503 let sig = self_ty.fn_sig(cx);
504 if sig.is_fn_trait_compatible() {
505 fn_item_to_async_callable(cx, sig)
506 } else {
507 Err(NoSolution)
508 }
509 }
510
511 ty::Closure(_, args) => {
512 let args = args.as_closure();
513 let bound_sig = args.sig();
514 let sig = bound_sig.skip_binder();
515 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
516 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![
519 bound_sig
520 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
521 .upcast(cx),
522 ];
523
524 let kind_ty = args.kind_ty();
527 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
528 if !closure_kind.extends(goal_kind) {
529 return Err(NoSolution);
530 }
531 } else {
532 let async_fn_kind_trait_def_id =
533 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
534 nested.push(
542 ty::TraitRef::new(
543 cx,
544 async_fn_kind_trait_def_id,
545 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
546 )
547 .upcast(cx),
548 );
549 }
550
551 let future_output_def_id =
552 cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
553 let future_output_ty =
554 Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]);
555 Ok((
556 bound_sig.rebind(AsyncCallableRelevantTypes {
557 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
558 output_coroutine_ty: sig.output(),
559 coroutine_return_ty: future_output_ty,
560 }),
561 nested,
562 ))
563 }
564
565 ty::Bool
566 | ty::Char
567 | ty::Int(_)
568 | ty::Uint(_)
569 | ty::Float(_)
570 | ty::Adt(_, _)
571 | ty::Foreign(_)
572 | ty::Str
573 | ty::Array(_, _)
574 | ty::Pat(_, _)
575 | ty::Slice(_)
576 | ty::RawPtr(_, _)
577 | ty::Ref(_, _, _)
578 | ty::Dynamic(_, _)
579 | ty::Coroutine(_, _)
580 | ty::CoroutineWitness(..)
581 | ty::Never
582 | ty::UnsafeBinder(_)
583 | ty::Tuple(_)
584 | ty::Alias(ty::IsRigid::Yes, _)
585 | ty::Param(_)
586 | ty::Placeholder(..)
587 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
588 | ty::Error(_) => Err(NoSolution),
589
590 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
591 | ty::Alias(ty::IsRigid::No, _)
592 | ty::Bound(..) => {
593 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
594 }
595 }
596}
597
598fn fn_item_to_async_callable<I: Interner>(
599 cx: I,
600 bound_sig: ty::Binder<I, ty::FnSig<I>>,
601) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
602 let sig = bound_sig.skip_binder();
603 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
604 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![
607 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
608 ];
609 let future_output_def_id =
610 cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
611 let future_output_ty =
612 Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]);
613 Ok((
614 bound_sig.rebind(AsyncCallableRelevantTypes {
615 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
616 output_coroutine_ty: sig.output(),
617 coroutine_return_ty: future_output_ty,
618 }),
619 nested,
620 ))
621}
622
623fn coroutine_closure_to_certain_coroutine<I: Interner>(
626 cx: I,
627 goal_kind: ty::ClosureKind,
628 goal_region: I::Region,
629 def_id: I::CoroutineClosureId,
630 args: ty::CoroutineClosureArgs<I>,
631 sig: ty::CoroutineClosureSignature<I>,
632) -> I::Ty {
633 sig.to_coroutine_given_kind_and_upvars(
634 cx,
635 args.parent_args(),
636 cx.coroutine_for_closure(def_id),
637 goal_kind,
638 goal_region,
639 args.tupled_upvars_ty(),
640 args.coroutine_captures_by_ref_ty(),
641 )
642}
643
644fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
650 cx: I,
651 goal_kind: ty::ClosureKind,
652 goal_region: I::Region,
653 def_id: I::CoroutineClosureId,
654 args: ty::CoroutineClosureArgs<I>,
655 sig: ty::CoroutineClosureSignature<I>,
656) -> I::Ty {
657 let upvars_projection_def_id =
658 cx.require_projection_lang_item(SolverProjectionLangItem::AsyncFnKindUpvars);
659 let tupled_upvars_ty = Ty::new_projection(
660 cx,
661 ty::IsRigid::No,
662 upvars_projection_def_id,
663 [
664 I::GenericArg::from(args.kind_ty()),
665 Ty::from_closure_kind(cx, goal_kind).into(),
666 goal_region.into(),
667 sig.tupled_inputs_ty.into(),
668 args.tupled_upvars_ty().into(),
669 args.coroutine_captures_by_ref_ty().into(),
670 ],
671 );
672 sig.to_coroutine(
673 cx,
674 args.parent_args(),
675 Ty::from_closure_kind(cx, goal_kind),
676 cx.coroutine_for_closure(def_id),
677 tupled_upvars_ty,
678 )
679}
680
681x;#[instrument(level = "trace", skip(cx), ret)]
688pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
689 cx: I,
690 self_ty: I::Ty,
691) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
692 match self_ty.kind() {
693 ty::FnDef(def_id, args) => {
694 let args = args.no_bound_vars().unwrap();
696
697 let sig = cx.fn_sig(def_id);
698 if sig.skip_binder().is_fn_trait_compatible()
699 && !cx.has_target_features(def_id)
700 && cx.fn_is_const(def_id)
701 {
702 Ok((
703 sig.instantiate(cx, args)
704 .skip_norm_wip()
705 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
706 def_id.into(),
707 args,
708 ))
709 } else {
710 return Err(NoSolution);
711 }
712 }
713 ty::FnPtr(..) => {
715 return Err(NoSolution);
716 }
717 ty::Closure(def, args) => {
718 if cx.closure_is_const(def) {
719 let closure_args = args.as_closure();
720 Ok((
721 closure_args
722 .sig()
723 .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
724 def.into(),
725 args,
726 ))
727 } else {
728 return Err(NoSolution);
729 }
730 }
731 ty::CoroutineClosure(..) => {
733 return Err(NoSolution);
734 }
735
736 ty::Bool
737 | ty::Char
738 | ty::Int(_)
739 | ty::Uint(_)
740 | ty::Float(_)
741 | ty::Adt(_, _)
742 | ty::Foreign(_)
743 | ty::Str
744 | ty::Array(_, _)
745 | ty::Slice(_)
746 | ty::RawPtr(_, _)
747 | ty::Ref(_, _, _)
748 | ty::Dynamic(_, _)
749 | ty::Coroutine(_, _)
750 | ty::CoroutineWitness(..)
751 | ty::Never
752 | ty::Tuple(_)
753 | ty::Pat(_, _)
754 | ty::Alias(ty::IsRigid::Yes, _)
755 | ty::Param(_)
756 | ty::Placeholder(..)
757 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
758 | ty::Error(_)
759 | ty::UnsafeBinder(_) => return Err(NoSolution),
760
761 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
762 | ty::Alias(ty::IsRigid::No, _)
763 | ty::Bound(..) => {
764 panic!("unexpected type `{self_ty:?}`")
765 }
766 }
767}
768
769pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
772 cx: I,
773 self_ty: I::Ty,
774) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
775 let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
776
777 match self_ty.kind() {
778 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()vec![]),
780
781 ty::Adt(adt_def, args) => {
784 let mut const_conditions: Vec<_> = adt_def
785 .all_field_tys(cx)
786 .iter_instantiated(cx, args)
787 .map(Unnormalized::skip_norm_wip)
788 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
789 .collect();
790 match adt_def.destructor(cx) {
791 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
793 Some(AdtDestructorKind::Const) => {
795 let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
796 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
797 const_conditions.push(drop_trait_ref);
798 }
799 None => {}
801 }
802 Ok(const_conditions)
803 }
804
805 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
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, [ty])]))vec![ty::TraitRef::new(cx, destruct_def_id, [ty])])
807 }
808
809 ty::Tuple(tys) => Ok(tys
810 .iter()
811 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
812 .collect()),
813
814 ty::Bool
816 | ty::Char
817 | ty::Int(..)
818 | ty::Uint(..)
819 | ty::Float(..)
820 | ty::Str
821 | ty::RawPtr(..)
822 | ty::Ref(..)
823 | ty::FnDef(..)
824 | ty::FnPtr(..)
825 | ty::Never
826 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
827 | ty::Error(_) => Ok(::alloc::vec::Vec::new()vec![]),
828
829 ty::Closure(_, args) => {
831 let closure_args = args.as_closure();
832 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()])])
833 }
834 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
837 Err(NoSolution)
838 }
839
840 ty::UnsafeBinder(_) => Err(NoSolution),
843
844 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
845 Err(NoSolution)
846 }
847
848 ty::Bound(..)
849 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
850 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
851 }
852 }
853}
854
855pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
890 ecx: &mut EvalCtxt<'_, D>,
891 param_env: I::ParamEnv,
892 trait_ref: Binder<I, ty::TraitRef<I>>,
893 object_bounds: I::BoundExistentialPredicates,
894) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
895where
896 D: SolverDelegate<Interner = I>,
897 I: Interner,
898{
899 let cx = ecx.cx();
900 let trait_ref = ecx.instantiate_binder_with_infer(trait_ref);
901 let mut requirements = ::alloc::vec::Vec::new()vec![];
902 requirements.extend(elaborate::elaborate(
910 cx,
911 cx.explicit_super_predicates_of(trait_ref.def_id)
912 .iter_instantiated(cx, trait_ref.args)
913 .map(Unnormalized::skip_norm_wip)
914 .map(|(pred, _)| pred),
915 ));
916
917 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
920 if cx.generics_require_sized_self(associated_type_def_id) {
923 continue;
924 }
925
926 requirements.extend(
927 cx.item_bounds(associated_type_def_id)
928 .iter_instantiated(cx, trait_ref.args)
929 .map(Unnormalized::skip_norm_wip),
930 );
931 }
932
933 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
934 for bound in object_bounds.iter() {
935 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
936 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
941 replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
942 }
943 }
944
945 let mut folder = ReplaceProjectionWith {
946 ecx,
947 param_env,
948 self_ty: trait_ref.self_ty(),
949 mapping: &replace_projection_with,
950 nested: ::alloc::vec::Vec::new()vec![],
951 };
952
953 let requirements = requirements.try_fold_with(&mut folder)?;
954 Ok(folder
955 .nested
956 .into_iter()
957 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
958 .collect())
959}
960
961struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
962 ecx: &'a mut EvalCtxt<'b, D>,
963 param_env: I::ParamEnv,
964 self_ty: I::Ty,
965 mapping: &'a HashMap<I::TraitAssocTermId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
966 nested: Vec<Goal<I, I::Predicate>>,
967}
968
969impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
970where
971 D: SolverDelegate<Interner = I>,
972 I: Interner,
973{
974 fn projection_may_match(
975 &mut self,
976 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
977 target_projection: ty::AliasTerm<I>,
978 ) -> bool {
979 source_projection.item_def_id() == target_projection.expect_projection_def_id()
980 && self
981 .ecx
982 .probe(|_| ProbeKind::ProjectionCompatibility)
983 .enter_without_propagated_nested_goals(|ecx| {
984 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
985 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
986 ecx.try_evaluate_added_goals()
987 })
988 .is_ok()
989 }
990
991 fn try_eagerly_replace_alias(
996 &mut self,
997 alias_term: ty::AliasTerm<I>,
998 ) -> Result<Option<I::Term>, Ambiguous> {
999 if alias_term.self_ty() != self.self_ty {
1000 return Ok(None);
1001 }
1002
1003 let Some(replacements) = self.mapping.get(&alias_term.expect_projection_def_id()) else {
1004 return Ok(None);
1005 };
1006
1007 let mut matching_projections = replacements
1011 .iter()
1012 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
1013 let Some(replacement) = matching_projections.next() else {
1014 {
::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);
1016 };
1017 if matching_projections.next().is_some() {
1019 return Err(Ambiguous);
1023 }
1024
1025 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
1026 self.nested.extend(
1027 self.ecx
1028 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
1029 .expect("expected to be able to unify goal projection with dyn's projection"),
1030 );
1031
1032 Ok(Some(replacement.term))
1033 }
1034}
1035
1036pub(crate) struct Ambiguous;
1038
1039impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1040where
1041 D: SolverDelegate<Interner = I>,
1042 I: Interner,
1043{
1044 type Error = Ambiguous;
1045
1046 fn cx(&self) -> I {
1047 self.ecx.cx()
1048 }
1049
1050 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
1051 if let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind()
1052 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1053 {
1054 Ok(term.expect_ty())
1055 } else {
1056 ty.try_super_fold_with(self)
1057 }
1058 }
1059}