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::AnonConst { 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 {
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,
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 {
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 cx,
420 ty::UnevaluatedConstKind::Projection {
421 def_id: target_item_def_id.into().try_into().unwrap(),
422 },
423 target_args,
424 );
425 return ecx.evaluate_const_and_instantiate_normalizes_to_term(goal, uv);
426 }
427 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
428 };
429
430 ecx.instantiate_normalizes_to_term(goal, term);
431 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into)
432 })
433 }
434
435 fn consider_error_guaranteed_candidate(
438 _ecx: &mut EvalCtxt<'_, D>,
439 _guar: I::ErrorGuaranteed,
440 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
441 Err(NoSolution.into())
442 }
443
444 fn consider_auto_trait_candidate(
445 ecx: &mut EvalCtxt<'_, D>,
446 _goal: Goal<I, Self>,
447 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
448 ecx.cx().delay_bug("associated types not allowed on auto traits");
449 Err(NoSolution.into())
450 }
451
452 fn consider_trait_alias_candidate(
453 _ecx: &mut EvalCtxt<'_, D>,
454 goal: Goal<I, Self>,
455 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
456 {
::core::panicking::panic_fmt(format_args!("trait aliases do not have associated types: {0:?}",
goal));
};panic!("trait aliases do not have associated types: {:?}", goal);
457 }
458
459 fn consider_builtin_sizedness_candidates(
460 _ecx: &mut EvalCtxt<'_, D>,
461 goal: Goal<I, Self>,
462 _sizedness: SizedTraitKind,
463 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
464 {
::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);
465 }
466
467 fn consider_builtin_copy_clone_candidate(
468 _ecx: &mut EvalCtxt<'_, D>,
469 goal: Goal<I, Self>,
470 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
471 {
::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);
472 }
473
474 fn consider_builtin_fn_ptr_trait_candidate(
475 _ecx: &mut EvalCtxt<'_, D>,
476 goal: Goal<I, Self>,
477 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
478 {
::core::panicking::panic_fmt(format_args!("`FnPtr` does not have an associated type: {0:?}",
goal));
};panic!("`FnPtr` does not have an associated type: {:?}", goal);
479 }
480
481 fn consider_builtin_fn_trait_candidates(
482 ecx: &mut EvalCtxt<'_, D>,
483 goal: Goal<I, Self>,
484 goal_kind: ty::ClosureKind,
485 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
486 let cx = ecx.cx();
487 let Some(tupled_inputs_and_output) =
488 structural_traits::extract_tupled_inputs_and_output_from_callable(
489 cx,
490 goal.predicate.self_ty(),
491 goal_kind,
492 )?
493 else {
494 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
495 };
496 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
497
498 let output_is_sized_pred =
501 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
502
503 let pred = ty::ProjectionPredicate {
504 projection_term: ty::AliasTerm::new(
505 cx,
506 goal.predicate.alias.kind,
507 [goal.predicate.self_ty(), inputs],
508 ),
509 term: output.into(),
510 }
511 .upcast(cx);
512
513 Self::probe_and_consider_implied_clause(
514 ecx,
515 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
516 goal,
517 pred,
518 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
519 )
520 .map_err(Into::into)
521 }
522
523 fn consider_builtin_async_fn_trait_candidates(
524 ecx: &mut EvalCtxt<'_, D>,
525 goal: Goal<I, Self>,
526 goal_kind: ty::ClosureKind,
527 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
528 let cx = ecx.cx();
529 let def_id = goal.predicate.def_id().try_into().unwrap();
530
531 let env_region = match goal_kind {
532 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
533 ty::ClosureKind::FnOnce => Region::new_static(cx),
535 };
536 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
537 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
538 cx,
539 goal.predicate.self_ty(),
540 goal_kind,
541 env_region,
542 )?;
543 let AsyncCallableRelevantTypes {
544 tupled_inputs_ty,
545 output_coroutine_ty,
546 coroutine_return_ty,
547 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
548
549 let output_is_sized_pred = ty::TraitRef::new(
552 cx,
553 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
554 [output_coroutine_ty],
555 );
556
557 let (projection_term, term) = if cx
558 .is_projection_lang_item(def_id, SolverProjectionLangItem::CallOnceFuture)
559 {
560 (
561 ty::AliasTerm::new(
562 cx,
563 goal.predicate.alias.kind,
564 [goal.predicate.self_ty(), tupled_inputs_ty],
565 ),
566 output_coroutine_ty.into(),
567 )
568 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CallRefFuture) {
569 (
570 ty::AliasTerm::new(
571 cx,
572 goal.predicate.alias.kind,
573 [
574 I::GenericArg::from(goal.predicate.self_ty()),
575 tupled_inputs_ty.into(),
576 env_region.into(),
577 ],
578 ),
579 output_coroutine_ty.into(),
580 )
581 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::AsyncFnOnceOutput) {
582 (
583 ty::AliasTerm::new(
584 cx,
585 goal.predicate.alias.kind,
586 [goal.predicate.self_ty(), tupled_inputs_ty],
587 ),
588 coroutine_return_ty.into(),
589 )
590 } else {
591 {
::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())
592 };
593 let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
594
595 Self::probe_and_consider_implied_clause(
596 ecx,
597 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
598 goal,
599 pred,
600 [goal.with(cx, output_is_sized_pred)]
601 .into_iter()
602 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
603 .map(|goal| (GoalSource::ImplWhereBound, goal)),
604 )
605 }
606
607 fn consider_builtin_async_fn_kind_helper_candidate(
608 ecx: &mut EvalCtxt<'_, D>,
609 goal: Goal<I, Self>,
610 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
611 let [
612 closure_fn_kind_ty,
613 goal_kind_ty,
614 borrow_region,
615 tupled_inputs_ty,
616 tupled_upvars_ty,
617 coroutine_captures_by_ref_ty,
618 ] = *goal.predicate.alias.args.as_slice()
619 else {
620 ::core::panicking::panic("explicit panic");panic!();
621 };
622
623 if tupled_upvars_ty.expect_ty().is_ty_var() {
625 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
626 }
627
628 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
629 return Err(NoSolution.into());
631 };
632 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
633 return Err(NoSolution.into());
634 };
635 if !closure_kind.extends(goal_kind) {
636 return Err(NoSolution.into());
637 }
638
639 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
640 ecx.cx(),
641 goal_kind,
642 tupled_inputs_ty.expect_ty(),
643 tupled_upvars_ty.expect_ty(),
644 coroutine_captures_by_ref_ty.expect_ty(),
645 borrow_region.expect_region(),
646 );
647
648 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
649 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into());
650 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
651 })
652 }
653
654 fn consider_builtin_tuple_candidate(
655 _ecx: &mut EvalCtxt<'_, D>,
656 goal: Goal<I, Self>,
657 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
658 {
::core::panicking::panic_fmt(format_args!("`Tuple` does not have an associated type: {0:?}",
goal));
};panic!("`Tuple` does not have an associated type: {:?}", goal);
659 }
660
661 fn consider_builtin_pointee_candidate(
662 ecx: &mut EvalCtxt<'_, D>,
663 goal: Goal<I, Self>,
664 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
665 let cx = ecx.cx();
666 let metadata_def_id = cx.require_projection_lang_item(SolverProjectionLangItem::Metadata);
667 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());
668 let metadata_ty = match goal.predicate.self_ty().kind() {
669 ty::Bool
670 | ty::Char
671 | ty::Int(..)
672 | ty::Uint(..)
673 | ty::Float(..)
674 | ty::Array(..)
675 | ty::Pat(..)
676 | ty::RawPtr(..)
677 | ty::Ref(..)
678 | ty::FnDef(..)
679 | ty::FnPtr(..)
680 | ty::Closure(..)
681 | ty::CoroutineClosure(..)
682 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
683 | ty::Coroutine(..)
684 | ty::CoroutineWitness(..)
685 | ty::Never
686 | ty::Foreign(..) => Ty::new_unit(cx),
687
688 ty::Error(e) => Ty::new_error(cx, e),
689
690 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
691
692 ty::Dynamic(_, _) => {
693 let dyn_metadata = cx.require_adt_lang_item(SolverAdtLangItem::DynMetadata);
694 cx.type_of(dyn_metadata.into())
695 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
696 .skip_norm_wip()
697 }
698
699 ty::Alias(_) | ty::Param(_) | ty::Placeholder(..) => {
700 let alias_bound_result =
705 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
706 let sized_predicate = ty::TraitRef::new(
707 cx,
708 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
709 [I::GenericArg::from(goal.predicate.self_ty())],
710 );
711 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
712 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
713 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
714 });
715
716 let alias_bound_result = match alias_bound_result.map_err_to_rerun()? {
717 Ok(i) => Ok(i),
718 Err(NoSolution) => Err(NoSolution),
719 };
720
721 return alias_bound_result.or_else(|NoSolution| {
724 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
725 this.structurally_instantiate_normalizes_to_term(
726 goal,
727 goal.predicate.alias,
728 );
729 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
730 })
731 });
732 }
733
734 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
735 None => Ty::new_unit(cx),
736 Some(tail_ty) => Ty::new_projection(
737 cx,
738 metadata_def_id,
739 [tail_ty.instantiate(cx, args).skip_norm_wip()],
740 ),
741 },
742 ty::Adt(_, _) => Ty::new_unit(cx),
743
744 ty::Tuple(elements) => match elements.last() {
745 None => Ty::new_unit(cx),
746 Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
747 },
748
749 ty::UnsafeBinder(_) => {
750 ::core::panicking::panic("not yet implemented")todo!()
752 }
753
754 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
755 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as Pointee>::Metadata`",
goal.predicate.self_ty()));
}panic!(
756 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
757 goal.predicate.self_ty()
758 ),
759 };
760
761 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
762 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
763 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
764 })
765 }
766
767 fn consider_builtin_future_candidate(
768 ecx: &mut EvalCtxt<'_, D>,
769 goal: Goal<I, Self>,
770 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
771 let self_ty = goal.predicate.self_ty();
772 let ty::Coroutine(def_id, args) = self_ty.kind() else {
773 return Err(NoSolution.into());
774 };
775
776 let cx = ecx.cx();
778 if !cx.coroutine_is_async(def_id) {
779 return Err(NoSolution.into());
780 }
781
782 let term = args.as_coroutine().return_ty().into();
783
784 Self::probe_and_consider_implied_clause(
785 ecx,
786 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
787 goal,
788 ty::ProjectionPredicate {
789 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.alias.kind, [self_ty]),
790 term,
791 }
792 .upcast(cx),
793 [],
796 )
797 }
798
799 fn consider_builtin_iterator_candidate(
800 ecx: &mut EvalCtxt<'_, D>,
801 goal: Goal<I, Self>,
802 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
803 let self_ty = goal.predicate.self_ty();
804 let ty::Coroutine(def_id, args) = self_ty.kind() else {
805 return Err(NoSolution.into());
806 };
807
808 let cx = ecx.cx();
810 if !cx.coroutine_is_gen(def_id) {
811 return Err(NoSolution.into());
812 }
813
814 let term = args.as_coroutine().yield_ty().into();
815
816 Self::probe_and_consider_implied_clause(
817 ecx,
818 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
819 goal,
820 ty::ProjectionPredicate {
821 projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.alias.kind, [self_ty]),
822 term,
823 }
824 .upcast(cx),
825 [],
828 )
829 .map_err(Into::into)
830 }
831
832 fn consider_builtin_fused_iterator_candidate(
833 _ecx: &mut EvalCtxt<'_, D>,
834 goal: Goal<I, Self>,
835 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
836 {
::core::panicking::panic_fmt(format_args!("`FusedIterator` does not have an associated type: {0:?}",
goal));
};panic!("`FusedIterator` does not have an associated type: {:?}", goal);
837 }
838
839 fn consider_builtin_async_iterator_candidate(
840 ecx: &mut EvalCtxt<'_, D>,
841 goal: Goal<I, Self>,
842 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
843 let self_ty = goal.predicate.self_ty();
844 let ty::Coroutine(def_id, args) = self_ty.kind() else {
845 return Err(NoSolution.into());
846 };
847
848 let cx = ecx.cx();
850 if !cx.coroutine_is_async_gen(def_id) {
851 return Err(NoSolution.into());
852 }
853
854 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
855 let expected_ty = ecx.next_ty_infer();
856 let wrapped_expected_ty = Ty::new_adt(
859 cx,
860 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
861 cx.mk_args(&[Ty::new_adt(
862 cx,
863 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
864 cx.mk_args(&[expected_ty.into()]),
865 )
866 .into()]),
867 );
868 let yield_ty = args.as_coroutine().yield_ty();
869 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
870 ecx.instantiate_normalizes_to_term(goal, expected_ty.into());
871 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
872 })
873 }
874
875 fn consider_builtin_coroutine_candidate(
876 ecx: &mut EvalCtxt<'_, D>,
877 goal: Goal<I, Self>,
878 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
879 let self_ty = goal.predicate.self_ty();
880 let ty::Coroutine(def_id, args) = self_ty.kind() else {
881 return Err(NoSolution.into());
882 };
883
884 let cx = ecx.cx();
886 if !cx.is_general_coroutine(def_id) {
887 return Err(NoSolution.into());
888 }
889
890 let coroutine = args.as_coroutine();
891 let def_id = goal.predicate.def_id().try_into().unwrap();
892
893 let term = if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineReturn)
894 {
895 coroutine.return_ty().into()
896 } else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::CoroutineYield) {
897 coroutine.yield_ty().into()
898 } else {
899 {
::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())
900 };
901
902 Self::probe_and_consider_implied_clause(
903 ecx,
904 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
905 goal,
906 ty::ProjectionPredicate {
907 projection_term: ty::AliasTerm::new(
908 ecx.cx(),
909 goal.predicate.alias.kind,
910 [self_ty, coroutine.resume_ty()],
911 ),
912 term,
913 }
914 .upcast(cx),
915 [],
918 )
919 }
920
921 fn consider_structural_builtin_unsize_candidates(
922 _ecx: &mut EvalCtxt<'_, D>,
923 goal: Goal<I, Self>,
924 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
925 {
::core::panicking::panic_fmt(format_args!("`Unsize` does not have an associated type: {0:?}",
goal));
};panic!("`Unsize` does not have an associated type: {:?}", goal);
926 }
927
928 fn consider_builtin_discriminant_kind_candidate(
929 ecx: &mut EvalCtxt<'_, D>,
930 goal: Goal<I, Self>,
931 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
932 let self_ty = goal.predicate.self_ty();
933 let discriminant_ty = match self_ty.kind() {
934 ty::Bool
935 | ty::Char
936 | ty::Int(..)
937 | ty::Uint(..)
938 | ty::Float(..)
939 | ty::Array(..)
940 | ty::Pat(..)
941 | ty::RawPtr(..)
942 | ty::Ref(..)
943 | ty::FnDef(..)
944 | ty::FnPtr(..)
945 | ty::Closure(..)
946 | ty::CoroutineClosure(..)
947 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
948 | ty::Coroutine(..)
949 | ty::CoroutineWitness(..)
950 | ty::Never
951 | ty::Foreign(..)
952 | ty::Adt(_, _)
953 | ty::Str
954 | ty::Slice(_)
955 | ty::Dynamic(_, _)
956 | ty::Tuple(_)
957 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
958
959 ty::UnsafeBinder(_) => {
960 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("discr subgoal...")));
}todo!("discr subgoal...")
962 }
963
964 ty::Alias(_) | ty::Param(_) | ty::Placeholder(..) => {
968 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
969 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
970 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
971 });
972 }
973
974 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
975 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
goal.predicate.self_ty()));
}panic!(
976 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
977 goal.predicate.self_ty()
978 ),
979 };
980
981 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
982 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into());
983 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
984 })
985 }
986
987 fn consider_builtin_destruct_candidate(
988 _ecx: &mut EvalCtxt<'_, D>,
989 goal: Goal<I, Self>,
990 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
991 {
::core::panicking::panic_fmt(format_args!("`Destruct` does not have an associated type: {0:?}",
goal));
};panic!("`Destruct` does not have an associated type: {:?}", goal);
992 }
993
994 fn consider_builtin_transmute_candidate(
995 _ecx: &mut EvalCtxt<'_, D>,
996 goal: Goal<I, Self>,
997 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
998 {
::core::panicking::panic_fmt(format_args!("`TransmuteFrom` does not have an associated type: {0:?}",
goal));
}panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
999 }
1000
1001 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
1002 _ecx: &mut EvalCtxt<'_, D>,
1003 goal: Goal<I, Self>,
1004 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1005 {
::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)
1006 }
1007
1008 fn consider_builtin_field_candidate(
1009 ecx: &mut EvalCtxt<'_, D>,
1010 goal: Goal<I, Self>,
1011 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1012 let self_ty = goal.predicate.self_ty();
1013 let ty::Adt(def, args) = self_ty.kind() else {
1014 return Err(NoSolution.into());
1015 };
1016 let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
1017 else {
1018 return Err(NoSolution.into());
1019 };
1020 let ty = match ecx.cx().as_projection_lang_item(goal.predicate.def_id().try_into().unwrap())
1021 {
1022 Some(SolverProjectionLangItem::FieldBase) => base,
1023 Some(SolverProjectionLangItem::FieldType) => ty,
1024 _ => {
::core::panicking::panic_fmt(format_args!("unexpected associated type {0:?} in `Field`",
goal.predicate));
}panic!("unexpected associated type {:?} in `Field`", goal.predicate),
1025 };
1026 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1027 ecx.instantiate_normalizes_to_term(goal, ty.into());
1028 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1029 })
1030 }
1031}
1032
1033impl<D, I> EvalCtxt<'_, D>
1034where
1035 D: SolverDelegate<Interner = I>,
1036 I: Interner,
1037{
1038 fn translate_args(
1039 &mut self,
1040 goal: Goal<I, ty::NormalizesTo<I>>,
1041 impl_def_id: I::ImplId,
1042 impl_args: I::GenericArgs,
1043 impl_trait_ref: rustc_type_ir::TraitRef<I>,
1044 target_container_def_id: I::DefId,
1045 ) -> Result<I::GenericArgs, NoSolution> {
1046 let cx = self.cx();
1047 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
1048 goal.predicate.alias.args
1050 } else if target_container_def_id == impl_def_id.into() {
1051 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
1054 } else {
1055 let target_args = self.fresh_args_for_item(target_container_def_id);
1056 let target_trait_ref = cx
1057 .impl_trait_ref(target_container_def_id.try_into().unwrap())
1058 .instantiate(cx, target_args)
1059 .skip_norm_wip();
1060 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
1062 self.add_goals(
1065 GoalSource::Misc,
1066 cx.predicates_of(target_container_def_id)
1067 .iter_instantiated(cx, target_args)
1068 .map(Unnormalized::skip_norm_wip)
1069 .map(|pred| goal.with(cx, pred)),
1070 );
1071 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
1072 })
1073 }
1074}