1mod anon_const;
2mod free_alias;
3mod inherent;
4mod opaque_types;
5
6use rustc_type_ir::fast_reject::DeepRejectCtxt;
7use rustc_type_ir::inherent::*;
8use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
9use rustc_type_ir::solve::SizedTraitKind;
10use rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _};
11use tracing::instrument;
12
13use crate::delegate::SolverDelegate;
14use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
15use crate::solve::assembly::{self, Candidate};
16use crate::solve::inspect::ProbeKind;
17use crate::solve::{
18 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
19 NoSolution, QueryResult,
20};
21
22impl<D, I> EvalCtxt<'_, D>
23where
24 D: SolverDelegate<Interner = I>,
25 I: Interner,
26{
27 #[instrument(level = "trace", skip(self), ret)]
28 pub(super) fn compute_normalizes_to_goal(
29 &mut self,
30 goal: Goal<I, NormalizesTo<I>>,
31 ) -> QueryResult<I> {
32 debug_assert!(self.term_is_fully_unconstrained(goal));
33 let cx = self.cx();
34 match goal.predicate.alias.kind(cx) {
35 ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
36 let trait_ref = goal.predicate.alias.trait_ref(cx);
37 let (_, proven_via) =
38 self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
39 let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(cx, trait_ref);
40 ecx.compute_trait_goal(trait_goal)
41 })?;
42 self.assemble_and_merge_candidates(proven_via, goal, |ecx| {
43 ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
44 this.structurally_instantiate_normalizes_to_term(
45 goal,
46 goal.predicate.alias,
47 );
48 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
49 })
50 })
51 }
52 ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => {
53 self.normalize_inherent_associated_term(goal)
54 }
55 ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal),
56 ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst => {
57 self.normalize_free_alias(goal)
58 }
59 ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal),
60 }
61 }
62
63 pub fn instantiate_normalizes_to_term(
69 &mut self,
70 goal: Goal<I, NormalizesTo<I>>,
71 term: I::Term,
72 ) {
73 self.eq(goal.param_env, goal.predicate.term, term)
74 .expect("expected goal term to be fully unconstrained");
75 }
76
77 pub fn structurally_instantiate_normalizes_to_term(
80 &mut self,
81 goal: Goal<I, NormalizesTo<I>>,
82 term: ty::AliasTerm<I>,
83 ) {
84 self.relate_rigid_alias_non_alias(goal.param_env, term, ty::Invariant, goal.predicate.term)
85 .expect("expected goal term to be fully unconstrained");
86 }
87}
88
89impl<D, I> assembly::GoalKind<D> for NormalizesTo<I>
90where
91 D: SolverDelegate<Interner = I>,
92 I: Interner,
93{
94 fn self_ty(self) -> I::Ty {
95 self.self_ty()
96 }
97
98 fn trait_ref(self, cx: I) -> ty::TraitRef<I> {
99 self.alias.trait_ref(cx)
100 }
101
102 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
103 self.with_replaced_self_ty(cx, self_ty)
104 }
105
106 fn trait_def_id(self, cx: I) -> I::TraitId {
107 self.trait_def_id(cx)
108 }
109
110 fn fast_reject_assumption(
111 ecx: &mut EvalCtxt<'_, D>,
112 goal: Goal<I, Self>,
113 assumption: I::Clause,
114 ) -> Result<(), NoSolution> {
115 if let Some(projection_pred) = assumption.as_projection_clause()
116 && projection_pred.item_def_id() == goal.predicate.def_id()
117 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
118 goal.predicate.alias.args,
119 projection_pred.skip_binder().projection_term.args,
120 )
121 {
122 Ok(())
123 } else {
124 Err(NoSolution)
125 }
126 }
127
128 fn match_assumption(
129 ecx: &mut EvalCtxt<'_, D>,
130 goal: Goal<I, Self>,
131 assumption: I::Clause,
132 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
133 ) -> QueryResult<I> {
134 let cx = ecx.cx();
135 match goal.predicate.alias.kind(cx) {
145 ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
146 for arg in goal.predicate.alias.own_args(cx).iter() {
147 let Some(term) = arg.as_term() else {
148 continue;
149 };
150 let term = ecx.structurally_normalize_term(goal.param_env, term)?;
151 if term.is_infer() {
152 return ecx.evaluate_added_goals_and_make_canonical_response(
153 Certainty::AMBIGUOUS,
154 );
155 }
156 }
157 }
158 ty::AliasTermKind::OpaqueTy
159 | ty::AliasTermKind::InherentTy
160 | ty::AliasTermKind::InherentConst
161 | ty::AliasTermKind::FreeTy
162 | ty::AliasTermKind::FreeConst
163 | ty::AliasTermKind::UnevaluatedConst => {}
164 }
165
166 let projection_pred = assumption.as_projection_clause().unwrap();
167
168 let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred);
169 ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?;
170
171 ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term);
172
173 ecx.add_goals(
176 GoalSource::AliasWellFormed,
177 cx.own_predicates_of(goal.predicate.def_id())
178 .iter_instantiated(cx, goal.predicate.alias.args)
179 .map(|pred| goal.with(cx, pred)),
180 );
181
182 then(ecx)
183 }
184
185 fn consider_additional_alias_assumptions(
186 _ecx: &mut EvalCtxt<'_, D>,
187 _goal: Goal<I, Self>,
188 _alias_ty: ty::AliasTy<I>,
189 ) -> Vec<Candidate<I>> {
190 vec![]
191 }
192
193 fn consider_impl_candidate(
194 ecx: &mut EvalCtxt<'_, D>,
195 goal: Goal<I, NormalizesTo<I>>,
196 impl_def_id: I::ImplId,
197 ) -> Result<Candidate<I>, NoSolution> {
198 let cx = ecx.cx();
199
200 let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
201 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
202 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
203 goal.predicate.alias.trait_ref(cx).args,
204 impl_trait_ref.skip_binder().args,
205 ) {
206 return Err(NoSolution);
207 }
208
209 let impl_polarity = cx.impl_polarity(impl_def_id);
211 match impl_polarity {
212 ty::ImplPolarity::Negative => return Err(NoSolution),
213 ty::ImplPolarity::Reservation => {
214 unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
215 }
216 ty::ImplPolarity::Positive => {}
217 };
218
219 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
220 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
221 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
222
223 ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
224
225 let where_clause_bounds = cx
226 .predicates_of(impl_def_id.into())
227 .iter_instantiated(cx, impl_args)
228 .map(|pred| goal.with(cx, pred));
229 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
230
231 ecx.try_evaluate_added_goals()?;
236
237 ecx.add_goals(
240 GoalSource::AliasWellFormed,
241 cx.own_predicates_of(goal.predicate.def_id())
242 .iter_instantiated(cx, goal.predicate.alias.args)
243 .map(|pred| goal.with(cx, pred)),
244 );
245
246 let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
247 let error_term = match goal.predicate.alias.kind(cx) {
248 ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(),
249 ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(),
250 kind => panic!("expected projection, found {kind:?}"),
251 };
252 ecx.instantiate_normalizes_to_term(goal, error_term);
253 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
254 };
255
256 let target_item_def_id = match ecx.fetch_eligible_assoc_item(
257 goal_trait_ref,
258 goal.predicate.def_id(),
259 impl_def_id,
260 ) {
261 Ok(Some(target_item_def_id)) => target_item_def_id,
262 Ok(None) => {
263 match ecx.typing_mode() {
264 ty::TypingMode::Coherence => {
276 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
277 return ecx
278 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
279 }
280 ty::TypingMode::Analysis { .. }
282 | ty::TypingMode::Borrowck { .. }
283 | ty::TypingMode::PostBorrowckAnalysis { .. }
284 | ty::TypingMode::PostAnalysis => {
285 ecx.structurally_instantiate_normalizes_to_term(
286 goal,
287 goal.predicate.alias,
288 );
289 return ecx
290 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
291 }
292 };
293 }
294 Err(guar) => return error_response(ecx, guar),
295 };
296
297 if !cx.has_item_definition(target_item_def_id) {
298 if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
304 match ecx.typing_mode() {
305 ty::TypingMode::Coherence => {
316 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
317 return ecx
318 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
319 }
320 ty::TypingMode::Analysis { .. }
321 | ty::TypingMode::Borrowck { .. }
322 | ty::TypingMode::PostBorrowckAnalysis { .. }
323 | ty::TypingMode::PostAnalysis => {
324 ecx.structurally_instantiate_normalizes_to_term(
325 goal,
326 goal.predicate.alias,
327 );
328 return ecx
329 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
330 }
331 }
332 } else {
333 return error_response(ecx, cx.delay_bug("missing item"));
334 }
335 }
336
337 let target_container_def_id = cx.parent(target_item_def_id);
338
339 let target_args = ecx.translate_args(
350 goal,
351 impl_def_id,
352 impl_args,
353 impl_trait_ref,
354 target_container_def_id,
355 )?;
356
357 if !cx.check_args_compatible(target_item_def_id, target_args) {
358 return error_response(
359 ecx,
360 cx.delay_bug("associated item has mismatched arguments"),
361 );
362 }
363
364 let term = match goal.predicate.alias.kind(cx) {
366 ty::AliasTermKind::ProjectionTy => {
367 cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
368 }
369 ty::AliasTermKind::ProjectionConst => {
370 if cx.features().associated_const_equality() {
373 panic!("associated const projection is not supported yet")
374 } else {
375 ty::EarlyBinder::bind(
376 Const::new_error_with_message(
377 cx,
378 "associated const projection is not supported yet",
379 )
380 .into(),
381 )
382 }
383 }
384 kind => panic!("expected projection, found {kind:?}"),
385 };
386
387 ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args));
388 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
389 })
390 }
391
392 fn consider_error_guaranteed_candidate(
395 _ecx: &mut EvalCtxt<'_, D>,
396 _guar: I::ErrorGuaranteed,
397 ) -> Result<Candidate<I>, NoSolution> {
398 Err(NoSolution)
399 }
400
401 fn consider_auto_trait_candidate(
402 ecx: &mut EvalCtxt<'_, D>,
403 _goal: Goal<I, Self>,
404 ) -> Result<Candidate<I>, NoSolution> {
405 ecx.cx().delay_bug("associated types not allowed on auto traits");
406 Err(NoSolution)
407 }
408
409 fn consider_trait_alias_candidate(
410 _ecx: &mut EvalCtxt<'_, D>,
411 goal: Goal<I, Self>,
412 ) -> Result<Candidate<I>, NoSolution> {
413 panic!("trait aliases do not have associated types: {:?}", goal);
414 }
415
416 fn consider_builtin_sizedness_candidates(
417 _ecx: &mut EvalCtxt<'_, D>,
418 goal: Goal<I, Self>,
419 _sizedness: SizedTraitKind,
420 ) -> Result<Candidate<I>, NoSolution> {
421 panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
422 }
423
424 fn consider_builtin_copy_clone_candidate(
425 _ecx: &mut EvalCtxt<'_, D>,
426 goal: Goal<I, Self>,
427 ) -> Result<Candidate<I>, NoSolution> {
428 panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
429 }
430
431 fn consider_builtin_fn_ptr_trait_candidate(
432 _ecx: &mut EvalCtxt<'_, D>,
433 goal: Goal<I, Self>,
434 ) -> Result<Candidate<I>, NoSolution> {
435 panic!("`FnPtr` does not have an associated type: {:?}", goal);
436 }
437
438 fn consider_builtin_fn_trait_candidates(
439 ecx: &mut EvalCtxt<'_, D>,
440 goal: Goal<I, Self>,
441 goal_kind: ty::ClosureKind,
442 ) -> Result<Candidate<I>, NoSolution> {
443 let cx = ecx.cx();
444 let tupled_inputs_and_output =
445 match structural_traits::extract_tupled_inputs_and_output_from_callable(
446 cx,
447 goal.predicate.self_ty(),
448 goal_kind,
449 )? {
450 Some(tupled_inputs_and_output) => tupled_inputs_and_output,
451 None => {
452 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
453 }
454 };
455
456 let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
459 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
460 });
461
462 let pred = tupled_inputs_and_output
463 .map_bound(|(inputs, output)| ty::ProjectionPredicate {
464 projection_term: ty::AliasTerm::new(
465 cx,
466 goal.predicate.def_id(),
467 [goal.predicate.self_ty(), inputs],
468 ),
469 term: output.into(),
470 })
471 .upcast(cx);
472
473 Self::probe_and_consider_implied_clause(
474 ecx,
475 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
476 goal,
477 pred,
478 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
479 )
480 }
481
482 fn consider_builtin_async_fn_trait_candidates(
483 ecx: &mut EvalCtxt<'_, D>,
484 goal: Goal<I, Self>,
485 goal_kind: ty::ClosureKind,
486 ) -> Result<Candidate<I>, NoSolution> {
487 let cx = ecx.cx();
488
489 let env_region = match goal_kind {
490 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
491 ty::ClosureKind::FnOnce => Region::new_static(cx),
493 };
494 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
495 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
496 cx,
497 goal.predicate.self_ty(),
498 goal_kind,
499 env_region,
500 )?;
501
502 let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
505 |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
506 ty::TraitRef::new(
507 cx,
508 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
509 [output_ty],
510 )
511 },
512 );
513
514 let pred = tupled_inputs_and_output_and_coroutine
515 .map_bound(
516 |AsyncCallableRelevantTypes {
517 tupled_inputs_ty,
518 output_coroutine_ty,
519 coroutine_return_ty,
520 }| {
521 let (projection_term, term) = if cx
522 .is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture)
523 {
524 (
525 ty::AliasTerm::new(
526 cx,
527 goal.predicate.def_id(),
528 [goal.predicate.self_ty(), tupled_inputs_ty],
529 ),
530 output_coroutine_ty.into(),
531 )
532 } else if cx
533 .is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture)
534 {
535 (
536 ty::AliasTerm::new(
537 cx,
538 goal.predicate.def_id(),
539 [
540 I::GenericArg::from(goal.predicate.self_ty()),
541 tupled_inputs_ty.into(),
542 env_region.into(),
543 ],
544 ),
545 output_coroutine_ty.into(),
546 )
547 } else if cx
548 .is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput)
549 {
550 (
551 ty::AliasTerm::new(
552 cx,
553 goal.predicate.def_id(),
554 [
555 I::GenericArg::from(goal.predicate.self_ty()),
556 tupled_inputs_ty.into(),
557 ],
558 ),
559 coroutine_return_ty.into(),
560 )
561 } else {
562 panic!(
563 "no such associated type in `AsyncFn*`: {:?}",
564 goal.predicate.def_id()
565 )
566 };
567 ty::ProjectionPredicate { projection_term, term }
568 },
569 )
570 .upcast(cx);
571
572 Self::probe_and_consider_implied_clause(
573 ecx,
574 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
575 goal,
576 pred,
577 [goal.with(cx, output_is_sized_pred)]
578 .into_iter()
579 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
580 .map(|goal| (GoalSource::ImplWhereBound, goal)),
581 )
582 }
583
584 fn consider_builtin_async_fn_kind_helper_candidate(
585 ecx: &mut EvalCtxt<'_, D>,
586 goal: Goal<I, Self>,
587 ) -> Result<Candidate<I>, NoSolution> {
588 let [
589 closure_fn_kind_ty,
590 goal_kind_ty,
591 borrow_region,
592 tupled_inputs_ty,
593 tupled_upvars_ty,
594 coroutine_captures_by_ref_ty,
595 ] = *goal.predicate.alias.args.as_slice()
596 else {
597 panic!();
598 };
599
600 if tupled_upvars_ty.expect_ty().is_ty_var() {
602 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
603 }
604
605 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
606 return Err(NoSolution);
608 };
609 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
610 return Err(NoSolution);
611 };
612 if !closure_kind.extends(goal_kind) {
613 return Err(NoSolution);
614 }
615
616 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
617 ecx.cx(),
618 goal_kind,
619 tupled_inputs_ty.expect_ty(),
620 tupled_upvars_ty.expect_ty(),
621 coroutine_captures_by_ref_ty.expect_ty(),
622 borrow_region.expect_region(),
623 );
624
625 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
626 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into());
627 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
628 })
629 }
630
631 fn consider_builtin_tuple_candidate(
632 _ecx: &mut EvalCtxt<'_, D>,
633 goal: Goal<I, Self>,
634 ) -> Result<Candidate<I>, NoSolution> {
635 panic!("`Tuple` does not have an associated type: {:?}", goal);
636 }
637
638 fn consider_builtin_pointee_candidate(
639 ecx: &mut EvalCtxt<'_, D>,
640 goal: Goal<I, Self>,
641 ) -> Result<Candidate<I>, NoSolution> {
642 let cx = ecx.cx();
643 let metadata_def_id = cx.require_lang_item(SolverLangItem::Metadata);
644 assert_eq!(metadata_def_id, goal.predicate.def_id());
645 let metadata_ty = match goal.predicate.self_ty().kind() {
646 ty::Bool
647 | ty::Char
648 | ty::Int(..)
649 | ty::Uint(..)
650 | ty::Float(..)
651 | ty::Array(..)
652 | ty::Pat(..)
653 | ty::RawPtr(..)
654 | ty::Ref(..)
655 | ty::FnDef(..)
656 | ty::FnPtr(..)
657 | ty::Closure(..)
658 | ty::CoroutineClosure(..)
659 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
660 | ty::Coroutine(..)
661 | ty::CoroutineWitness(..)
662 | ty::Never
663 | ty::Foreign(..) => Ty::new_unit(cx),
664
665 ty::Error(e) => Ty::new_error(cx, e),
666
667 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
668
669 ty::Dynamic(_, _, ty::Dyn) => {
670 let dyn_metadata = cx.require_lang_item(SolverLangItem::DynMetadata);
671 cx.type_of(dyn_metadata)
672 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
673 }
674
675 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
676 let alias_bound_result =
681 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
682 let sized_predicate = ty::TraitRef::new(
683 cx,
684 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
685 [I::GenericArg::from(goal.predicate.self_ty())],
686 );
687 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
688 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
689 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
690 });
691 return alias_bound_result.or_else(|NoSolution| {
694 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
695 this.structurally_instantiate_normalizes_to_term(
696 goal,
697 goal.predicate.alias,
698 );
699 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
700 })
701 });
702 }
703
704 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
705 None => Ty::new_unit(cx),
706 Some(tail_ty) => {
707 Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
708 }
709 },
710 ty::Adt(_, _) => Ty::new_unit(cx),
711
712 ty::Tuple(elements) => match elements.last() {
713 None => Ty::new_unit(cx),
714 Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
715 },
716
717 ty::UnsafeBinder(_) => {
718 todo!()
720 }
721
722 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
723 | ty::Bound(..) => panic!(
724 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
725 goal.predicate.self_ty()
726 ),
727 };
728
729 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
730 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
731 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
732 })
733 }
734
735 fn consider_builtin_future_candidate(
736 ecx: &mut EvalCtxt<'_, D>,
737 goal: Goal<I, Self>,
738 ) -> Result<Candidate<I>, NoSolution> {
739 let self_ty = goal.predicate.self_ty();
740 let ty::Coroutine(def_id, args) = self_ty.kind() else {
741 return Err(NoSolution);
742 };
743
744 let cx = ecx.cx();
746 if !cx.coroutine_is_async(def_id) {
747 return Err(NoSolution);
748 }
749
750 let term = args.as_coroutine().return_ty().into();
751
752 Self::probe_and_consider_implied_clause(
753 ecx,
754 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
755 goal,
756 ty::ProjectionPredicate {
757 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
758 term,
759 }
760 .upcast(cx),
761 [],
764 )
765 }
766
767 fn consider_builtin_iterator_candidate(
768 ecx: &mut EvalCtxt<'_, D>,
769 goal: Goal<I, Self>,
770 ) -> Result<Candidate<I>, NoSolution> {
771 let self_ty = goal.predicate.self_ty();
772 let ty::Coroutine(def_id, args) = self_ty.kind() else {
773 return Err(NoSolution);
774 };
775
776 let cx = ecx.cx();
778 if !cx.coroutine_is_gen(def_id) {
779 return Err(NoSolution);
780 }
781
782 let term = args.as_coroutine().yield_ty().into();
783
784 Self::probe_and_consider_implied_clause(
785 ecx,
786 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
787 goal,
788 ty::ProjectionPredicate {
789 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
790 term,
791 }
792 .upcast(cx),
793 [],
796 )
797 }
798
799 fn consider_builtin_fused_iterator_candidate(
800 _ecx: &mut EvalCtxt<'_, D>,
801 goal: Goal<I, Self>,
802 ) -> Result<Candidate<I>, NoSolution> {
803 panic!("`FusedIterator` does not have an associated type: {:?}", goal);
804 }
805
806 fn consider_builtin_async_iterator_candidate(
807 ecx: &mut EvalCtxt<'_, D>,
808 goal: Goal<I, Self>,
809 ) -> Result<Candidate<I>, NoSolution> {
810 let self_ty = goal.predicate.self_ty();
811 let ty::Coroutine(def_id, args) = self_ty.kind() else {
812 return Err(NoSolution);
813 };
814
815 let cx = ecx.cx();
817 if !cx.coroutine_is_async_gen(def_id) {
818 return Err(NoSolution);
819 }
820
821 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
822 let expected_ty = ecx.next_ty_infer();
823 let wrapped_expected_ty = Ty::new_adt(
826 cx,
827 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
828 cx.mk_args(&[Ty::new_adt(
829 cx,
830 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
831 cx.mk_args(&[expected_ty.into()]),
832 )
833 .into()]),
834 );
835 let yield_ty = args.as_coroutine().yield_ty();
836 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
837 ecx.instantiate_normalizes_to_term(goal, expected_ty.into());
838 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
839 })
840 }
841
842 fn consider_builtin_coroutine_candidate(
843 ecx: &mut EvalCtxt<'_, D>,
844 goal: Goal<I, Self>,
845 ) -> Result<Candidate<I>, NoSolution> {
846 let self_ty = goal.predicate.self_ty();
847 let ty::Coroutine(def_id, args) = self_ty.kind() else {
848 return Err(NoSolution);
849 };
850
851 let cx = ecx.cx();
853 if !cx.is_general_coroutine(def_id) {
854 return Err(NoSolution);
855 }
856
857 let coroutine = args.as_coroutine();
858
859 let term = if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineReturn) {
860 coroutine.return_ty().into()
861 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineYield) {
862 coroutine.yield_ty().into()
863 } else {
864 panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id())
865 };
866
867 Self::probe_and_consider_implied_clause(
868 ecx,
869 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
870 goal,
871 ty::ProjectionPredicate {
872 projection_term: ty::AliasTerm::new(
873 ecx.cx(),
874 goal.predicate.def_id(),
875 [self_ty, coroutine.resume_ty()],
876 ),
877 term,
878 }
879 .upcast(cx),
880 [],
883 )
884 }
885
886 fn consider_structural_builtin_unsize_candidates(
887 _ecx: &mut EvalCtxt<'_, D>,
888 goal: Goal<I, Self>,
889 ) -> Vec<Candidate<I>> {
890 panic!("`Unsize` does not have an associated type: {:?}", goal);
891 }
892
893 fn consider_builtin_discriminant_kind_candidate(
894 ecx: &mut EvalCtxt<'_, D>,
895 goal: Goal<I, Self>,
896 ) -> Result<Candidate<I>, NoSolution> {
897 let self_ty = goal.predicate.self_ty();
898 let discriminant_ty = match self_ty.kind() {
899 ty::Bool
900 | ty::Char
901 | ty::Int(..)
902 | ty::Uint(..)
903 | ty::Float(..)
904 | ty::Array(..)
905 | ty::Pat(..)
906 | ty::RawPtr(..)
907 | ty::Ref(..)
908 | ty::FnDef(..)
909 | ty::FnPtr(..)
910 | ty::Closure(..)
911 | ty::CoroutineClosure(..)
912 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
913 | ty::Coroutine(..)
914 | ty::CoroutineWitness(..)
915 | ty::Never
916 | ty::Foreign(..)
917 | ty::Adt(_, _)
918 | ty::Str
919 | ty::Slice(_)
920 | ty::Dynamic(_, _, _)
921 | ty::Tuple(_)
922 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
923
924 ty::UnsafeBinder(_) => {
925 todo!("discr subgoal...")
927 }
928
929 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
933 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
934 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
935 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
936 });
937 }
938
939 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
940 | ty::Bound(..) => panic!(
941 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
942 goal.predicate.self_ty()
943 ),
944 };
945
946 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
947 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into());
948 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
949 })
950 }
951
952 fn consider_builtin_destruct_candidate(
953 _ecx: &mut EvalCtxt<'_, D>,
954 goal: Goal<I, Self>,
955 ) -> Result<Candidate<I>, NoSolution> {
956 panic!("`Destruct` does not have an associated type: {:?}", goal);
957 }
958
959 fn consider_builtin_transmute_candidate(
960 _ecx: &mut EvalCtxt<'_, D>,
961 goal: Goal<I, Self>,
962 ) -> Result<Candidate<I>, NoSolution> {
963 panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
964 }
965
966 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
967 _ecx: &mut EvalCtxt<'_, D>,
968 goal: Goal<I, Self>,
969 ) -> Result<Candidate<I>, NoSolution> {
970 unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
971 }
972}
973
974impl<D, I> EvalCtxt<'_, D>
975where
976 D: SolverDelegate<Interner = I>,
977 I: Interner,
978{
979 fn translate_args(
980 &mut self,
981 goal: Goal<I, ty::NormalizesTo<I>>,
982 impl_def_id: I::ImplId,
983 impl_args: I::GenericArgs,
984 impl_trait_ref: rustc_type_ir::TraitRef<I>,
985 target_container_def_id: I::DefId,
986 ) -> Result<I::GenericArgs, NoSolution> {
987 let cx = self.cx();
988 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
989 goal.predicate.alias.args
991 } else if target_container_def_id == impl_def_id.into() {
992 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
995 } else {
996 let target_args = self.fresh_args_for_item(target_container_def_id);
997 let target_trait_ref = cx
998 .impl_trait_ref(target_container_def_id.try_into().unwrap())
999 .instantiate(cx, target_args);
1000 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
1002 self.add_goals(
1005 GoalSource::Misc,
1006 cx.predicates_of(target_container_def_id)
1007 .iter_instantiated(cx, target_args)
1008 .map(|pred| goal.with(cx, pred)),
1009 );
1010 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
1011 })
1012 }
1013}