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