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