1use std::debug_assert_matches;
2
3use rustc_type_ir::fast_reject::DeepRejectCtxt;
4use rustc_type_ir::inherent::*;
5use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem};
6use rustc_type_ir::solve::{
7 FetchEligibleAssocItemResponse, NoSolutionOrRerunNonErased, QueryResultOrRerunNonErased,
8 RerunNonErased, RerunReason, RerunResultExt,
9};
10use rustc_type_ir::{
11 self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Unnormalized, Upcast as _,
12};
13use tracing::instrument;
14
15use crate::delegate::SolverDelegate;
16use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
17use crate::solve::assembly::{self, Candidate};
18use crate::solve::inspect::ProbeKind;
19use crate::solve::{
20 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeInfo,
21 NoSolution, SizedTraitKind,
22};
23
24impl<D, I> EvalCtxt<'_, D>
25where
26 D: SolverDelegate<Interner = I>,
27 I: Interner,
28{
29 x;#[instrument(level = "trace", skip(self), ret)]
30 pub(super) fn compute_normalizes_to_goal(
31 &mut self,
32 goal: Goal<I, NormalizesTo<I>>,
33 ) -> QueryResultOrRerunNonErased<I> {
34 debug_assert!(self.term_is_fully_unconstrained(goal));
35 debug_assert_matches!(
36 goal.predicate.alias.kind,
37 ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. }
38 );
39
40 let cx = self.cx();
41
42 let trait_ref = goal.predicate.alias.trait_ref(cx);
43 let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
44 let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(cx, trait_ref);
45 ecx.compute_trait_goal(trait_goal)
46 })?;
47 self.assemble_and_merge_candidates(
48 proven_via,
49 goal,
50 |ecx| {
51 for arg in goal.predicate.alias.own_args(cx).iter() {
61 let Some(term) = arg.as_term() else {
62 continue;
63 };
64 match ecx.structurally_normalize_term(goal.param_env, term) {
65 Ok(term) => {
66 if term.is_infer() {
67 return Some(ecx.evaluate_added_goals_and_make_canonical_response(
68 Certainty::AMBIGUOUS,
69 ));
70 }
71 }
72 Err(
73 e @ (NoSolutionOrRerunNonErased::NoSolution(NoSolution)
74 | NoSolutionOrRerunNonErased::RerunNonErased(_)),
75 ) => {
76 return Some(Err(e));
77 }
78 }
79 }
80
81 None
82 },
83 |ecx| {
84 ecx.probe(|&result| ProbeKind::RigidAlias { result })
85 .enter(|this| {
86 this.structurally_instantiate_normalizes_to_term(
87 goal,
88 goal.predicate.alias,
89 );
90 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
91 })
92 .map_err(Into::into)
93 },
94 )
95 }
96
97 pub fn push_const_arg_has_type_goal(
100 &mut self,
101 param_env: I::ParamEnv,
102 alias: ty::AliasTerm<I>,
103 term: I::Term,
104 ) -> Result<(), NoSolutionOrRerunNonErased> {
105 if let Some(ct) = term.as_const() {
106 let cx = self.cx();
107 let expected_ty = alias.expect_ct().type_of(cx).skip_norm_wip();
108 self.add_goal(
109 GoalSource::Misc,
110 Goal {
111 param_env,
112 predicate: ty::ClauseKind::ConstArgHasType(ct, expected_ty).upcast(cx),
113 },
114 )?;
115 }
116 Ok(())
117 }
118
119 fn instantiate_normalizes_to_term(
146 &mut self,
147 goal: Goal<I, NormalizesTo<I>>,
148 term: I::Term,
149 ) -> Result<(), NoSolutionOrRerunNonErased> {
150 self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, term)?;
151 self.eq(goal.param_env, goal.predicate.term, term)
152 .expect("expected goal term to be fully unconstrained");
153 Ok(())
154 }
155
156 fn structurally_instantiate_normalizes_to_term(
159 &mut self,
160 goal: Goal<I, NormalizesTo<I>>,
161 term: ty::AliasTerm<I>,
162 ) {
163 self.relate(
164 goal.param_env,
165 term.to_term(self.cx(), ty::IsRigid::Yes),
166 ty::Invariant,
167 goal.predicate.term,
168 )
169 .expect("expected goal term to be fully unconstrained");
170 }
171}
172
173impl<D, I> assembly::GoalKind<D> for NormalizesTo<I>
174where
175 D: SolverDelegate<Interner = I>,
176 I: Interner,
177{
178 fn self_ty(self) -> I::Ty {
179 self.self_ty()
180 }
181
182 fn trait_ref(self, cx: I) -> ty::TraitRef<I> {
183 self.alias.trait_ref(cx)
184 }
185
186 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
187 self.with_replaced_self_ty(cx, self_ty)
188 }
189
190 fn trait_def_id(self, cx: I) -> I::TraitId {
191 self.trait_def_id(cx)
192 }
193
194 fn fast_reject_assumption(
195 ecx: &mut EvalCtxt<'_, D>,
196 goal: Goal<I, Self>,
197 assumption: I::Clause,
198 ) -> Result<(), NoSolution> {
199 let alias_def_id = match goal.predicate.alias.kind {
200 ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(),
201 ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(),
202 _ => return Err(NoSolution),
203 };
204 if let Some(projection_pred) = assumption.as_projection_clause()
205 && projection_pred.item_def_id() == alias_def_id
206 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
207 goal.predicate.alias.args,
208 projection_pred.skip_binder().projection_term.args,
209 )
210 {
211 Ok(())
212 } else {
213 Err(NoSolution)
214 }
215 }
216
217 fn match_assumption(
218 ecx: &mut EvalCtxt<'_, D>,
219 goal: Goal<I, Self>,
220 assumption: I::Clause,
221 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
222 ) -> QueryResultOrRerunNonErased<I> {
223 let cx = ecx.cx();
224 let projection_pred = assumption.as_projection_clause().unwrap();
225 let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred);
226 ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?;
227
228 ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term)?;
229
230 ecx.add_goals(
233 GoalSource::AliasWellFormed,
234 cx.own_predicates_of(goal.predicate.alias.expect_projection_def_id().into())
235 .iter_instantiated(cx, goal.predicate.alias.args)
236 .map(Unnormalized::skip_norm_wip)
237 .map(|pred| goal.with(cx, pred)),
238 )?;
239
240 then(ecx)
241 }
242
243 fn probe_and_consider_object_bound_candidate(
247 ecx: &mut EvalCtxt<'_, D>,
248 source: CandidateSource<I>,
249 goal: Goal<I, Self>,
250 assumption: I::Clause,
251 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
252 Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
253 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
254 })
255 }
256
257 fn consider_additional_alias_assumptions(
258 _ecx: &mut EvalCtxt<'_, D>,
259 _goal: Goal<I, Self>,
260 _alias_ty: ty::AliasTy<I>,
261 ) -> Vec<Candidate<I>> {
262 ::alloc::vec::Vec::new()vec![]
263 }
264
265 fn consider_impl_candidate(
266 ecx: &mut EvalCtxt<'_, D>,
267 goal: Goal<I, NormalizesTo<I>>,
268 impl_def_id: I::ImplId,
269 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
270 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
271 let cx = ecx.cx();
272
273 let alias_def_id = goal.predicate.alias.expect_projection_def_id();
274 let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
275 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
276 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
277 goal.predicate.alias.trait_ref(cx).args,
278 impl_trait_ref.skip_binder().args,
279 ) {
280 return Err(NoSolution.into());
281 }
282
283 let impl_polarity = cx.impl_polarity(impl_def_id);
285 match impl_polarity {
286 ty::ImplPolarity::Negative => return Err(NoSolution.into()),
287 ty::ImplPolarity::Reservation => {
288 {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("reservation impl for trait with assoc item: {0:?}",
goal)));
}unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
289 }
290 ty::ImplPolarity::Positive => {}
291 };
292
293 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
294 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
295 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
296
297 ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
298
299 let where_clause_bounds = cx
300 .predicates_of(impl_def_id.into())
301 .iter_instantiated(cx, impl_args)
302 .map(Unnormalized::skip_norm_wip)
303 .map(|pred| goal.with(cx, pred));
304 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
305
306 ecx.try_evaluate_added_goals()?;
311
312 ecx.add_goals(
316 GoalSource::AliasWellFormed,
317 cx.own_predicates_of(alias_def_id.into())
318 .iter_instantiated(cx, goal.predicate.alias.args)
319 .map(Unnormalized::skip_norm_wip)
320 .map(|pred| goal.with(cx, pred)),
321 )?;
322
323 let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
324 let error_term = match goal.predicate.alias.kind {
325 ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(),
326 ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(),
327 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
328 };
329 ecx.instantiate_normalizes_to_term(goal, error_term)?;
330 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
331 };
332
333 let target_item_def_id =
334 match ecx.fetch_eligible_assoc_item(goal_trait_ref, alias_def_id, impl_def_id) {
335 FetchEligibleAssocItemResponse::Found(target_item_def_id) => target_item_def_id,
336 FetchEligibleAssocItemResponse::NotFound(tm) => {
337 match tm {
338 ty::TypingMode::Coherence => {
350 ecx.add_goal(
351 GoalSource::Misc,
352 goal.with(cx, PredicateKind::Ambiguous),
353 )?;
354 return ecx
355 .evaluate_added_goals_and_make_canonical_response(
356 Certainty::Yes,
357 )
358 .map_err(Into::into);
359 }
360 ty::TypingMode::Typeck { .. }
362 | ty::TypingMode::PostTypeckUntilBorrowck { .. }
363 | ty::TypingMode::PostBorrowck { .. }
364 | ty::TypingMode::PostAnalysis
365 | ty::TypingMode::Codegen => {
366 ecx.structurally_instantiate_normalizes_to_term(
367 goal,
368 goal.predicate.alias,
369 );
370 return ecx
371 .evaluate_added_goals_and_make_canonical_response(
372 Certainty::Yes,
373 )
374 .map_err(Into::into);
375 }
376 };
377 }
378 FetchEligibleAssocItemResponse::Err(guar) => return error_response(ecx, guar),
379 FetchEligibleAssocItemResponse::NotFoundBecauseErased => {
380 ecx.opaque_accesses.rerun_always(RerunReason::FetchEligibleAssocItem)?;
381 return Err(NoSolution.into());
382 }
383 };
384
385 if !cx.has_item_definition(target_item_def_id) {
386 if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
392 if ecx.typing_mode().is_coherence() {
393 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous))?;
404 return then(ecx, Certainty::Yes).map_err(Into::into);
405 } else {
406 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
407 return then(ecx, Certainty::Yes).map_err(Into::into);
408 }
409 } else {
410 return error_response(ecx, cx.delay_bug("missing item"));
411 }
412 }
413
414 let target_container_def_id = cx.impl_or_trait_assoc_term_parent(target_item_def_id);
415
416 let target_args = ecx.translate_args(
427 goal,
428 impl_def_id,
429 impl_args,
430 impl_trait_ref,
431 target_container_def_id,
432 )?;
433
434 if !cx.check_args_compatible(target_item_def_id.into(), target_args) {
435 return error_response(
436 ecx,
437 cx.delay_bug("associated item has mismatched arguments"),
438 );
439 }
440
441 let term = match goal.predicate.alias.kind {
443 ty::AliasTermKind::ProjectionTy { .. } => {
444 let t = cx.type_of(target_item_def_id.into()).instantiate(cx, target_args);
445 let t = ecx.normalize(GoalSource::Misc, goal.param_env, t)?;
446 t.into()
447 }
448 ty::AliasTermKind::ProjectionConst { .. }
449 if cx.is_type_const(target_item_def_id.into()) =>
450 {
451 let c =
452 cx.const_of_item(target_item_def_id.into()).instantiate(cx, target_args);
453 let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?;
454 c.into()
455 }
456 ty::AliasTermKind::ProjectionConst { .. } => {
457 let uv = ty::UnevaluatedConst::new(
458 cx,
459 ty::UnevaluatedConstKind::Projection {
460 def_id: target_item_def_id.into().try_into().unwrap(),
461 },
462 target_args,
463 );
464 return ecx.evaluate_const_and_instantiate_projection_term(
465 goal.param_env,
466 goal.predicate.alias,
467 goal.predicate.term,
468 uv,
469 );
470 }
471 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
472 };
473
474 ecx.instantiate_normalizes_to_term(goal, term)?;
475 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into)
476 })
477 }
478
479 fn consider_error_guaranteed_candidate(
482 ecx: &mut EvalCtxt<'_, D>,
483 goal: Goal<I, Self>,
484 guar: I::ErrorGuaranteed,
485 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
486 let cx = ecx.cx();
487 let error_term = match goal.predicate.alias.kind {
488 ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(),
489 ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(),
490 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
491 };
492
493 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
494 ecx.instantiate_normalizes_to_term(goal, error_term)?;
495 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
496 })
497 }
498
499 fn consider_auto_trait_candidate(
500 ecx: &mut EvalCtxt<'_, D>,
501 _goal: Goal<I, Self>,
502 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
503 ecx.cx().delay_bug("associated types not allowed on auto traits");
504 Err(NoSolution.into())
505 }
506
507 fn consider_trait_alias_candidate(
508 _ecx: &mut EvalCtxt<'_, D>,
509 goal: Goal<I, Self>,
510 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
511 {
::core::panicking::panic_fmt(format_args!("trait aliases do not have associated types: {0:?}",
goal));
};panic!("trait aliases do not have associated types: {:?}", goal);
512 }
513
514 fn consider_builtin_sizedness_candidates(
515 _ecx: &mut EvalCtxt<'_, D>,
516 goal: Goal<I, Self>,
517 _sizedness: SizedTraitKind,
518 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
519 {
::core::panicking::panic_fmt(format_args!("`Sized`/`MetaSized` does not have an associated type: {0:?}",
goal));
};panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
520 }
521
522 fn consider_builtin_copy_clone_candidate(
523 _ecx: &mut EvalCtxt<'_, D>,
524 goal: Goal<I, Self>,
525 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
526 {
::core::panicking::panic_fmt(format_args!("`Copy`/`Clone` does not have an associated type: {0:?}",
goal));
};panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
527 }
528
529 fn consider_builtin_fn_ptr_trait_candidate(
530 _ecx: &mut EvalCtxt<'_, D>,
531 goal: Goal<I, Self>,
532 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
533 {
::core::panicking::panic_fmt(format_args!("`FnPtr` does not have an associated type: {0:?}",
goal));
};panic!("`FnPtr` does not have an associated type: {:?}", goal);
534 }
535
536 fn consider_builtin_fn_trait_candidates(
537 ecx: &mut EvalCtxt<'_, D>,
538 goal: Goal<I, Self>,
539 goal_kind: ty::ClosureKind,
540 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
541 let cx = ecx.cx();
542 let Some(tupled_inputs_and_output) =
543 structural_traits::extract_tupled_inputs_and_output_from_callable(
544 cx,
545 goal.predicate.self_ty(),
546 goal_kind,
547 )?
548 else {
549 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
550 };
551 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
552
553 let output_is_sized_pred =
556 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
557
558 let pred = ty::ProjectionPredicate {
559 projection_term: ty::AliasTerm::new(
560 cx,
561 goal.predicate.alias.kind,
562 [goal.predicate.self_ty(), inputs],
563 ),
564 term: output.into(),
565 }
566 .upcast(cx);
567
568 Self::probe_and_consider_implied_clause(
569 ecx,
570 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
571 goal,
572 pred,
573 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
574 )
575 .map_err(Into::into)
576 }
577
578 fn consider_builtin_async_fn_trait_candidates(
579 ecx: &mut EvalCtxt<'_, D>,
580 goal: Goal<I, Self>,
581 goal_kind: ty::ClosureKind,
582 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
583 let cx = ecx.cx();
584 let def_id = goal.predicate.alias.expect_projection_ty_def_id();
585
586 let env_region = match goal_kind {
587 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
588 ty::ClosureKind::FnOnce => Region::new_static(cx),
590 };
591 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
592 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
593 cx,
594 goal.predicate.self_ty(),
595 goal_kind,
596 env_region,
597 )?;
598 let AsyncCallableRelevantTypes {
599 tupled_inputs_ty,
600 output_coroutine_ty,
601 coroutine_return_ty,
602 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
603
604 let output_is_sized_pred = ty::TraitRef::new(
607 cx,
608 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
609 [output_coroutine_ty],
610 );
611
612 let (projection_term, term) = if cx
613 .is_projection_lang_item(def_id, SolverProjectionLangItem::CallOnceFuture)
614 {
615 (
616 ty::AliasTerm::new(
617 cx,
618 goal.predicate.alias.kind,
619 [goal.predicate.self_ty(), tupled_inputs_ty],
620 ),
621 output_coroutine_ty.into(),
622 )
623 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CallRefFuture) {
624 (
625 ty::AliasTerm::new(
626 cx,
627 goal.predicate.alias.kind,
628 [
629 I::GenericArg::from(goal.predicate.self_ty()),
630 tupled_inputs_ty.into(),
631 env_region.into(),
632 ],
633 ),
634 output_coroutine_ty.into(),
635 )
636 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::AsyncFnOnceOutput) {
637 (
638 ty::AliasTerm::new(
639 cx,
640 goal.predicate.alias.kind,
641 [goal.predicate.self_ty(), tupled_inputs_ty],
642 ),
643 coroutine_return_ty.into(),
644 )
645 } else {
646 {
::core::panicking::panic_fmt(format_args!("no such associated type in `AsyncFn*`: {0:?}",
def_id));
}panic!("no such associated type in `AsyncFn*`: {:?}", def_id)
647 };
648 let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
649
650 Self::probe_and_consider_implied_clause(
651 ecx,
652 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
653 goal,
654 pred,
655 [goal.with(cx, output_is_sized_pred)]
656 .into_iter()
657 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
658 .map(|goal| (GoalSource::ImplWhereBound, goal)),
659 )
660 }
661
662 fn consider_builtin_async_fn_kind_helper_candidate(
663 ecx: &mut EvalCtxt<'_, D>,
664 goal: Goal<I, Self>,
665 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
666 let [
667 closure_fn_kind_ty,
668 goal_kind_ty,
669 borrow_region,
670 tupled_inputs_ty,
671 tupled_upvars_ty,
672 coroutine_captures_by_ref_ty,
673 ] = *goal.predicate.alias.args.as_slice()
674 else {
675 ::core::panicking::panic("explicit panic");panic!();
676 };
677
678 if tupled_upvars_ty.expect_ty().is_ty_var() {
680 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
681 }
682
683 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
684 return Err(NoSolution.into());
686 };
687 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
688 return Err(NoSolution.into());
689 };
690 if !closure_kind.extends(goal_kind) {
691 return Err(NoSolution.into());
692 }
693
694 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
695 ecx.cx(),
696 goal_kind,
697 tupled_inputs_ty.expect_ty(),
698 tupled_upvars_ty.expect_ty(),
699 coroutine_captures_by_ref_ty.expect_ty(),
700 borrow_region.expect_region(),
701 );
702
703 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
704 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into())?;
705 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
706 })
707 }
708
709 fn consider_builtin_tuple_candidate(
710 _ecx: &mut EvalCtxt<'_, D>,
711 goal: Goal<I, Self>,
712 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
713 {
::core::panicking::panic_fmt(format_args!("`Tuple` does not have an associated type: {0:?}",
goal));
};panic!("`Tuple` does not have an associated type: {:?}", goal);
714 }
715
716 fn consider_builtin_pointee_candidate(
717 ecx: &mut EvalCtxt<'_, D>,
718 goal: Goal<I, Self>,
719 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
720 let cx = ecx.cx();
721 let metadata_def_id = cx.require_projection_lang_item(SolverProjectionLangItem::Metadata);
722 {
match (&ty::AliasTermKind::ProjectionTy { def_id: metadata_def_id },
&goal.predicate.alias.kind) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(
723 ty::AliasTermKind::ProjectionTy { def_id: metadata_def_id },
724 goal.predicate.alias.kind
725 );
726 let metadata_ty = match goal.predicate.self_ty().kind() {
727 ty::Bool
728 | ty::Char
729 | ty::Int(..)
730 | ty::Uint(..)
731 | ty::Float(..)
732 | ty::Array(..)
733 | ty::Pat(..)
734 | ty::RawPtr(..)
735 | ty::Ref(..)
736 | ty::FnDef(..)
737 | ty::FnPtr(..)
738 | ty::Closure(..)
739 | ty::CoroutineClosure(..)
740 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
741 | ty::Coroutine(..)
742 | ty::CoroutineWitness(..)
743 | ty::Never
744 | ty::Foreign(..) => Ty::new_unit(cx),
745
746 ty::Error(e) => Ty::new_error(cx, e),
747
748 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
749
750 ty::Dynamic(_, _) => {
751 let dyn_metadata = cx.require_adt_lang_item(SolverAdtLangItem::DynMetadata);
752 cx.type_of(dyn_metadata.into())
753 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
754 .skip_norm_wip()
755 }
756
757 ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => {
758 let alias_bound_result =
763 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
764 let sized_predicate = ty::TraitRef::new(
765 cx,
766 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
767 [I::GenericArg::from(goal.predicate.self_ty())],
768 );
769 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate))?;
770 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into())?;
771 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
772 });
773
774 let alias_bound_result = match alias_bound_result.map_err_to_rerun()? {
775 Ok(i) => Ok(i),
776 Err(NoSolution) => Err(NoSolution),
777 };
778
779 return alias_bound_result.or_else(|NoSolution| {
782 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
783 this.structurally_instantiate_normalizes_to_term(
784 goal,
785 goal.predicate.alias,
786 );
787 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
788 })
789 });
790 }
791
792 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
793 None => Ty::new_unit(cx),
794 Some(tail_ty) => Ty::new_projection(
795 cx,
796 ty::IsRigid::No,
797 metadata_def_id,
798 [tail_ty.instantiate(cx, args).skip_norm_wip()],
799 ),
800 },
801 ty::Adt(_, _) => Ty::new_unit(cx),
802
803 ty::Tuple(elements) => match elements.last() {
804 None => Ty::new_unit(cx),
805 Some(tail_ty) => {
806 Ty::new_projection(cx, ty::IsRigid::No, metadata_def_id, [tail_ty])
807 }
808 },
809
810 ty::UnsafeBinder(_) => {
811 ::core::panicking::panic("not yet implemented")todo!()
813 }
814
815 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
816 | ty::Alias(ty::IsRigid::No, _)
817 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as Pointee>::Metadata`",
goal.predicate.self_ty()));
}panic!(
818 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
819 goal.predicate.self_ty()
820 ),
821 };
822
823 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
824 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into())?;
825 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
826 })
827 }
828
829 fn consider_builtin_future_candidate(
830 ecx: &mut EvalCtxt<'_, D>,
831 goal: Goal<I, Self>,
832 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
833 let self_ty = goal.predicate.self_ty();
834 let ty::Coroutine(def_id, args) = self_ty.kind() else {
835 return Err(NoSolution.into());
836 };
837
838 let cx = ecx.cx();
840 if !cx.coroutine_is_async(def_id) {
841 return Err(NoSolution.into());
842 }
843
844 let term = args.as_coroutine().return_ty().into();
845
846 Self::probe_and_consider_implied_clause(
847 ecx,
848 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
849 goal,
850 ty::ProjectionPredicate {
851 projection_term: ty::AliasTerm::new(
852 ecx.cx(),
853 cx.alias_term_kind_from_def_id(
854 goal.predicate.alias.expect_projection_def_id().into(),
855 ),
856 [self_ty],
857 ),
858 term,
859 }
860 .upcast(cx),
861 [],
864 )
865 }
866
867 fn consider_builtin_iterator_candidate(
868 ecx: &mut EvalCtxt<'_, D>,
869 goal: Goal<I, Self>,
870 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
871 let self_ty = goal.predicate.self_ty();
872 let ty::Coroutine(def_id, args) = self_ty.kind() else {
873 return Err(NoSolution.into());
874 };
875
876 let cx = ecx.cx();
878 if !cx.coroutine_is_gen(def_id) {
879 return Err(NoSolution.into());
880 }
881
882 let term = args.as_coroutine().yield_ty().into();
883
884 Self::probe_and_consider_implied_clause(
885 ecx,
886 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
887 goal,
888 ty::ProjectionPredicate {
889 projection_term: ty::AliasTerm::new(
890 ecx.cx(),
891 cx.alias_term_kind_from_def_id(
892 goal.predicate.alias.expect_projection_def_id().into(),
893 ),
894 [self_ty],
895 ),
896 term,
897 }
898 .upcast(cx),
899 [],
902 )
903 .map_err(Into::into)
904 }
905
906 fn consider_builtin_fused_iterator_candidate(
907 _ecx: &mut EvalCtxt<'_, D>,
908 goal: Goal<I, Self>,
909 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
910 {
::core::panicking::panic_fmt(format_args!("`FusedIterator` does not have an associated type: {0:?}",
goal));
};panic!("`FusedIterator` does not have an associated type: {:?}", goal);
911 }
912
913 fn consider_builtin_async_iterator_candidate(
914 ecx: &mut EvalCtxt<'_, D>,
915 goal: Goal<I, Self>,
916 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
917 let self_ty = goal.predicate.self_ty();
918 let ty::Coroutine(def_id, args) = self_ty.kind() else {
919 return Err(NoSolution.into());
920 };
921
922 let cx = ecx.cx();
924 if !cx.coroutine_is_async_gen(def_id) {
925 return Err(NoSolution.into());
926 }
927
928 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
929 let expected_ty = ecx.next_ty_infer();
930 let wrapped_expected_ty = Ty::new_adt(
933 cx,
934 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
935 cx.mk_args(&[Ty::new_adt(
936 cx,
937 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
938 cx.mk_args(&[expected_ty.into()]),
939 )
940 .into()]),
941 );
942 let yield_ty = args.as_coroutine().yield_ty();
943 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
944 ecx.instantiate_normalizes_to_term(goal, expected_ty.into())?;
945 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
946 })
947 }
948
949 fn consider_builtin_coroutine_candidate(
950 ecx: &mut EvalCtxt<'_, D>,
951 goal: Goal<I, Self>,
952 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
953 let self_ty = goal.predicate.self_ty();
954 let ty::Coroutine(def_id, args) = self_ty.kind() else {
955 return Err(NoSolution.into());
956 };
957
958 let cx = ecx.cx();
960 if !cx.is_general_coroutine(def_id) {
961 return Err(NoSolution.into());
962 }
963
964 let coroutine = args.as_coroutine();
965 let def_id = goal.predicate.alias.expect_projection_ty_def_id();
966
967 let term = if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineReturn)
968 {
969 coroutine.return_ty().into()
970 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineYield) {
971 coroutine.yield_ty().into()
972 } else {
973 {
::core::panicking::panic_fmt(format_args!("unexpected associated item `{0:?}` for `{1:?}`",
def_id, self_ty));
}panic!("unexpected associated item `{:?}` for `{self_ty:?}`", def_id)
974 };
975
976 Self::probe_and_consider_implied_clause(
977 ecx,
978 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
979 goal,
980 ty::ProjectionPredicate {
981 projection_term: ty::AliasTerm::new(
982 ecx.cx(),
983 goal.predicate.alias.kind,
984 [self_ty, coroutine.resume_ty()],
985 ),
986 term,
987 }
988 .upcast(cx),
989 [],
992 )
993 }
994
995 fn consider_structural_builtin_unsize_candidates(
996 _ecx: &mut EvalCtxt<'_, D>,
997 goal: Goal<I, Self>,
998 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
999 {
::core::panicking::panic_fmt(format_args!("`Unsize` does not have an associated type: {0:?}",
goal));
};panic!("`Unsize` does not have an associated type: {:?}", goal);
1000 }
1001
1002 fn consider_builtin_discriminant_kind_candidate(
1003 ecx: &mut EvalCtxt<'_, D>,
1004 goal: Goal<I, Self>,
1005 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1006 let self_ty = goal.predicate.self_ty();
1007 let discriminant_ty = match self_ty.kind() {
1008 ty::Bool
1009 | ty::Char
1010 | ty::Int(..)
1011 | ty::Uint(..)
1012 | ty::Float(..)
1013 | ty::Array(..)
1014 | ty::Pat(..)
1015 | ty::RawPtr(..)
1016 | ty::Ref(..)
1017 | ty::FnDef(..)
1018 | ty::FnPtr(..)
1019 | ty::Closure(..)
1020 | ty::CoroutineClosure(..)
1021 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
1022 | ty::Coroutine(..)
1023 | ty::CoroutineWitness(..)
1024 | ty::Never
1025 | ty::Foreign(..)
1026 | ty::Adt(_, _)
1027 | ty::Str
1028 | ty::Slice(_)
1029 | ty::Dynamic(_, _)
1030 | ty::Tuple(_)
1031 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
1032
1033 ty::UnsafeBinder(_) => {
1034 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("discr subgoal...")));
}todo!("discr subgoal...")
1036 }
1037
1038 ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => {
1042 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1043 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
1044 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1045 });
1046 }
1047
1048 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
1049 | ty::Alias(ty::IsRigid::No, _)
1050 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
goal.predicate.self_ty()));
}panic!(
1051 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
1052 goal.predicate.self_ty()
1053 ),
1054 };
1055
1056 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1057 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into())?;
1058 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1059 })
1060 }
1061
1062 fn consider_builtin_destruct_candidate(
1063 _ecx: &mut EvalCtxt<'_, D>,
1064 goal: Goal<I, Self>,
1065 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1066 {
::core::panicking::panic_fmt(format_args!("`Destruct` does not have an associated type: {0:?}",
goal));
};panic!("`Destruct` does not have an associated type: {:?}", goal);
1067 }
1068
1069 fn consider_builtin_transmute_candidate(
1070 _ecx: &mut EvalCtxt<'_, D>,
1071 goal: Goal<I, Self>,
1072 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1073 {
::core::panicking::panic_fmt(format_args!("`TransmuteFrom` does not have an associated type: {0:?}",
goal));
}panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
1074 }
1075
1076 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
1077 _ecx: &mut EvalCtxt<'_, D>,
1078 goal: Goal<I, Self>,
1079 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1080 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("`BikeshedGuaranteedNoDrop` does not have an associated type: {0:?}",
goal)));
}unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
1081 }
1082
1083 fn consider_builtin_field_candidate(
1084 ecx: &mut EvalCtxt<'_, D>,
1085 goal: Goal<I, Self>,
1086 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1087 let self_ty = goal.predicate.self_ty();
1088 let ty::Adt(def, args) = self_ty.kind() else {
1089 return Err(NoSolution.into());
1090 };
1091 let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
1092 else {
1093 return Err(NoSolution.into());
1094 };
1095 let def_id = goal.predicate.alias.expect_projection_ty_def_id();
1096 let ty = match ecx.cx().as_projection_lang_item(def_id) {
1097 Some(SolverProjectionLangItem::FieldBase) => base,
1098 Some(SolverProjectionLangItem::FieldType) => ty,
1099 _ => {
::core::panicking::panic_fmt(format_args!("unexpected associated type {0:?} in `Field`",
goal.predicate));
}panic!("unexpected associated type {:?} in `Field`", goal.predicate),
1100 };
1101 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1102 ecx.instantiate_normalizes_to_term(goal, ty.into())?;
1103 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1104 })
1105 }
1106}
1107
1108impl<D, I> EvalCtxt<'_, D>
1109where
1110 D: SolverDelegate<Interner = I>,
1111 I: Interner,
1112{
1113 fn translate_args(
1114 &mut self,
1115 goal: Goal<I, ty::NormalizesTo<I>>,
1116 impl_def_id: I::ImplId,
1117 impl_args: I::GenericArgs,
1118 impl_trait_ref: rustc_type_ir::TraitRef<I>,
1119 target_container_def_id: I::DefId,
1120 ) -> Result<I::GenericArgs, NoSolutionOrRerunNonErased> {
1121 let cx = self.cx();
1122 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
1123 goal.predicate.alias.args
1125 } else if target_container_def_id == impl_def_id.into() {
1126 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
1129 } else {
1130 let target_args = self.fresh_args_for_item(target_container_def_id);
1131 let target_trait_ref = cx
1132 .impl_trait_ref(target_container_def_id.try_into().unwrap())
1133 .instantiate(cx, target_args)
1134 .skip_norm_wip();
1135 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
1137 self.add_goals(
1140 GoalSource::Misc,
1141 cx.predicates_of(target_container_def_id)
1142 .iter_instantiated(cx, target_args)
1143 .map(Unnormalized::skip_norm_wip)
1144 .map(|pred| goal.with(cx, pred)),
1145 )?;
1146 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
1147 })
1148 }
1149}