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