1use std::debug_assert_matches;
2
3use rustc_type_ir::fast_reject::DeepRejectCtxt;
4use rustc_type_ir::inherent::*;
5use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem};
6use rustc_type_ir::solve::{
7 FetchEligibleAssocItemResponse, NoSolutionOrRerunNonErased, QueryResultOrRerunNonErased,
8 RerunNonErased, RerunReason, RerunResultExt,
9};
10use rustc_type_ir::{
11 self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Region, Unnormalized, Upcast as _,
12};
13use tracing::instrument;
14
15use crate::delegate::SolverDelegate;
16use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
17use crate::solve::assembly::{self, Candidate};
18use crate::solve::inspect::ProbeKind;
19use crate::solve::{
20 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeInfo,
21 NoSolution, SizedTraitKind,
22};
23
24impl<D, I> EvalCtxt<'_, D>
25where
26 D: SolverDelegate<Interner = I>,
27 I: Interner,
28{
29 x;#[instrument(level = "trace", skip(self), ret)]
30 pub(super) fn compute_normalizes_to_goal(
31 &mut self,
32 goal: Goal<I, NormalizesTo<I>>,
33 ) -> QueryResultOrRerunNonErased<I> {
34 debug_assert!(self.term_is_fully_unconstrained(goal));
35 debug_assert_matches!(
36 goal.predicate.alias.kind,
37 ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. }
38 );
39
40 let cx = self.cx();
41
42 let trait_ref = goal.predicate.alias.trait_ref(cx);
43 let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
44 let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(cx, trait_ref);
45 ecx.compute_trait_goal(trait_goal)
46 })?;
47 self.assemble_and_merge_candidates(
48 proven_via,
49 goal,
50 |ecx| {
51 for arg in goal.predicate.alias.own_args(cx).iter() {
61 let Some(term) = arg.as_term() else {
62 continue;
63 };
64 match ecx.structurally_normalize_term(goal.param_env, term) {
65 Ok(term) => {
66 if term.is_infer() {
67 return Some(ecx.evaluate_added_goals_and_make_canonical_response(
68 Certainty::AMBIGUOUS,
69 ));
70 }
71 }
72 Err(
73 e @ (NoSolutionOrRerunNonErased::NoSolution(NoSolution)
74 | NoSolutionOrRerunNonErased::RerunNonErased(_)),
75 ) => {
76 return Some(Err(e));
77 }
78 }
79 }
80
81 None
82 },
83 |ecx| {
84 ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
85 this.instantiate_normalizes_to_as_rigid(goal)?;
86 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
87 })
88 },
89 )
90 }
91
92 pub fn push_const_arg_has_type_goal(
95 &mut self,
96 param_env: I::ParamEnv,
97 alias: ty::AliasTerm<I>,
98 term: I::Term,
99 ) -> Result<(), NoSolutionOrRerunNonErased> {
100 if let Some(ct) = term.as_const() {
101 let cx = self.cx();
102 let expected_ty = alias.expect_ct().type_of(cx).skip_norm_wip();
103 self.add_goal(
104 GoalSource::Misc,
105 Goal {
106 param_env,
107 predicate: ty::ClauseKind::ConstArgHasType(ct, expected_ty).upcast(cx),
108 },
109 )?;
110 }
111 Ok(())
112 }
113
114 fn instantiate_normalizes_to_term(
137 &mut self,
138 goal: Goal<I, NormalizesTo<I>>,
139 value: I::Term,
140 ) -> Result<(), NoSolutionOrRerunNonErased> {
141 self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, value)?;
142 self.eq(goal.param_env, goal.predicate.term, value)?;
146 Ok(())
147 }
148
149 fn instantiate_normalizes_to_as_rigid(
150 &mut self,
151 goal: Goal<I, NormalizesTo<I>>,
152 ) -> Result<(), NoSolutionOrRerunNonErased> {
153 self.eq(
154 goal.param_env,
155 goal.predicate.term,
156 goal.predicate.alias.to_term(self.cx(), ty::IsRigid::Yes),
157 )
158 }
159}
160
161impl<D, I> assembly::GoalKind<D> for NormalizesTo<I>
162where
163 D: SolverDelegate<Interner = I>,
164 I: Interner,
165{
166 fn self_ty(self) -> I::Ty {
167 self.self_ty()
168 }
169
170 fn trait_ref(self, cx: I) -> ty::TraitRef<I> {
171 self.alias.trait_ref(cx)
172 }
173
174 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
175 self.with_replaced_self_ty(cx, self_ty)
176 }
177
178 fn trait_def_id(self, cx: I) -> I::TraitId {
179 self.trait_def_id(cx)
180 }
181
182 fn fast_reject_assumption(
183 ecx: &mut EvalCtxt<'_, D>,
184 goal: Goal<I, Self>,
185 assumption: I::Clause,
186 ) -> Result<(), NoSolution> {
187 let alias_def_id = match goal.predicate.alias.kind {
188 ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(),
189 ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(),
190 _ => return Err(NoSolution),
191 };
192 if let Some(projection_pred) = assumption.as_projection_clause()
193 && projection_pred.item_def_id() == alias_def_id
194 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
195 goal.predicate.alias.args,
196 projection_pred.skip_binder().projection_term.args,
197 )
198 {
199 Ok(())
200 } else {
201 Err(NoSolution)
202 }
203 }
204
205 fn match_assumption(
206 ecx: &mut EvalCtxt<'_, D>,
207 goal: Goal<I, Self>,
208 assumption: I::Clause,
209 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
210 ) -> QueryResultOrRerunNonErased<I> {
211 let cx = ecx.cx();
212 let projection_pred = assumption.as_projection_clause().unwrap();
213 let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred);
214 ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?;
215
216 ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term)?;
217
218 ecx.add_goals(
221 GoalSource::AliasWellFormed,
222 cx.own_clauses_of(goal.predicate.alias.expect_projection_def_id().into())
223 .iter_instantiated(cx, goal.predicate.alias.args)
224 .map(Unnormalized::skip_norm_wip)
225 .map(|clause| goal.with(cx, clause)),
226 )?;
227
228 then(ecx)
229 }
230
231 fn probe_and_consider_object_bound_candidate(
235 ecx: &mut EvalCtxt<'_, D>,
236 source: CandidateSource<I>,
237 goal: Goal<I, Self>,
238 assumption: I::Clause,
239 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
240 Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
241 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
242 })
243 }
244
245 fn consider_additional_alias_assumptions(
246 _ecx: &mut EvalCtxt<'_, D>,
247 _goal: Goal<I, Self>,
248 _alias_ty: ty::AliasTy<I>,
249 ) -> Vec<Candidate<I>> {
250 ::alloc::vec::Vec::new()vec![]
251 }
252
253 fn consider_impl_candidate(
254 ecx: &mut EvalCtxt<'_, D>,
255 goal: Goal<I, NormalizesTo<I>>,
256 impl_def_id: I::ImplId,
257 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
258 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
259 let cx = ecx.cx();
260
261 let alias_def_id = goal.predicate.alias.expect_projection_def_id();
262 let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
263 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
264 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
265 goal.predicate.alias.trait_ref(cx).args,
266 impl_trait_ref.skip_binder().args,
267 ) {
268 return Err(NoSolution.into());
269 }
270
271 let impl_polarity = cx.impl_polarity(impl_def_id);
273 match impl_polarity {
274 ty::ImplPolarity::Negative => return Err(NoSolution.into()),
275 ty::ImplPolarity::Reservation => {
276 {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("reservation impl for trait with assoc item: {0:?}",
goal)));
}unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
277 }
278 ty::ImplPolarity::Positive => {}
279 };
280
281 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
282 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
283 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
284
285 ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
286
287 let where_clause_bounds = cx
288 .clauses_of(impl_def_id.into())
289 .iter_instantiated(cx, impl_args)
290 .map(Unnormalized::skip_norm_wip)
291 .map(|clause| goal.with(cx, clause));
292 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
293
294 ecx.try_evaluate_added_goals()?;
299
300 ecx.add_goals(
304 GoalSource::AliasWellFormed,
305 cx.own_clauses_of(alias_def_id.into())
306 .iter_instantiated(cx, goal.predicate.alias.args)
307 .map(Unnormalized::skip_norm_wip)
308 .map(|clause| goal.with(cx, clause)),
309 )?;
310
311 let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
312 let error_term = match goal.predicate.alias.kind {
313 ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(),
314 ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(),
315 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
316 };
317 ecx.instantiate_normalizes_to_term(goal, error_term)?;
318 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
319 };
320
321 let target_item_def_id =
322 match ecx.fetch_eligible_assoc_item(goal_trait_ref, alias_def_id, impl_def_id) {
323 FetchEligibleAssocItemResponse::Found(target_item_def_id) => target_item_def_id,
324 FetchEligibleAssocItemResponse::NotFound(tm) => {
325 match tm {
326 ty::TypingMode::Coherence => {
338 ecx.add_goal(
339 GoalSource::Misc,
340 goal.with(cx, PredicateKind::Ambiguous),
341 )?;
342 return ecx.evaluate_added_goals_and_make_canonical_response(
343 Certainty::Yes,
344 );
345 }
346 ty::TypingMode::Typeck { .. }
348 | ty::TypingMode::PostTypeckUntilBorrowck { .. }
349 | ty::TypingMode::PostBorrowck { .. }
350 | ty::TypingMode::PostAnalysis
351 | ty::TypingMode::Reflection
352 | ty::TypingMode::Codegen => {
353 ecx.instantiate_normalizes_to_as_rigid(goal)?;
354 return ecx.evaluate_added_goals_and_make_canonical_response(
355 Certainty::Yes,
356 );
357 }
358 };
359 }
360 FetchEligibleAssocItemResponse::Err(guar) => return error_response(ecx, guar),
361 FetchEligibleAssocItemResponse::NotFoundBecauseErased => {
362 ecx.opaque_accesses.rerun_always(RerunReason::FetchEligibleAssocItem)?;
363 return Err(NoSolution.into());
364 }
365 };
366
367 if !cx.has_item_definition(target_item_def_id) {
368 if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
374 if ecx.typing_mode().is_coherence() {
375 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous))?;
386 return then(ecx, Certainty::Yes);
387 } else {
388 ecx.instantiate_normalizes_to_as_rigid(goal)?;
389 return then(ecx, Certainty::Yes);
390 }
391 } else {
392 return error_response(ecx, cx.delay_bug("missing item"));
393 }
394 }
395
396 let target_container_def_id = cx.impl_or_trait_assoc_term_parent(target_item_def_id);
397
398 let target_args = ecx.translate_args(
409 goal,
410 impl_def_id,
411 impl_args,
412 impl_trait_ref,
413 target_container_def_id,
414 )?;
415
416 if !cx.check_args_compatible(target_item_def_id.into(), target_args) {
417 return error_response(
418 ecx,
419 cx.delay_bug("associated item has mismatched arguments"),
420 );
421 }
422
423 let term = match goal.predicate.alias.kind {
425 ty::AliasTermKind::ProjectionTy { .. } => {
426 let t = cx.type_of(target_item_def_id.into()).instantiate(cx, target_args);
427 let t = ecx.normalize(GoalSource::Misc, goal.param_env, t)?;
428 t.into()
429 }
430 ty::AliasTermKind::ProjectionConst { .. }
431 if cx.is_type_const(target_item_def_id.into()) =>
432 {
433 let c =
434 cx.const_of_item(target_item_def_id.into()).instantiate(cx, target_args);
435 let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?;
436 c.into()
437 }
438 ty::AliasTermKind::ProjectionConst { .. } => {
439 let alias_const = ty::AliasConst::new(
440 cx,
441 ty::AliasConstKind::Projection {
442 def_id: target_item_def_id.into().try_into().unwrap(),
443 },
444 target_args,
445 );
446 return ecx.evaluate_const_and_instantiate_projection_term(
447 goal.param_env,
448 goal.predicate.alias,
449 goal.predicate.term,
450 alias_const,
451 );
452 }
453 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
454 };
455
456 ecx.instantiate_normalizes_to_term(goal, term)?;
457 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
458 })
459 }
460
461 fn consider_error_guaranteed_candidate(
464 ecx: &mut EvalCtxt<'_, D>,
465 goal: Goal<I, Self>,
466 guar: I::ErrorGuaranteed,
467 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
468 let cx = ecx.cx();
469 let error_term = match goal.predicate.alias.kind {
470 ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(),
471 ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(),
472 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
473 };
474
475 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
476 ecx.instantiate_normalizes_to_term(goal, error_term)?;
477 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
478 })
479 }
480
481 fn consider_auto_trait_candidate(
482 ecx: &mut EvalCtxt<'_, D>,
483 _goal: Goal<I, Self>,
484 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
485 ecx.cx().delay_bug("associated types not allowed on auto traits");
486 Err(NoSolution.into())
487 }
488
489 fn consider_trait_alias_candidate(
490 _ecx: &mut EvalCtxt<'_, D>,
491 goal: Goal<I, Self>,
492 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
493 {
::core::panicking::panic_fmt(format_args!("trait aliases do not have associated types: {0:?}",
goal));
};panic!("trait aliases do not have associated types: {:?}", goal);
494 }
495
496 fn consider_builtin_sizedness_candidates(
497 _ecx: &mut EvalCtxt<'_, D>,
498 goal: Goal<I, Self>,
499 _sizedness: SizedTraitKind,
500 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
501 {
::core::panicking::panic_fmt(format_args!("`Sized`/`MetaSized` does not have an associated type: {0:?}",
goal));
};panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
502 }
503
504 fn consider_builtin_copy_clone_candidate(
505 _ecx: &mut EvalCtxt<'_, D>,
506 goal: Goal<I, Self>,
507 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
508 {
::core::panicking::panic_fmt(format_args!("`Copy`/`Clone` does not have an associated type: {0:?}",
goal));
};panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
509 }
510
511 fn consider_builtin_fn_ptr_trait_candidate(
512 _ecx: &mut EvalCtxt<'_, D>,
513 goal: Goal<I, Self>,
514 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
515 {
::core::panicking::panic_fmt(format_args!("`FnPtr` does not have an associated type: {0:?}",
goal));
};panic!("`FnPtr` does not have an associated type: {:?}", goal);
516 }
517
518 fn consider_builtin_fn_trait_candidates(
519 ecx: &mut EvalCtxt<'_, D>,
520 goal: Goal<I, Self>,
521 goal_kind: ty::ClosureKind,
522 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
523 let cx = ecx.cx();
524 let Some(tupled_inputs_and_output) =
525 structural_traits::extract_tupled_inputs_and_output_from_callable(
526 cx,
527 goal.predicate.self_ty(),
528 goal_kind,
529 )?
530 else {
531 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
532 };
533 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
534
535 let output_is_sized_pred =
538 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
539
540 let pred = ty::ProjectionPredicate {
541 projection_term: ty::AliasTerm::new(
542 cx,
543 goal.predicate.alias.kind,
544 [goal.predicate.self_ty(), inputs],
545 ),
546 term: output.into(),
547 }
548 .upcast(cx);
549
550 Self::probe_and_consider_implied_clause(
551 ecx,
552 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
553 goal,
554 pred,
555 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
556 )
557 }
558
559 fn consider_builtin_async_fn_trait_candidates(
560 ecx: &mut EvalCtxt<'_, D>,
561 goal: Goal<I, Self>,
562 goal_kind: ty::ClosureKind,
563 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
564 let cx = ecx.cx();
565 let def_id = goal.predicate.alias.expect_projection_ty_def_id();
566
567 let env_region = match goal_kind {
568 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
569 ty::ClosureKind::FnOnce => Region::new_static(cx),
571 };
572 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
573 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
574 cx,
575 goal.predicate.self_ty(),
576 goal_kind,
577 env_region,
578 )?;
579 let AsyncCallableRelevantTypes {
580 tupled_inputs_ty,
581 output_coroutine_ty,
582 coroutine_return_ty,
583 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
584
585 let output_is_sized_pred = ty::TraitRef::new(
588 cx,
589 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
590 [output_coroutine_ty],
591 );
592
593 let (projection_term, term) = if cx
594 .is_projection_lang_item(def_id, SolverProjectionLangItem::CallOnceFuture)
595 {
596 (
597 ty::AliasTerm::new(
598 cx,
599 goal.predicate.alias.kind,
600 [goal.predicate.self_ty(), tupled_inputs_ty],
601 ),
602 output_coroutine_ty.into(),
603 )
604 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CallRefFuture) {
605 (
606 ty::AliasTerm::new(
607 cx,
608 goal.predicate.alias.kind,
609 [
610 I::GenericArg::from(goal.predicate.self_ty()),
611 tupled_inputs_ty.into(),
612 env_region.into(),
613 ],
614 ),
615 output_coroutine_ty.into(),
616 )
617 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::AsyncFnOnceOutput) {
618 (
619 ty::AliasTerm::new(
620 cx,
621 goal.predicate.alias.kind,
622 [goal.predicate.self_ty(), tupled_inputs_ty],
623 ),
624 coroutine_return_ty.into(),
625 )
626 } else {
627 {
::core::panicking::panic_fmt(format_args!("no such associated type in `AsyncFn*`: {0:?}",
def_id));
}panic!("no such associated type in `AsyncFn*`: {:?}", def_id)
628 };
629 let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
630
631 Self::probe_and_consider_implied_clause(
632 ecx,
633 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
634 goal,
635 pred,
636 [goal.with(cx, output_is_sized_pred)]
637 .into_iter()
638 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
639 .map(|goal| (GoalSource::ImplWhereBound, goal)),
640 )
641 }
642
643 fn consider_builtin_async_fn_kind_helper_candidate(
644 ecx: &mut EvalCtxt<'_, D>,
645 goal: Goal<I, Self>,
646 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
647 let [
648 closure_fn_kind_ty,
649 goal_kind_ty,
650 borrow_region,
651 tupled_inputs_ty,
652 tupled_upvars_ty,
653 coroutine_captures_by_ref_ty,
654 ] = *goal.predicate.alias.args.as_slice()
655 else {
656 ::core::panicking::panic("explicit panic");panic!();
657 };
658
659 if tupled_upvars_ty.expect_ty().is_ty_var() {
661 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
662 }
663
664 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
665 return Err(NoSolution.into());
667 };
668 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
669 return Err(NoSolution.into());
670 };
671 if !closure_kind.extends(goal_kind) {
672 return Err(NoSolution.into());
673 }
674
675 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
676 ecx.cx(),
677 goal_kind,
678 tupled_inputs_ty.expect_ty(),
679 tupled_upvars_ty.expect_ty(),
680 coroutine_captures_by_ref_ty.expect_ty(),
681 borrow_region.expect_region(),
682 );
683
684 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
685 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into())?;
686 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
687 })
688 }
689
690 fn consider_builtin_tuple_candidate(
691 _ecx: &mut EvalCtxt<'_, D>,
692 goal: Goal<I, Self>,
693 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
694 {
::core::panicking::panic_fmt(format_args!("`Tuple` does not have an associated type: {0:?}",
goal));
};panic!("`Tuple` does not have an associated type: {:?}", goal);
695 }
696
697 fn consider_builtin_pointee_candidate(
698 ecx: &mut EvalCtxt<'_, D>,
699 goal: Goal<I, Self>,
700 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
701 let cx = ecx.cx();
702 let metadata_def_id = cx.require_projection_lang_item(SolverProjectionLangItem::Metadata);
703 {
match (&ty::AliasTermKind::ProjectionTy { def_id: metadata_def_id },
&goal.predicate.alias.kind) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(
704 ty::AliasTermKind::ProjectionTy { def_id: metadata_def_id },
705 goal.predicate.alias.kind
706 );
707 let metadata_ty = match goal.predicate.self_ty().kind() {
708 ty::Bool
709 | ty::Char
710 | ty::Int(..)
711 | ty::Uint(..)
712 | ty::Float(..)
713 | ty::Array(..)
714 | ty::Pat(..)
715 | ty::RawPtr(..)
716 | ty::Ref(..)
717 | ty::FnDef(..)
718 | ty::FnPtr(..)
719 | ty::Closure(..)
720 | ty::CoroutineClosure(..)
721 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
722 | ty::Coroutine(..)
723 | ty::CoroutineWitness(..)
724 | ty::Never
725 | ty::Foreign(..) => Ty::new_unit(cx),
726
727 ty::Error(e) => Ty::new_error(cx, e),
728
729 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
730
731 ty::Dynamic(_, _) => {
732 let dyn_metadata = cx.require_adt_lang_item(SolverAdtLangItem::DynMetadata);
733 cx.type_of(dyn_metadata.into())
734 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
735 .skip_norm_wip()
736 }
737
738 ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => {
739 let alias_bound_result = ecx
744 .probe_builtin_trait_candidate(BuiltinImplSource::Misc)
745 .enter(|ecx| {
746 let sized_predicate = ty::TraitRef::new(
747 cx,
748 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
749 [I::GenericArg::from(goal.predicate.self_ty())],
750 );
751 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate))?;
752 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into())?;
753 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
754 })
755 .map_err_to_rerun()?;
756
757 return alias_bound_result.or_else(|NoSolution| {
760 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
761 this.instantiate_normalizes_to_as_rigid(goal)?;
762 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
763 })
764 });
765 }
766
767 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
768 None => Ty::new_unit(cx),
769 Some(tail_ty) => Ty::new_projection(
770 cx,
771 ty::IsRigid::No,
772 metadata_def_id,
773 [tail_ty.instantiate(cx, args).skip_norm_wip()],
774 ),
775 },
776 ty::Adt(_, _) => Ty::new_unit(cx),
777
778 ty::Tuple(elements) => match elements.last() {
779 None => Ty::new_unit(cx),
780 Some(tail_ty) => {
781 Ty::new_projection(cx, ty::IsRigid::No, metadata_def_id, [tail_ty])
782 }
783 },
784
785 ty::UnsafeBinder(_) => {
786 ::core::panicking::panic("not implemented")unimplemented!()
788 }
789
790 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
791 | ty::Alias(ty::IsRigid::No, _)
792 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as Pointee>::Metadata`",
goal.predicate.self_ty()));
}panic!(
793 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
794 goal.predicate.self_ty()
795 ),
796 };
797
798 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
799 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into())?;
800 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
801 })
802 }
803
804 fn consider_builtin_future_candidate(
805 ecx: &mut EvalCtxt<'_, D>,
806 goal: Goal<I, Self>,
807 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
808 let self_ty = goal.predicate.self_ty();
809 let ty::Coroutine(def_id, args) = self_ty.kind() else {
810 return Err(NoSolution.into());
811 };
812
813 let cx = ecx.cx();
815 if !cx.coroutine_is_async(def_id) {
816 return Err(NoSolution.into());
817 }
818
819 let term = args.as_coroutine().return_ty().into();
820
821 Self::probe_and_consider_implied_clause(
822 ecx,
823 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
824 goal,
825 ty::ProjectionPredicate {
826 projection_term: ty::AliasTerm::new(
827 ecx.cx(),
828 cx.alias_term_kind_from_def_id(
829 goal.predicate.alias.expect_projection_def_id().into(),
830 ),
831 [self_ty],
832 ),
833 term,
834 }
835 .upcast(cx),
836 [],
839 )
840 }
841
842 fn consider_builtin_iterator_candidate(
843 ecx: &mut EvalCtxt<'_, D>,
844 goal: Goal<I, Self>,
845 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
846 let self_ty = goal.predicate.self_ty();
847 let ty::Coroutine(def_id, args) = self_ty.kind() else {
848 return Err(NoSolution.into());
849 };
850
851 let cx = ecx.cx();
853 if !cx.coroutine_is_gen(def_id) {
854 return Err(NoSolution.into());
855 }
856
857 let term = args.as_coroutine().yield_ty().into();
858
859 Self::probe_and_consider_implied_clause(
860 ecx,
861 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
862 goal,
863 ty::ProjectionPredicate {
864 projection_term: ty::AliasTerm::new(
865 ecx.cx(),
866 cx.alias_term_kind_from_def_id(
867 goal.predicate.alias.expect_projection_def_id().into(),
868 ),
869 [self_ty],
870 ),
871 term,
872 }
873 .upcast(cx),
874 [],
877 )
878 }
879
880 fn consider_builtin_fused_iterator_candidate(
881 _ecx: &mut EvalCtxt<'_, D>,
882 goal: Goal<I, Self>,
883 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
884 {
::core::panicking::panic_fmt(format_args!("`FusedIterator` does not have an associated type: {0:?}",
goal));
};panic!("`FusedIterator` does not have an associated type: {:?}", goal);
885 }
886
887 fn consider_builtin_async_iterator_candidate(
888 ecx: &mut EvalCtxt<'_, D>,
889 goal: Goal<I, Self>,
890 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
891 let self_ty = goal.predicate.self_ty();
892 let ty::Coroutine(def_id, args) = self_ty.kind() else {
893 return Err(NoSolution.into());
894 };
895
896 let cx = ecx.cx();
898 if !cx.coroutine_is_async_gen(def_id) {
899 return Err(NoSolution.into());
900 }
901
902 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
903 let expected_ty = ecx.next_ty_infer();
904 let wrapped_expected_ty = Ty::new_adt(
907 cx,
908 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
909 cx.mk_args(&[Ty::new_adt(
910 cx,
911 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
912 cx.mk_args(&[expected_ty.into()]),
913 )
914 .into()]),
915 );
916 let yield_ty = args.as_coroutine().yield_ty();
917 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
918 ecx.instantiate_normalizes_to_term(goal, expected_ty.into())?;
919 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
920 })
921 }
922
923 fn consider_builtin_coroutine_candidate(
924 ecx: &mut EvalCtxt<'_, D>,
925 goal: Goal<I, Self>,
926 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
927 let self_ty = goal.predicate.self_ty();
928 let ty::Coroutine(def_id, args) = self_ty.kind() else {
929 return Err(NoSolution.into());
930 };
931
932 let cx = ecx.cx();
934 if !cx.is_general_coroutine(def_id) {
935 return Err(NoSolution.into());
936 }
937
938 let coroutine = args.as_coroutine();
939 let def_id = goal.predicate.alias.expect_projection_ty_def_id();
940
941 let term = if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineReturn)
942 {
943 coroutine.return_ty().into()
944 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineYield) {
945 coroutine.yield_ty().into()
946 } else {
947 {
::core::panicking::panic_fmt(format_args!("unexpected associated item `{0:?}` for `{1:?}`",
def_id, self_ty));
}panic!("unexpected associated item `{:?}` for `{self_ty:?}`", def_id)
948 };
949
950 Self::probe_and_consider_implied_clause(
951 ecx,
952 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
953 goal,
954 ty::ProjectionPredicate {
955 projection_term: ty::AliasTerm::new(
956 ecx.cx(),
957 goal.predicate.alias.kind,
958 [self_ty, coroutine.resume_ty()],
959 ),
960 term,
961 }
962 .upcast(cx),
963 [],
966 )
967 }
968
969 fn consider_structural_builtin_unsize_candidates(
970 _ecx: &mut EvalCtxt<'_, D>,
971 goal: Goal<I, Self>,
972 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
973 {
::core::panicking::panic_fmt(format_args!("`Unsize` does not have an associated type: {0:?}",
goal));
};panic!("`Unsize` does not have an associated type: {:?}", goal);
974 }
975
976 fn consider_builtin_discriminant_kind_candidate(
977 ecx: &mut EvalCtxt<'_, D>,
978 goal: Goal<I, Self>,
979 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
980 let self_ty = goal.predicate.self_ty();
981 let discriminant_ty = match self_ty.kind() {
982 ty::Bool
983 | ty::Char
984 | ty::Int(..)
985 | ty::Uint(..)
986 | ty::Float(..)
987 | ty::Array(..)
988 | ty::Pat(..)
989 | ty::RawPtr(..)
990 | ty::Ref(..)
991 | ty::FnDef(..)
992 | ty::FnPtr(..)
993 | ty::Closure(..)
994 | ty::CoroutineClosure(..)
995 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
996 | ty::Coroutine(..)
997 | ty::CoroutineWitness(..)
998 | ty::Never
999 | ty::Foreign(..)
1000 | ty::Adt(_, _)
1001 | ty::Str
1002 | ty::Slice(_)
1003 | ty::Dynamic(_, _)
1004 | ty::Tuple(_)
1005 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
1006
1007 ty::UnsafeBinder(_) => {
1008 {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("discr subgoal...")));
}unimplemented!("discr subgoal...")
1010 }
1011
1012 ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => {
1016 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1017 ecx.instantiate_normalizes_to_as_rigid(goal)?;
1018 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1019 });
1020 }
1021
1022 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
1023 | ty::Alias(ty::IsRigid::No, _)
1024 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
goal.predicate.self_ty()));
}panic!(
1025 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
1026 goal.predicate.self_ty()
1027 ),
1028 };
1029
1030 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1031 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into())?;
1032 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1033 })
1034 }
1035
1036 fn consider_builtin_destruct_candidate(
1037 _ecx: &mut EvalCtxt<'_, D>,
1038 goal: Goal<I, Self>,
1039 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1040 {
::core::panicking::panic_fmt(format_args!("`Destruct` does not have an associated type: {0:?}",
goal));
};panic!("`Destruct` does not have an associated type: {:?}", goal);
1041 }
1042
1043 fn consider_builtin_transmute_candidate(
1044 _ecx: &mut EvalCtxt<'_, D>,
1045 goal: Goal<I, Self>,
1046 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1047 {
::core::panicking::panic_fmt(format_args!("`TransmuteFrom` does not have an associated type: {0:?}",
goal));
}panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
1048 }
1049
1050 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
1051 _ecx: &mut EvalCtxt<'_, D>,
1052 goal: Goal<I, Self>,
1053 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1054 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("`BikeshedGuaranteedNoDrop` does not have an associated type: {0:?}",
goal)));
}unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
1055 }
1056
1057 fn consider_builtin_field_candidate(
1058 ecx: &mut EvalCtxt<'_, D>,
1059 goal: Goal<I, Self>,
1060 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1061 let self_ty = goal.predicate.self_ty();
1062 let ty::Adt(def, args) = self_ty.kind() else {
1063 return Err(NoSolution.into());
1064 };
1065 let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
1066 else {
1067 return Err(NoSolution.into());
1068 };
1069 let def_id = goal.predicate.alias.expect_projection_ty_def_id();
1070 let ty = match ecx.cx().as_projection_lang_item(def_id) {
1071 Some(SolverProjectionLangItem::FieldBase) => base,
1072 Some(SolverProjectionLangItem::FieldType) => ty,
1073 _ => {
::core::panicking::panic_fmt(format_args!("unexpected associated type {0:?} in `Field`",
goal.predicate));
}panic!("unexpected associated type {:?} in `Field`", goal.predicate),
1074 };
1075 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1076 ecx.instantiate_normalizes_to_term(goal, ty.into())?;
1077 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1078 })
1079 }
1080
1081 fn consider_builtin_try_as_dyn_candidate(
1082 _ecx: &mut EvalCtxt<'_, D>,
1083 _goal: Goal<I, Self>,
1084 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1085 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("try_as_dyn helper trait doesn\'t have assoc types")));
}unreachable!("try_as_dyn helper trait doesn't have assoc types")
1086 }
1087}
1088
1089impl<D, I> EvalCtxt<'_, D>
1090where
1091 D: SolverDelegate<Interner = I>,
1092 I: Interner,
1093{
1094 fn translate_args(
1095 &mut self,
1096 goal: Goal<I, ty::NormalizesTo<I>>,
1097 impl_def_id: I::ImplId,
1098 impl_args: I::GenericArgs,
1099 impl_trait_ref: rustc_type_ir::TraitRef<I>,
1100 target_container_def_id: I::DefId,
1101 ) -> Result<I::GenericArgs, NoSolutionOrRerunNonErased> {
1102 let cx = self.cx();
1103 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
1104 goal.predicate.alias.args
1106 } else if target_container_def_id == impl_def_id.into() {
1107 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
1110 } else {
1111 let target_args = self.fresh_args_for_item(target_container_def_id);
1112 let target_trait_ref = cx
1113 .impl_trait_ref(target_container_def_id.try_into().unwrap())
1114 .instantiate(cx, target_args)
1115 .skip_norm_wip();
1116 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
1118 self.add_goals(
1121 GoalSource::Misc,
1122 cx.clauses_of(target_container_def_id)
1123 .iter_instantiated(cx, target_args)
1124 .map(Unnormalized::skip_norm_wip)
1125 .map(|clause| goal.with(cx, clause)),
1126 )?;
1127 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
1128 })
1129 }
1130}