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, 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);
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(|pred| goal.with(cx, pred));
106 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
107
108 ecx.add_goals(
112 GoalSource::Misc,
113 cx.impl_super_outlives(impl_def_id)
114 .iter_instantiated(cx, impl_args)
115 .map(|pred| goal.with(cx, pred)),
116 );
117
118 then(ecx, maximal_certainty)
119 })
120 }
121
122 fn consider_error_guaranteed_candidate(
123 ecx: &mut EvalCtxt<'_, D>,
124 _guar: I::ErrorGuaranteed,
125 ) -> Result<Candidate<I>, NoSolution> {
126 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
127 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
128 }
129
130 fn fast_reject_assumption(
131 ecx: &mut EvalCtxt<'_, D>,
132 goal: Goal<I, Self>,
133 assumption: I::Clause,
134 ) -> Result<(), NoSolution> {
135 fn trait_def_id_matches<I: Interner>(
136 cx: I,
137 clause_def_id: I::TraitId,
138 goal_def_id: I::TraitId,
139 polarity: PredicatePolarity,
140 ) -> bool {
141 clause_def_id == goal_def_id
142 || (polarity == PredicatePolarity::Positive
147 && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
148 && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
149 }
150
151 if let Some(trait_clause) = assumption.as_trait_clause()
152 && trait_clause.polarity() == goal.predicate.polarity
153 && trait_def_id_matches(
154 ecx.cx(),
155 trait_clause.def_id(),
156 goal.predicate.def_id(),
157 goal.predicate.polarity,
158 )
159 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
160 goal.predicate.trait_ref.args,
161 trait_clause.skip_binder().trait_ref.args,
162 )
163 {
164 return Ok(());
165 } else {
166 Err(NoSolution)
167 }
168 }
169
170 fn match_assumption(
171 ecx: &mut EvalCtxt<'_, D>,
172 goal: Goal<I, Self>,
173 assumption: I::Clause,
174 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
175 ) -> QueryResult<I> {
176 let trait_clause = assumption.as_trait_clause().unwrap();
177
178 if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
184 && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
185 {
186 let meta_sized_clause =
187 trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
188 return Self::match_assumption(ecx, goal, meta_sized_clause, then);
189 }
190
191 let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
192 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
193
194 then(ecx)
195 }
196
197 fn consider_auto_trait_candidate(
198 ecx: &mut EvalCtxt<'_, D>,
199 goal: Goal<I, Self>,
200 ) -> Result<Candidate<I>, NoSolution> {
201 let cx = ecx.cx();
202 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
203 return Err(NoSolution);
204 }
205
206 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
207 return result;
208 }
209
210 if cx.trait_is_unsafe(goal.predicate.def_id())
213 && goal.predicate.self_ty().has_unsafe_fields()
214 {
215 return Err(NoSolution);
216 }
217
218 if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) =
234 goal.predicate.self_ty().kind()
235 {
236 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));
237 for item_bound in cx.item_self_bounds(def_id).skip_binder() {
238 if item_bound
239 .as_trait_clause()
240 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
241 {
242 return Err(NoSolution);
243 }
244 }
245 }
246
247 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
249 return cand;
250 }
251
252 ecx.probe_and_evaluate_goal_for_constituent_tys(
253 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
254 goal,
255 structural_traits::instantiate_constituent_tys_for_auto_trait,
256 )
257 }
258
259 fn consider_trait_alias_candidate(
260 ecx: &mut EvalCtxt<'_, D>,
261 goal: Goal<I, Self>,
262 ) -> Result<Candidate<I>, NoSolution> {
263 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
264 return Err(NoSolution);
265 }
266
267 let cx = ecx.cx();
268
269 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
270 let nested_obligations = cx
271 .predicates_of(goal.predicate.def_id().into())
272 .iter_instantiated(cx, goal.predicate.trait_ref.args)
273 .map(|p| goal.with(cx, p));
274 ecx.add_goals(GoalSource::Misc, nested_obligations);
280 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
281 })
282 }
283
284 fn consider_builtin_sizedness_candidates(
285 ecx: &mut EvalCtxt<'_, D>,
286 goal: Goal<I, Self>,
287 sizedness: SizedTraitKind,
288 ) -> Result<Candidate<I>, NoSolution> {
289 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
290 return Err(NoSolution);
291 }
292
293 ecx.probe_and_evaluate_goal_for_constituent_tys(
294 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
295 goal,
296 |ecx, ty| {
297 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
298 ecx, sizedness, ty,
299 )
300 },
301 )
302 }
303
304 fn consider_builtin_copy_clone_candidate(
305 ecx: &mut EvalCtxt<'_, D>,
306 goal: Goal<I, Self>,
307 ) -> Result<Candidate<I>, NoSolution> {
308 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
309 return Err(NoSolution);
310 }
311
312 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
314 return cand;
315 }
316
317 ecx.probe_and_evaluate_goal_for_constituent_tys(
318 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
319 goal,
320 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
321 )
322 }
323
324 fn consider_builtin_fn_ptr_trait_candidate(
325 ecx: &mut EvalCtxt<'_, D>,
326 goal: Goal<I, Self>,
327 ) -> Result<Candidate<I>, NoSolution> {
328 let self_ty = goal.predicate.self_ty();
329 match goal.predicate.polarity {
330 ty::PredicatePolarity::Positive => {
332 if self_ty.is_fn_ptr() {
333 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
334 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
335 })
336 } else {
337 Err(NoSolution)
338 }
339 }
340 ty::PredicatePolarity::Negative => {
342 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
345 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
346 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
347 })
348 } else {
349 Err(NoSolution)
350 }
351 }
352 }
353 }
354
355 fn consider_builtin_fn_trait_candidates(
356 ecx: &mut EvalCtxt<'_, D>,
357 goal: Goal<I, Self>,
358 goal_kind: ty::ClosureKind,
359 ) -> Result<Candidate<I>, NoSolution> {
360 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
361 return Err(NoSolution);
362 }
363
364 let cx = ecx.cx();
365 let Some(tupled_inputs_and_output) =
366 structural_traits::extract_tupled_inputs_and_output_from_callable(
367 cx,
368 goal.predicate.self_ty(),
369 goal_kind,
370 )?
371 else {
372 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
373 };
374 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
375
376 let output_is_sized_pred =
379 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
380
381 let pred =
382 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
383 .upcast(cx);
384 Self::probe_and_consider_implied_clause(
385 ecx,
386 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
387 goal,
388 pred,
389 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
390 )
391 }
392
393 fn consider_builtin_async_fn_trait_candidates(
394 ecx: &mut EvalCtxt<'_, D>,
395 goal: Goal<I, Self>,
396 goal_kind: ty::ClosureKind,
397 ) -> Result<Candidate<I>, NoSolution> {
398 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
399 return Err(NoSolution);
400 }
401
402 let cx = ecx.cx();
403 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
404 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
405 cx,
406 goal.predicate.self_ty(),
407 goal_kind,
408 Region::new_static(cx),
410 )?;
411 let AsyncCallableRelevantTypes {
412 tupled_inputs_ty,
413 output_coroutine_ty,
414 coroutine_return_ty: _,
415 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
416
417 let output_is_sized_pred = ty::TraitRef::new(
420 cx,
421 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
422 [output_coroutine_ty],
423 );
424
425 let pred = ty::TraitRef::new(
426 cx,
427 goal.predicate.def_id(),
428 [goal.predicate.self_ty(), tupled_inputs_ty],
429 )
430 .upcast(cx);
431 Self::probe_and_consider_implied_clause(
432 ecx,
433 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
434 goal,
435 pred,
436 [goal.with(cx, output_is_sized_pred)]
437 .into_iter()
438 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
439 .map(|goal| (GoalSource::ImplWhereBound, goal)),
440 )
441 }
442
443 fn consider_builtin_async_fn_kind_helper_candidate(
444 ecx: &mut EvalCtxt<'_, D>,
445 goal: Goal<I, Self>,
446 ) -> Result<Candidate<I>, NoSolution> {
447 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
448 ::core::panicking::panic("explicit panic");panic!();
449 };
450
451 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
452 return Err(NoSolution);
454 };
455 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
456 if closure_kind.extends(goal_kind) {
457 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
458 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
459 } else {
460 Err(NoSolution)
461 }
462 }
463
464 fn consider_builtin_tuple_candidate(
471 ecx: &mut EvalCtxt<'_, D>,
472 goal: Goal<I, Self>,
473 ) -> Result<Candidate<I>, NoSolution> {
474 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
475 return Err(NoSolution);
476 }
477
478 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
479 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
480 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
481 } else {
482 Err(NoSolution)
483 }
484 }
485
486 fn consider_builtin_pointee_candidate(
487 ecx: &mut EvalCtxt<'_, D>,
488 goal: Goal<I, Self>,
489 ) -> Result<Candidate<I>, NoSolution> {
490 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
491 return Err(NoSolution);
492 }
493
494 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
495 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
496 }
497
498 fn consider_builtin_future_candidate(
499 ecx: &mut EvalCtxt<'_, D>,
500 goal: Goal<I, Self>,
501 ) -> Result<Candidate<I>, NoSolution> {
502 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
503 return Err(NoSolution);
504 }
505
506 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
507 return Err(NoSolution);
508 };
509
510 let cx = ecx.cx();
512 if !cx.coroutine_is_async(def_id) {
513 return Err(NoSolution);
514 }
515
516 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
520 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
521 }
522
523 fn consider_builtin_iterator_candidate(
524 ecx: &mut EvalCtxt<'_, D>,
525 goal: Goal<I, Self>,
526 ) -> Result<Candidate<I>, NoSolution> {
527 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
528 return Err(NoSolution);
529 }
530
531 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
532 return Err(NoSolution);
533 };
534
535 let cx = ecx.cx();
537 if !cx.coroutine_is_gen(def_id) {
538 return Err(NoSolution);
539 }
540
541 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
545 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
546 }
547
548 fn consider_builtin_fused_iterator_candidate(
549 ecx: &mut EvalCtxt<'_, D>,
550 goal: Goal<I, Self>,
551 ) -> Result<Candidate<I>, NoSolution> {
552 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
553 return Err(NoSolution);
554 }
555
556 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
557 return Err(NoSolution);
558 };
559
560 let cx = ecx.cx();
562 if !cx.coroutine_is_gen(def_id) {
563 return Err(NoSolution);
564 }
565
566 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
568 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
569 }
570
571 fn consider_builtin_async_iterator_candidate(
572 ecx: &mut EvalCtxt<'_, D>,
573 goal: Goal<I, Self>,
574 ) -> Result<Candidate<I>, NoSolution> {
575 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
576 return Err(NoSolution);
577 }
578
579 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
580 return Err(NoSolution);
581 };
582
583 let cx = ecx.cx();
585 if !cx.coroutine_is_async_gen(def_id) {
586 return Err(NoSolution);
587 }
588
589 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
593 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
594 }
595
596 fn consider_builtin_coroutine_candidate(
597 ecx: &mut EvalCtxt<'_, D>,
598 goal: Goal<I, Self>,
599 ) -> Result<Candidate<I>, NoSolution> {
600 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
601 return Err(NoSolution);
602 }
603
604 let self_ty = goal.predicate.self_ty();
605 let ty::Coroutine(def_id, args) = self_ty.kind() else {
606 return Err(NoSolution);
607 };
608
609 let cx = ecx.cx();
611 if !cx.is_general_coroutine(def_id) {
612 return Err(NoSolution);
613 }
614
615 let coroutine = args.as_coroutine();
616 Self::probe_and_consider_implied_clause(
617 ecx,
618 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
619 goal,
620 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
621 .upcast(cx),
622 [],
625 )
626 }
627
628 fn consider_builtin_discriminant_kind_candidate(
629 ecx: &mut EvalCtxt<'_, D>,
630 goal: Goal<I, Self>,
631 ) -> Result<Candidate<I>, NoSolution> {
632 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
633 return Err(NoSolution);
634 }
635
636 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
638 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
639 }
640
641 fn consider_builtin_destruct_candidate(
642 ecx: &mut EvalCtxt<'_, D>,
643 goal: Goal<I, Self>,
644 ) -> Result<Candidate<I>, NoSolution> {
645 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
646 return Err(NoSolution);
647 }
648
649 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
652 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
653 }
654
655 fn consider_builtin_transmute_candidate(
656 ecx: &mut EvalCtxt<'_, D>,
657 goal: Goal<I, Self>,
658 ) -> Result<Candidate<I>, NoSolution> {
659 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
660 return Err(NoSolution);
661 }
662
663 if goal.predicate.has_non_region_placeholders() {
665 return Err(NoSolution);
666 }
667
668 if goal.has_non_region_infer() {
671 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
672 }
673
674 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
675 let assume = ecx.structurally_normalize_const(
676 goal.param_env,
677 goal.predicate.trait_ref.args.const_at(2),
678 )?;
679
680 let certainty = ecx.is_transmutable(
681 goal.predicate.trait_ref.args.type_at(0),
682 goal.predicate.trait_ref.args.type_at(1),
683 assume,
684 )?;
685 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
686 })
687 }
688
689 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
702 ecx: &mut EvalCtxt<'_, D>,
703 goal: Goal<I, Self>,
704 ) -> Result<Candidate<I>, NoSolution> {
705 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
706 return Err(NoSolution);
707 }
708
709 let cx = ecx.cx();
710 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
711 let ty = goal.predicate.self_ty();
712 match ty.kind() {
713 ty::Ref(..) => {}
715 ty::Adt(def, _) if def.is_manually_drop() => {}
717 ty::Tuple(tys) => {
720 ecx.add_goals(
721 GoalSource::ImplWhereBound,
722 tys.iter().map(|elem_ty| {
723 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
724 }),
725 );
726 }
727 ty::Array(elem_ty, _) => {
728 ecx.add_goal(
729 GoalSource::ImplWhereBound,
730 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
731 );
732 }
733
734 ty::FnDef(..)
738 | ty::FnPtr(..)
739 | ty::Error(_)
740 | ty::Uint(_)
741 | ty::Int(_)
742 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
743 | ty::Bool
744 | ty::Float(_)
745 | ty::Char
746 | ty::RawPtr(..)
747 | ty::Never
748 | ty::Pat(..)
749 | ty::Dynamic(..)
750 | ty::Str
751 | ty::Slice(_)
752 | ty::Foreign(..)
753 | ty::Adt(..)
754 | ty::Alias(..)
755 | ty::Param(_)
756 | ty::Placeholder(..)
757 | ty::Closure(..)
758 | ty::CoroutineClosure(..)
759 | ty::Coroutine(..)
760 | ty::UnsafeBinder(_)
761 | ty::CoroutineWitness(..) => {
762 ecx.add_goal(
763 GoalSource::ImplWhereBound,
764 goal.with(
765 cx,
766 ty::TraitRef::new(
767 cx,
768 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
769 [ty],
770 ),
771 ),
772 );
773 }
774
775 ty::Bound(..)
776 | ty::Infer(
777 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
778 ) => {
779 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
780 }
781 }
782
783 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
784 })
785 }
786
787 fn consider_structural_builtin_unsize_candidates(
795 ecx: &mut EvalCtxt<'_, D>,
796 goal: Goal<I, Self>,
797 ) -> Vec<Candidate<I>> {
798 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
799 return ::alloc::vec::Vec::new()vec![];
800 }
801
802 let result_to_single = |result| match result {
803 Ok(resp) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[resp]))vec![resp],
804 Err(NoSolution) => ::alloc::vec::Vec::new()vec![],
805 };
806
807 ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| {
808 let a_ty = goal.predicate.self_ty();
809 let Ok(b_ty) = ecx.structurally_normalize_ty(
812 goal.param_env,
813 goal.predicate.trait_ref.args.type_at(1),
814 ) else {
815 return ::alloc::vec::Vec::new()vec![];
816 };
817
818 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
819 match (a_ty.kind(), b_ty.kind()) {
820 (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:?}"),
821
822 (_, ty::Infer(ty::TyVar(..))) => {
823 result_to_single(ecx.forced_ambiguity(MaybeCause::Ambiguity))
824 }
825
826 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => ecx
828 .consider_builtin_dyn_upcast_candidates(
829 goal, a_data, a_region, b_data, b_region,
830 ),
831
832 (_, ty::Dynamic(b_region, b_data)) => result_to_single(
834 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data),
835 ),
836
837 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
839 result_to_single(ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty))
840 }
841
842 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
844 if a_def.is_struct() && a_def == b_def =>
845 {
846 result_to_single(
847 ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args),
848 )
849 }
850
851 _ => ::alloc::vec::Vec::new()vec![],
852 }
853 })
854 }
855
856 fn consider_builtin_field_candidate(
857 ecx: &mut EvalCtxt<'_, D>,
858 goal: Goal<I, Self>,
859 ) -> Result<Candidate<I>, NoSolution> {
860 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
861 return Err(NoSolution);
862 }
863 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
864 && let Some(FieldInfo { base, ty, .. }) =
865 def.field_representing_type_info(ecx.cx(), args)
866 && {
867 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
868 ecx.add_goal(
876 GoalSource::ImplWhereBound,
877 Goal {
878 param_env: goal.param_env,
879 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
880 },
881 );
882 ecx.add_goal(
883 GoalSource::ImplWhereBound,
884 Goal {
885 param_env: goal.param_env,
886 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
887 },
888 );
889 ecx.try_evaluate_added_goals()? == Certainty::Yes
890 }
891 && match base.kind() {
892 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
893 ty::Tuple(..) => true,
894 _ => false,
895 }
896 {
897 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
898 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
899 } else {
900 Err(NoSolution)
901 }
902 }
903}
904
905#[inline(always)]
911fn trait_predicate_with_def_id<I: Interner>(
912 cx: I,
913 clause: ty::Binder<I, ty::TraitPredicate<I>>,
914 did: I::TraitId,
915) -> I::Clause {
916 clause
917 .map_bound(|c| TraitPredicate {
918 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
919 polarity: c.polarity,
920 })
921 .upcast(cx)
922}
923
924impl<D, I> EvalCtxt<'_, D>
925where
926 D: SolverDelegate<Interner = I>,
927 I: Interner,
928{
929 fn consider_builtin_dyn_upcast_candidates(
939 &mut self,
940 goal: Goal<I, (I::Ty, I::Ty)>,
941 a_data: I::BoundExistentialPredicates,
942 a_region: I::Region,
943 b_data: I::BoundExistentialPredicates,
944 b_region: I::Region,
945 ) -> Vec<Candidate<I>> {
946 let cx = self.cx();
947 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
948
949 let mut responses = ::alloc::vec::Vec::new()vec![];
950 let b_principal_def_id = b_data.principal_def_id();
953 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
954 responses.extend(self.consider_builtin_upcast_to_principal(
955 goal,
956 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
957 a_data,
958 a_region,
959 b_data,
960 b_region,
961 a_data.principal(),
962 ));
963 } else if let Some(a_principal) = a_data.principal() {
964 for (idx, new_a_principal) in
965 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
966 .enumerate()
967 .skip(1)
968 {
969 responses.extend(self.consider_builtin_upcast_to_principal(
970 goal,
971 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
972 a_data,
973 a_region,
974 b_data,
975 b_region,
976 Some(new_a_principal.map_bound(|trait_ref| {
977 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
978 })),
979 ));
980 }
981 }
982
983 responses
984 }
985
986 fn consider_builtin_unsize_to_dyn_candidate(
987 &mut self,
988 goal: Goal<I, (I::Ty, I::Ty)>,
989 b_data: I::BoundExistentialPredicates,
990 b_region: I::Region,
991 ) -> Result<Candidate<I>, NoSolution> {
992 let cx = self.cx();
993 let Goal { predicate: (a_ty, _), .. } = goal;
994
995 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
997 return Err(NoSolution);
998 }
999
1000 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1001 ecx.add_goals(
1004 GoalSource::ImplWhereBound,
1005 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1006 );
1007
1008 ecx.add_goal(
1010 GoalSource::ImplWhereBound,
1011 goal.with(
1012 cx,
1013 ty::TraitRef::new(
1014 cx,
1015 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1016 [a_ty],
1017 ),
1018 ),
1019 );
1020
1021 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)));
1023 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1024 })
1025 }
1026
1027 fn consider_builtin_upcast_to_principal(
1028 &mut self,
1029 goal: Goal<I, (I::Ty, I::Ty)>,
1030 source: CandidateSource<I>,
1031 a_data: I::BoundExistentialPredicates,
1032 a_region: I::Region,
1033 b_data: I::BoundExistentialPredicates,
1034 b_region: I::Region,
1035 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1036 ) -> Result<Candidate<I>, NoSolution> {
1037 let param_env = goal.param_env;
1038
1039 let a_auto_traits: IndexSet<I::TraitId> = a_data
1043 .auto_traits()
1044 .into_iter()
1045 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1046 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1047 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1048 }))
1049 .collect();
1050
1051 let projection_may_match =
1056 |ecx: &mut EvalCtxt<'_, D>,
1057 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1058 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1059 source_projection.item_def_id() == target_projection.item_def_id()
1060 && ecx
1061 .probe(|_| ProbeKind::ProjectionCompatibility)
1062 .enter(|ecx| -> Result<_, NoSolution> {
1063 ecx.enter_forall(target_projection, |ecx, target_projection| {
1064 let source_projection =
1065 ecx.instantiate_binder_with_infer(source_projection);
1066 ecx.eq(param_env, source_projection, target_projection)?;
1067 ecx.try_evaluate_added_goals()
1068 })
1069 })
1070 .is_ok()
1071 };
1072
1073 self.probe_trait_candidate(source).enter(|ecx| {
1074 for bound in b_data.iter() {
1075 match bound.skip_binder() {
1076 ty::ExistentialPredicate::Trait(target_principal) => {
1079 let source_principal = upcast_principal.unwrap();
1080 let target_principal = bound.rebind(target_principal);
1081 ecx.enter_forall(target_principal, |ecx, target_principal| {
1082 let source_principal =
1083 ecx.instantiate_binder_with_infer(source_principal);
1084 ecx.eq(param_env, source_principal, target_principal)?;
1085 ecx.try_evaluate_added_goals()
1086 })?;
1087 }
1088 ty::ExistentialPredicate::Projection(target_projection) => {
1094 let target_projection = bound.rebind(target_projection);
1095 let mut matching_projections =
1096 a_data.projection_bounds().into_iter().filter(|source_projection| {
1097 projection_may_match(ecx, *source_projection, target_projection)
1098 });
1099 let Some(source_projection) = matching_projections.next() else {
1100 return Err(NoSolution);
1101 };
1102 if matching_projections.next().is_some() {
1103 return ecx.evaluate_added_goals_and_make_canonical_response(
1104 Certainty::AMBIGUOUS,
1105 );
1106 }
1107 ecx.enter_forall(target_projection, |ecx, target_projection| {
1108 let source_projection =
1109 ecx.instantiate_binder_with_infer(source_projection);
1110 ecx.eq(param_env, source_projection, target_projection)?;
1111 ecx.try_evaluate_added_goals()
1112 })?;
1113 }
1114 ty::ExistentialPredicate::AutoTrait(def_id) => {
1116 if !a_auto_traits.contains(&def_id) {
1117 return Err(NoSolution);
1118 }
1119 }
1120 }
1121 }
1122
1123 ecx.add_goal(
1125 GoalSource::ImplWhereBound,
1126 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1127 );
1128
1129 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1130 })
1131 }
1132
1133 fn consider_builtin_array_unsize(
1142 &mut self,
1143 goal: Goal<I, (I::Ty, I::Ty)>,
1144 a_elem_ty: I::Ty,
1145 b_elem_ty: I::Ty,
1146 ) -> Result<Candidate<I>, NoSolution> {
1147 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1148 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1149 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1150 }
1151
1152 fn consider_builtin_struct_unsize(
1166 &mut self,
1167 goal: Goal<I, (I::Ty, I::Ty)>,
1168 def: I::AdtDef,
1169 a_args: I::GenericArgs,
1170 b_args: I::GenericArgs,
1171 ) -> Result<Candidate<I>, NoSolution> {
1172 let cx = self.cx();
1173 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1174
1175 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1176 if unsizing_params.is_empty() {
1179 return Err(NoSolution);
1180 }
1181
1182 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1183
1184 let a_tail_ty = tail_field_ty.instantiate(cx, a_args);
1185 let b_tail_ty = tail_field_ty.instantiate(cx, b_args);
1186
1187 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1191 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1192 }));
1193 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1194
1195 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1198 self.add_goal(
1199 GoalSource::ImplWhereBound,
1200 goal.with(
1201 cx,
1202 ty::TraitRef::new(
1203 cx,
1204 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1205 [a_tail_ty, b_tail_ty],
1206 ),
1207 ),
1208 );
1209 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1210 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1211 }
1212
1213 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1218 &mut self,
1219 goal: Goal<I, TraitPredicate<I>>,
1220 ) -> Option<Result<Candidate<I>, NoSolution>> {
1221 let self_ty = goal.predicate.self_ty();
1222 let check_impls = || {
1223 let mut disqualifying_impl = None;
1224 self.cx().for_each_relevant_impl(
1225 goal.predicate.def_id(),
1226 goal.predicate.self_ty(),
1227 |impl_def_id| {
1228 disqualifying_impl = Some(impl_def_id);
1229 },
1230 );
1231 if let Some(def_id) = disqualifying_impl {
1232 {
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:1232",
"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(1232u32),
::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");
1233 return Some(Err(NoSolution));
1236 } else {
1237 None
1238 }
1239 };
1240
1241 match self_ty.kind() {
1242 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1248 Some(self.forced_ambiguity(MaybeCause::Ambiguity))
1249 }
1250
1251 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1254
1255 ty::Dynamic(..)
1258 | ty::Param(..)
1259 | ty::Foreign(..)
1260 | ty::Alias(ty::AliasTy {
1261 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1262 ..
1263 })
1264 | ty::Placeholder(..) => Some(Err(NoSolution)),
1265
1266 ty::Infer(_) | ty::Bound(_, _) => {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`"),
1267
1268 ty::Coroutine(def_id, _)
1272 if self
1273 .cx()
1274 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1275 {
1276 match self.cx().coroutine_movability(def_id) {
1277 Movability::Static => Some(Err(NoSolution)),
1278 Movability::Movable => Some(
1279 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1280 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1281 }),
1282 ),
1283 }
1284 }
1285
1286 ty::Alias(..) => None,
1291
1292 ty::Bool
1299 | ty::Char
1300 | ty::Int(_)
1301 | ty::Uint(_)
1302 | ty::Float(_)
1303 | ty::Str
1304 | ty::Array(_, _)
1305 | ty::Pat(_, _)
1306 | ty::Slice(_)
1307 | ty::RawPtr(_, _)
1308 | ty::Ref(_, _, _)
1309 | ty::FnDef(_, _)
1310 | ty::FnPtr(..)
1311 | ty::Closure(..)
1312 | ty::CoroutineClosure(..)
1313 | ty::Coroutine(_, _)
1314 | ty::CoroutineWitness(..)
1315 | ty::Never
1316 | ty::Tuple(_)
1317 | ty::Adt(_, _)
1318 | ty::UnsafeBinder(_) => check_impls(),
1319 ty::Error(_) => None,
1320 }
1321 }
1322
1323 fn probe_and_evaluate_goal_for_constituent_tys(
1328 &mut self,
1329 source: CandidateSource<I>,
1330 goal: Goal<I, TraitPredicate<I>>,
1331 constituent_tys: impl Fn(
1332 &EvalCtxt<'_, D>,
1333 I::Ty,
1334 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1335 ) -> Result<Candidate<I>, NoSolution> {
1336 self.probe_trait_candidate(source).enter(|ecx| {
1337 let goals =
1338 ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| {
1339 tys.into_iter()
1340 .map(|ty| {
1341 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1342 })
1343 .collect::<Vec<_>>()
1344 });
1345 ecx.add_goals(GoalSource::ImplWhereBound, goals);
1346 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1347 })
1348 }
1349}
1350
1351#[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)]
1362pub(super) enum TraitGoalProvenVia {
1363 Misc,
1369 ParamEnv,
1370 AliasBound,
1371}
1372
1373impl<D, I> EvalCtxt<'_, D>
1374where
1375 D: SolverDelegate<Interner = I>,
1376 I: Interner,
1377{
1378 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1391 match self.typing_mode() {
1392 TypingMode::Coherence => return,
1393 TypingMode::Analysis { .. }
1394 | TypingMode::Borrowck { .. }
1395 | TypingMode::PostBorrowckAnalysis { .. }
1396 | TypingMode::PostAnalysis => {}
1397 }
1398
1399 if candidates
1400 .iter()
1401 .find(|c| {
1402 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1403 })
1404 .is_some_and(|c| has_only_region_constraints(c.result))
1405 {
1406 candidates.retain(|c| {
1407 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1408 {
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:1408",
"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(1408u32),
::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");
1409 false
1410 } else {
1411 true
1412 }
1413 });
1414 }
1415 }
1416
1417 x;#[instrument(level = "debug", skip(self), ret)]
1418 pub(super) fn merge_trait_candidates(
1419 &mut self,
1420 candidate_preference_mode: CandidatePreferenceMode,
1421 mut candidates: Vec<Candidate<I>>,
1422 failed_candidate_info: FailedCandidateInfo,
1423 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1424 if self.typing_mode().is_coherence() {
1425 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1426 Ok((response, Some(TraitGoalProvenVia::Misc)))
1427 } else {
1428 self.flounder(&candidates).map(|r| (r, None))
1429 };
1430 }
1431
1432 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1437 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1438 });
1439 if let Some(candidate) = trivial_builtin_impls.next() {
1440 assert!(trivial_builtin_impls.next().is_none());
1443 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1444 }
1445
1446 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1449 && candidates.iter().any(|c| {
1450 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1451 })
1452 {
1453 let alias_bounds: Vec<_> = candidates
1454 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1455 .collect();
1456 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1457 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1458 } else {
1459 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1460 };
1461 }
1462
1463 let has_non_global_where_bounds = candidates
1466 .iter()
1467 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1468 if has_non_global_where_bounds {
1469 let where_bounds: Vec<_> = candidates
1470 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1471 .collect();
1472 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1473 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1474 };
1475 match info {
1476 MergeCandidateInfo::AlwaysApplicable(i) => {
1492 for (j, c) in where_bounds.into_iter().enumerate() {
1493 if i != j {
1494 self.ignore_candidate_head_usages(c.head_usages)
1495 }
1496 }
1497 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1501 }
1502 MergeCandidateInfo::EqualResponse => {}
1503 }
1504 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1505 }
1506
1507 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1509 let alias_bounds: Vec<_> = candidates
1510 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1511 .collect();
1512 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1513 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1514 } else {
1515 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1516 };
1517 }
1518
1519 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1520 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1521
1522 let proven_via = if candidates
1527 .iter()
1528 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1529 {
1530 TraitGoalProvenVia::ParamEnv
1531 } else {
1532 candidates
1533 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1534 TraitGoalProvenVia::Misc
1535 };
1536
1537 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1538 Ok((response, Some(proven_via)))
1539 } else {
1540 self.flounder(&candidates).map(|r| (r, None))
1541 }
1542 }
1543
1544 #[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(1544u32),
::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))]
1545 pub(super) fn compute_trait_goal(
1546 &mut self,
1547 goal: Goal<I, TraitPredicate<I>>,
1548 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1549 let (candidates, failed_candidate_info) =
1550 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1551 let candidate_preference_mode =
1552 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1553 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1554 }
1555
1556 fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
1557 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1558 match self.typing_mode() {
1559 TypingMode::Analysis {
1560 defining_opaque_types_and_generators: stalled_generators,
1561 } => {
1562 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1563 {
1564 return Some(self.forced_ambiguity(MaybeCause::Ambiguity));
1565 }
1566 }
1567 TypingMode::Coherence
1568 | TypingMode::PostAnalysis
1569 | TypingMode::Borrowck { defining_opaque_types: _ }
1570 | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
1571 }
1572 }
1573
1574 None
1575 }
1576}