1mod anon_const;
2mod inherent;
3mod opaque_types;
4mod weak_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, 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 candidates = self.assemble_and_evaluate_candidates(goal);
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.merge_candidates(proven_via, candidates, |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.add_goal(GoalSource::AliasWellFormed, goal.with(cx, trait_ref));
49 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
50 })
51 })
52 }
53 ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal),
54 ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal),
55 ty::AliasTermKind::WeakTy => self.normalize_weak_type(goal),
56 ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal),
57 }
58 }
59
60 pub fn instantiate_normalizes_to_term(
66 &mut self,
67 goal: Goal<I, NormalizesTo<I>>,
68 term: I::Term,
69 ) {
70 self.eq(goal.param_env, goal.predicate.term, term)
71 .expect("expected goal term to be fully unconstrained");
72 }
73
74 pub fn structurally_instantiate_normalizes_to_term(
77 &mut self,
78 goal: Goal<I, NormalizesTo<I>>,
79 term: ty::AliasTerm<I>,
80 ) {
81 self.relate_rigid_alias_non_alias(goal.param_env, term, ty::Invariant, goal.predicate.term)
82 .expect("expected goal term to be fully unconstrained");
83 }
84}
85
86impl<D, I> assembly::GoalKind<D> for NormalizesTo<I>
87where
88 D: SolverDelegate<Interner = I>,
89 I: Interner,
90{
91 fn self_ty(self) -> I::Ty {
92 self.self_ty()
93 }
94
95 fn trait_ref(self, cx: I) -> ty::TraitRef<I> {
96 self.alias.trait_ref(cx)
97 }
98
99 fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
100 self.with_self_ty(cx, self_ty)
101 }
102
103 fn trait_def_id(self, cx: I) -> I::DefId {
104 self.trait_def_id(cx)
105 }
106
107 fn probe_and_match_goal_against_assumption(
108 ecx: &mut EvalCtxt<'_, D>,
109 source: CandidateSource<I>,
110 goal: Goal<I, Self>,
111 assumption: I::Clause,
112 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
113 ) -> Result<Candidate<I>, NoSolution> {
114 if let Some(projection_pred) = assumption.as_projection_clause() {
115 if projection_pred.item_def_id() == goal.predicate.def_id() {
116 let cx = ecx.cx();
117 if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
118 goal.predicate.alias.args,
119 projection_pred.skip_binder().projection_term.args,
120 ) {
121 return Err(NoSolution);
122 }
123 ecx.probe_trait_candidate(source).enter(|ecx| {
124 let assumption_projection_pred =
125 ecx.instantiate_binder_with_infer(projection_pred);
126 ecx.eq(
127 goal.param_env,
128 goal.predicate.alias,
129 assumption_projection_pred.projection_term,
130 )?;
131
132 ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term);
133
134 ecx.add_goals(
137 GoalSource::Misc,
138 cx.own_predicates_of(goal.predicate.def_id())
139 .iter_instantiated(cx, goal.predicate.alias.args)
140 .map(|pred| goal.with(cx, pred)),
141 );
142
143 then(ecx)
144 })
145 } else {
146 Err(NoSolution)
147 }
148 } else {
149 Err(NoSolution)
150 }
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.add_goals(
202 GoalSource::Misc,
203 cx.own_predicates_of(goal.predicate.def_id())
204 .iter_instantiated(cx, goal.predicate.alias.args)
205 .map(|pred| goal.with(cx, pred)),
206 );
207
208 let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
209 let error_term = match goal.predicate.alias.kind(cx) {
210 ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(),
211 ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(),
212 kind => panic!("expected projection, found {kind:?}"),
213 };
214 ecx.instantiate_normalizes_to_term(goal, error_term);
215 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
216 };
217
218 let target_item_def_id = match ecx.fetch_eligible_assoc_item(
222 goal_trait_ref,
223 goal.predicate.def_id(),
224 impl_def_id,
225 ) {
226 Ok(Some(target_item_def_id)) => target_item_def_id,
227 Ok(None) => {
228 return ecx
229 .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
230 }
231 Err(guar) => return error_response(ecx, guar),
232 };
233
234 if !cx.has_item_definition(target_item_def_id) {
235 return error_response(ecx, cx.delay_bug("missing item"));
236 }
237
238 let target_container_def_id = cx.parent(target_item_def_id);
239
240 let target_args = ecx.translate_args(
251 goal,
252 impl_def_id,
253 impl_args,
254 impl_trait_ref,
255 target_container_def_id,
256 )?;
257
258 if !cx.check_args_compatible(target_item_def_id, target_args) {
259 return error_response(
260 ecx,
261 cx.delay_bug("associated item has mismatched arguments"),
262 );
263 }
264
265 let term = match goal.predicate.alias.kind(cx) {
267 ty::AliasTermKind::ProjectionTy => {
268 cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
269 }
270 ty::AliasTermKind::ProjectionConst => {
271 if cx.features().associated_const_equality() {
272 panic!("associated const projection is not supported yet")
273 } else {
274 ty::EarlyBinder::bind(
275 Const::new_error_with_message(
276 cx,
277 "associated const projection is not supported yet",
278 )
279 .into(),
280 )
281 }
282 }
283 kind => panic!("expected projection, found {kind:?}"),
284 };
285
286 ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args));
287 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
288 })
289 }
290
291 fn consider_error_guaranteed_candidate(
294 _ecx: &mut EvalCtxt<'_, D>,
295 _guar: I::ErrorGuaranteed,
296 ) -> Result<Candidate<I>, NoSolution> {
297 Err(NoSolution)
298 }
299
300 fn consider_auto_trait_candidate(
301 ecx: &mut EvalCtxt<'_, D>,
302 _goal: Goal<I, Self>,
303 ) -> Result<Candidate<I>, NoSolution> {
304 ecx.cx().delay_bug("associated types not allowed on auto traits");
305 Err(NoSolution)
306 }
307
308 fn consider_trait_alias_candidate(
309 _ecx: &mut EvalCtxt<'_, D>,
310 goal: Goal<I, Self>,
311 ) -> Result<Candidate<I>, NoSolution> {
312 panic!("trait aliases do not have associated types: {:?}", goal);
313 }
314
315 fn consider_builtin_sized_candidate(
316 _ecx: &mut EvalCtxt<'_, D>,
317 goal: Goal<I, Self>,
318 ) -> Result<Candidate<I>, NoSolution> {
319 panic!("`Sized` does not have an associated type: {:?}", goal);
320 }
321
322 fn consider_builtin_copy_clone_candidate(
323 _ecx: &mut EvalCtxt<'_, D>,
324 goal: Goal<I, Self>,
325 ) -> Result<Candidate<I>, NoSolution> {
326 panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
327 }
328
329 fn consider_builtin_fn_ptr_trait_candidate(
330 _ecx: &mut EvalCtxt<'_, D>,
331 goal: Goal<I, Self>,
332 ) -> Result<Candidate<I>, NoSolution> {
333 panic!("`FnPtr` does not have an associated type: {:?}", goal);
334 }
335
336 fn consider_builtin_fn_trait_candidates(
337 ecx: &mut EvalCtxt<'_, D>,
338 goal: Goal<I, Self>,
339 goal_kind: ty::ClosureKind,
340 ) -> Result<Candidate<I>, NoSolution> {
341 let cx = ecx.cx();
342 let tupled_inputs_and_output =
343 match structural_traits::extract_tupled_inputs_and_output_from_callable(
344 cx,
345 goal.predicate.self_ty(),
346 goal_kind,
347 )? {
348 Some(tupled_inputs_and_output) => tupled_inputs_and_output,
349 None => {
350 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
351 }
352 };
353
354 let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
357 ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output])
358 });
359
360 let pred = tupled_inputs_and_output
361 .map_bound(|(inputs, output)| ty::ProjectionPredicate {
362 projection_term: ty::AliasTerm::new(
363 cx,
364 goal.predicate.def_id(),
365 [goal.predicate.self_ty(), inputs],
366 ),
367 term: output.into(),
368 })
369 .upcast(cx);
370
371 Self::probe_and_consider_implied_clause(
372 ecx,
373 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
374 goal,
375 pred,
376 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
377 )
378 }
379
380 fn consider_builtin_async_fn_trait_candidates(
381 ecx: &mut EvalCtxt<'_, D>,
382 goal: Goal<I, Self>,
383 goal_kind: ty::ClosureKind,
384 ) -> Result<Candidate<I>, NoSolution> {
385 let cx = ecx.cx();
386
387 let env_region = match goal_kind {
388 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
389 ty::ClosureKind::FnOnce => Region::new_static(cx),
391 };
392 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
393 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
394 cx,
395 goal.predicate.self_ty(),
396 goal_kind,
397 env_region,
398 )?;
399
400 let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
403 |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
404 ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output_ty])
405 },
406 );
407
408 let pred = tupled_inputs_and_output_and_coroutine
409 .map_bound(
410 |AsyncCallableRelevantTypes {
411 tupled_inputs_ty,
412 output_coroutine_ty,
413 coroutine_return_ty,
414 }| {
415 let (projection_term, term) = if cx
416 .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallOnceFuture)
417 {
418 (
419 ty::AliasTerm::new(
420 cx,
421 goal.predicate.def_id(),
422 [goal.predicate.self_ty(), tupled_inputs_ty],
423 ),
424 output_coroutine_ty.into(),
425 )
426 } else if cx
427 .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallRefFuture)
428 {
429 (
430 ty::AliasTerm::new(
431 cx,
432 goal.predicate.def_id(),
433 [
434 I::GenericArg::from(goal.predicate.self_ty()),
435 tupled_inputs_ty.into(),
436 env_region.into(),
437 ],
438 ),
439 output_coroutine_ty.into(),
440 )
441 } else if cx.is_lang_item(
442 goal.predicate.def_id(),
443 TraitSolverLangItem::AsyncFnOnceOutput,
444 ) {
445 (
446 ty::AliasTerm::new(
447 cx,
448 goal.predicate.def_id(),
449 [
450 I::GenericArg::from(goal.predicate.self_ty()),
451 tupled_inputs_ty.into(),
452 ],
453 ),
454 coroutine_return_ty.into(),
455 )
456 } else {
457 panic!(
458 "no such associated type in `AsyncFn*`: {:?}",
459 goal.predicate.def_id()
460 )
461 };
462 ty::ProjectionPredicate { projection_term, term }
463 },
464 )
465 .upcast(cx);
466
467 Self::probe_and_consider_implied_clause(
468 ecx,
469 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
470 goal,
471 pred,
472 [goal.with(cx, output_is_sized_pred)]
473 .into_iter()
474 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
475 .map(|goal| (GoalSource::ImplWhereBound, goal)),
476 )
477 }
478
479 fn consider_builtin_async_fn_kind_helper_candidate(
480 ecx: &mut EvalCtxt<'_, D>,
481 goal: Goal<I, Self>,
482 ) -> Result<Candidate<I>, NoSolution> {
483 let [
484 closure_fn_kind_ty,
485 goal_kind_ty,
486 borrow_region,
487 tupled_inputs_ty,
488 tupled_upvars_ty,
489 coroutine_captures_by_ref_ty,
490 ] = *goal.predicate.alias.args.as_slice()
491 else {
492 panic!();
493 };
494
495 if tupled_upvars_ty.expect_ty().is_ty_var() {
497 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
498 }
499
500 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
501 return Err(NoSolution);
503 };
504 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
505 return Err(NoSolution);
506 };
507 if !closure_kind.extends(goal_kind) {
508 return Err(NoSolution);
509 }
510
511 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
512 ecx.cx(),
513 goal_kind,
514 tupled_inputs_ty.expect_ty(),
515 tupled_upvars_ty.expect_ty(),
516 coroutine_captures_by_ref_ty.expect_ty(),
517 borrow_region.expect_region(),
518 );
519
520 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
521 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into());
522 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
523 })
524 }
525
526 fn consider_builtin_tuple_candidate(
527 _ecx: &mut EvalCtxt<'_, D>,
528 goal: Goal<I, Self>,
529 ) -> Result<Candidate<I>, NoSolution> {
530 panic!("`Tuple` does not have an associated type: {:?}", goal);
531 }
532
533 fn consider_builtin_pointee_candidate(
534 ecx: &mut EvalCtxt<'_, D>,
535 goal: Goal<I, Self>,
536 ) -> Result<Candidate<I>, NoSolution> {
537 let cx = ecx.cx();
538 let metadata_def_id = cx.require_lang_item(TraitSolverLangItem::Metadata);
539 assert_eq!(metadata_def_id, goal.predicate.def_id());
540 let metadata_ty = match goal.predicate.self_ty().kind() {
541 ty::Bool
542 | ty::Char
543 | ty::Int(..)
544 | ty::Uint(..)
545 | ty::Float(..)
546 | ty::Array(..)
547 | ty::Pat(..)
548 | ty::RawPtr(..)
549 | ty::Ref(..)
550 | ty::FnDef(..)
551 | ty::FnPtr(..)
552 | ty::Closure(..)
553 | ty::CoroutineClosure(..)
554 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
555 | ty::Coroutine(..)
556 | ty::CoroutineWitness(..)
557 | ty::Never
558 | ty::Foreign(..)
559 | ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(cx),
560
561 ty::Error(e) => Ty::new_error(cx, e),
562
563 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
564
565 ty::Dynamic(_, _, ty::Dyn) => {
566 let dyn_metadata = cx.require_lang_item(TraitSolverLangItem::DynMetadata);
567 cx.type_of(dyn_metadata)
568 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
569 }
570
571 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
572 let alias_bound_result =
577 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
578 let sized_predicate = ty::TraitRef::new(
579 cx,
580 cx.require_lang_item(TraitSolverLangItem::Sized),
581 [I::GenericArg::from(goal.predicate.self_ty())],
582 );
583 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
584 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
585 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
586 });
587 return alias_bound_result.or_else(|NoSolution| {
590 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
591 this.structurally_instantiate_normalizes_to_term(
592 goal,
593 goal.predicate.alias,
594 );
595 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
596 })
597 });
598 }
599
600 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
601 None => Ty::new_unit(cx),
602 Some(tail_ty) => {
603 Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)])
604 }
605 },
606 ty::Adt(_, _) => Ty::new_unit(cx),
607
608 ty::Tuple(elements) => match elements.last() {
609 None => Ty::new_unit(cx),
610 Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
611 },
612
613 ty::UnsafeBinder(_) => {
614 todo!()
616 }
617
618 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
619 | ty::Bound(..) => panic!(
620 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
621 goal.predicate.self_ty()
622 ),
623 };
624
625 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
626 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
627 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
628 })
629 }
630
631 fn consider_builtin_future_candidate(
632 ecx: &mut EvalCtxt<'_, D>,
633 goal: Goal<I, Self>,
634 ) -> Result<Candidate<I>, NoSolution> {
635 let self_ty = goal.predicate.self_ty();
636 let ty::Coroutine(def_id, args) = self_ty.kind() else {
637 return Err(NoSolution);
638 };
639
640 let cx = ecx.cx();
642 if !cx.coroutine_is_async(def_id) {
643 return Err(NoSolution);
644 }
645
646 let term = args.as_coroutine().return_ty().into();
647
648 Self::probe_and_consider_implied_clause(
649 ecx,
650 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
651 goal,
652 ty::ProjectionPredicate {
653 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
654 term,
655 }
656 .upcast(cx),
657 [],
660 )
661 }
662
663 fn consider_builtin_iterator_candidate(
664 ecx: &mut EvalCtxt<'_, D>,
665 goal: Goal<I, Self>,
666 ) -> Result<Candidate<I>, NoSolution> {
667 let self_ty = goal.predicate.self_ty();
668 let ty::Coroutine(def_id, args) = self_ty.kind() else {
669 return Err(NoSolution);
670 };
671
672 let cx = ecx.cx();
674 if !cx.coroutine_is_gen(def_id) {
675 return Err(NoSolution);
676 }
677
678 let term = args.as_coroutine().yield_ty().into();
679
680 Self::probe_and_consider_implied_clause(
681 ecx,
682 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
683 goal,
684 ty::ProjectionPredicate {
685 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]),
686 term,
687 }
688 .upcast(cx),
689 [],
692 )
693 }
694
695 fn consider_builtin_fused_iterator_candidate(
696 _ecx: &mut EvalCtxt<'_, D>,
697 goal: Goal<I, Self>,
698 ) -> Result<Candidate<I>, NoSolution> {
699 panic!("`FusedIterator` does not have an associated type: {:?}", goal);
700 }
701
702 fn consider_builtin_async_iterator_candidate(
703 ecx: &mut EvalCtxt<'_, D>,
704 goal: Goal<I, Self>,
705 ) -> Result<Candidate<I>, NoSolution> {
706 let self_ty = goal.predicate.self_ty();
707 let ty::Coroutine(def_id, args) = self_ty.kind() else {
708 return Err(NoSolution);
709 };
710
711 let cx = ecx.cx();
713 if !cx.coroutine_is_async_gen(def_id) {
714 return Err(NoSolution);
715 }
716
717 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
718 let expected_ty = ecx.next_ty_infer();
719 let wrapped_expected_ty = Ty::new_adt(
722 cx,
723 cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Poll)),
724 cx.mk_args(&[Ty::new_adt(
725 cx,
726 cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Option)),
727 cx.mk_args(&[expected_ty.into()]),
728 )
729 .into()]),
730 );
731 let yield_ty = args.as_coroutine().yield_ty();
732 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
733 ecx.instantiate_normalizes_to_term(goal, expected_ty.into());
734 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
735 })
736 }
737
738 fn consider_builtin_coroutine_candidate(
739 ecx: &mut EvalCtxt<'_, D>,
740 goal: Goal<I, Self>,
741 ) -> Result<Candidate<I>, NoSolution> {
742 let self_ty = goal.predicate.self_ty();
743 let ty::Coroutine(def_id, args) = self_ty.kind() else {
744 return Err(NoSolution);
745 };
746
747 let cx = ecx.cx();
749 if !cx.is_general_coroutine(def_id) {
750 return Err(NoSolution);
751 }
752
753 let coroutine = args.as_coroutine();
754
755 let term = if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn)
756 {
757 coroutine.return_ty().into()
758 } else if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) {
759 coroutine.yield_ty().into()
760 } else {
761 panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id())
762 };
763
764 Self::probe_and_consider_implied_clause(
765 ecx,
766 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
767 goal,
768 ty::ProjectionPredicate {
769 projection_term: ty::AliasTerm::new(
770 ecx.cx(),
771 goal.predicate.def_id(),
772 [self_ty, coroutine.resume_ty()],
773 ),
774 term,
775 }
776 .upcast(cx),
777 [],
780 )
781 }
782
783 fn consider_structural_builtin_unsize_candidates(
784 _ecx: &mut EvalCtxt<'_, D>,
785 goal: Goal<I, Self>,
786 ) -> Vec<Candidate<I>> {
787 panic!("`Unsize` does not have an associated type: {:?}", goal);
788 }
789
790 fn consider_builtin_discriminant_kind_candidate(
791 ecx: &mut EvalCtxt<'_, D>,
792 goal: Goal<I, Self>,
793 ) -> Result<Candidate<I>, NoSolution> {
794 let self_ty = goal.predicate.self_ty();
795 let discriminant_ty = match self_ty.kind() {
796 ty::Bool
797 | ty::Char
798 | ty::Int(..)
799 | ty::Uint(..)
800 | ty::Float(..)
801 | ty::Array(..)
802 | ty::Pat(..)
803 | ty::RawPtr(..)
804 | ty::Ref(..)
805 | ty::FnDef(..)
806 | ty::FnPtr(..)
807 | ty::Closure(..)
808 | ty::CoroutineClosure(..)
809 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
810 | ty::Coroutine(..)
811 | ty::CoroutineWitness(..)
812 | ty::Never
813 | ty::Foreign(..)
814 | ty::Adt(_, _)
815 | ty::Str
816 | ty::Slice(_)
817 | ty::Dynamic(_, _, _)
818 | ty::Tuple(_)
819 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
820
821 ty::UnsafeBinder(_) => {
822 todo!("discr subgoal...")
824 }
825
826 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
830 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
831 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
832 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
833 });
834 }
835
836 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
837 | ty::Bound(..) => panic!(
838 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
839 goal.predicate.self_ty()
840 ),
841 };
842
843 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
844 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into());
845 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
846 })
847 }
848
849 fn consider_builtin_async_destruct_candidate(
850 ecx: &mut EvalCtxt<'_, D>,
851 goal: Goal<I, Self>,
852 ) -> Result<Candidate<I>, NoSolution> {
853 let self_ty = goal.predicate.self_ty();
854 let async_destructor_ty = match self_ty.kind() {
855 ty::Bool
856 | ty::Char
857 | ty::Int(..)
858 | ty::Uint(..)
859 | ty::Float(..)
860 | ty::Array(..)
861 | ty::RawPtr(..)
862 | ty::Ref(..)
863 | ty::FnDef(..)
864 | ty::FnPtr(..)
865 | ty::Closure(..)
866 | ty::CoroutineClosure(..)
867 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
868 | ty::Never
869 | ty::Adt(_, _)
870 | ty::Str
871 | ty::Slice(_)
872 | ty::Tuple(_)
873 | ty::Error(_) => self_ty.async_destructor_ty(ecx.cx()),
874
875 ty::UnsafeBinder(_) => {
876 todo!()
878 }
879
880 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
884 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
885 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
886 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
887 });
888 }
889
890 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
891 | ty::Foreign(..)
892 | ty::Bound(..) => panic!(
893 "unexpected self ty `{:?}` when normalizing `<T as AsyncDestruct>::AsyncDestructor`",
894 goal.predicate.self_ty()
895 ),
896
897 ty::Pat(..) | ty::Dynamic(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => panic!(
898 "`consider_builtin_async_destruct_candidate` is not yet implemented for type: {self_ty:?}"
899 ),
900 };
901
902 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
903 ecx.eq(goal.param_env, goal.predicate.term, async_destructor_ty.into())
904 .expect("expected goal term to be fully unconstrained");
905 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
906 })
907 }
908
909 fn consider_builtin_destruct_candidate(
910 _ecx: &mut EvalCtxt<'_, D>,
911 goal: Goal<I, Self>,
912 ) -> Result<Candidate<I>, NoSolution> {
913 panic!("`Destruct` does not have an associated type: {:?}", goal);
914 }
915
916 fn consider_builtin_transmute_candidate(
917 _ecx: &mut EvalCtxt<'_, D>,
918 goal: Goal<I, Self>,
919 ) -> Result<Candidate<I>, NoSolution> {
920 panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
921 }
922
923 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
924 _ecx: &mut EvalCtxt<'_, D>,
925 goal: Goal<I, Self>,
926 ) -> Result<Candidate<I>, NoSolution> {
927 unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
928 }
929}
930
931impl<D, I> EvalCtxt<'_, D>
932where
933 D: SolverDelegate<Interner = I>,
934 I: Interner,
935{
936 fn translate_args(
937 &mut self,
938 goal: Goal<I, ty::NormalizesTo<I>>,
939 impl_def_id: I::DefId,
940 impl_args: I::GenericArgs,
941 impl_trait_ref: rustc_type_ir::TraitRef<I>,
942 target_container_def_id: I::DefId,
943 ) -> Result<I::GenericArgs, NoSolution> {
944 let cx = self.cx();
945 Ok(if target_container_def_id == impl_trait_ref.def_id {
946 goal.predicate.alias.args
948 } else if target_container_def_id == impl_def_id {
949 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, impl_args)
952 } else {
953 let target_args = self.fresh_args_for_item(target_container_def_id);
954 let target_trait_ref =
955 cx.impl_trait_ref(target_container_def_id).instantiate(cx, target_args);
956 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
958 self.add_goals(
961 GoalSource::Misc,
962 cx.predicates_of(target_container_def_id)
963 .iter_instantiated(cx, target_args)
964 .map(|pred| goal.with(cx, pred)),
965 );
966 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, target_args)
967 })
968 }
969}