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 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
198 ) -> Result<Candidate<I>, NoSolution> {
199 let cx = ecx.cx();
200
201 let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
202 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
203 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
204 goal.predicate.alias.trait_ref(cx).args,
205 impl_trait_ref.skip_binder().args,
206 ) {
207 return Err(NoSolution);
208 }
209
210 let impl_polarity = cx.impl_polarity(impl_def_id);
212 match impl_polarity {
213 ty::ImplPolarity::Negative => return Err(NoSolution),
214 ty::ImplPolarity::Reservation => {
215 unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
216 }
217 ty::ImplPolarity::Positive => {}
218 };
219
220 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
221 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
222 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
223
224 ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
225
226 let where_clause_bounds = cx
227 .predicates_of(impl_def_id.into())
228 .iter_instantiated(cx, impl_args)
229 .map(|pred| goal.with(cx, pred));
230 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
231
232 ecx.try_evaluate_added_goals()?;
237
238 ecx.add_goals(
241 GoalSource::AliasWellFormed,
242 cx.own_predicates_of(goal.predicate.def_id())
243 .iter_instantiated(cx, goal.predicate.alias.args)
244 .map(|pred| goal.with(cx, pred)),
245 );
246
247 let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
248 let error_term = match goal.predicate.alias.kind(cx) {
249 ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(),
250 ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(),
251 kind => panic!("expected projection, found {kind:?}"),
252 };
253 ecx.instantiate_normalizes_to_term(goal, error_term);
254 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
255 };
256
257 let target_item_def_id = match ecx.fetch_eligible_assoc_item(
258 goal_trait_ref,
259 goal.predicate.def_id(),
260 impl_def_id,
261 ) {
262 Ok(Some(target_item_def_id)) => target_item_def_id,
263 Ok(None) => {
264 match ecx.typing_mode() {
265 ty::TypingMode::Coherence => {
277 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
278 return ecx
279 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
280 }
281 ty::TypingMode::Analysis { .. }
283 | ty::TypingMode::Borrowck { .. }
284 | ty::TypingMode::PostBorrowckAnalysis { .. }
285 | ty::TypingMode::PostAnalysis => {
286 ecx.structurally_instantiate_normalizes_to_term(
287 goal,
288 goal.predicate.alias,
289 );
290 return ecx
291 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
292 }
293 };
294 }
295 Err(guar) => return error_response(ecx, guar),
296 };
297
298 if !cx.has_item_definition(target_item_def_id) {
299 if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
305 match ecx.typing_mode() {
306 ty::TypingMode::Coherence => {
317 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
318 return then(ecx, 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 then(ecx, Certainty::Yes);
329 }
330 }
331 } else {
332 return error_response(ecx, cx.delay_bug("missing item"));
333 }
334 }
335
336 let target_container_def_id = cx.parent(target_item_def_id);
337
338 let target_args = ecx.translate_args(
349 goal,
350 impl_def_id,
351 impl_args,
352 impl_trait_ref,
353 target_container_def_id,
354 )?;
355
356 if !cx.check_args_compatible(target_item_def_id, target_args) {
357 return error_response(
358 ecx,
359 cx.delay_bug("associated item has mismatched arguments"),
360 );
361 }
362
363 let term = match goal.predicate.alias.kind(cx) {
365 ty::AliasTermKind::ProjectionTy => {
366 cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
367 }
368 ty::AliasTermKind::ProjectionConst => {
369 if cx.features().associated_const_equality() {
372 panic!("associated const projection is not supported yet")
373 } else {
374 ty::EarlyBinder::bind(
375 Const::new_error_with_message(
376 cx,
377 "associated const projection is not supported yet",
378 )
379 .into(),
380 )
381 }
382 }
383 kind => panic!("expected projection, found {kind:?}"),
384 };
385
386 ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args));
387 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
388 })
389 }
390
391 fn consider_error_guaranteed_candidate(
394 _ecx: &mut EvalCtxt<'_, D>,
395 _guar: I::ErrorGuaranteed,
396 ) -> Result<Candidate<I>, NoSolution> {
397 Err(NoSolution)
398 }
399
400 fn consider_auto_trait_candidate(
401 ecx: &mut EvalCtxt<'_, D>,
402 _goal: Goal<I, Self>,
403 ) -> Result<Candidate<I>, NoSolution> {
404 ecx.cx().delay_bug("associated types not allowed on auto traits");
405 Err(NoSolution)
406 }
407
408 fn consider_trait_alias_candidate(
409 _ecx: &mut EvalCtxt<'_, D>,
410 goal: Goal<I, Self>,
411 ) -> Result<Candidate<I>, NoSolution> {
412 panic!("trait aliases do not have associated types: {:?}", goal);
413 }
414
415 fn consider_builtin_sizedness_candidates(
416 _ecx: &mut EvalCtxt<'_, D>,
417 goal: Goal<I, Self>,
418 _sizedness: SizedTraitKind,
419 ) -> Result<Candidate<I>, NoSolution> {
420 panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
421 }
422
423 fn consider_builtin_copy_clone_candidate(
424 _ecx: &mut EvalCtxt<'_, D>,
425 goal: Goal<I, Self>,
426 ) -> Result<Candidate<I>, NoSolution> {
427 panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
428 }
429
430 fn consider_builtin_fn_ptr_trait_candidate(
431 _ecx: &mut EvalCtxt<'_, D>,
432 goal: Goal<I, Self>,
433 ) -> Result<Candidate<I>, NoSolution> {
434 panic!("`FnPtr` does not have an associated type: {:?}", goal);
435 }
436
437 fn consider_builtin_fn_trait_candidates(
438 ecx: &mut EvalCtxt<'_, D>,
439 goal: Goal<I, Self>,
440 goal_kind: ty::ClosureKind,
441 ) -> Result<Candidate<I>, NoSolution> {
442 let cx = ecx.cx();
443 let tupled_inputs_and_output =
444 match structural_traits::extract_tupled_inputs_and_output_from_callable(
445 cx,
446 goal.predicate.self_ty(),
447 goal_kind,
448 )? {
449 Some(tupled_inputs_and_output) => tupled_inputs_and_output,
450 None => {
451 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
452 }
453 };
454 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
455
456 let output_is_sized_pred =
459 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
460
461 let pred = ty::ProjectionPredicate {
462 projection_term: ty::AliasTerm::new(
463 cx,
464 goal.predicate.def_id(),
465 [goal.predicate.self_ty(), inputs],
466 ),
467 term: output.into(),
468 }
469 .upcast(cx);
470
471 Self::probe_and_consider_implied_clause(
472 ecx,
473 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
474 goal,
475 pred,
476 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
477 )
478 }
479
480 fn consider_builtin_async_fn_trait_candidates(
481 ecx: &mut EvalCtxt<'_, D>,
482 goal: Goal<I, Self>,
483 goal_kind: ty::ClosureKind,
484 ) -> Result<Candidate<I>, NoSolution> {
485 let cx = ecx.cx();
486
487 let env_region = match goal_kind {
488 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
489 ty::ClosureKind::FnOnce => Region::new_static(cx),
491 };
492 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
493 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
494 cx,
495 goal.predicate.self_ty(),
496 goal_kind,
497 env_region,
498 )?;
499 let AsyncCallableRelevantTypes {
500 tupled_inputs_ty,
501 output_coroutine_ty,
502 coroutine_return_ty,
503 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
504
505 let output_is_sized_pred = ty::TraitRef::new(
508 cx,
509 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
510 [output_coroutine_ty],
511 );
512
513 let (projection_term, term) =
514 if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture) {
515 (
516 ty::AliasTerm::new(
517 cx,
518 goal.predicate.def_id(),
519 [goal.predicate.self_ty(), tupled_inputs_ty],
520 ),
521 output_coroutine_ty.into(),
522 )
523 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture) {
524 (
525 ty::AliasTerm::new(
526 cx,
527 goal.predicate.def_id(),
528 [
529 I::GenericArg::from(goal.predicate.self_ty()),
530 tupled_inputs_ty.into(),
531 env_region.into(),
532 ],
533 ),
534 output_coroutine_ty.into(),
535 )
536 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput) {
537 (
538 ty::AliasTerm::new(
539 cx,
540 goal.predicate.def_id(),
541 [goal.predicate.self_ty(), tupled_inputs_ty],
542 ),
543 coroutine_return_ty.into(),
544 )
545 } else {
546 panic!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id())
547 };
548 let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
549
550 Self::probe_and_consider_implied_clause(
551 ecx,
552 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
553 goal,
554 pred,
555 [goal.with(cx, output_is_sized_pred)]
556 .into_iter()
557 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
558 .map(|goal| (GoalSource::ImplWhereBound, goal)),
559 )
560 }
561
562 fn consider_builtin_async_fn_kind_helper_candidate(
563 ecx: &mut EvalCtxt<'_, D>,
564 goal: Goal<I, Self>,
565 ) -> Result<Candidate<I>, NoSolution> {
566 let [
567 closure_fn_kind_ty,
568 goal_kind_ty,
569 borrow_region,
570 tupled_inputs_ty,
571 tupled_upvars_ty,
572 coroutine_captures_by_ref_ty,
573 ] = *goal.predicate.alias.args.as_slice()
574 else {
575 panic!();
576 };
577
578 if tupled_upvars_ty.expect_ty().is_ty_var() {
580 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
581 }
582
583 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
584 return Err(NoSolution);
586 };
587 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
588 return Err(NoSolution);
589 };
590 if !closure_kind.extends(goal_kind) {
591 return Err(NoSolution);
592 }
593
594 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
595 ecx.cx(),
596 goal_kind,
597 tupled_inputs_ty.expect_ty(),
598 tupled_upvars_ty.expect_ty(),
599 coroutine_captures_by_ref_ty.expect_ty(),
600 borrow_region.expect_region(),
601 );
602
603 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
604 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into());
605 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
606 })
607 }
608
609 fn consider_builtin_tuple_candidate(
610 _ecx: &mut EvalCtxt<'_, D>,
611 goal: Goal<I, Self>,
612 ) -> Result<Candidate<I>, NoSolution> {
613 panic!("`Tuple` does not have an associated type: {:?}", goal);
614 }
615
616 fn consider_builtin_pointee_candidate(
617 ecx: &mut EvalCtxt<'_, D>,
618 goal: Goal<I, Self>,
619 ) -> Result<Candidate<I>, NoSolution> {
620 let cx = ecx.cx();
621 let metadata_def_id = cx.require_lang_item(SolverLangItem::Metadata);
622 assert_eq!(metadata_def_id, goal.predicate.def_id());
623 let metadata_ty = match goal.predicate.self_ty().kind() {
624 ty::Bool
625 | ty::Char
626 | ty::Int(..)
627 | ty::Uint(..)
628 | ty::Float(..)
629 | ty::Array(..)
630 | ty::Pat(..)
631 | ty::RawPtr(..)
632 | ty::Ref(..)
633 | ty::FnDef(..)
634 | ty::FnPtr(..)
635 | ty::Closure(..)
636 | ty::CoroutineClosure(..)
637 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
638 | ty::Coroutine(..)
639 | ty::CoroutineWitness(..)
640 | ty::Never
641 | ty::Foreign(..) => Ty::new_unit(cx),
642
643 ty::Error(e) => Ty::new_error(cx, e),
644
645 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
646
647 ty::Dynamic(_, _) => {
648 let dyn_metadata = cx.require_lang_item(SolverLangItem::DynMetadata);
649 cx.type_of(dyn_metadata)
650 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
651 }
652
653 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
654 let alias_bound_result =
659 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
660 let sized_predicate = ty::TraitRef::new(
661 cx,
662 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
663 [I::GenericArg::from(goal.predicate.self_ty())],
664 );
665 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
666 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
667 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
668 });
669 return alias_bound_result.or_else(|NoSolution| {
672 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
673 this.structurally_instantiate_normalizes_to_term(
674 goal,
675 goal.predicate.alias,
676 );
677 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
678 })
679 });
680 }
681
682 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
683 None => Ty::new_unit(cx),
684 Some(tail_ty) => {
685 Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
686 }
687 },
688 ty::Adt(_, _) => Ty::new_unit(cx),
689
690 ty::Tuple(elements) => match elements.last() {
691 None => Ty::new_unit(cx),
692 Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
693 },
694
695 ty::UnsafeBinder(_) => {
696 todo!()
698 }
699
700 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
701 | ty::Bound(..) => panic!(
702 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
703 goal.predicate.self_ty()
704 ),
705 };
706
707 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
708 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
709 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
710 })
711 }
712
713 fn consider_builtin_future_candidate(
714 ecx: &mut EvalCtxt<'_, D>,
715 goal: Goal<I, Self>,
716 ) -> Result<Candidate<I>, NoSolution> {
717 let self_ty = goal.predicate.self_ty();
718 let ty::Coroutine(def_id, args) = self_ty.kind() else {
719 return Err(NoSolution);
720 };
721
722 let cx = ecx.cx();
724 if !cx.coroutine_is_async(def_id) {
725 return Err(NoSolution);
726 }
727
728 let term = args.as_coroutine().return_ty().into();
729
730 Self::probe_and_consider_implied_clause(
731 ecx,
732 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
733 goal,
734 ty::ProjectionPredicate {
735 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
736 term,
737 }
738 .upcast(cx),
739 [],
742 )
743 }
744
745 fn consider_builtin_iterator_candidate(
746 ecx: &mut EvalCtxt<'_, D>,
747 goal: Goal<I, Self>,
748 ) -> Result<Candidate<I>, NoSolution> {
749 let self_ty = goal.predicate.self_ty();
750 let ty::Coroutine(def_id, args) = self_ty.kind() else {
751 return Err(NoSolution);
752 };
753
754 let cx = ecx.cx();
756 if !cx.coroutine_is_gen(def_id) {
757 return Err(NoSolution);
758 }
759
760 let term = args.as_coroutine().yield_ty().into();
761
762 Self::probe_and_consider_implied_clause(
763 ecx,
764 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
765 goal,
766 ty::ProjectionPredicate {
767 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
768 term,
769 }
770 .upcast(cx),
771 [],
774 )
775 }
776
777 fn consider_builtin_fused_iterator_candidate(
778 _ecx: &mut EvalCtxt<'_, D>,
779 goal: Goal<I, Self>,
780 ) -> Result<Candidate<I>, NoSolution> {
781 panic!("`FusedIterator` does not have an associated type: {:?}", goal);
782 }
783
784 fn consider_builtin_async_iterator_candidate(
785 ecx: &mut EvalCtxt<'_, D>,
786 goal: Goal<I, Self>,
787 ) -> Result<Candidate<I>, NoSolution> {
788 let self_ty = goal.predicate.self_ty();
789 let ty::Coroutine(def_id, args) = self_ty.kind() else {
790 return Err(NoSolution);
791 };
792
793 let cx = ecx.cx();
795 if !cx.coroutine_is_async_gen(def_id) {
796 return Err(NoSolution);
797 }
798
799 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
800 let expected_ty = ecx.next_ty_infer();
801 let wrapped_expected_ty = Ty::new_adt(
804 cx,
805 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
806 cx.mk_args(&[Ty::new_adt(
807 cx,
808 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
809 cx.mk_args(&[expected_ty.into()]),
810 )
811 .into()]),
812 );
813 let yield_ty = args.as_coroutine().yield_ty();
814 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
815 ecx.instantiate_normalizes_to_term(goal, expected_ty.into());
816 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
817 })
818 }
819
820 fn consider_builtin_coroutine_candidate(
821 ecx: &mut EvalCtxt<'_, D>,
822 goal: Goal<I, Self>,
823 ) -> Result<Candidate<I>, NoSolution> {
824 let self_ty = goal.predicate.self_ty();
825 let ty::Coroutine(def_id, args) = self_ty.kind() else {
826 return Err(NoSolution);
827 };
828
829 let cx = ecx.cx();
831 if !cx.is_general_coroutine(def_id) {
832 return Err(NoSolution);
833 }
834
835 let coroutine = args.as_coroutine();
836
837 let term = if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineReturn) {
838 coroutine.return_ty().into()
839 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineYield) {
840 coroutine.yield_ty().into()
841 } else {
842 panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id())
843 };
844
845 Self::probe_and_consider_implied_clause(
846 ecx,
847 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
848 goal,
849 ty::ProjectionPredicate {
850 projection_term: ty::AliasTerm::new(
851 ecx.cx(),
852 goal.predicate.def_id(),
853 [self_ty, coroutine.resume_ty()],
854 ),
855 term,
856 }
857 .upcast(cx),
858 [],
861 )
862 }
863
864 fn consider_structural_builtin_unsize_candidates(
865 _ecx: &mut EvalCtxt<'_, D>,
866 goal: Goal<I, Self>,
867 ) -> Vec<Candidate<I>> {
868 panic!("`Unsize` does not have an associated type: {:?}", goal);
869 }
870
871 fn consider_builtin_discriminant_kind_candidate(
872 ecx: &mut EvalCtxt<'_, D>,
873 goal: Goal<I, Self>,
874 ) -> Result<Candidate<I>, NoSolution> {
875 let self_ty = goal.predicate.self_ty();
876 let discriminant_ty = match self_ty.kind() {
877 ty::Bool
878 | ty::Char
879 | ty::Int(..)
880 | ty::Uint(..)
881 | ty::Float(..)
882 | ty::Array(..)
883 | ty::Pat(..)
884 | ty::RawPtr(..)
885 | ty::Ref(..)
886 | ty::FnDef(..)
887 | ty::FnPtr(..)
888 | ty::Closure(..)
889 | ty::CoroutineClosure(..)
890 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
891 | ty::Coroutine(..)
892 | ty::CoroutineWitness(..)
893 | ty::Never
894 | ty::Foreign(..)
895 | ty::Adt(_, _)
896 | ty::Str
897 | ty::Slice(_)
898 | ty::Dynamic(_, _)
899 | ty::Tuple(_)
900 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
901
902 ty::UnsafeBinder(_) => {
903 todo!("discr subgoal...")
905 }
906
907 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
911 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
912 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
913 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
914 });
915 }
916
917 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
918 | ty::Bound(..) => panic!(
919 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
920 goal.predicate.self_ty()
921 ),
922 };
923
924 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
925 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into());
926 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
927 })
928 }
929
930 fn consider_builtin_destruct_candidate(
931 _ecx: &mut EvalCtxt<'_, D>,
932 goal: Goal<I, Self>,
933 ) -> Result<Candidate<I>, NoSolution> {
934 panic!("`Destruct` does not have an associated type: {:?}", goal);
935 }
936
937 fn consider_builtin_transmute_candidate(
938 _ecx: &mut EvalCtxt<'_, D>,
939 goal: Goal<I, Self>,
940 ) -> Result<Candidate<I>, NoSolution> {
941 panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
942 }
943
944 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
945 _ecx: &mut EvalCtxt<'_, D>,
946 goal: Goal<I, Self>,
947 ) -> Result<Candidate<I>, NoSolution> {
948 unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
949 }
950}
951
952impl<D, I> EvalCtxt<'_, D>
953where
954 D: SolverDelegate<Interner = I>,
955 I: Interner,
956{
957 fn translate_args(
958 &mut self,
959 goal: Goal<I, ty::NormalizesTo<I>>,
960 impl_def_id: I::ImplId,
961 impl_args: I::GenericArgs,
962 impl_trait_ref: rustc_type_ir::TraitRef<I>,
963 target_container_def_id: I::DefId,
964 ) -> Result<I::GenericArgs, NoSolution> {
965 let cx = self.cx();
966 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
967 goal.predicate.alias.args
969 } else if target_container_def_id == impl_def_id.into() {
970 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
973 } else {
974 let target_args = self.fresh_args_for_item(target_container_def_id);
975 let target_trait_ref = cx
976 .impl_trait_ref(target_container_def_id.try_into().unwrap())
977 .instantiate(cx, target_args);
978 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
980 self.add_goals(
983 GoalSource::Misc,
984 cx.predicates_of(target_container_def_id)
985 .iter_instantiated(cx, target_args)
986 .map(|pred| goal.with(cx, pred)),
987 );
988 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
989 })
990 }
991}