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