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, SolverLangItem, SolverTraitLangItem};
9use rustc_type_ir::{
10 self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Unnormalized, Upcast as _,
11};
12use tracing::instrument;
13
14use crate::delegate::SolverDelegate;
15use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
16use crate::solve::assembly::{self, Candidate};
17use crate::solve::inspect::ProbeKind;
18use crate::solve::{
19 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeInfo,
20 NoSolution, QueryResult, SizedTraitKind,
21};
22
23impl<D, I> EvalCtxt<'_, D>
24where
25 D: SolverDelegate<Interner = I>,
26 I: Interner,
27{
28 x;#[instrument(level = "trace", skip(self), ret)]
29 pub(super) fn compute_normalizes_to_goal(
30 &mut self,
31 goal: Goal<I, NormalizesTo<I>>,
32 ) -> QueryResult<I> {
33 debug_assert!(self.term_is_fully_unconstrained(goal));
34 let cx = self.cx();
35 match goal.predicate.alias.kind(cx) {
36 ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => {
37 let trait_ref = goal.predicate.alias.trait_ref(cx);
38 let (_, proven_via) =
39 self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
40 let trait_goal: Goal<I, ty::TraitPredicate<I>> = goal.with(cx, trait_ref);
41 ecx.compute_trait_goal(trait_goal)
42 })?;
43 self.assemble_and_merge_candidates(
44 proven_via,
45 goal,
46 |ecx| {
47 for arg in goal.predicate.alias.own_args(cx).iter() {
57 let Some(term) = arg.as_term() else {
58 continue;
59 };
60 match ecx.structurally_normalize_term(goal.param_env, term) {
61 Ok(term) => {
62 if term.is_infer() {
63 return Some(
64 ecx.evaluate_added_goals_and_make_canonical_response(
65 Certainty::AMBIGUOUS,
66 ),
67 );
68 }
69 }
70 Err(NoSolution) => return Some(Err(NoSolution)),
71 }
72 }
73
74 None
75 },
76 |ecx| {
77 ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
78 this.structurally_instantiate_normalizes_to_term(
79 goal,
80 goal.predicate.alias,
81 );
82 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
83 })
84 },
85 )
86 }
87 ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => {
88 self.normalize_inherent_associated_term(goal)
89 }
90 ty::AliasTermKind::OpaqueTy { .. } => self.normalize_opaque_type(goal),
91 ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => {
92 self.normalize_free_alias(goal)
93 }
94 ty::AliasTermKind::UnevaluatedConst { .. } => self.normalize_anon_const(goal),
95 }
96 }
97
98 pub fn instantiate_normalizes_to_term(
104 &mut self,
105 goal: Goal<I, NormalizesTo<I>>,
106 term: I::Term,
107 ) {
108 self.eq(goal.param_env, goal.predicate.term, term)
109 .expect("expected goal term to be fully unconstrained");
110 }
111
112 pub fn structurally_instantiate_normalizes_to_term(
115 &mut self,
116 goal: Goal<I, NormalizesTo<I>>,
117 term: ty::AliasTerm<I>,
118 ) {
119 self.relate_rigid_alias_non_alias(goal.param_env, term, ty::Invariant, goal.predicate.term)
120 .expect("expected goal term to be fully unconstrained");
121 }
122}
123
124impl<D, I> assembly::GoalKind<D> for NormalizesTo<I>
125where
126 D: SolverDelegate<Interner = I>,
127 I: Interner,
128{
129 fn self_ty(self) -> I::Ty {
130 self.self_ty()
131 }
132
133 fn trait_ref(self, cx: I) -> ty::TraitRef<I> {
134 self.alias.trait_ref(cx)
135 }
136
137 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
138 self.with_replaced_self_ty(cx, self_ty)
139 }
140
141 fn trait_def_id(self, cx: I) -> I::TraitId {
142 self.trait_def_id(cx)
143 }
144
145 fn fast_reject_assumption(
146 ecx: &mut EvalCtxt<'_, D>,
147 goal: Goal<I, Self>,
148 assumption: I::Clause,
149 ) -> Result<(), NoSolution> {
150 if let Some(projection_pred) = assumption.as_projection_clause()
151 && projection_pred.item_def_id() == goal.predicate.def_id()
152 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
153 goal.predicate.alias.args,
154 projection_pred.skip_binder().projection_term.args,
155 )
156 {
157 Ok(())
158 } else {
159 Err(NoSolution)
160 }
161 }
162
163 fn match_assumption(
164 ecx: &mut EvalCtxt<'_, D>,
165 goal: Goal<I, Self>,
166 assumption: I::Clause,
167 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
168 ) -> QueryResult<I> {
169 let cx = ecx.cx();
170 let projection_pred = assumption.as_projection_clause().unwrap();
171 let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred);
172 ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?;
173
174 ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term);
175
176 ecx.add_goals(
179 GoalSource::AliasWellFormed,
180 cx.own_predicates_of(goal.predicate.def_id())
181 .iter_instantiated(cx, goal.predicate.alias.args)
182 .map(Unnormalized::skip_norm_wip)
183 .map(|pred| goal.with(cx, pred)),
184 );
185
186 then(ecx)
187 }
188
189 fn probe_and_consider_object_bound_candidate(
193 ecx: &mut EvalCtxt<'_, D>,
194 source: CandidateSource<I>,
195 goal: Goal<I, Self>,
196 assumption: I::Clause,
197 ) -> Result<Candidate<I>, NoSolution> {
198 Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
199 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
200 })
201 }
202
203 fn consider_additional_alias_assumptions(
204 _ecx: &mut EvalCtxt<'_, D>,
205 _goal: Goal<I, Self>,
206 _alias_ty: ty::AliasTy<I>,
207 ) -> Vec<Candidate<I>> {
208 ::alloc::vec::Vec::new()vec![]
209 }
210
211 fn consider_impl_candidate(
212 ecx: &mut EvalCtxt<'_, D>,
213 goal: Goal<I, NormalizesTo<I>>,
214 impl_def_id: I::ImplId,
215 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
216 ) -> Result<Candidate<I>, NoSolution> {
217 let cx = ecx.cx();
218
219 let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
220 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
221 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
222 goal.predicate.alias.trait_ref(cx).args,
223 impl_trait_ref.skip_binder().args,
224 ) {
225 return Err(NoSolution);
226 }
227
228 let impl_polarity = cx.impl_polarity(impl_def_id);
230 match impl_polarity {
231 ty::ImplPolarity::Negative => return Err(NoSolution),
232 ty::ImplPolarity::Reservation => {
233 {
::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)
234 }
235 ty::ImplPolarity::Positive => {}
236 };
237
238 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
239 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
240 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
241
242 ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
243
244 let where_clause_bounds = cx
245 .predicates_of(impl_def_id.into())
246 .iter_instantiated(cx, impl_args)
247 .map(Unnormalized::skip_norm_wip)
248 .map(|pred| goal.with(cx, pred));
249 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
250
251 ecx.try_evaluate_added_goals()?;
256
257 ecx.add_goals(
261 GoalSource::AliasWellFormed,
262 cx.own_predicates_of(goal.predicate.def_id())
263 .iter_instantiated(cx, goal.predicate.alias.args)
264 .map(Unnormalized::skip_norm_wip)
265 .map(|pred| goal.with(cx, pred)),
266 );
267
268 let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
269 let error_term = match goal.predicate.alias.kind(cx) {
270 ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(),
271 ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(),
272 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
273 };
274 ecx.instantiate_normalizes_to_term(goal, error_term);
275 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
276 };
277
278 let target_item_def_id = match ecx.fetch_eligible_assoc_item(
279 goal_trait_ref,
280 goal.predicate.def_id(),
281 impl_def_id,
282 ) {
283 Ok(Some(target_item_def_id)) => target_item_def_id,
284 Ok(None) => {
285 match ecx.typing_mode() {
286 ty::TypingMode::Coherence => {
298 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
299 return ecx
300 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
301 }
302 ty::TypingMode::Analysis { .. }
304 | ty::TypingMode::Borrowck { .. }
305 | ty::TypingMode::PostBorrowckAnalysis { .. }
306 | ty::TypingMode::PostAnalysis => {
307 ecx.structurally_instantiate_normalizes_to_term(
308 goal,
309 goal.predicate.alias,
310 );
311 return ecx
312 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
313 }
314 };
315 }
316 Err(guar) => return error_response(ecx, guar),
317 };
318
319 if !cx.has_item_definition(target_item_def_id) {
320 if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
326 match ecx.typing_mode() {
327 ty::TypingMode::Coherence => {
338 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
339 return then(ecx, Certainty::Yes);
340 }
341 ty::TypingMode::Analysis { .. }
342 | ty::TypingMode::Borrowck { .. }
343 | ty::TypingMode::PostBorrowckAnalysis { .. }
344 | ty::TypingMode::PostAnalysis => {
345 ecx.structurally_instantiate_normalizes_to_term(
346 goal,
347 goal.predicate.alias,
348 );
349 return then(ecx, Certainty::Yes);
350 }
351 }
352 } else {
353 return error_response(ecx, cx.delay_bug("missing item"));
354 }
355 }
356
357 let target_container_def_id = cx.parent(target_item_def_id);
358
359 let target_args = ecx.translate_args(
370 goal,
371 impl_def_id,
372 impl_args,
373 impl_trait_ref,
374 target_container_def_id,
375 )?;
376
377 if !cx.check_args_compatible(target_item_def_id, target_args) {
378 return error_response(
379 ecx,
380 cx.delay_bug("associated item has mismatched arguments"),
381 );
382 }
383
384 let term = match goal.predicate.alias.kind(cx) {
386 ty::AliasTermKind::ProjectionTy { .. } => {
387 cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
388 }
389 ty::AliasTermKind::ProjectionConst { .. } => {
390 cx.const_of_item(target_item_def_id).map_bound(|ct| ct.into())
391 }
392 kind => {
::core::panicking::panic_fmt(format_args!("expected projection, found {0:?}",
kind));
}panic!("expected projection, found {kind:?}"),
393 };
394
395 ecx.instantiate_normalizes_to_term(
396 goal,
397 term.instantiate(cx, target_args).skip_norm_wip(),
398 );
399 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
400 })
401 }
402
403 fn consider_error_guaranteed_candidate(
406 _ecx: &mut EvalCtxt<'_, D>,
407 _guar: I::ErrorGuaranteed,
408 ) -> Result<Candidate<I>, NoSolution> {
409 Err(NoSolution)
410 }
411
412 fn consider_auto_trait_candidate(
413 ecx: &mut EvalCtxt<'_, D>,
414 _goal: Goal<I, Self>,
415 ) -> Result<Candidate<I>, NoSolution> {
416 ecx.cx().delay_bug("associated types not allowed on auto traits");
417 Err(NoSolution)
418 }
419
420 fn consider_trait_alias_candidate(
421 _ecx: &mut EvalCtxt<'_, D>,
422 goal: Goal<I, Self>,
423 ) -> Result<Candidate<I>, NoSolution> {
424 {
::core::panicking::panic_fmt(format_args!("trait aliases do not have associated types: {0:?}",
goal));
};panic!("trait aliases do not have associated types: {:?}", goal);
425 }
426
427 fn consider_builtin_sizedness_candidates(
428 _ecx: &mut EvalCtxt<'_, D>,
429 goal: Goal<I, Self>,
430 _sizedness: SizedTraitKind,
431 ) -> Result<Candidate<I>, NoSolution> {
432 {
::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);
433 }
434
435 fn consider_builtin_copy_clone_candidate(
436 _ecx: &mut EvalCtxt<'_, D>,
437 goal: Goal<I, Self>,
438 ) -> Result<Candidate<I>, NoSolution> {
439 {
::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);
440 }
441
442 fn consider_builtin_fn_ptr_trait_candidate(
443 _ecx: &mut EvalCtxt<'_, D>,
444 goal: Goal<I, Self>,
445 ) -> Result<Candidate<I>, NoSolution> {
446 {
::core::panicking::panic_fmt(format_args!("`FnPtr` does not have an associated type: {0:?}",
goal));
};panic!("`FnPtr` does not have an associated type: {:?}", goal);
447 }
448
449 fn consider_builtin_fn_trait_candidates(
450 ecx: &mut EvalCtxt<'_, D>,
451 goal: Goal<I, Self>,
452 goal_kind: ty::ClosureKind,
453 ) -> Result<Candidate<I>, NoSolution> {
454 let cx = ecx.cx();
455 let Some(tupled_inputs_and_output) =
456 structural_traits::extract_tupled_inputs_and_output_from_callable(
457 cx,
458 goal.predicate.self_ty(),
459 goal_kind,
460 )?
461 else {
462 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
463 };
464 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
465
466 let output_is_sized_pred =
469 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
470
471 let pred = ty::ProjectionPredicate {
472 projection_term: ty::AliasTerm::new(
473 cx,
474 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
475 [goal.predicate.self_ty(), inputs],
476 ),
477 term: output.into(),
478 }
479 .upcast(cx);
480
481 Self::probe_and_consider_implied_clause(
482 ecx,
483 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
484 goal,
485 pred,
486 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
487 )
488 }
489
490 fn consider_builtin_async_fn_trait_candidates(
491 ecx: &mut EvalCtxt<'_, D>,
492 goal: Goal<I, Self>,
493 goal_kind: ty::ClosureKind,
494 ) -> Result<Candidate<I>, NoSolution> {
495 let cx = ecx.cx();
496
497 let env_region = match goal_kind {
498 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2),
499 ty::ClosureKind::FnOnce => Region::new_static(cx),
501 };
502 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
503 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
504 cx,
505 goal.predicate.self_ty(),
506 goal_kind,
507 env_region,
508 )?;
509 let AsyncCallableRelevantTypes {
510 tupled_inputs_ty,
511 output_coroutine_ty,
512 coroutine_return_ty,
513 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
514
515 let output_is_sized_pred = ty::TraitRef::new(
518 cx,
519 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
520 [output_coroutine_ty],
521 );
522
523 let (projection_term, term) =
524 if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallOnceFuture) {
525 (
526 ty::AliasTerm::new(
527 cx,
528 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
529 [goal.predicate.self_ty(), tupled_inputs_ty],
530 ),
531 output_coroutine_ty.into(),
532 )
533 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CallRefFuture) {
534 (
535 ty::AliasTerm::new(
536 cx,
537 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
538 [
539 I::GenericArg::from(goal.predicate.self_ty()),
540 tupled_inputs_ty.into(),
541 env_region.into(),
542 ],
543 ),
544 output_coroutine_ty.into(),
545 )
546 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::AsyncFnOnceOutput) {
547 (
548 ty::AliasTerm::new(
549 cx,
550 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
551 [goal.predicate.self_ty(), tupled_inputs_ty],
552 ),
553 coroutine_return_ty.into(),
554 )
555 } else {
556 {
::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())
557 };
558 let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
559
560 Self::probe_and_consider_implied_clause(
561 ecx,
562 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
563 goal,
564 pred,
565 [goal.with(cx, output_is_sized_pred)]
566 .into_iter()
567 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
568 .map(|goal| (GoalSource::ImplWhereBound, goal)),
569 )
570 }
571
572 fn consider_builtin_async_fn_kind_helper_candidate(
573 ecx: &mut EvalCtxt<'_, D>,
574 goal: Goal<I, Self>,
575 ) -> Result<Candidate<I>, NoSolution> {
576 let [
577 closure_fn_kind_ty,
578 goal_kind_ty,
579 borrow_region,
580 tupled_inputs_ty,
581 tupled_upvars_ty,
582 coroutine_captures_by_ref_ty,
583 ] = *goal.predicate.alias.args.as_slice()
584 else {
585 ::core::panicking::panic("explicit panic");panic!();
586 };
587
588 if tupled_upvars_ty.expect_ty().is_ty_var() {
590 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
591 }
592
593 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
594 return Err(NoSolution);
596 };
597 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
598 return Err(NoSolution);
599 };
600 if !closure_kind.extends(goal_kind) {
601 return Err(NoSolution);
602 }
603
604 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
605 ecx.cx(),
606 goal_kind,
607 tupled_inputs_ty.expect_ty(),
608 tupled_upvars_ty.expect_ty(),
609 coroutine_captures_by_ref_ty.expect_ty(),
610 borrow_region.expect_region(),
611 );
612
613 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
614 ecx.instantiate_normalizes_to_term(goal, upvars_ty.into());
615 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
616 })
617 }
618
619 fn consider_builtin_tuple_candidate(
620 _ecx: &mut EvalCtxt<'_, D>,
621 goal: Goal<I, Self>,
622 ) -> Result<Candidate<I>, NoSolution> {
623 {
::core::panicking::panic_fmt(format_args!("`Tuple` does not have an associated type: {0:?}",
goal));
};panic!("`Tuple` does not have an associated type: {:?}", goal);
624 }
625
626 fn consider_builtin_pointee_candidate(
627 ecx: &mut EvalCtxt<'_, D>,
628 goal: Goal<I, Self>,
629 ) -> Result<Candidate<I>, NoSolution> {
630 let cx = ecx.cx();
631 let metadata_def_id = cx.require_lang_item(SolverLangItem::Metadata);
632 match (&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!(metadata_def_id, goal.predicate.def_id());
633 let metadata_ty = match goal.predicate.self_ty().kind() {
634 ty::Bool
635 | ty::Char
636 | ty::Int(..)
637 | ty::Uint(..)
638 | ty::Float(..)
639 | ty::Array(..)
640 | ty::Pat(..)
641 | ty::RawPtr(..)
642 | ty::Ref(..)
643 | ty::FnDef(..)
644 | ty::FnPtr(..)
645 | ty::Closure(..)
646 | ty::CoroutineClosure(..)
647 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
648 | ty::Coroutine(..)
649 | ty::CoroutineWitness(..)
650 | ty::Never
651 | ty::Foreign(..) => Ty::new_unit(cx),
652
653 ty::Error(e) => Ty::new_error(cx, e),
654
655 ty::Str | ty::Slice(_) => Ty::new_usize(cx),
656
657 ty::Dynamic(_, _) => {
658 let dyn_metadata = cx.require_lang_item(SolverLangItem::DynMetadata);
659 cx.type_of(dyn_metadata)
660 .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())])
661 .skip_norm_wip()
662 }
663
664 ty::Alias(_) | ty::Param(_) | ty::Placeholder(..) => {
665 let alias_bound_result =
670 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
671 let sized_predicate = ty::TraitRef::new(
672 cx,
673 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
674 [I::GenericArg::from(goal.predicate.self_ty())],
675 );
676 ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
677 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
678 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
679 });
680 return alias_bound_result.or_else(|NoSolution| {
683 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| {
684 this.structurally_instantiate_normalizes_to_term(
685 goal,
686 goal.predicate.alias,
687 );
688 this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
689 })
690 });
691 }
692
693 ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) {
694 None => Ty::new_unit(cx),
695 Some(tail_ty) => Ty::new_projection(
696 cx,
697 metadata_def_id,
698 [tail_ty.instantiate(cx, args).skip_norm_wip()],
699 ),
700 },
701 ty::Adt(_, _) => Ty::new_unit(cx),
702
703 ty::Tuple(elements) => match elements.last() {
704 None => Ty::new_unit(cx),
705 Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
706 },
707
708 ty::UnsafeBinder(_) => {
709 ::core::panicking::panic("not yet implemented")todo!()
711 }
712
713 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
714 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as Pointee>::Metadata`",
goal.predicate.self_ty()));
}panic!(
715 "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
716 goal.predicate.self_ty()
717 ),
718 };
719
720 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
721 ecx.instantiate_normalizes_to_term(goal, metadata_ty.into());
722 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
723 })
724 }
725
726 fn consider_builtin_future_candidate(
727 ecx: &mut EvalCtxt<'_, D>,
728 goal: Goal<I, Self>,
729 ) -> Result<Candidate<I>, NoSolution> {
730 let self_ty = goal.predicate.self_ty();
731 let ty::Coroutine(def_id, args) = self_ty.kind() else {
732 return Err(NoSolution);
733 };
734
735 let cx = ecx.cx();
737 if !cx.coroutine_is_async(def_id) {
738 return Err(NoSolution);
739 }
740
741 let term = args.as_coroutine().return_ty().into();
742
743 Self::probe_and_consider_implied_clause(
744 ecx,
745 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
746 goal,
747 ty::ProjectionPredicate {
748 projection_term: ty::AliasTerm::new(
749 ecx.cx(),
750 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
751 [self_ty],
752 ),
753 term,
754 }
755 .upcast(cx),
756 [],
759 )
760 }
761
762 fn consider_builtin_iterator_candidate(
763 ecx: &mut EvalCtxt<'_, D>,
764 goal: Goal<I, Self>,
765 ) -> Result<Candidate<I>, NoSolution> {
766 let self_ty = goal.predicate.self_ty();
767 let ty::Coroutine(def_id, args) = self_ty.kind() else {
768 return Err(NoSolution);
769 };
770
771 let cx = ecx.cx();
773 if !cx.coroutine_is_gen(def_id) {
774 return Err(NoSolution);
775 }
776
777 let term = args.as_coroutine().yield_ty().into();
778
779 Self::probe_and_consider_implied_clause(
780 ecx,
781 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
782 goal,
783 ty::ProjectionPredicate {
784 projection_term: ty::AliasTerm::new(
785 ecx.cx(),
786 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
787 [self_ty],
788 ),
789 term,
790 }
791 .upcast(cx),
792 [],
795 )
796 }
797
798 fn consider_builtin_fused_iterator_candidate(
799 _ecx: &mut EvalCtxt<'_, D>,
800 goal: Goal<I, Self>,
801 ) -> Result<Candidate<I>, NoSolution> {
802 {
::core::panicking::panic_fmt(format_args!("`FusedIterator` does not have an associated type: {0:?}",
goal));
};panic!("`FusedIterator` does not have an associated type: {:?}", goal);
803 }
804
805 fn consider_builtin_async_iterator_candidate(
806 ecx: &mut EvalCtxt<'_, D>,
807 goal: Goal<I, Self>,
808 ) -> Result<Candidate<I>, NoSolution> {
809 let self_ty = goal.predicate.self_ty();
810 let ty::Coroutine(def_id, args) = self_ty.kind() else {
811 return Err(NoSolution);
812 };
813
814 let cx = ecx.cx();
816 if !cx.coroutine_is_async_gen(def_id) {
817 return Err(NoSolution);
818 }
819
820 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
821 let expected_ty = ecx.next_ty_infer();
822 let wrapped_expected_ty = Ty::new_adt(
825 cx,
826 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)),
827 cx.mk_args(&[Ty::new_adt(
828 cx,
829 cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)),
830 cx.mk_args(&[expected_ty.into()]),
831 )
832 .into()]),
833 );
834 let yield_ty = args.as_coroutine().yield_ty();
835 ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?;
836 ecx.instantiate_normalizes_to_term(goal, expected_ty.into());
837 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
838 })
839 }
840
841 fn consider_builtin_coroutine_candidate(
842 ecx: &mut EvalCtxt<'_, D>,
843 goal: Goal<I, Self>,
844 ) -> Result<Candidate<I>, NoSolution> {
845 let self_ty = goal.predicate.self_ty();
846 let ty::Coroutine(def_id, args) = self_ty.kind() else {
847 return Err(NoSolution);
848 };
849
850 let cx = ecx.cx();
852 if !cx.is_general_coroutine(def_id) {
853 return Err(NoSolution);
854 }
855
856 let coroutine = args.as_coroutine();
857
858 let term = if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineReturn) {
859 coroutine.return_ty().into()
860 } else if cx.is_lang_item(goal.predicate.def_id(), SolverLangItem::CoroutineYield) {
861 coroutine.yield_ty().into()
862 } else {
863 {
::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())
864 };
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(
872 ecx.cx(),
873 cx.alias_term_kind_from_def_id(goal.predicate.def_id()),
874 [self_ty, coroutine.resume_ty()],
875 ),
876 term,
877 }
878 .upcast(cx),
879 [],
882 )
883 }
884
885 fn consider_structural_builtin_unsize_candidates(
886 _ecx: &mut EvalCtxt<'_, D>,
887 goal: Goal<I, Self>,
888 ) -> Vec<Candidate<I>> {
889 {
::core::panicking::panic_fmt(format_args!("`Unsize` does not have an associated type: {0:?}",
goal));
};panic!("`Unsize` does not have an associated type: {:?}", goal);
890 }
891
892 fn consider_builtin_discriminant_kind_candidate(
893 ecx: &mut EvalCtxt<'_, D>,
894 goal: Goal<I, Self>,
895 ) -> Result<Candidate<I>, NoSolution> {
896 let self_ty = goal.predicate.self_ty();
897 let discriminant_ty = match self_ty.kind() {
898 ty::Bool
899 | ty::Char
900 | ty::Int(..)
901 | ty::Uint(..)
902 | ty::Float(..)
903 | ty::Array(..)
904 | ty::Pat(..)
905 | ty::RawPtr(..)
906 | ty::Ref(..)
907 | ty::FnDef(..)
908 | ty::FnPtr(..)
909 | ty::Closure(..)
910 | ty::CoroutineClosure(..)
911 | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
912 | ty::Coroutine(..)
913 | ty::CoroutineWitness(..)
914 | ty::Never
915 | ty::Foreign(..)
916 | ty::Adt(_, _)
917 | ty::Str
918 | ty::Slice(_)
919 | ty::Dynamic(_, _)
920 | ty::Tuple(_)
921 | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
922
923 ty::UnsafeBinder(_) => {
924 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("discr subgoal...")));
}todo!("discr subgoal...")
926 }
927
928 ty::Alias(_) | ty::Param(_) | ty::Placeholder(..) => {
932 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
933 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
934 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
935 });
936 }
937
938 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
939 | ty::Bound(..) => {
::core::panicking::panic_fmt(format_args!("unexpected self ty `{0:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
goal.predicate.self_ty()));
}panic!(
940 "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
941 goal.predicate.self_ty()
942 ),
943 };
944
945 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
946 ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into());
947 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
948 })
949 }
950
951 fn consider_builtin_destruct_candidate(
952 _ecx: &mut EvalCtxt<'_, D>,
953 goal: Goal<I, Self>,
954 ) -> Result<Candidate<I>, NoSolution> {
955 {
::core::panicking::panic_fmt(format_args!("`Destruct` does not have an associated type: {0:?}",
goal));
};panic!("`Destruct` does not have an associated type: {:?}", goal);
956 }
957
958 fn consider_builtin_transmute_candidate(
959 _ecx: &mut EvalCtxt<'_, D>,
960 goal: Goal<I, Self>,
961 ) -> Result<Candidate<I>, NoSolution> {
962 {
::core::panicking::panic_fmt(format_args!("`TransmuteFrom` does not have an associated type: {0:?}",
goal));
}panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
963 }
964
965 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
966 _ecx: &mut EvalCtxt<'_, D>,
967 goal: Goal<I, Self>,
968 ) -> Result<Candidate<I>, NoSolution> {
969 {
::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)
970 }
971
972 fn consider_builtin_field_candidate(
973 ecx: &mut EvalCtxt<'_, D>,
974 goal: Goal<I, Self>,
975 ) -> Result<Candidate<I>, NoSolution> {
976 let self_ty = goal.predicate.self_ty();
977 let ty::Adt(def, args) = self_ty.kind() else {
978 return Err(NoSolution);
979 };
980 let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
981 else {
982 return Err(NoSolution);
983 };
984 let ty = match ecx.cx().as_lang_item(goal.predicate.def_id()) {
985 Some(SolverLangItem::FieldBase) => base,
986 Some(SolverLangItem::FieldType) => ty,
987 _ => {
::core::panicking::panic_fmt(format_args!("unexpected associated type {0:?} in `Field`",
goal.predicate));
}panic!("unexpected associated type {:?} in `Field`", goal.predicate),
988 };
989 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
990 ecx.instantiate_normalizes_to_term(goal, ty.into());
991 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
992 })
993 }
994}
995
996impl<D, I> EvalCtxt<'_, D>
997where
998 D: SolverDelegate<Interner = I>,
999 I: Interner,
1000{
1001 fn translate_args(
1002 &mut self,
1003 goal: Goal<I, ty::NormalizesTo<I>>,
1004 impl_def_id: I::ImplId,
1005 impl_args: I::GenericArgs,
1006 impl_trait_ref: rustc_type_ir::TraitRef<I>,
1007 target_container_def_id: I::DefId,
1008 ) -> Result<I::GenericArgs, NoSolution> {
1009 let cx = self.cx();
1010 Ok(if target_container_def_id == impl_trait_ref.def_id.into() {
1011 goal.predicate.alias.args
1013 } else if target_container_def_id == impl_def_id.into() {
1014 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), impl_args)
1017 } else {
1018 let target_args = self.fresh_args_for_item(target_container_def_id);
1019 let target_trait_ref = cx
1020 .impl_trait_ref(target_container_def_id.try_into().unwrap())
1021 .instantiate(cx, target_args)
1022 .skip_norm_wip();
1023 self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
1025 self.add_goals(
1028 GoalSource::Misc,
1029 cx.predicates_of(target_container_def_id)
1030 .iter_instantiated(cx, target_args)
1031 .map(Unnormalized::skip_norm_wip)
1032 .map(|pred| goal.with(cx, pred)),
1033 );
1034 goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args)
1035 })
1036 }
1037}