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