1use rustc_type_ir::data_structures::IndexSet;
4use rustc_type_ir::fast_reject::DeepRejectCtxt;
5use rustc_type_ir::inherent::*;
6use rustc_type_ir::lang_items::SolverTraitLangItem;
7use rustc_type_ir::solve::{
8 AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, MaybeInfo,
9 NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunNonErased,
10 RerunReason, RerunResultExt, SizedTraitKind,
11};
12use rustc_type_ir::{
13 self as ty, FieldInfo, Interner, MayBeErased, Movability, PredicatePolarity, Region,
14 TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _,
15 elaborate,
16};
17use tracing::{debug, instrument, trace, warn};
18
19use crate::delegate::SolverDelegate;
20use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
21use crate::solve::assembly::{
22 self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate, FailedCandidateInfo,
23};
24use crate::solve::inspect::ProbeKind;
25use crate::solve::{
26 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
27 MergeCandidateInfo, NoSolution, ParamEnvSource, StalledOnCoroutines,
28 has_only_region_constraints,
29};
30
31impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
32where
33 D: SolverDelegate<Interner = I>,
34 I: Interner,
35{
36 fn self_ty(self) -> I::Ty {
37 self.self_ty()
38 }
39
40 fn trait_ref(self, _: I) -> ty::TraitRef<I> {
41 self.trait_ref
42 }
43
44 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
45 self.with_replaced_self_ty(cx, self_ty)
46 }
47
48 fn trait_def_id(self, _: I) -> I::TraitId {
49 self.def_id()
50 }
51
52 fn consider_additional_alias_assumptions(
53 _ecx: &mut EvalCtxt<'_, D>,
54 _goal: Goal<I, Self>,
55 _alias_ty: ty::AliasTy<I>,
56 ) -> Vec<Candidate<I>> {
57 ::alloc::vec::Vec::new()vec![]
58 }
59
60 fn consider_impl_candidate(
61 ecx: &mut EvalCtxt<'_, D>,
62 goal: Goal<I, TraitPredicate<I>>,
63 impl_def_id: I::ImplId,
64 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
65 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
66 let cx = ecx.cx();
67
68 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
69 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
70 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
71 {
72 return Err(NoSolution.into());
73 }
74
75 let impl_polarity = cx.impl_polarity(impl_def_id);
78 let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
79 (ty::ImplPolarity::Reservation, _) => {
81 if ecx.typing_mode().is_coherence() {
82 Certainty::AMBIGUOUS
83 } else {
84 return Err(NoSolution.into());
85 }
86 }
87
88 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
90 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => Certainty::Yes,
91
92 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative)
94 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Positive) => {
95 return Err(NoSolution.into());
96 }
97 };
98
99 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
100 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
101 ecx.record_impl_args(impl_args);
102 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
103
104 ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
105 let where_clause_bounds = cx
106 .predicates_of(impl_def_id.into())
107 .iter_instantiated(cx, impl_args)
108 .map(Unnormalized::skip_norm_wip)
109 .map(|pred| goal.with(cx, pred));
110 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
111
112 ecx.add_goals(
116 GoalSource::Misc,
117 cx.impl_super_outlives(impl_def_id)
118 .iter_instantiated(cx, impl_args)
119 .map(Unnormalized::skip_norm_wip)
120 .map(|pred| goal.with(cx, pred)),
121 )?;
122
123 then(ecx, maximal_certainty)
124 })
125 }
126
127 fn consider_error_guaranteed_candidate(
128 ecx: &mut EvalCtxt<'_, D>,
129 _goal: Goal<I, Self>,
130 _guar: I::ErrorGuaranteed,
131 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
132 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
133 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
134 }
135
136 fn fast_reject_assumption(
137 ecx: &mut EvalCtxt<'_, D>,
138 goal: Goal<I, Self>,
139 assumption: I::Clause,
140 ) -> Result<(), NoSolution> {
141 fn trait_def_id_matches<I: Interner>(
142 cx: I,
143 clause_def_id: I::TraitId,
144 goal_def_id: I::TraitId,
145 polarity: PredicatePolarity,
146 ) -> bool {
147 clause_def_id == goal_def_id
148 || (polarity == PredicatePolarity::Positive
153 && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
154 && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
155 }
156
157 if let Some(trait_clause) = assumption.as_trait_clause()
158 && trait_clause.polarity() == goal.predicate.polarity
159 && trait_def_id_matches(
160 ecx.cx(),
161 trait_clause.def_id(),
162 goal.predicate.def_id(),
163 goal.predicate.polarity,
164 )
165 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
166 goal.predicate.trait_ref.args,
167 trait_clause.skip_binder().trait_ref.args,
168 )
169 {
170 return Ok(());
171 } else {
172 Err(NoSolution)
173 }
174 }
175
176 fn match_assumption(
177 ecx: &mut EvalCtxt<'_, D>,
178 goal: Goal<I, Self>,
179 assumption: I::Clause,
180 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
181 ) -> QueryResultOrRerunNonErased<I> {
182 let trait_clause = assumption.as_trait_clause().unwrap();
183
184 if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
190 && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
191 {
192 let meta_sized_clause =
193 trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
194 return Self::match_assumption(ecx, goal, meta_sized_clause, then);
195 }
196
197 let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
198 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
199
200 then(ecx)
201 }
202
203 fn consider_auto_trait_candidate(
204 ecx: &mut EvalCtxt<'_, D>,
205 goal: Goal<I, Self>,
206 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
207 let cx = ecx.cx();
208 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
209 return Err(NoSolution.into());
210 }
211
212 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
213 return result;
214 }
215
216 if cx.trait_is_unsafe(goal.predicate.def_id())
219 && goal.predicate.self_ty().has_unsafe_fields()
220 {
221 return Err(NoSolution.into());
222 }
223
224 if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) =
240 goal.predicate.self_ty().kind()
241 {
242 if true {
if !(is_rigid == ty::IsRigid::Yes) {
::core::panicking::panic("assertion failed: is_rigid == ty::IsRigid::Yes")
};
};debug_assert!(is_rigid == ty::IsRigid::Yes);
243 if ecx.opaque_accesses.might_rerun() {
244 ecx.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)?;
245 return Err(NoSolution.into());
246 }
247
248 for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() {
249 if item_bound
250 .as_trait_clause()
251 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
252 {
253 return Err(NoSolution.into());
254 }
255 }
256 }
257
258 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
260 return cand;
261 }
262
263 ecx.probe_and_evaluate_goal_for_constituent_tys(
264 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
265 goal,
266 structural_traits::instantiate_constituent_tys_for_auto_trait,
267 )
268 }
269
270 fn consider_trait_alias_candidate(
271 ecx: &mut EvalCtxt<'_, D>,
272 goal: Goal<I, Self>,
273 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
274 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
275 return Err(NoSolution.into());
276 }
277
278 let cx = ecx.cx();
279
280 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
281 let nested_obligations = cx
282 .predicates_of(goal.predicate.def_id().into())
283 .iter_instantiated(cx, goal.predicate.trait_ref.args)
284 .map(Unnormalized::skip_norm_wip)
285 .map(|p| goal.with(cx, p));
286 ecx.add_goals(GoalSource::Misc, nested_obligations)?;
292 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
293 })
294 }
295
296 fn consider_builtin_sizedness_candidates(
297 ecx: &mut EvalCtxt<'_, D>,
298 goal: Goal<I, Self>,
299 sizedness: SizedTraitKind,
300 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
301 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
302 return Err(NoSolution.into());
303 }
304
305 ecx.probe_and_evaluate_goal_for_constituent_tys(
306 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
307 goal,
308 |ecx, ty| {
309 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
310 ecx, sizedness, ty,
311 )
312 },
313 )
314 }
315
316 fn consider_builtin_copy_clone_candidate(
317 ecx: &mut EvalCtxt<'_, D>,
318 goal: Goal<I, Self>,
319 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
320 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
321 return Err(NoSolution.into());
322 }
323
324 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
326 return cand;
327 }
328
329 ecx.probe_and_evaluate_goal_for_constituent_tys(
330 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
331 goal,
332 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
333 )
334 }
335
336 fn consider_builtin_fn_ptr_trait_candidate(
337 ecx: &mut EvalCtxt<'_, D>,
338 goal: Goal<I, Self>,
339 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
340 let self_ty = goal.predicate.self_ty();
341 match goal.predicate.polarity {
342 ty::PredicatePolarity::Positive => {
344 if self_ty.is_fn_ptr() {
345 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
346 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
347 })
348 } else {
349 Err(NoSolution.into())
350 }
351 }
352 ty::PredicatePolarity::Negative => {
354 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
357 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
358 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
359 })
360 } else {
361 Err(NoSolution.into())
362 }
363 }
364 }
365 }
366
367 fn consider_builtin_fn_trait_candidates(
368 ecx: &mut EvalCtxt<'_, D>,
369 goal: Goal<I, Self>,
370 goal_kind: ty::ClosureKind,
371 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
372 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
373 return Err(NoSolution.into());
374 }
375
376 let cx = ecx.cx();
377 let Some(tupled_inputs_and_output) =
378 structural_traits::extract_tupled_inputs_and_output_from_callable(
379 cx,
380 goal.predicate.self_ty(),
381 goal_kind,
382 )?
383 else {
384 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
385 };
386 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
387
388 let output_is_sized_pred =
391 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
392
393 let pred =
394 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
395 .upcast(cx);
396 Self::probe_and_consider_implied_clause(
397 ecx,
398 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
399 goal,
400 pred,
401 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
402 )
403 }
404
405 fn consider_builtin_async_fn_trait_candidates(
406 ecx: &mut EvalCtxt<'_, D>,
407 goal: Goal<I, Self>,
408 goal_kind: ty::ClosureKind,
409 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
410 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
411 return Err(NoSolution.into());
412 }
413
414 let cx = ecx.cx();
415 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
416 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
417 cx,
418 goal.predicate.self_ty(),
419 goal_kind,
420 Region::new_static(cx),
422 )?;
423 let AsyncCallableRelevantTypes {
424 tupled_inputs_ty,
425 output_coroutine_ty,
426 coroutine_return_ty: _,
427 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
428
429 let output_is_sized_pred = ty::TraitRef::new(
432 cx,
433 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
434 [output_coroutine_ty],
435 );
436
437 let pred = ty::TraitRef::new(
438 cx,
439 goal.predicate.def_id(),
440 [goal.predicate.self_ty(), tupled_inputs_ty],
441 )
442 .upcast(cx);
443 Self::probe_and_consider_implied_clause(
444 ecx,
445 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
446 goal,
447 pred,
448 [goal.with(cx, output_is_sized_pred)]
449 .into_iter()
450 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
451 .map(|goal| (GoalSource::ImplWhereBound, goal)),
452 )
453 }
454
455 fn consider_builtin_async_fn_kind_helper_candidate(
456 ecx: &mut EvalCtxt<'_, D>,
457 goal: Goal<I, Self>,
458 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
459 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
460 ::core::panicking::panic("explicit panic");panic!();
461 };
462
463 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
464 return Err(NoSolution.into());
466 };
467 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
468 if closure_kind.extends(goal_kind) {
469 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
470 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
471 } else {
472 Err(NoSolution.into())
473 }
474 }
475
476 fn consider_builtin_tuple_candidate(
483 ecx: &mut EvalCtxt<'_, D>,
484 goal: Goal<I, Self>,
485 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
486 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
487 return Err(NoSolution.into());
488 }
489
490 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
491 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
492 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
493 } else {
494 Err(NoSolution.into())
495 }
496 }
497
498 fn consider_builtin_pointee_candidate(
499 ecx: &mut EvalCtxt<'_, D>,
500 goal: Goal<I, Self>,
501 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
502 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
503 return Err(NoSolution.into());
504 }
505
506 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
507 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
508 }
509
510 fn consider_builtin_future_candidate(
511 ecx: &mut EvalCtxt<'_, D>,
512 goal: Goal<I, Self>,
513 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
514 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
515 return Err(NoSolution.into());
516 }
517
518 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
519 return Err(NoSolution.into());
520 };
521
522 let cx = ecx.cx();
524 if !cx.coroutine_is_async(def_id) {
525 return Err(NoSolution.into());
526 }
527
528 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
532 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
533 }
534
535 fn consider_builtin_iterator_candidate(
536 ecx: &mut EvalCtxt<'_, D>,
537 goal: Goal<I, Self>,
538 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
539 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
540 return Err(NoSolution.into());
541 }
542
543 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
544 return Err(NoSolution.into());
545 };
546
547 let cx = ecx.cx();
549 if !cx.coroutine_is_gen(def_id) {
550 return Err(NoSolution.into());
551 }
552
553 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
557 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
558 }
559
560 fn consider_builtin_fused_iterator_candidate(
561 ecx: &mut EvalCtxt<'_, D>,
562 goal: Goal<I, Self>,
563 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
564 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
565 return Err(NoSolution.into());
566 }
567
568 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
569 return Err(NoSolution.into());
570 };
571
572 let cx = ecx.cx();
574 if !cx.coroutine_is_gen(def_id) {
575 return Err(NoSolution.into());
576 }
577
578 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
580 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
581 }
582
583 fn consider_builtin_async_iterator_candidate(
584 ecx: &mut EvalCtxt<'_, D>,
585 goal: Goal<I, Self>,
586 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
587 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
588 return Err(NoSolution.into());
589 }
590
591 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
592 return Err(NoSolution.into());
593 };
594
595 let cx = ecx.cx();
597 if !cx.coroutine_is_async_gen(def_id) {
598 return Err(NoSolution.into());
599 }
600
601 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
605 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
606 }
607
608 fn consider_builtin_coroutine_candidate(
609 ecx: &mut EvalCtxt<'_, D>,
610 goal: Goal<I, Self>,
611 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
612 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
613 return Err(NoSolution.into());
614 }
615
616 let self_ty = goal.predicate.self_ty();
617 let ty::Coroutine(def_id, args) = self_ty.kind() else {
618 return Err(NoSolution.into());
619 };
620
621 let cx = ecx.cx();
623 if !cx.is_general_coroutine(def_id) {
624 return Err(NoSolution.into());
625 }
626
627 let coroutine = args.as_coroutine();
628 Self::probe_and_consider_implied_clause(
629 ecx,
630 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
631 goal,
632 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
633 .upcast(cx),
634 [],
637 )
638 }
639
640 fn consider_builtin_discriminant_kind_candidate(
641 ecx: &mut EvalCtxt<'_, D>,
642 goal: Goal<I, Self>,
643 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
644 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
645 return Err(NoSolution.into());
646 }
647
648 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
650 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
651 }
652
653 fn consider_builtin_destruct_candidate(
654 ecx: &mut EvalCtxt<'_, D>,
655 goal: Goal<I, Self>,
656 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
657 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
658 return Err(NoSolution.into());
659 }
660
661 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
664 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
665 }
666
667 fn consider_builtin_transmute_candidate(
668 ecx: &mut EvalCtxt<'_, D>,
669 goal: Goal<I, Self>,
670 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
671 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
672 return Err(NoSolution.into());
673 }
674
675 if goal.predicate.has_non_region_placeholders() {
677 return Err(NoSolution.into());
678 }
679
680 if goal.has_non_region_infer() {
683 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
684 }
685
686 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(
687 |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
688 let assume = ecx.structurally_normalize_const(
689 goal.param_env,
690 goal.predicate.trait_ref.args.const_at(2),
691 )?;
692
693 let certainty = ecx.is_transmutable(
694 goal.predicate.trait_ref.args.type_at(0),
695 goal.predicate.trait_ref.args.type_at(1),
696 assume,
697 )?;
698 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
699 },
700 )
701 }
702
703 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
716 ecx: &mut EvalCtxt<'_, D>,
717 goal: Goal<I, Self>,
718 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
719 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
720 return Err(NoSolution.into());
721 }
722
723 let cx = ecx.cx();
724 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
725 let ty = goal.predicate.self_ty();
726 match ty.kind() {
727 ty::Ref(..) => {}
729 ty::Adt(def, _) if def.is_manually_drop() => {}
731 ty::Tuple(tys) => {
734 ecx.add_goals(
735 GoalSource::ImplWhereBound,
736 tys.iter().map(|elem_ty| {
737 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
738 }),
739 )?;
740 }
741 ty::Array(elem_ty, _) => {
742 ecx.add_goal(
743 GoalSource::ImplWhereBound,
744 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
745 )?;
746 }
747
748 ty::FnDef(..)
752 | ty::FnPtr(..)
753 | ty::Error(_)
754 | ty::Uint(_)
755 | ty::Int(_)
756 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
757 | ty::Bool
758 | ty::Float(_)
759 | ty::Char
760 | ty::RawPtr(..)
761 | ty::Never
762 | ty::Pat(..)
763 | ty::Dynamic(..)
764 | ty::Str
765 | ty::Slice(_)
766 | ty::Foreign(..)
767 | ty::Adt(..)
768 | ty::Alias(..)
769 | ty::Param(_)
770 | ty::Placeholder(..)
771 | ty::Closure(..)
772 | ty::CoroutineClosure(..)
773 | ty::Coroutine(..)
774 | ty::UnsafeBinder(_)
775 | ty::CoroutineWitness(..) => {
776 ecx.add_goal(
777 GoalSource::ImplWhereBound,
778 goal.with(
779 cx,
780 ty::TraitRef::new(
781 cx,
782 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
783 [ty],
784 ),
785 ),
786 )?;
787 }
788
789 ty::Bound(..)
790 | ty::Infer(
791 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
792 ) => {
793 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
794 }
795 }
796
797 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
798 })
799 }
800
801 fn consider_structural_builtin_unsize_candidates(
809 ecx: &mut EvalCtxt<'_, D>,
810 goal: Goal<I, Self>,
811 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
812 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
813 return Ok(::alloc::vec::Vec::new()vec![]);
814 }
815
816 let result = ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(
817 |ecx| -> Result<Vec<Candidate<I>>, NoSolutionOrRerunNonErased> {
818 let a_ty = goal.predicate.self_ty();
819 let b_ty = ecx.structurally_normalize_ty(
822 goal.param_env,
823 goal.predicate.trait_ref.args.type_at(1),
824 )?;
825
826 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
827 match (a_ty.kind(), b_ty.kind()) {
828 (ty::Infer(ty::TyVar(..)), ..) => {
::core::panicking::panic_fmt(format_args!("unexpected infer {0:?} {1:?}",
a_ty, b_ty));
}panic!("unexpected infer {a_ty:?} {b_ty:?}"),
829
830 (_, ty::Infer(ty::TyVar(..))) => {
831 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?]))vec![ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?])
832 }
833
834 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => Ok(ecx
836 .consider_builtin_dyn_upcast_candidates(
837 goal, a_data, a_region, b_data, b_region,
838 )),
839
840 (_, ty::Dynamic(b_region, b_data)) => Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region,
b_data)?]))vec![
842 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data)?,
843 ]),
844
845 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
847 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?]))vec![ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?])
848 }
849
850 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
852 if a_def.is_struct() && a_def == b_def =>
853 {
854 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?]))vec![ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?])
855 }
856
857 _ => Err(NoSolution.into()),
858 }
859 },
860 );
861
862 match result.map_err_to_rerun()? {
863 Ok(resp) => Ok(resp),
864 Err(NoSolution) => Ok(::alloc::vec::Vec::new()vec![]),
865 }
866 }
867
868 fn consider_builtin_field_candidate(
869 ecx: &mut EvalCtxt<'_, D>,
870 goal: Goal<I, Self>,
871 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
872 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
873 return Err(NoSolution.into());
874 }
875 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
876 && let Some(FieldInfo { base, ty, .. }) =
877 def.field_representing_type_info(ecx.cx(), args)
878 && {
879 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
880 ecx.add_goal(
888 GoalSource::ImplWhereBound,
889 Goal {
890 param_env: goal.param_env,
891 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
892 },
893 )?;
894 ecx.add_goal(
895 GoalSource::ImplWhereBound,
896 Goal {
897 param_env: goal.param_env,
898 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
899 },
900 )?;
901 ecx.try_evaluate_added_goals()? == Certainty::Yes
904 }
905 && match base.kind() {
906 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
907 ty::Tuple(..) => true,
908 _ => false,
909 }
910 {
911 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
912 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
913 } else {
914 Err(NoSolution.into())
915 }
916 }
917}
918
919#[inline(always)]
925fn trait_predicate_with_def_id<I: Interner>(
926 cx: I,
927 clause: ty::Binder<I, ty::TraitPredicate<I>>,
928 did: I::TraitId,
929) -> I::Clause {
930 clause
931 .map_bound(|c| TraitPredicate {
932 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
933 polarity: c.polarity,
934 })
935 .upcast(cx)
936}
937
938impl<D, I> EvalCtxt<'_, D>
939where
940 D: SolverDelegate<Interner = I>,
941 I: Interner,
942{
943 fn consider_builtin_dyn_upcast_candidates(
953 &mut self,
954 goal: Goal<I, (I::Ty, I::Ty)>,
955 a_data: I::BoundExistentialPredicates,
956 a_region: Region<I>,
957 b_data: I::BoundExistentialPredicates,
958 b_region: Region<I>,
959 ) -> Vec<Candidate<I>> {
960 let cx = self.cx();
961 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
962
963 let mut responses = ::alloc::vec::Vec::new()vec![];
964 let b_principal_def_id = b_data.principal_def_id();
967 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
968 responses.extend(self.consider_builtin_upcast_to_principal(
969 goal,
970 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
971 a_data,
972 a_region,
973 b_data,
974 b_region,
975 a_data.principal(),
976 ));
977 } else if let Some(a_principal) = a_data.principal() {
978 for (idx, new_a_principal) in
979 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
980 .enumerate()
981 .skip(1)
982 {
983 responses.extend(self.consider_builtin_upcast_to_principal(
984 goal,
985 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
986 a_data,
987 a_region,
988 b_data,
989 b_region,
990 Some(new_a_principal.map_bound(|trait_ref| {
991 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
992 })),
993 ));
994 }
995 }
996
997 responses
998 }
999
1000 fn consider_builtin_unsize_to_dyn_candidate(
1001 &mut self,
1002 goal: Goal<I, (I::Ty, I::Ty)>,
1003 b_data: I::BoundExistentialPredicates,
1004 b_region: Region<I>,
1005 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1006 let cx = self.cx();
1007 let Goal { predicate: (a_ty, _), .. } = goal;
1008
1009 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1011 return Err(NoSolution.into());
1012 }
1013
1014 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1015 ecx.add_goals(
1018 GoalSource::ImplWhereBound,
1019 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1020 )?;
1021
1022 ecx.add_goal(
1024 GoalSource::ImplWhereBound,
1025 goal.with(
1026 cx,
1027 ty::TraitRef::new(
1028 cx,
1029 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1030 [a_ty],
1031 ),
1032 ),
1033 )?;
1034
1035 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)))?;
1037 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1038 })
1039 }
1040
1041 fn consider_builtin_upcast_to_principal(
1042 &mut self,
1043 goal: Goal<I, (I::Ty, I::Ty)>,
1044 source: CandidateSource<I>,
1045 a_data: I::BoundExistentialPredicates,
1046 a_region: Region<I>,
1047 b_data: I::BoundExistentialPredicates,
1048 b_region: Region<I>,
1049 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1050 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1051 let param_env = goal.param_env;
1052
1053 let a_auto_traits: IndexSet<I::TraitId> = a_data
1057 .auto_traits()
1058 .into_iter()
1059 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1060 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1061 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1062 }))
1063 .collect();
1064
1065 let projection_may_match =
1070 |ecx: &mut EvalCtxt<'_, D>,
1071 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1072 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1073 source_projection.item_def_id() == target_projection.item_def_id()
1074 && ecx
1075 .probe(|_| ProbeKind::ProjectionCompatibility)
1076 .enter(|ecx| {
1077 ecx.enter_forall_with_assumptions(
1078 target_projection,
1079 param_env,
1080 |ecx, target_projection| {
1081 let source_projection =
1082 ecx.instantiate_binder_with_infer(source_projection);
1083 ecx.eq(param_env, source_projection, target_projection)?;
1084 ecx.try_evaluate_added_goals()
1085 },
1086 )
1087 })
1088 .is_ok()
1089 };
1090
1091 self.probe_trait_candidate(source).enter(|ecx| {
1092 for bound in b_data.iter() {
1093 match bound.skip_binder() {
1094 ty::ExistentialPredicate::Trait(target_principal) => {
1097 let source_principal = upcast_principal.unwrap();
1098 let target_principal = bound.rebind(target_principal);
1099 ecx.enter_forall_with_assumptions(
1100 target_principal,
1101 param_env,
1102 |ecx, target_principal| {
1103 let source_principal =
1104 ecx.instantiate_binder_with_infer(source_principal);
1105 ecx.eq(param_env, source_principal, target_principal)?;
1106 ecx.try_evaluate_added_goals()
1107 },
1108 )?;
1109 }
1110 ty::ExistentialPredicate::Projection(target_projection) => {
1116 let target_projection = bound.rebind(target_projection);
1117 let mut matching_projections =
1118 a_data.projection_bounds().into_iter().filter(|source_projection| {
1119 projection_may_match(ecx, *source_projection, target_projection)
1120 });
1121 let Some(source_projection) = matching_projections.next() else {
1122 return Err(NoSolution.into());
1123 };
1124 if matching_projections.next().is_some() {
1125 return ecx.evaluate_added_goals_and_make_canonical_response(
1126 Certainty::AMBIGUOUS,
1127 );
1128 }
1129 ecx.enter_forall_with_assumptions(
1130 target_projection,
1131 param_env,
1132 |ecx, target_projection| {
1133 let source_projection =
1134 ecx.instantiate_binder_with_infer(source_projection);
1135 ecx.eq(param_env, source_projection, target_projection)?;
1136 ecx.try_evaluate_added_goals()
1137 },
1138 )?;
1139 }
1140 ty::ExistentialPredicate::AutoTrait(def_id) => {
1142 if !a_auto_traits.contains(&def_id) {
1143 return Err(NoSolution.into());
1144 }
1145 }
1146 }
1147 }
1148
1149 ecx.add_goal(
1151 GoalSource::ImplWhereBound,
1152 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1153 )?;
1154
1155 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1156 })
1157 }
1158
1159 fn consider_builtin_array_unsize(
1168 &mut self,
1169 goal: Goal<I, (I::Ty, I::Ty)>,
1170 a_elem_ty: I::Ty,
1171 b_elem_ty: I::Ty,
1172 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1173 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1174 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1175 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1176 }
1177
1178 fn consider_builtin_struct_unsize(
1192 &mut self,
1193 goal: Goal<I, (I::Ty, I::Ty)>,
1194 def: I::AdtDef,
1195 a_args: I::GenericArgs,
1196 b_args: I::GenericArgs,
1197 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1198 let cx = self.cx();
1199 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1200
1201 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1202 if unsizing_params.is_empty() {
1205 return Err(NoSolution.into());
1206 }
1207
1208 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1209
1210 let a_tail_ty = tail_field_ty.instantiate(cx, a_args).skip_norm_wip();
1211 let b_tail_ty = tail_field_ty.instantiate(cx, b_args).skip_norm_wip();
1212
1213 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1217 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1218 }));
1219 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1220
1221 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1224 self.add_goal(
1225 GoalSource::ImplWhereBound,
1226 goal.with(
1227 cx,
1228 ty::TraitRef::new(
1229 cx,
1230 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1231 [a_tail_ty, b_tail_ty],
1232 ),
1233 ),
1234 )?;
1235 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1236 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1237 }
1238
1239 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1244 &mut self,
1245 goal: Goal<I, TraitPredicate<I>>,
1246 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1247 let self_ty = goal.predicate.self_ty();
1248 let check_impls = || {
1249 let mut disqualifying_impl = None;
1250 self.cx().for_each_relevant_impl(goal.predicate.trait_ref, |impl_def_id| {
1251 disqualifying_impl = Some(impl_def_id);
1252 });
1253 if let Some(def_id) = disqualifying_impl {
1254 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1254",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1254u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("disqualified auto-trait implementation")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(?def_id, ?goal, "disqualified auto-trait implementation");
1255 return Some(Err(NoSolution.into()));
1258 } else {
1259 None
1260 }
1261 };
1262
1263 match self_ty.kind() {
1264 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1270 Some(self.forced_ambiguity(MaybeInfo::AMBIGUOUS))
1271 }
1272
1273 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1276
1277 ty::Dynamic(..)
1280 | ty::Param(..)
1281 | ty::Foreign(..)
1282 | ty::Alias(
1283 ty::IsRigid::Yes,
1284 ty::AliasTy {
1285 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1286 ..
1287 },
1288 )
1289 | ty::Placeholder(..) => Some(Err(NoSolution.into())),
1290
1291 ty::Coroutine(def_id, _)
1295 if self
1296 .cx()
1297 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1298 {
1299 match self.cx().coroutine_movability(def_id) {
1300 Movability::Static => Some(Err(NoSolution.into())),
1301 Movability::Movable => Some(
1302 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1303 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1304 }),
1305 ),
1306 }
1307 }
1308
1309 ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => None,
1314
1315 ty::Bool
1322 | ty::Char
1323 | ty::Int(_)
1324 | ty::Uint(_)
1325 | ty::Float(_)
1326 | ty::Str
1327 | ty::Array(_, _)
1328 | ty::Pat(_, _)
1329 | ty::Slice(_)
1330 | ty::RawPtr(_, _)
1331 | ty::Ref(_, _, _)
1332 | ty::FnDef(_, _)
1333 | ty::FnPtr(..)
1334 | ty::Closure(..)
1335 | ty::CoroutineClosure(..)
1336 | ty::Coroutine(_, _)
1337 | ty::CoroutineWitness(..)
1338 | ty::Never
1339 | ty::Tuple(_)
1340 | ty::Adt(_, _)
1341 | ty::UnsafeBinder(_) => check_impls(),
1342 ty::Error(_) => None,
1343
1344 ty::Infer(_) | ty::Alias(ty::IsRigid::No, _) | ty::Bound(_, _) => {
1345 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
1346 }
1347 }
1348 }
1349
1350 fn probe_and_evaluate_goal_for_constituent_tys(
1355 &mut self,
1356 source: CandidateSource<I>,
1357 goal: Goal<I, TraitPredicate<I>>,
1358 constituent_tys: impl Fn(
1359 &EvalCtxt<'_, D>,
1360 I::Ty,
1361 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1362 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1363 self.probe_trait_candidate(source).enter(|ecx| {
1364 let goals = ecx.enter_forall_with_assumptions(
1365 constituent_tys(ecx, goal.predicate.self_ty())?,
1366 goal.param_env,
1367 |ecx, tys| {
1368 tys.into_iter()
1369 .map(|ty| {
1370 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1371 })
1372 .collect::<Vec<_>>()
1373 },
1374 );
1375 ecx.add_goals(GoalSource::ImplWhereBound, goals)?;
1376 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1377 })
1378 }
1379}
1380
1381#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TraitGoalProvenVia {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
TraitGoalProvenVia::Misc => "Misc",
TraitGoalProvenVia::ParamEnv => "ParamEnv",
TraitGoalProvenVia::AliasBound => "AliasBound",
})
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for TraitGoalProvenVia {
#[inline]
fn clone(&self) -> TraitGoalProvenVia { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TraitGoalProvenVia { }Copy)]
1392pub(super) enum TraitGoalProvenVia {
1393 Misc,
1399 ParamEnv,
1400 AliasBound,
1401}
1402
1403impl<D, I> EvalCtxt<'_, D>
1404where
1405 D: SolverDelegate<Interner = I>,
1406 I: Interner,
1407{
1408 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1421 if self.typing_mode().is_coherence() {
1422 return;
1423 }
1424
1425 if candidates
1426 .iter()
1427 .find(|c| {
1428 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1429 })
1430 .is_some_and(|c| has_only_region_constraints(c.result))
1431 {
1432 candidates.retain(|c| {
1433 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1434 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1434",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1434u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("c")
}> =
::tracing::__macro_support::FieldName::new("c");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("unsoundly dropping impl in favor of builtin dyn-candidate")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&c)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
1435 false
1436 } else {
1437 true
1438 }
1439 });
1440 }
1441 }
1442
1443 x;#[instrument(level = "debug", skip(self), ret)]
1444 pub(super) fn merge_trait_candidates(
1445 &mut self,
1446 candidate_preference_mode: CandidatePreferenceMode,
1447 mut candidates: Vec<Candidate<I>>,
1448 failed_candidate_info: FailedCandidateInfo,
1449 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1450 if self.typing_mode().is_coherence() {
1451 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1452 Ok((response, Some(TraitGoalProvenVia::Misc)))
1453 } else {
1454 self.flounder(&candidates).map(|r| (r, None))
1455 };
1456 }
1457
1458 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1463 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1464 });
1465 if let Some(candidate) = trivial_builtin_impls.next() {
1466 assert!(trivial_builtin_impls.next().is_none());
1469 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1470 }
1471
1472 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1475 && candidates.iter().any(|c| {
1476 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1477 })
1478 {
1479 let alias_bounds: Vec<_> = candidates
1480 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1481 .collect();
1482 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1483 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1484 } else {
1485 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1486 };
1487 }
1488
1489 let has_non_global_where_bounds = candidates
1492 .iter()
1493 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1494 if has_non_global_where_bounds {
1495 let where_bounds: Vec<_> = candidates
1496 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1497 .collect();
1498 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1499 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1500 };
1501 match info {
1502 MergeCandidateInfo::AlwaysApplicable(i) => {
1518 for (j, c) in where_bounds.into_iter().enumerate() {
1519 if i != j {
1520 self.ignore_candidate_head_usages(c.head_usages)
1521 }
1522 }
1523 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1527 }
1528 MergeCandidateInfo::EqualResponse => {}
1529 }
1530 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1531 }
1532
1533 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1535 let alias_bounds: Vec<_> = candidates
1536 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1537 .collect();
1538 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1539 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1540 } else {
1541 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1542 };
1543 }
1544
1545 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1546 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1547
1548 let proven_via = if candidates
1553 .iter()
1554 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1555 {
1556 TraitGoalProvenVia::ParamEnv
1557 } else {
1558 candidates
1559 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1560 TraitGoalProvenVia::Misc
1561 };
1562
1563 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1564 Ok((response, Some(proven_via)))
1565 } else {
1566 self.flounder(&candidates).map(|r| (r, None))
1567 }
1568 }
1569
1570 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute_trait_goal",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1570u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
NoSolutionOrRerunNonErased> = loop {};
return __tracing_attr_fake_return;
}
{
let (candidates, failed_candidate_info) =
self.assemble_and_evaluate_candidates(goal,
AssembleCandidatesFrom::All)?;
let candidate_preference_mode =
CandidatePreferenceMode::compute(self.cx(),
goal.predicate.def_id());
self.merge_trait_candidates(candidate_preference_mode, candidates,
failed_candidate_info).map_err(Into::into)
}
}
}#[instrument(level = "trace", skip(self))]
1571 pub(super) fn compute_trait_goal(
1572 &mut self,
1573 goal: Goal<I, TraitPredicate<I>>,
1574 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1575 {
1576 let (candidates, failed_candidate_info) =
1577 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
1578 let candidate_preference_mode =
1579 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1580 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1581 .map_err(Into::into)
1582 }
1583
1584 fn try_stall_coroutine(
1585 &mut self,
1586 self_ty: I::Ty,
1587 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1588 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1589 match self.typing_mode() {
1590 TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => {
1591 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1592 {
1593 return Some(self.forced_ambiguity(MaybeInfo {
1594 cause: MaybeCause::Ambiguity,
1595 opaque_types_jank: OpaqueTypesJank::AllGood,
1596 stalled_on_coroutines: StalledOnCoroutines::Yes,
1597 }));
1598 }
1599 }
1600 TypingMode::ErasedNotCoherence(MayBeErased) => {
1601 return Some(
1603 match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1604 Err(e) => Err(e.into()),
1605 },
1606 );
1607 }
1608 TypingMode::Coherence
1609 | TypingMode::PostAnalysis
1610 | TypingMode::Codegen
1611 | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ }
1612 | TypingMode::PostBorrowck { defined_opaque_types: _ } => {}
1613 }
1614 }
1615
1616 None
1617 }
1618}