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
455 let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
458 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output])
459 });
460
461 let pred = tupled_inputs_and_output
462 .map_bound(|(inputs, output)| ty::ProjectionPredicate {
463 projection_term: ty::AliasTerm::new(
464 cx,
465 goal.predicate.def_id(),
466 [goal.predicate.self_ty(), inputs],
467 ),
468 term: output.into(),
469 })
470 .upcast(cx);
471
472 Self::probe_and_consider_implied_clause(
473 ecx,
474 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
475 goal,
476 pred,
477 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
478 )
479 }
480
481 fn consider_builtin_async_fn_trait_candidates(
482 ecx: &mut EvalCtxt<'_, D>,
483 goal: Goal<I, Self>,
484 goal_kind: ty::ClosureKind,
485 ) -> Result<Candidate<I>, NoSolution> {
486 let cx = ecx.cx();
487
488 let env_region = match goal_kind {
489 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
490 ty::ClosureKind::FnOnce => Region::new_static(cx),
492 };
493 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
494 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
495 cx,
496 goal.predicate.self_ty(),
497 goal_kind,
498 env_region,
499 )?;
500
501 let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
504 |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
505 ty::TraitRef::new(
506 cx,
507 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
508 [output_ty],
509 )
510 },
511 );
512
513 let pred = tupled_inputs_and_output_and_coroutine
514 .map_bound(
515 |AsyncCallableRelevantTypes {
516 tupled_inputs_ty,
517 output_coroutine_ty,
518 coroutine_return_ty,
519 }| {
520 let (projection_term, term) = if cx
521 .is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture)
522 {
523 (
524 ty::AliasTerm::new(
525 cx,
526 goal.predicate.def_id(),
527 [goal.predicate.self_ty(), tupled_inputs_ty],
528 ),
529 output_coroutine_ty.into(),
530 )
531 } else if cx
532 .is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture)
533 {
534 (
535 ty::AliasTerm::new(
536 cx,
537 goal.predicate.def_id(),
538 [
539 I::GenericArg::from(goal.predicate.self_ty()),
540 tupled_inputs_ty.into(),
541 env_region.into(),
542 ],
543 ),
544 output_coroutine_ty.into(),
545 )
546 } else if cx
547 .is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput)
548 {
549 (
550 ty::AliasTerm::new(
551 cx,
552 goal.predicate.def_id(),
553 [
554 I::GenericArg::from(goal.predicate.self_ty()),
555 tupled_inputs_ty.into(),
556 ],
557 ),
558 coroutine_return_ty.into(),
559 )
560 } else {
561 panic!(
562 "no such associated type in `AsyncFn*`: {:?}",
563 goal.predicate.def_id()
564 )
565 };
566 ty::ProjectionPredicate { projection_term, term }
567 },
568 )
569 .upcast(cx);
570
571 Self::probe_and_consider_implied_clause(
572 ecx,
573 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
574 goal,
575 pred,
576 [goal.with(cx, output_is_sized_pred)]
577 .into_iter()
578 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
579 .map(|goal| (GoalSource::ImplWhereBound, goal)),
580 )
581 }
582
583 fn consider_builtin_async_fn_kind_helper_candidate(
584 ecx: &mut EvalCtxt<'_, D>,
585 goal: Goal<I, Self>,
586 ) -> Result<Candidate<I>, NoSolution> {
587 let [
588 closure_fn_kind_ty,
589 goal_kind_ty,
590 borrow_region,
591 tupled_inputs_ty,
592 tupled_upvars_ty,
593 coroutine_captures_by_ref_ty,
594 ] = *goal.predicate.alias.args.as_slice()
595 else {
596 panic!();
597 };
598
599 if tupled_upvars_ty.expect_ty().is_ty_var() {
601 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
602 }
603
604 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
605 return Err(NoSolution);
607 };
608 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
609 return Err(NoSolution);
610 };
611 if !closure_kind.extends(goal_kind) {
612 return Err(NoSolution);
613 }
614
615 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
616 ecx.cx(),
617 goal_kind,
618 tupled_inputs_ty.expect_ty(),
619 tupled_upvars_ty.expect_ty(),
620 coroutine_captures_by_ref_ty.expect_ty(),
621 borrow_region.expect_region(),
622 );
623
624 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
625 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into());
626 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
627 })
628 }
629
630 fn consider_builtin_tuple_candidate(
631 _ecx: &mut EvalCtxt<'_, D>,
632 goal: Goal<I, Self>,
633 ) -> Result<Candidate<I>, NoSolution> {
634 panic!("`Tuple` does not have an associated type: {:?}", goal);
635 }
636
637 fn consider_builtin_pointee_candidate(
638 ecx: &mut EvalCtxt<'_, D>,
639 goal: Goal<I, Self>,
640 ) -> Result<Candidate<I>, NoSolution> {
641 let cx = ecx.cx();
642 let metadata_def_id = cx.require_lang_item(SolverLangItem::Metadata);
643 assert_eq!(metadata_def_id, goal.predicate.def_id());
644 let metadata_ty = match goal.predicate.self_ty().kind() {
645 ty::Bool
646 | ty::Char
647 | ty::Int(..)
648 | ty::Uint(..)
649 | ty::Float(..)
650 | ty::Array(..)
651 | ty::Pat(..)
652 | ty::RawPtr(..)
653 | ty::Ref(..)
654 | ty::FnDef(..)
655 | ty::FnPtr(..)
656 | ty::Closure(..)
657 | ty::CoroutineClosure(..)
658 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
659 | ty::Coroutine(..)
660 | ty::CoroutineWitness(..)
661 | ty::Never
662 | ty::Foreign(..) => Ty::new_unit(cx),
663
664 ty::Error(e) => Ty::new_error(cx, e),
665
666 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
667
668 ty::Dynamic(_, _, ty::Dyn) => {
669 let dyn_metadata = cx.require_lang_item(SolverLangItem::DynMetadata);
670 cx.type_of(dyn_metadata)
671 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
672 }
673
674 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
675 let alias_bound_result =
680 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
681 let sized_predicate = ty::TraitRef::new(
682 cx,
683 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
684 [I::GenericArg::from(goal.predicate.self_ty())],
685 );
686 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
687 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
688 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
689 });
690 return alias_bound_result.or_else(|NoSolution| {
693 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
694 this.structurally_instantiate_normalizes_to_term(
695 goal,
696 goal.predicate.alias,
697 );
698 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
699 })
700 });
701 }
702
703 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
704 None => Ty::new_unit(cx),
705 Some(tail_ty) => {
706 Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
707 }
708 },
709 ty::Adt(_, _) => Ty::new_unit(cx),
710
711 ty::Tuple(elements) => match elements.last() {
712 None => Ty::new_unit(cx),
713 Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
714 },
715
716 ty::UnsafeBinder(_) => {
717 todo!()
719 }
720
721 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
722 | ty::Bound(..) => panic!(
723 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
724 goal.predicate.self_ty()
725 ),
726 };
727
728 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
729 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
730 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
731 })
732 }
733
734 fn consider_builtin_future_candidate(
735 ecx: &mut EvalCtxt<'_, D>,
736 goal: Goal<I, Self>,
737 ) -> Result<Candidate<I>, NoSolution> {
738 let self_ty = goal.predicate.self_ty();
739 let ty::Coroutine(def_id, args) = self_ty.kind() else {
740 return Err(NoSolution);
741 };
742
743 let cx = ecx.cx();
745 if !cx.coroutine_is_async(def_id) {
746 return Err(NoSolution);
747 }
748
749 let term = args.as_coroutine().return_ty().into();
750
751 Self::probe_and_consider_implied_clause(
752 ecx,
753 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
754 goal,
755 ty::ProjectionPredicate {
756 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
757 term,
758 }
759 .upcast(cx),
760 [],
763 )
764 }
765
766 fn consider_builtin_iterator_candidate(
767 ecx: &mut EvalCtxt<'_, D>,
768 goal: Goal<I, Self>,
769 ) -> Result<Candidate<I>, NoSolution> {
770 let self_ty = goal.predicate.self_ty();
771 let ty::Coroutine(def_id, args) = self_ty.kind() else {
772 return Err(NoSolution);
773 };
774
775 let cx = ecx.cx();
777 if !cx.coroutine_is_gen(def_id) {
778 return Err(NoSolution);
779 }
780
781 let term = args.as_coroutine().yield_ty().into();
782
783 Self::probe_and_consider_implied_clause(
784 ecx,
785 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
786 goal,
787 ty::ProjectionPredicate {
788 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
789 term,
790 }
791 .upcast(cx),
792 [],
795 )
796 }
797
798 fn consider_builtin_fused_iterator_candidate(
799 _ecx: &mut EvalCtxt<'_, D>,
800 goal: Goal<I, Self>,
801 ) -> Result<Candidate<I>, NoSolution> {
802 panic!("`FusedIterator` does not have an associated type: {:?}", goal);
803 }
804
805 fn consider_builtin_async_iterator_candidate(
806 ecx: &mut EvalCtxt<'_, D>,
807 goal: Goal<I, Self>,
808 ) -> Result<Candidate<I>, NoSolution> {
809 let self_ty = goal.predicate.self_ty();
810 let ty::Coroutine(def_id, args) = self_ty.kind() else {
811 return Err(NoSolution);
812 };
813
814 let cx = ecx.cx();
816 if !cx.coroutine_is_async_gen(def_id) {
817 return Err(NoSolution);
818 }
819
820 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
821 let expected_ty = ecx.next_ty_infer();
822 let wrapped_expected_ty = Ty::new_adt(
825 cx,
826 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
827 cx.mk_args(&[Ty::new_adt(
828 cx,
829 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
830 cx.mk_args(&[expected_ty.into()]),
831 )
832 .into()]),
833 );
834 let yield_ty = args.as_coroutine().yield_ty();
835 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
836 ecx.instantiate_normalizes_to_term(goal, expected_ty.into());
837 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
838 })
839 }
840
841 fn consider_builtin_coroutine_candidate(
842 ecx: &mut EvalCtxt<'_, D>,
843 goal: Goal<I, Self>,
844 ) -> Result<Candidate<I>, NoSolution> {
845 let self_ty = goal.predicate.self_ty();
846 let ty::Coroutine(def_id, args) = self_ty.kind() else {
847 return Err(NoSolution);
848 };
849
850 let cx = ecx.cx();
852 if !cx.is_general_coroutine(def_id) {
853 return Err(NoSolution);
854 }
855
856 let coroutine = args.as_coroutine();
857
858 let term = if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineReturn) {
859 coroutine.return_ty().into()
860 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineYield) {
861 coroutine.yield_ty().into()
862 } else {
863 panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id())
864 };
865
866 Self::probe_and_consider_implied_clause(
867 ecx,
868 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
869 goal,
870 ty::ProjectionPredicate {
871 projection_term: ty::AliasTerm::new(
872 ecx.cx(),
873 goal.predicate.def_id(),
874 [self_ty, coroutine.resume_ty()],
875 ),
876 term,
877 }
878 .upcast(cx),
879 [],
882 )
883 }
884
885 fn consider_structural_builtin_unsize_candidates(
886 _ecx: &mut EvalCtxt<'_, D>,
887 goal: Goal<I, Self>,
888 ) -> Vec<Candidate<I>> {
889 panic!("`Unsize` does not have an associated type: {:?}", goal);
890 }
891
892 fn consider_builtin_discriminant_kind_candidate(
893 ecx: &mut EvalCtxt<'_, D>,
894 goal: Goal<I, Self>,
895 ) -> Result<Candidate<I>, NoSolution> {
896 let self_ty = goal.predicate.self_ty();
897 let discriminant_ty = match self_ty.kind() {
898 ty::Bool
899 | ty::Char
900 | ty::Int(..)
901 | ty::Uint(..)
902 | ty::Float(..)
903 | ty::Array(..)
904 | ty::Pat(..)
905 | ty::RawPtr(..)
906 | ty::Ref(..)
907 | ty::FnDef(..)
908 | ty::FnPtr(..)
909 | ty::Closure(..)
910 | ty::CoroutineClosure(..)
911 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
912 | ty::Coroutine(..)
913 | ty::CoroutineWitness(..)
914 | ty::Never
915 | ty::Foreign(..)
916 | ty::Adt(_, _)
917 | ty::Str
918 | ty::Slice(_)
919 | ty::Dynamic(_, _, _)
920 | ty::Tuple(_)
921 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
922
923 ty::UnsafeBinder(_) => {
924 todo!("discr subgoal...")
926 }
927
928 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
932 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
933 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
934 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
935 });
936 }
937
938 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
939 | ty::Bound(..) => panic!(
940 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
941 goal.predicate.self_ty()
942 ),
943 };
944
945 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
946 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into());
947 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
948 })
949 }
950
951 fn consider_builtin_destruct_candidate(
952 _ecx: &mut EvalCtxt<'_, D>,
953 goal: Goal<I, Self>,
954 ) -> Result<Candidate<I>, NoSolution> {
955 panic!("`Destruct` does not have an associated type: {:?}", goal);
956 }
957
958 fn consider_builtin_transmute_candidate(
959 _ecx: &mut EvalCtxt<'_, D>,
960 goal: Goal<I, Self>,
961 ) -> Result<Candidate<I>, NoSolution> {
962 panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
963 }
964
965 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
966 _ecx: &mut EvalCtxt<'_, D>,
967 goal: Goal<I, Self>,
968 ) -> Result<Candidate<I>, NoSolution> {
969 unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
970 }
971}
972
973impl<D, I> EvalCtxt<'_, D>
974where
975 D: SolverDelegate<Interner = I>,
976 I: Interner,
977{
978 fn translate_args(
979 &mut self,
980 goal: Goal<I, ty::NormalizesTo<I>>,
981 impl_def_id: I::ImplId,
982 impl_args: I::GenericArgs,
983 impl_trait_ref: rustc_type_ir::TraitRef<I>,
984 target_container_def_id: I::DefId,
985 ) -> Result<I::GenericArgs, NoSolution> {
986 let cx = self.cx();
987 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
988 goal.predicate.alias.args
990 } else if target_container_def_id == impl_def_id.into() {
991 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
994 } else {
995 let target_args = self.fresh_args_for_item(target_container_def_id);
996 let target_trait_ref = cx
997 .impl_trait_ref(target_container_def_id.try_into().unwrap())
998 .instantiate(cx, target_args);
999 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
1001 self.add_goals(
1004 GoalSource::Misc,
1005 cx.predicates_of(target_container_def_id)
1006 .iter_instantiated(cx, target_args)
1007 .map(|pred| goal.with(cx, pred)),
1008 );
1009 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
1010 })
1011 }
1012}