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