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(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![
110 cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip(),
111 ]))
112 }
113 }
114}
115
116x;#[instrument(level = "trace", skip(ecx), ret)]
117pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
118 ecx: &EvalCtxt<'_, D>,
119 sizedness: SizedTraitKind,
120 ty: I::Ty,
121) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
122where
123 D: SolverDelegate<Interner = I>,
124 I: Interner,
125{
126 match ty.kind() {
127 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
131 | ty::Uint(_)
132 | ty::Int(_)
133 | ty::Bool
134 | ty::Float(_)
135 | ty::FnDef(..)
136 | ty::FnPtr(..)
137 | ty::RawPtr(..)
138 | ty::Char
139 | ty::Ref(..)
140 | ty::Coroutine(..)
141 | ty::CoroutineWitness(..)
142 | ty::Array(..)
143 | ty::Pat(..)
144 | ty::Closure(..)
145 | ty::CoroutineClosure(..)
146 | ty::Never
147 | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
148
149 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
151 SizedTraitKind::Sized => Err(NoSolution),
152 SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
153 },
154
155 ty::Foreign(..) => Err(NoSolution),
157
158 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
159
160 ty::Bound(..)
161 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
162 panic!("unexpected type `{ty:?}`")
163 }
164
165 ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
166
167 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
170
171 ty::Adt(def, args) => {
186 if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
187 Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args).skip_norm_wip()]))
188 } else {
189 Ok(ty::Binder::dummy(vec![]))
190 }
191 }
192 }
193}
194
195x;#[instrument(level = "trace", skip(ecx), ret)]
196pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
197 ecx: &EvalCtxt<'_, D>,
198 ty: I::Ty,
199) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
200where
201 D: SolverDelegate<Interner = I>,
202 I: Interner,
203{
204 match ty.kind() {
205 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
207
208 ty::Uint(_)
210 | ty::Int(_)
211 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
212 | ty::Bool
213 | ty::Float(_)
214 | ty::Char
215 | ty::RawPtr(..)
216 | ty::Never
217 | ty::Ref(_, _, Mutability::Not)
218 | ty::Array(..) => Err(NoSolution),
219
220 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
223
224 ty::Dynamic(..)
225 | ty::Str
226 | ty::Slice(_)
227 | ty::Foreign(..)
228 | ty::Ref(_, _, Mutability::Mut)
229 | ty::Adt(_, _)
230 | ty::Alias(_)
231 | ty::Param(_)
232 | ty::Placeholder(..) => Err(NoSolution),
233
234 ty::Bound(..)
235 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
236 panic!("unexpected type `{ty:?}`")
237 }
238
239 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
241
242 ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
244
245 ty::CoroutineClosure(_, args) => {
247 Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
248 }
249
250 ty::Coroutine(def_id, args) => match ecx.cx().coroutine_movability(def_id) {
253 Movability::Static => Err(NoSolution),
254 Movability::Movable => {
255 if ecx.cx().features().coroutine_clone() {
256 Ok(ty::Binder::dummy(vec![
257 args.as_coroutine().tupled_upvars_ty(),
258 Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
259 ]))
260 } else {
261 Err(NoSolution)
262 }
263 }
264 },
265
266 ty::UnsafeBinder(_) => Err(NoSolution),
267
268 ty::CoroutineWitness(def_id, args) => Ok(ecx
270 .cx()
271 .coroutine_hidden_types(def_id)
272 .instantiate(ecx.cx(), args)
273 .skip_norm_wip()
274 .map_bound(|bound| bound.types.to_vec())),
275 }
276}
277
278pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
280 cx: I,
281 self_ty: I::Ty,
282 goal_kind: ty::ClosureKind,
283) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
284 match self_ty.kind() {
285 ty::FnDef(def_id, args) => {
287 let sig = cx.fn_sig(def_id);
288 if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
289 Ok(Some(
290 sig.instantiate(cx, args)
291 .skip_norm_wip()
292 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
293 ))
294 } else {
295 Err(NoSolution)
296 }
297 }
298 ty::FnPtr(sig_tys, hdr) => {
300 let sig = sig_tys.with(hdr);
301 if sig.is_fn_trait_compatible() {
302 Ok(Some(
303 sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
304 ))
305 } else {
306 Err(NoSolution)
307 }
308 }
309 ty::Closure(_, args) => {
310 let closure_args = args.as_closure();
311 match closure_args.kind_ty().to_opt_closure_kind() {
312 Some(closure_kind) => {
315 if !closure_kind.extends(goal_kind) {
316 return Err(NoSolution);
317 }
318 }
319 None => {
322 if goal_kind != ty::ClosureKind::FnOnce {
323 return Ok(None);
324 }
325 }
326 }
327 Ok(Some(
328 closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
329 ))
330 }
331
332 ty::CoroutineClosure(def_id, args) => {
337 let args = args.as_coroutine_closure();
338 let kind_ty = args.kind_ty();
339 let sig = args.coroutine_closure_sig().skip_binder();
340
341 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
342 && !args.tupled_upvars_ty().is_ty_var()
343 {
344 if !kind.extends(goal_kind) {
345 return Err(NoSolution);
346 }
347
348 if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
353 return Err(NoSolution);
354 }
355
356 coroutine_closure_to_certain_coroutine(
357 cx,
358 goal_kind,
359 Region::new_static(cx),
361 def_id,
362 args,
363 sig,
364 )
365 } else {
366 if goal_kind != ty::ClosureKind::FnOnce {
369 return Ok(None);
370 }
371
372 coroutine_closure_to_ambiguous_coroutine(
373 cx,
374 goal_kind, Region::new_static(cx),
376 def_id,
377 args,
378 sig,
379 )
380 };
381
382 Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
383 }
384
385 ty::Bool
386 | ty::Char
387 | ty::Int(_)
388 | ty::Uint(_)
389 | ty::Float(_)
390 | ty::Adt(_, _)
391 | ty::Foreign(_)
392 | ty::Str
393 | ty::Array(_, _)
394 | ty::Slice(_)
395 | ty::RawPtr(_, _)
396 | ty::Ref(_, _, _)
397 | ty::Dynamic(_, _)
398 | ty::Coroutine(_, _)
399 | ty::CoroutineWitness(..)
400 | ty::Never
401 | ty::Tuple(_)
402 | ty::Pat(_, _)
403 | ty::UnsafeBinder(_)
404 | ty::Alias(_)
405 | ty::Param(_)
406 | ty::Placeholder(..)
407 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
408 | ty::Error(_) => Err(NoSolution),
409
410 ty::Bound(..)
411 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
412 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
413 }
414 }
415}
416
417#[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)]
420#[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)]
421pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
422 pub tupled_inputs_ty: I::Ty,
423 pub output_coroutine_ty: I::Ty,
426 pub coroutine_return_ty: I::Ty,
429}
430
431pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
437 cx: I,
438 self_ty: I::Ty,
439 goal_kind: ty::ClosureKind,
440 env_region: I::Region,
441) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
442 match self_ty.kind() {
443 ty::CoroutineClosure(def_id, args) => {
444 let args = args.as_coroutine_closure();
445 let kind_ty = args.kind_ty();
446 let sig = args.coroutine_closure_sig().skip_binder();
447 let mut nested = ::alloc::vec::Vec::new()vec![];
448
449 let coroutine_ty = if let Some(kind) = kind_ty.to_opt_closure_kind()
450 && !args.tupled_upvars_ty().is_ty_var()
451 {
452 if !kind.extends(goal_kind) {
453 return Err(NoSolution);
454 }
455
456 coroutine_closure_to_certain_coroutine(cx, goal_kind, env_region, def_id, args, sig)
457 } else {
458 nested.push(
466 ty::TraitRef::new(
467 cx,
468 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper),
469 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
470 )
471 .upcast(cx),
472 );
473
474 coroutine_closure_to_ambiguous_coroutine(
475 cx, goal_kind, env_region, def_id, args, sig,
476 )
477 };
478
479 Ok((
480 args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
481 tupled_inputs_ty: sig.tupled_inputs_ty,
482 output_coroutine_ty: coroutine_ty,
483 coroutine_return_ty: sig.return_ty,
484 }),
485 nested,
486 ))
487 }
488
489 ty::FnDef(def_id, _) => {
490 let sig = self_ty.fn_sig(cx);
491 if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
492 fn_item_to_async_callable(cx, sig)
493 } else {
494 Err(NoSolution)
495 }
496 }
497 ty::FnPtr(..) => {
498 let sig = self_ty.fn_sig(cx);
499 if sig.is_fn_trait_compatible() {
500 fn_item_to_async_callable(cx, sig)
501 } else {
502 Err(NoSolution)
503 }
504 }
505
506 ty::Closure(_, args) => {
507 let args = args.as_closure();
508 let bound_sig = args.sig();
509 let sig = bound_sig.skip_binder();
510 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
511 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![
514 bound_sig
515 .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
516 .upcast(cx),
517 ];
518
519 let kind_ty = args.kind_ty();
522 if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
523 if !closure_kind.extends(goal_kind) {
524 return Err(NoSolution);
525 }
526 } else {
527 let async_fn_kind_trait_def_id =
528 cx.require_trait_lang_item(SolverTraitLangItem::AsyncFnKindHelper);
529 nested.push(
537 ty::TraitRef::new(
538 cx,
539 async_fn_kind_trait_def_id,
540 [kind_ty, Ty::from_closure_kind(cx, goal_kind)],
541 )
542 .upcast(cx),
543 );
544 }
545
546 let future_output_def_id =
547 cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
548 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
549 Ok((
550 bound_sig.rebind(AsyncCallableRelevantTypes {
551 tupled_inputs_ty: sig.inputs().get(0).unwrap(),
552 output_coroutine_ty: sig.output(),
553 coroutine_return_ty: future_output_ty,
554 }),
555 nested,
556 ))
557 }
558
559 ty::Bool
560 | ty::Char
561 | ty::Int(_)
562 | ty::Uint(_)
563 | ty::Float(_)
564 | ty::Adt(_, _)
565 | ty::Foreign(_)
566 | ty::Str
567 | ty::Array(_, _)
568 | ty::Pat(_, _)
569 | ty::Slice(_)
570 | ty::RawPtr(_, _)
571 | ty::Ref(_, _, _)
572 | ty::Dynamic(_, _)
573 | ty::Coroutine(_, _)
574 | ty::CoroutineWitness(..)
575 | ty::Never
576 | ty::UnsafeBinder(_)
577 | ty::Tuple(_)
578 | ty::Alias(_)
579 | ty::Param(_)
580 | ty::Placeholder(..)
581 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
582 | ty::Error(_) => Err(NoSolution),
583
584 ty::Bound(..)
585 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
586 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
587 }
588 }
589}
590
591fn fn_item_to_async_callable<I: Interner>(
592 cx: I,
593 bound_sig: ty::Binder<I, ty::FnSig<I>>,
594) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
595 let sig = bound_sig.skip_binder();
596 let future_trait_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Future);
597 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![
600 bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
601 ];
602 let future_output_def_id =
603 cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput);
604 let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
605 Ok((
606 bound_sig.rebind(AsyncCallableRelevantTypes {
607 tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
608 output_coroutine_ty: sig.output(),
609 coroutine_return_ty: future_output_ty,
610 }),
611 nested,
612 ))
613}
614
615fn coroutine_closure_to_certain_coroutine<I: Interner>(
618 cx: I,
619 goal_kind: ty::ClosureKind,
620 goal_region: I::Region,
621 def_id: I::CoroutineClosureId,
622 args: ty::CoroutineClosureArgs<I>,
623 sig: ty::CoroutineClosureSignature<I>,
624) -> I::Ty {
625 sig.to_coroutine_given_kind_and_upvars(
626 cx,
627 args.parent_args(),
628 cx.coroutine_for_closure(def_id),
629 goal_kind,
630 goal_region,
631 args.tupled_upvars_ty(),
632 args.coroutine_captures_by_ref_ty(),
633 )
634}
635
636fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
642 cx: I,
643 goal_kind: ty::ClosureKind,
644 goal_region: I::Region,
645 def_id: I::CoroutineClosureId,
646 args: ty::CoroutineClosureArgs<I>,
647 sig: ty::CoroutineClosureSignature<I>,
648) -> I::Ty {
649 let upvars_projection_def_id =
650 cx.require_projection_lang_item(SolverProjectionLangItem::AsyncFnKindUpvars);
651 let tupled_upvars_ty = Ty::new_projection(
652 cx,
653 upvars_projection_def_id,
654 [
655 I::GenericArg::from(args.kind_ty()),
656 Ty::from_closure_kind(cx, goal_kind).into(),
657 goal_region.into(),
658 sig.tupled_inputs_ty.into(),
659 args.tupled_upvars_ty().into(),
660 args.coroutine_captures_by_ref_ty().into(),
661 ],
662 );
663 sig.to_coroutine(
664 cx,
665 args.parent_args(),
666 Ty::from_closure_kind(cx, goal_kind),
667 cx.coroutine_for_closure(def_id),
668 tupled_upvars_ty,
669 )
670}
671
672x;#[instrument(level = "trace", skip(cx), ret)]
679pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
680 cx: I,
681 self_ty: I::Ty,
682) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::DefId, I::GenericArgs), NoSolution> {
683 match self_ty.kind() {
684 ty::FnDef(def_id, args) => {
685 let sig = cx.fn_sig(def_id);
686 if sig.skip_binder().is_fn_trait_compatible()
687 && !cx.has_target_features(def_id)
688 && cx.fn_is_const(def_id)
689 {
690 Ok((
691 sig.instantiate(cx, args)
692 .skip_norm_wip()
693 .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
694 def_id.into(),
695 args,
696 ))
697 } else {
698 return Err(NoSolution);
699 }
700 }
701 ty::FnPtr(..) => {
703 return Err(NoSolution);
704 }
705 ty::Closure(def, args) => {
706 if cx.closure_is_const(def) {
707 let closure_args = args.as_closure();
708 Ok((
709 closure_args
710 .sig()
711 .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
712 def.into(),
713 args,
714 ))
715 } else {
716 return Err(NoSolution);
717 }
718 }
719 ty::CoroutineClosure(..) => {
721 return Err(NoSolution);
722 }
723
724 ty::Bool
725 | ty::Char
726 | ty::Int(_)
727 | ty::Uint(_)
728 | ty::Float(_)
729 | ty::Adt(_, _)
730 | ty::Foreign(_)
731 | ty::Str
732 | ty::Array(_, _)
733 | ty::Slice(_)
734 | ty::RawPtr(_, _)
735 | ty::Ref(_, _, _)
736 | ty::Dynamic(_, _)
737 | ty::Coroutine(_, _)
738 | ty::CoroutineWitness(..)
739 | ty::Never
740 | ty::Tuple(_)
741 | ty::Pat(_, _)
742 | ty::Alias(_)
743 | ty::Param(_)
744 | ty::Placeholder(..)
745 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
746 | ty::Error(_)
747 | ty::UnsafeBinder(_) => return Err(NoSolution),
748
749 ty::Bound(..)
750 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
751 panic!("unexpected type `{self_ty:?}`")
752 }
753 }
754}
755
756pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
759 cx: I,
760 self_ty: I::Ty,
761) -> Result<Vec<ty::TraitRef<I>>, NoSolution> {
762 let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct);
763
764 match self_ty.kind() {
765 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => Ok(::alloc::vec::Vec::new()vec![]),
767
768 ty::Adt(adt_def, args) => {
771 let mut const_conditions: Vec<_> = adt_def
772 .all_field_tys(cx)
773 .iter_instantiated(cx, args)
774 .map(Unnormalized::skip_norm_wip)
775 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
776 .collect();
777 match adt_def.destructor(cx) {
778 Some(AdtDestructorKind::NotConst) => return Err(NoSolution),
780 Some(AdtDestructorKind::Const) => {
782 let drop_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Drop);
783 let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]);
784 const_conditions.push(drop_trait_ref);
785 }
786 None => {}
788 }
789 Ok(const_conditions)
790 }
791
792 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
793 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])])
794 }
795
796 ty::Tuple(tys) => Ok(tys
797 .iter()
798 .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty]))
799 .collect()),
800
801 ty::Bool
803 | ty::Char
804 | ty::Int(..)
805 | ty::Uint(..)
806 | ty::Float(..)
807 | ty::Str
808 | ty::RawPtr(..)
809 | ty::Ref(..)
810 | ty::FnDef(..)
811 | ty::FnPtr(..)
812 | ty::Never
813 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
814 | ty::Error(_) => Ok(::alloc::vec::Vec::new()vec![]),
815
816 ty::Closure(_, args) => {
818 let closure_args = args.as_closure();
819 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()])])
820 }
821 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
824 Err(NoSolution)
825 }
826
827 ty::UnsafeBinder(_) => Err(NoSolution),
830
831 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
832 Err(NoSolution)
833 }
834
835 ty::Bound(..)
836 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
837 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
838 }
839 }
840}
841
842pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
877 ecx: &mut EvalCtxt<'_, D>,
878 param_env: I::ParamEnv,
879 trait_ref: Binder<I, ty::TraitRef<I>>,
880 object_bounds: I::BoundExistentialPredicates,
881) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
882where
883 D: SolverDelegate<Interner = I>,
884 I: Interner,
885{
886 let cx = ecx.cx();
887 let trait_ref = ecx.instantiate_binder_with_infer(trait_ref);
888 let mut requirements = ::alloc::vec::Vec::new()vec![];
889 requirements.extend(elaborate::elaborate(
897 cx,
898 cx.explicit_super_predicates_of(trait_ref.def_id)
899 .iter_instantiated(cx, trait_ref.args)
900 .map(Unnormalized::skip_norm_wip)
901 .map(|(pred, _)| pred),
902 ));
903
904 for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) {
907 if cx.generics_require_sized_self(associated_type_def_id) {
910 continue;
911 }
912
913 requirements.extend(
914 cx.item_bounds(associated_type_def_id)
915 .iter_instantiated(cx, trait_ref.args)
916 .map(Unnormalized::skip_norm_wip),
917 );
918 }
919
920 let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
921 for bound in object_bounds.iter() {
922 if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
923 let proj = proj.with_self_ty(cx, trait_ref.self_ty());
928 replace_projection_with
929 .entry(proj.def_id().into())
930 .or_default()
931 .push(bound.rebind(proj));
932 }
933 }
934
935 let mut folder = ReplaceProjectionWith {
936 ecx,
937 param_env,
938 self_ty: trait_ref.self_ty(),
939 mapping: &replace_projection_with,
940 nested: ::alloc::vec::Vec::new()vec![],
941 };
942
943 let requirements = requirements.try_fold_with(&mut folder)?;
944 Ok(folder
945 .nested
946 .into_iter()
947 .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
948 .collect())
949}
950
951struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
952 ecx: &'a mut EvalCtxt<'b, D>,
953 param_env: I::ParamEnv,
954 self_ty: I::Ty,
955 mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
956 nested: Vec<Goal<I, I::Predicate>>,
957}
958
959impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
960where
961 D: SolverDelegate<Interner = I>,
962 I: Interner,
963{
964 fn projection_may_match(
965 &mut self,
966 source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
967 target_projection: ty::AliasTerm<I>,
968 ) -> bool {
969 source_projection.item_def_id() == target_projection.def_id()
970 && self
971 .ecx
972 .probe(|_| ProbeKind::ProjectionCompatibility)
973 .enter_without_propagated_nested_goals(|ecx| {
974 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
975 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
976 ecx.try_evaluate_added_goals()
977 })
978 .is_ok()
979 }
980
981 fn try_eagerly_replace_alias(
986 &mut self,
987 alias_term: ty::AliasTerm<I>,
988 ) -> Result<Option<I::Term>, Ambiguous> {
989 if alias_term.self_ty() != self.self_ty {
990 return Ok(None);
991 }
992
993 let Some(replacements) = self.mapping.get(&alias_term.def_id()) else {
994 return Ok(None);
995 };
996
997 let mut matching_projections = replacements
1001 .iter()
1002 .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
1003 let Some(replacement) = matching_projections.next() else {
1004 {
::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);
1006 };
1007 if matching_projections.next().is_some() {
1009 return Err(Ambiguous);
1013 }
1014
1015 let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
1016 self.nested.extend(
1017 self.ecx
1018 .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
1019 .expect("expected to be able to unify goal projection with dyn's projection"),
1020 );
1021
1022 Ok(Some(replacement.term))
1023 }
1024}
1025
1026pub(crate) struct Ambiguous;
1028
1029impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
1030where
1031 D: SolverDelegate<Interner = I>,
1032 I: Interner,
1033{
1034 type Error = Ambiguous;
1035
1036 fn cx(&self) -> I {
1037 self.ecx.cx()
1038 }
1039
1040 fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
1041 if let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind()
1042 && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())?
1043 {
1044 Ok(term.expect_ty())
1045 } else {
1046 ty.try_super_fold_with(self)
1047 }
1048 }
1049}