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, OpaqueTypesJank,
9 SizedTraitKind,
10};
11use rustc_type_ir::{
12 self as ty, FieldInfo, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
13 TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, elaborate,
14};
15use tracing::{debug, instrument, trace};
16
17use crate::delegate::SolverDelegate;
18use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
19use crate::solve::assembly::{
20 self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate, FailedCandidateInfo,
21};
22use crate::solve::inspect::ProbeKind;
23use crate::solve::{
24 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
25 MergeCandidateInfo, NoSolution, ParamEnvSource, QueryResult, StalledOnCoroutines,
26 has_only_region_constraints,
27};
28
29impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
30where
31 D: SolverDelegate<Interner = I>,
32 I: Interner,
33{
34 fn self_ty(self) -> I::Ty {
35 self.self_ty()
36 }
37
38 fn trait_ref(self, _: I) -> ty::TraitRef<I> {
39 self.trait_ref
40 }
41
42 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
43 self.with_replaced_self_ty(cx, self_ty)
44 }
45
46 fn trait_def_id(self, _: I) -> I::TraitId {
47 self.def_id()
48 }
49
50 fn consider_additional_alias_assumptions(
51 _ecx: &mut EvalCtxt<'_, D>,
52 _goal: Goal<I, Self>,
53 _alias_ty: ty::AliasTy<I>,
54 ) -> Vec<Candidate<I>> {
55 ::alloc::vec::Vec::new()vec![]
56 }
57
58 fn consider_impl_candidate(
59 ecx: &mut EvalCtxt<'_, D>,
60 goal: Goal<I, TraitPredicate<I>>,
61 impl_def_id: I::ImplId,
62 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
63 ) -> Result<Candidate<I>, NoSolution> {
64 let cx = ecx.cx();
65
66 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
67 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
68 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
69 {
70 return Err(NoSolution);
71 }
72
73 let impl_polarity = cx.impl_polarity(impl_def_id);
76 let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
77 (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
80 TypingMode::Coherence => Certainty::AMBIGUOUS,
81 TypingMode::Analysis { .. }
82 | TypingMode::Borrowck { .. }
83 | TypingMode::PostBorrowckAnalysis { .. }
84 | TypingMode::PostAnalysis => return Err(NoSolution),
85 },
86
87 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
89 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => Certainty::Yes,
90
91 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative)
93 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Positive) => {
94 return Err(NoSolution);
95 }
96 };
97
98 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
99 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
100 ecx.record_impl_args(impl_args);
101 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
102
103 ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
104 let where_clause_bounds = cx
105 .predicates_of(impl_def_id.into())
106 .iter_instantiated(cx, impl_args)
107 .map(Unnormalized::skip_norm_wip)
108 .map(|pred| goal.with(cx, pred));
109 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
110
111 ecx.add_goals(
115 GoalSource::Misc,
116 cx.impl_super_outlives(impl_def_id)
117 .iter_instantiated(cx, impl_args)
118 .map(Unnormalized::skip_norm_wip)
119 .map(|pred| goal.with(cx, pred)),
120 );
121
122 then(ecx, maximal_certainty)
123 })
124 }
125
126 fn consider_error_guaranteed_candidate(
127 ecx: &mut EvalCtxt<'_, D>,
128 _guar: I::ErrorGuaranteed,
129 ) -> Result<Candidate<I>, NoSolution> {
130 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
131 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
132 }
133
134 fn fast_reject_assumption(
135 ecx: &mut EvalCtxt<'_, D>,
136 goal: Goal<I, Self>,
137 assumption: I::Clause,
138 ) -> Result<(), NoSolution> {
139 fn trait_def_id_matches<I: Interner>(
140 cx: I,
141 clause_def_id: I::TraitId,
142 goal_def_id: I::TraitId,
143 polarity: PredicatePolarity,
144 ) -> bool {
145 clause_def_id == goal_def_id
146 || (polarity == PredicatePolarity::Positive
151 && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
152 && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
153 }
154
155 if let Some(trait_clause) = assumption.as_trait_clause()
156 && trait_clause.polarity() == goal.predicate.polarity
157 && trait_def_id_matches(
158 ecx.cx(),
159 trait_clause.def_id(),
160 goal.predicate.def_id(),
161 goal.predicate.polarity,
162 )
163 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
164 goal.predicate.trait_ref.args,
165 trait_clause.skip_binder().trait_ref.args,
166 )
167 {
168 return Ok(());
169 } else {
170 Err(NoSolution)
171 }
172 }
173
174 fn match_assumption(
175 ecx: &mut EvalCtxt<'_, D>,
176 goal: Goal<I, Self>,
177 assumption: I::Clause,
178 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
179 ) -> QueryResult<I> {
180 let trait_clause = assumption.as_trait_clause().unwrap();
181
182 if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
188 && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
189 {
190 let meta_sized_clause =
191 trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
192 return Self::match_assumption(ecx, goal, meta_sized_clause, then);
193 }
194
195 let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
196 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
197
198 then(ecx)
199 }
200
201 fn consider_auto_trait_candidate(
202 ecx: &mut EvalCtxt<'_, D>,
203 goal: Goal<I, Self>,
204 ) -> Result<Candidate<I>, NoSolution> {
205 let cx = ecx.cx();
206 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
207 return Err(NoSolution);
208 }
209
210 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
211 return result;
212 }
213
214 if cx.trait_is_unsafe(goal.predicate.def_id())
217 && goal.predicate.self_ty().has_unsafe_fields()
218 {
219 return Err(NoSolution);
220 }
221
222 if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) =
238 goal.predicate.self_ty().kind()
239 {
240 if true {
if !ecx.opaque_type_is_rigid(def_id) {
::core::panicking::panic("assertion failed: ecx.opaque_type_is_rigid(def_id)")
};
};debug_assert!(ecx.opaque_type_is_rigid(def_id));
241 for item_bound in cx.item_self_bounds(def_id).skip_binder() {
242 if item_bound
243 .as_trait_clause()
244 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
245 {
246 return Err(NoSolution);
247 }
248 }
249 }
250
251 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
253 return cand;
254 }
255
256 ecx.probe_and_evaluate_goal_for_constituent_tys(
257 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
258 goal,
259 structural_traits::instantiate_constituent_tys_for_auto_trait,
260 )
261 }
262
263 fn consider_trait_alias_candidate(
264 ecx: &mut EvalCtxt<'_, D>,
265 goal: Goal<I, Self>,
266 ) -> Result<Candidate<I>, NoSolution> {
267 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
268 return Err(NoSolution);
269 }
270
271 let cx = ecx.cx();
272
273 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
274 let nested_obligations = cx
275 .predicates_of(goal.predicate.def_id().into())
276 .iter_instantiated(cx, goal.predicate.trait_ref.args)
277 .map(Unnormalized::skip_norm_wip)
278 .map(|p| goal.with(cx, p));
279 ecx.add_goals(GoalSource::Misc, nested_obligations);
285 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
286 })
287 }
288
289 fn consider_builtin_sizedness_candidates(
290 ecx: &mut EvalCtxt<'_, D>,
291 goal: Goal<I, Self>,
292 sizedness: SizedTraitKind,
293 ) -> Result<Candidate<I>, NoSolution> {
294 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
295 return Err(NoSolution);
296 }
297
298 ecx.probe_and_evaluate_goal_for_constituent_tys(
299 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
300 goal,
301 |ecx, ty| {
302 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
303 ecx, sizedness, ty,
304 )
305 },
306 )
307 }
308
309 fn consider_builtin_copy_clone_candidate(
310 ecx: &mut EvalCtxt<'_, D>,
311 goal: Goal<I, Self>,
312 ) -> Result<Candidate<I>, NoSolution> {
313 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
314 return Err(NoSolution);
315 }
316
317 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
319 return cand;
320 }
321
322 ecx.probe_and_evaluate_goal_for_constituent_tys(
323 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
324 goal,
325 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
326 )
327 }
328
329 fn consider_builtin_fn_ptr_trait_candidate(
330 ecx: &mut EvalCtxt<'_, D>,
331 goal: Goal<I, Self>,
332 ) -> Result<Candidate<I>, NoSolution> {
333 let self_ty = goal.predicate.self_ty();
334 match goal.predicate.polarity {
335 ty::PredicatePolarity::Positive => {
337 if self_ty.is_fn_ptr() {
338 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
339 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
340 })
341 } else {
342 Err(NoSolution)
343 }
344 }
345 ty::PredicatePolarity::Negative => {
347 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
350 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
351 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
352 })
353 } else {
354 Err(NoSolution)
355 }
356 }
357 }
358 }
359
360 fn consider_builtin_fn_trait_candidates(
361 ecx: &mut EvalCtxt<'_, D>,
362 goal: Goal<I, Self>,
363 goal_kind: ty::ClosureKind,
364 ) -> Result<Candidate<I>, NoSolution> {
365 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
366 return Err(NoSolution);
367 }
368
369 let cx = ecx.cx();
370 let Some(tupled_inputs_and_output) =
371 structural_traits::extract_tupled_inputs_and_output_from_callable(
372 cx,
373 goal.predicate.self_ty(),
374 goal_kind,
375 )?
376 else {
377 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
378 };
379 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
380
381 let output_is_sized_pred =
384 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
385
386 let pred =
387 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
388 .upcast(cx);
389 Self::probe_and_consider_implied_clause(
390 ecx,
391 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
392 goal,
393 pred,
394 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
395 )
396 }
397
398 fn consider_builtin_async_fn_trait_candidates(
399 ecx: &mut EvalCtxt<'_, D>,
400 goal: Goal<I, Self>,
401 goal_kind: ty::ClosureKind,
402 ) -> Result<Candidate<I>, NoSolution> {
403 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
404 return Err(NoSolution);
405 }
406
407 let cx = ecx.cx();
408 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
409 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
410 cx,
411 goal.predicate.self_ty(),
412 goal_kind,
413 Region::new_static(cx),
415 )?;
416 let AsyncCallableRelevantTypes {
417 tupled_inputs_ty,
418 output_coroutine_ty,
419 coroutine_return_ty: _,
420 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
421
422 let output_is_sized_pred = ty::TraitRef::new(
425 cx,
426 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
427 [output_coroutine_ty],
428 );
429
430 let pred = ty::TraitRef::new(
431 cx,
432 goal.predicate.def_id(),
433 [goal.predicate.self_ty(), tupled_inputs_ty],
434 )
435 .upcast(cx);
436 Self::probe_and_consider_implied_clause(
437 ecx,
438 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
439 goal,
440 pred,
441 [goal.with(cx, output_is_sized_pred)]
442 .into_iter()
443 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
444 .map(|goal| (GoalSource::ImplWhereBound, goal)),
445 )
446 }
447
448 fn consider_builtin_async_fn_kind_helper_candidate(
449 ecx: &mut EvalCtxt<'_, D>,
450 goal: Goal<I, Self>,
451 ) -> Result<Candidate<I>, NoSolution> {
452 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
453 ::core::panicking::panic("explicit panic");panic!();
454 };
455
456 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
457 return Err(NoSolution);
459 };
460 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
461 if closure_kind.extends(goal_kind) {
462 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
463 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
464 } else {
465 Err(NoSolution)
466 }
467 }
468
469 fn consider_builtin_tuple_candidate(
476 ecx: &mut EvalCtxt<'_, D>,
477 goal: Goal<I, Self>,
478 ) -> Result<Candidate<I>, NoSolution> {
479 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
480 return Err(NoSolution);
481 }
482
483 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
484 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
485 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
486 } else {
487 Err(NoSolution)
488 }
489 }
490
491 fn consider_builtin_pointee_candidate(
492 ecx: &mut EvalCtxt<'_, D>,
493 goal: Goal<I, Self>,
494 ) -> Result<Candidate<I>, NoSolution> {
495 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
496 return Err(NoSolution);
497 }
498
499 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
500 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
501 }
502
503 fn consider_builtin_future_candidate(
504 ecx: &mut EvalCtxt<'_, D>,
505 goal: Goal<I, Self>,
506 ) -> Result<Candidate<I>, NoSolution> {
507 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
508 return Err(NoSolution);
509 }
510
511 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
512 return Err(NoSolution);
513 };
514
515 let cx = ecx.cx();
517 if !cx.coroutine_is_async(def_id) {
518 return Err(NoSolution);
519 }
520
521 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
525 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
526 }
527
528 fn consider_builtin_iterator_candidate(
529 ecx: &mut EvalCtxt<'_, D>,
530 goal: Goal<I, Self>,
531 ) -> Result<Candidate<I>, NoSolution> {
532 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
533 return Err(NoSolution);
534 }
535
536 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
537 return Err(NoSolution);
538 };
539
540 let cx = ecx.cx();
542 if !cx.coroutine_is_gen(def_id) {
543 return Err(NoSolution);
544 }
545
546 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
550 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
551 }
552
553 fn consider_builtin_fused_iterator_candidate(
554 ecx: &mut EvalCtxt<'_, D>,
555 goal: Goal<I, Self>,
556 ) -> Result<Candidate<I>, NoSolution> {
557 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
558 return Err(NoSolution);
559 }
560
561 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
562 return Err(NoSolution);
563 };
564
565 let cx = ecx.cx();
567 if !cx.coroutine_is_gen(def_id) {
568 return Err(NoSolution);
569 }
570
571 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
573 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
574 }
575
576 fn consider_builtin_async_iterator_candidate(
577 ecx: &mut EvalCtxt<'_, D>,
578 goal: Goal<I, Self>,
579 ) -> Result<Candidate<I>, NoSolution> {
580 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
581 return Err(NoSolution);
582 }
583
584 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
585 return Err(NoSolution);
586 };
587
588 let cx = ecx.cx();
590 if !cx.coroutine_is_async_gen(def_id) {
591 return Err(NoSolution);
592 }
593
594 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
598 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
599 }
600
601 fn consider_builtin_coroutine_candidate(
602 ecx: &mut EvalCtxt<'_, D>,
603 goal: Goal<I, Self>,
604 ) -> Result<Candidate<I>, NoSolution> {
605 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
606 return Err(NoSolution);
607 }
608
609 let self_ty = goal.predicate.self_ty();
610 let ty::Coroutine(def_id, args) = self_ty.kind() else {
611 return Err(NoSolution);
612 };
613
614 let cx = ecx.cx();
616 if !cx.is_general_coroutine(def_id) {
617 return Err(NoSolution);
618 }
619
620 let coroutine = args.as_coroutine();
621 Self::probe_and_consider_implied_clause(
622 ecx,
623 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
624 goal,
625 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
626 .upcast(cx),
627 [],
630 )
631 }
632
633 fn consider_builtin_discriminant_kind_candidate(
634 ecx: &mut EvalCtxt<'_, D>,
635 goal: Goal<I, Self>,
636 ) -> Result<Candidate<I>, NoSolution> {
637 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
638 return Err(NoSolution);
639 }
640
641 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
643 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
644 }
645
646 fn consider_builtin_destruct_candidate(
647 ecx: &mut EvalCtxt<'_, D>,
648 goal: Goal<I, Self>,
649 ) -> Result<Candidate<I>, NoSolution> {
650 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
651 return Err(NoSolution);
652 }
653
654 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
657 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
658 }
659
660 fn consider_builtin_transmute_candidate(
661 ecx: &mut EvalCtxt<'_, D>,
662 goal: Goal<I, Self>,
663 ) -> Result<Candidate<I>, NoSolution> {
664 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
665 return Err(NoSolution);
666 }
667
668 if goal.predicate.has_non_region_placeholders() {
670 return Err(NoSolution);
671 }
672
673 if goal.has_non_region_infer() {
676 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
677 }
678
679 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
680 let assume = ecx.structurally_normalize_const(
681 goal.param_env,
682 goal.predicate.trait_ref.args.const_at(2),
683 )?;
684
685 let certainty = ecx.is_transmutable(
686 goal.predicate.trait_ref.args.type_at(0),
687 goal.predicate.trait_ref.args.type_at(1),
688 assume,
689 )?;
690 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
691 })
692 }
693
694 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
707 ecx: &mut EvalCtxt<'_, D>,
708 goal: Goal<I, Self>,
709 ) -> Result<Candidate<I>, NoSolution> {
710 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
711 return Err(NoSolution);
712 }
713
714 let cx = ecx.cx();
715 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
716 let ty = goal.predicate.self_ty();
717 match ty.kind() {
718 ty::Ref(..) => {}
720 ty::Adt(def, _) if def.is_manually_drop() => {}
722 ty::Tuple(tys) => {
725 ecx.add_goals(
726 GoalSource::ImplWhereBound,
727 tys.iter().map(|elem_ty| {
728 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
729 }),
730 );
731 }
732 ty::Array(elem_ty, _) => {
733 ecx.add_goal(
734 GoalSource::ImplWhereBound,
735 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
736 );
737 }
738
739 ty::FnDef(..)
743 | ty::FnPtr(..)
744 | ty::Error(_)
745 | ty::Uint(_)
746 | ty::Int(_)
747 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
748 | ty::Bool
749 | ty::Float(_)
750 | ty::Char
751 | ty::RawPtr(..)
752 | ty::Never
753 | ty::Pat(..)
754 | ty::Dynamic(..)
755 | ty::Str
756 | ty::Slice(_)
757 | ty::Foreign(..)
758 | ty::Adt(..)
759 | ty::Alias(..)
760 | ty::Param(_)
761 | ty::Placeholder(..)
762 | ty::Closure(..)
763 | ty::CoroutineClosure(..)
764 | ty::Coroutine(..)
765 | ty::UnsafeBinder(_)
766 | ty::CoroutineWitness(..) => {
767 ecx.add_goal(
768 GoalSource::ImplWhereBound,
769 goal.with(
770 cx,
771 ty::TraitRef::new(
772 cx,
773 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
774 [ty],
775 ),
776 ),
777 );
778 }
779
780 ty::Bound(..)
781 | ty::Infer(
782 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
783 ) => {
784 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
785 }
786 }
787
788 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
789 })
790 }
791
792 fn consider_structural_builtin_unsize_candidates(
800 ecx: &mut EvalCtxt<'_, D>,
801 goal: Goal<I, Self>,
802 ) -> Vec<Candidate<I>> {
803 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
804 return ::alloc::vec::Vec::new()vec![];
805 }
806
807 let result_to_single = |result| match result {
808 Ok(resp) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[resp]))vec![resp],
809 Err(NoSolution) => ::alloc::vec::Vec::new()vec![],
810 };
811
812 ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| {
813 let a_ty = goal.predicate.self_ty();
814 let Ok(b_ty) = ecx.structurally_normalize_ty(
817 goal.param_env,
818 goal.predicate.trait_ref.args.type_at(1),
819 ) else {
820 return ::alloc::vec::Vec::new()vec![];
821 };
822
823 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
824 match (a_ty.kind(), b_ty.kind()) {
825 (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:?}"),
826
827 (_, ty::Infer(ty::TyVar(..))) => {
828 result_to_single(ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS))
829 }
830
831 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => ecx
833 .consider_builtin_dyn_upcast_candidates(
834 goal, a_data, a_region, b_data, b_region,
835 ),
836
837 (_, ty::Dynamic(b_region, b_data)) => result_to_single(
839 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data),
840 ),
841
842 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
844 result_to_single(ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty))
845 }
846
847 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
849 if a_def.is_struct() && a_def == b_def =>
850 {
851 result_to_single(
852 ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args),
853 )
854 }
855
856 _ => ::alloc::vec::Vec::new()vec![],
857 }
858 })
859 }
860
861 fn consider_builtin_field_candidate(
862 ecx: &mut EvalCtxt<'_, D>,
863 goal: Goal<I, Self>,
864 ) -> Result<Candidate<I>, NoSolution> {
865 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
866 return Err(NoSolution);
867 }
868 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
869 && let Some(FieldInfo { base, ty, .. }) =
870 def.field_representing_type_info(ecx.cx(), args)
871 && {
872 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
873 ecx.add_goal(
881 GoalSource::ImplWhereBound,
882 Goal {
883 param_env: goal.param_env,
884 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
885 },
886 );
887 ecx.add_goal(
888 GoalSource::ImplWhereBound,
889 Goal {
890 param_env: goal.param_env,
891 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
892 },
893 );
894 ecx.try_evaluate_added_goals()? == Certainty::Yes
895 }
896 && match base.kind() {
897 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
898 ty::Tuple(..) => true,
899 _ => false,
900 }
901 {
902 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
903 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
904 } else {
905 Err(NoSolution)
906 }
907 }
908}
909
910#[inline(always)]
916fn trait_predicate_with_def_id<I: Interner>(
917 cx: I,
918 clause: ty::Binder<I, ty::TraitPredicate<I>>,
919 did: I::TraitId,
920) -> I::Clause {
921 clause
922 .map_bound(|c| TraitPredicate {
923 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
924 polarity: c.polarity,
925 })
926 .upcast(cx)
927}
928
929impl<D, I> EvalCtxt<'_, D>
930where
931 D: SolverDelegate<Interner = I>,
932 I: Interner,
933{
934 fn consider_builtin_dyn_upcast_candidates(
944 &mut self,
945 goal: Goal<I, (I::Ty, I::Ty)>,
946 a_data: I::BoundExistentialPredicates,
947 a_region: I::Region,
948 b_data: I::BoundExistentialPredicates,
949 b_region: I::Region,
950 ) -> Vec<Candidate<I>> {
951 let cx = self.cx();
952 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
953
954 let mut responses = ::alloc::vec::Vec::new()vec![];
955 let b_principal_def_id = b_data.principal_def_id();
958 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
959 responses.extend(self.consider_builtin_upcast_to_principal(
960 goal,
961 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
962 a_data,
963 a_region,
964 b_data,
965 b_region,
966 a_data.principal(),
967 ));
968 } else if let Some(a_principal) = a_data.principal() {
969 for (idx, new_a_principal) in
970 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
971 .enumerate()
972 .skip(1)
973 {
974 responses.extend(self.consider_builtin_upcast_to_principal(
975 goal,
976 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
977 a_data,
978 a_region,
979 b_data,
980 b_region,
981 Some(new_a_principal.map_bound(|trait_ref| {
982 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
983 })),
984 ));
985 }
986 }
987
988 responses
989 }
990
991 fn consider_builtin_unsize_to_dyn_candidate(
992 &mut self,
993 goal: Goal<I, (I::Ty, I::Ty)>,
994 b_data: I::BoundExistentialPredicates,
995 b_region: I::Region,
996 ) -> Result<Candidate<I>, NoSolution> {
997 let cx = self.cx();
998 let Goal { predicate: (a_ty, _), .. } = goal;
999
1000 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1002 return Err(NoSolution);
1003 }
1004
1005 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1006 ecx.add_goals(
1009 GoalSource::ImplWhereBound,
1010 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1011 );
1012
1013 ecx.add_goal(
1015 GoalSource::ImplWhereBound,
1016 goal.with(
1017 cx,
1018 ty::TraitRef::new(
1019 cx,
1020 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1021 [a_ty],
1022 ),
1023 ),
1024 );
1025
1026 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)));
1028 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1029 })
1030 }
1031
1032 fn consider_builtin_upcast_to_principal(
1033 &mut self,
1034 goal: Goal<I, (I::Ty, I::Ty)>,
1035 source: CandidateSource<I>,
1036 a_data: I::BoundExistentialPredicates,
1037 a_region: I::Region,
1038 b_data: I::BoundExistentialPredicates,
1039 b_region: I::Region,
1040 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1041 ) -> Result<Candidate<I>, NoSolution> {
1042 let param_env = goal.param_env;
1043
1044 let a_auto_traits: IndexSet<I::TraitId> = a_data
1048 .auto_traits()
1049 .into_iter()
1050 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1051 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1052 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1053 }))
1054 .collect();
1055
1056 let projection_may_match =
1061 |ecx: &mut EvalCtxt<'_, D>,
1062 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1063 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1064 source_projection.item_def_id() == target_projection.item_def_id()
1065 && ecx
1066 .probe(|_| ProbeKind::ProjectionCompatibility)
1067 .enter(|ecx| -> Result<_, NoSolution> {
1068 ecx.enter_forall(target_projection, |ecx, target_projection| {
1069 let source_projection =
1070 ecx.instantiate_binder_with_infer(source_projection);
1071 ecx.eq(param_env, source_projection, target_projection)?;
1072 ecx.try_evaluate_added_goals()
1073 })
1074 })
1075 .is_ok()
1076 };
1077
1078 self.probe_trait_candidate(source).enter(|ecx| {
1079 for bound in b_data.iter() {
1080 match bound.skip_binder() {
1081 ty::ExistentialPredicate::Trait(target_principal) => {
1084 let source_principal = upcast_principal.unwrap();
1085 let target_principal = bound.rebind(target_principal);
1086 ecx.enter_forall(target_principal, |ecx, target_principal| {
1087 let source_principal =
1088 ecx.instantiate_binder_with_infer(source_principal);
1089 ecx.eq(param_env, source_principal, target_principal)?;
1090 ecx.try_evaluate_added_goals()
1091 })?;
1092 }
1093 ty::ExistentialPredicate::Projection(target_projection) => {
1099 let target_projection = bound.rebind(target_projection);
1100 let mut matching_projections =
1101 a_data.projection_bounds().into_iter().filter(|source_projection| {
1102 projection_may_match(ecx, *source_projection, target_projection)
1103 });
1104 let Some(source_projection) = matching_projections.next() else {
1105 return Err(NoSolution);
1106 };
1107 if matching_projections.next().is_some() {
1108 return ecx.evaluate_added_goals_and_make_canonical_response(
1109 Certainty::AMBIGUOUS,
1110 );
1111 }
1112 ecx.enter_forall(target_projection, |ecx, target_projection| {
1113 let source_projection =
1114 ecx.instantiate_binder_with_infer(source_projection);
1115 ecx.eq(param_env, source_projection, target_projection)?;
1116 ecx.try_evaluate_added_goals()
1117 })?;
1118 }
1119 ty::ExistentialPredicate::AutoTrait(def_id) => {
1121 if !a_auto_traits.contains(&def_id) {
1122 return Err(NoSolution);
1123 }
1124 }
1125 }
1126 }
1127
1128 ecx.add_goal(
1130 GoalSource::ImplWhereBound,
1131 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1132 );
1133
1134 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1135 })
1136 }
1137
1138 fn consider_builtin_array_unsize(
1147 &mut self,
1148 goal: Goal<I, (I::Ty, I::Ty)>,
1149 a_elem_ty: I::Ty,
1150 b_elem_ty: I::Ty,
1151 ) -> Result<Candidate<I>, NoSolution> {
1152 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1153 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1154 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1155 }
1156
1157 fn consider_builtin_struct_unsize(
1171 &mut self,
1172 goal: Goal<I, (I::Ty, I::Ty)>,
1173 def: I::AdtDef,
1174 a_args: I::GenericArgs,
1175 b_args: I::GenericArgs,
1176 ) -> Result<Candidate<I>, NoSolution> {
1177 let cx = self.cx();
1178 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1179
1180 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1181 if unsizing_params.is_empty() {
1184 return Err(NoSolution);
1185 }
1186
1187 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1188
1189 let a_tail_ty = tail_field_ty.instantiate(cx, a_args).skip_norm_wip();
1190 let b_tail_ty = tail_field_ty.instantiate(cx, b_args).skip_norm_wip();
1191
1192 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1196 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1197 }));
1198 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1199
1200 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1203 self.add_goal(
1204 GoalSource::ImplWhereBound,
1205 goal.with(
1206 cx,
1207 ty::TraitRef::new(
1208 cx,
1209 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1210 [a_tail_ty, b_tail_ty],
1211 ),
1212 ),
1213 );
1214 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1215 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1216 }
1217
1218 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1223 &mut self,
1224 goal: Goal<I, TraitPredicate<I>>,
1225 ) -> Option<Result<Candidate<I>, NoSolution>> {
1226 let self_ty = goal.predicate.self_ty();
1227 let check_impls = || {
1228 let mut disqualifying_impl = None;
1229 self.cx().for_each_relevant_impl(
1230 goal.predicate.def_id(),
1231 goal.predicate.self_ty(),
1232 |impl_def_id| {
1233 disqualifying_impl = Some(impl_def_id);
1234 },
1235 );
1236 if let Some(def_id) = disqualifying_impl {
1237 {
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:1237",
"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(1237u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message", "def_id",
"goal"], ::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("disqualified auto-trait implementation")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&def_id) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&goal) as
&dyn Value))])
});
} else { ; }
};trace!(?def_id, ?goal, "disqualified auto-trait implementation");
1238 return Some(Err(NoSolution));
1241 } else {
1242 None
1243 }
1244 };
1245
1246 match self_ty.kind() {
1247 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1253 Some(self.forced_ambiguity(MaybeInfo::AMBIGUOUS))
1254 }
1255
1256 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1259
1260 ty::Dynamic(..)
1263 | ty::Param(..)
1264 | ty::Foreign(..)
1265 | ty::Alias(ty::AliasTy {
1266 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1267 ..
1268 })
1269 | ty::Placeholder(..) => Some(Err(NoSolution)),
1270
1271 ty::Infer(_) | ty::Bound(_, _) => {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`"),
1272
1273 ty::Coroutine(def_id, _)
1277 if self
1278 .cx()
1279 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1280 {
1281 match self.cx().coroutine_movability(def_id) {
1282 Movability::Static => Some(Err(NoSolution)),
1283 Movability::Movable => Some(
1284 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1285 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1286 }),
1287 ),
1288 }
1289 }
1290
1291 ty::Alias(..) => None,
1296
1297 ty::Bool
1304 | ty::Char
1305 | ty::Int(_)
1306 | ty::Uint(_)
1307 | ty::Float(_)
1308 | ty::Str
1309 | ty::Array(_, _)
1310 | ty::Pat(_, _)
1311 | ty::Slice(_)
1312 | ty::RawPtr(_, _)
1313 | ty::Ref(_, _, _)
1314 | ty::FnDef(_, _)
1315 | ty::FnPtr(..)
1316 | ty::Closure(..)
1317 | ty::CoroutineClosure(..)
1318 | ty::Coroutine(_, _)
1319 | ty::CoroutineWitness(..)
1320 | ty::Never
1321 | ty::Tuple(_)
1322 | ty::Adt(_, _)
1323 | ty::UnsafeBinder(_) => check_impls(),
1324 ty::Error(_) => None,
1325 }
1326 }
1327
1328 fn probe_and_evaluate_goal_for_constituent_tys(
1333 &mut self,
1334 source: CandidateSource<I>,
1335 goal: Goal<I, TraitPredicate<I>>,
1336 constituent_tys: impl Fn(
1337 &EvalCtxt<'_, D>,
1338 I::Ty,
1339 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1340 ) -> Result<Candidate<I>, NoSolution> {
1341 self.probe_trait_candidate(source).enter(|ecx| {
1342 let goals =
1343 ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| {
1344 tys.into_iter()
1345 .map(|ty| {
1346 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1347 })
1348 .collect::<Vec<_>>()
1349 });
1350 ecx.add_goals(GoalSource::ImplWhereBound, goals);
1351 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1352 })
1353 }
1354}
1355
1356#[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)]
1367pub(super) enum TraitGoalProvenVia {
1368 Misc,
1374 ParamEnv,
1375 AliasBound,
1376}
1377
1378impl<D, I> EvalCtxt<'_, D>
1379where
1380 D: SolverDelegate<Interner = I>,
1381 I: Interner,
1382{
1383 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1396 match self.typing_mode() {
1397 TypingMode::Coherence => return,
1398 TypingMode::Analysis { .. }
1399 | TypingMode::Borrowck { .. }
1400 | TypingMode::PostBorrowckAnalysis { .. }
1401 | TypingMode::PostAnalysis => {}
1402 }
1403
1404 if candidates
1405 .iter()
1406 .find(|c| {
1407 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1408 })
1409 .is_some_and(|c| has_only_region_constraints(c.result))
1410 {
1411 candidates.retain(|c| {
1412 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1413 {
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:1413",
"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(1413u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message", "c"],
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("unsoundly dropping impl in favor of builtin dyn-candidate")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&c) as
&dyn Value))])
});
} else { ; }
};debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
1414 false
1415 } else {
1416 true
1417 }
1418 });
1419 }
1420 }
1421
1422 x;#[instrument(level = "debug", skip(self), ret)]
1423 pub(super) fn merge_trait_candidates(
1424 &mut self,
1425 candidate_preference_mode: CandidatePreferenceMode,
1426 mut candidates: Vec<Candidate<I>>,
1427 failed_candidate_info: FailedCandidateInfo,
1428 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1429 if self.typing_mode().is_coherence() {
1430 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1431 Ok((response, Some(TraitGoalProvenVia::Misc)))
1432 } else {
1433 self.flounder(&candidates).map(|r| (r, None))
1434 };
1435 }
1436
1437 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1442 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1443 });
1444 if let Some(candidate) = trivial_builtin_impls.next() {
1445 assert!(trivial_builtin_impls.next().is_none());
1448 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1449 }
1450
1451 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1454 && candidates.iter().any(|c| {
1455 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1456 })
1457 {
1458 let alias_bounds: Vec<_> = candidates
1459 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1460 .collect();
1461 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1462 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1463 } else {
1464 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1465 };
1466 }
1467
1468 let has_non_global_where_bounds = candidates
1471 .iter()
1472 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1473 if has_non_global_where_bounds {
1474 let where_bounds: Vec<_> = candidates
1475 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1476 .collect();
1477 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1478 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1479 };
1480 match info {
1481 MergeCandidateInfo::AlwaysApplicable(i) => {
1497 for (j, c) in where_bounds.into_iter().enumerate() {
1498 if i != j {
1499 self.ignore_candidate_head_usages(c.head_usages)
1500 }
1501 }
1502 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1506 }
1507 MergeCandidateInfo::EqualResponse => {}
1508 }
1509 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1510 }
1511
1512 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1514 let alias_bounds: Vec<_> = candidates
1515 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1516 .collect();
1517 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1518 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1519 } else {
1520 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1521 };
1522 }
1523
1524 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1525 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1526
1527 let proven_via = if candidates
1532 .iter()
1533 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1534 {
1535 TraitGoalProvenVia::ParamEnv
1536 } else {
1537 candidates
1538 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1539 TraitGoalProvenVia::Misc
1540 };
1541
1542 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1543 Ok((response, Some(proven_via)))
1544 } else {
1545 self.flounder(&candidates).map(|r| (r, None))
1546 }
1547 }
1548
1549 #[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(1549u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["goal"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn 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>),
NoSolution> = 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)
}
}
}#[instrument(level = "trace", skip(self))]
1550 pub(super) fn compute_trait_goal(
1551 &mut self,
1552 goal: Goal<I, TraitPredicate<I>>,
1553 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1554 let (candidates, failed_candidate_info) =
1555 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1556 let candidate_preference_mode =
1557 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1558 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1559 }
1560
1561 fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
1562 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1563 match self.typing_mode() {
1564 TypingMode::Analysis {
1565 defining_opaque_types_and_generators: stalled_generators,
1566 } => {
1567 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1568 {
1569 return Some(self.forced_ambiguity(MaybeInfo {
1570 cause: MaybeCause::Ambiguity,
1571 opaque_types_jank: OpaqueTypesJank::AllGood,
1572 stalled_on_coroutines: StalledOnCoroutines::Yes,
1573 }));
1574 }
1575 }
1576 TypingMode::Coherence
1577 | TypingMode::PostAnalysis
1578 | TypingMode::Borrowck { defining_opaque_types: _ }
1579 | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
1580 }
1581 }
1582
1583 None
1584 }
1585}