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 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
669 let assume = ecx.structurally_normalize_const(
670 goal.param_env,
671 goal.predicate.trait_ref.args.const_at(2),
672 )?;
673
674 let certainty = ecx.is_transmutable(
675 goal.predicate.trait_ref.args.type_at(0),
676 goal.predicate.trait_ref.args.type_at(1),
677 assume,
678 )?;
679 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
680 })
681 }
682
683 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
696 ecx: &mut EvalCtxt<'_, D>,
697 goal: Goal<I, Self>,
698 ) -> Result<Candidate<I>, NoSolution> {
699 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
700 return Err(NoSolution);
701 }
702
703 let cx = ecx.cx();
704 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
705 let ty = goal.predicate.self_ty();
706 match ty.kind() {
707 ty::Ref(..) => {}
709 ty::Adt(def, _) if def.is_manually_drop() => {}
711 ty::Tuple(tys) => {
714 ecx.add_goals(
715 GoalSource::ImplWhereBound,
716 tys.iter().map(|elem_ty| {
717 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
718 }),
719 );
720 }
721 ty::Array(elem_ty, _) => {
722 ecx.add_goal(
723 GoalSource::ImplWhereBound,
724 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
725 );
726 }
727
728 ty::FnDef(..)
732 | ty::FnPtr(..)
733 | ty::Error(_)
734 | ty::Uint(_)
735 | ty::Int(_)
736 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
737 | ty::Bool
738 | ty::Float(_)
739 | ty::Char
740 | ty::RawPtr(..)
741 | ty::Never
742 | ty::Pat(..)
743 | ty::Dynamic(..)
744 | ty::Str
745 | ty::Slice(_)
746 | ty::Foreign(..)
747 | ty::Adt(..)
748 | ty::Alias(..)
749 | ty::Param(_)
750 | ty::Placeholder(..)
751 | ty::Closure(..)
752 | ty::CoroutineClosure(..)
753 | ty::Coroutine(..)
754 | ty::UnsafeBinder(_)
755 | ty::CoroutineWitness(..) => {
756 ecx.add_goal(
757 GoalSource::ImplWhereBound,
758 goal.with(
759 cx,
760 ty::TraitRef::new(
761 cx,
762 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
763 [ty],
764 ),
765 ),
766 );
767 }
768
769 ty::Bound(..)
770 | ty::Infer(
771 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
772 ) => {
773 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
774 }
775 }
776
777 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
778 })
779 }
780
781 fn consider_structural_builtin_unsize_candidates(
789 ecx: &mut EvalCtxt<'_, D>,
790 goal: Goal<I, Self>,
791 ) -> Vec<Candidate<I>> {
792 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
793 return ::alloc::vec::Vec::new()vec![];
794 }
795
796 let result_to_single = |result| match result {
797 Ok(resp) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[resp]))vec![resp],
798 Err(NoSolution) => ::alloc::vec::Vec::new()vec![],
799 };
800
801 ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| {
802 let a_ty = goal.predicate.self_ty();
803 let Ok(b_ty) = ecx.structurally_normalize_ty(
806 goal.param_env,
807 goal.predicate.trait_ref.args.type_at(1),
808 ) else {
809 return ::alloc::vec::Vec::new()vec![];
810 };
811
812 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
813 match (a_ty.kind(), b_ty.kind()) {
814 (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:?}"),
815
816 (_, ty::Infer(ty::TyVar(..))) => {
817 result_to_single(ecx.forced_ambiguity(MaybeCause::Ambiguity))
818 }
819
820 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => ecx
822 .consider_builtin_dyn_upcast_candidates(
823 goal, a_data, a_region, b_data, b_region,
824 ),
825
826 (_, ty::Dynamic(b_region, b_data)) => result_to_single(
828 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data),
829 ),
830
831 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
833 result_to_single(ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty))
834 }
835
836 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
838 if a_def.is_struct() && a_def == b_def =>
839 {
840 result_to_single(
841 ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args),
842 )
843 }
844
845 _ => ::alloc::vec::Vec::new()vec![],
846 }
847 })
848 }
849
850 fn consider_builtin_field_candidate(
851 ecx: &mut EvalCtxt<'_, D>,
852 goal: Goal<I, Self>,
853 ) -> Result<Candidate<I>, NoSolution> {
854 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
855 return Err(NoSolution);
856 }
857 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
858 && let Some(FieldInfo { base, ty, .. }) =
859 def.field_representing_type_info(ecx.cx(), args)
860 && {
861 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
862 ecx.add_goal(
870 GoalSource::ImplWhereBound,
871 Goal {
872 param_env: goal.param_env,
873 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
874 },
875 );
876 ecx.add_goal(
877 GoalSource::ImplWhereBound,
878 Goal {
879 param_env: goal.param_env,
880 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
881 },
882 );
883 ecx.try_evaluate_added_goals()? == Certainty::Yes
884 }
885 && match base.kind() {
886 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
887 ty::Tuple(..) => true,
888 _ => false,
889 }
890 {
891 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
892 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
893 } else {
894 Err(NoSolution)
895 }
896 }
897}
898
899#[inline(always)]
905fn trait_predicate_with_def_id<I: Interner>(
906 cx: I,
907 clause: ty::Binder<I, ty::TraitPredicate<I>>,
908 did: I::TraitId,
909) -> I::Clause {
910 clause
911 .map_bound(|c| TraitPredicate {
912 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
913 polarity: c.polarity,
914 })
915 .upcast(cx)
916}
917
918impl<D, I> EvalCtxt<'_, D>
919where
920 D: SolverDelegate<Interner = I>,
921 I: Interner,
922{
923 fn consider_builtin_dyn_upcast_candidates(
933 &mut self,
934 goal: Goal<I, (I::Ty, I::Ty)>,
935 a_data: I::BoundExistentialPredicates,
936 a_region: I::Region,
937 b_data: I::BoundExistentialPredicates,
938 b_region: I::Region,
939 ) -> Vec<Candidate<I>> {
940 let cx = self.cx();
941 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
942
943 let mut responses = ::alloc::vec::Vec::new()vec![];
944 let b_principal_def_id = b_data.principal_def_id();
947 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
948 responses.extend(self.consider_builtin_upcast_to_principal(
949 goal,
950 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
951 a_data,
952 a_region,
953 b_data,
954 b_region,
955 a_data.principal(),
956 ));
957 } else if let Some(a_principal) = a_data.principal() {
958 for (idx, new_a_principal) in
959 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
960 .enumerate()
961 .skip(1)
962 {
963 responses.extend(self.consider_builtin_upcast_to_principal(
964 goal,
965 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
966 a_data,
967 a_region,
968 b_data,
969 b_region,
970 Some(new_a_principal.map_bound(|trait_ref| {
971 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
972 })),
973 ));
974 }
975 }
976
977 responses
978 }
979
980 fn consider_builtin_unsize_to_dyn_candidate(
981 &mut self,
982 goal: Goal<I, (I::Ty, I::Ty)>,
983 b_data: I::BoundExistentialPredicates,
984 b_region: I::Region,
985 ) -> Result<Candidate<I>, NoSolution> {
986 let cx = self.cx();
987 let Goal { predicate: (a_ty, _), .. } = goal;
988
989 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
991 return Err(NoSolution);
992 }
993
994 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
995 ecx.add_goals(
998 GoalSource::ImplWhereBound,
999 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1000 );
1001
1002 ecx.add_goal(
1004 GoalSource::ImplWhereBound,
1005 goal.with(
1006 cx,
1007 ty::TraitRef::new(
1008 cx,
1009 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1010 [a_ty],
1011 ),
1012 ),
1013 );
1014
1015 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)));
1017 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1018 })
1019 }
1020
1021 fn consider_builtin_upcast_to_principal(
1022 &mut self,
1023 goal: Goal<I, (I::Ty, I::Ty)>,
1024 source: CandidateSource<I>,
1025 a_data: I::BoundExistentialPredicates,
1026 a_region: I::Region,
1027 b_data: I::BoundExistentialPredicates,
1028 b_region: I::Region,
1029 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1030 ) -> Result<Candidate<I>, NoSolution> {
1031 let param_env = goal.param_env;
1032
1033 let a_auto_traits: IndexSet<I::TraitId> = a_data
1037 .auto_traits()
1038 .into_iter()
1039 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1040 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1041 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1042 }))
1043 .collect();
1044
1045 let projection_may_match =
1050 |ecx: &mut EvalCtxt<'_, D>,
1051 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1052 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1053 source_projection.item_def_id() == target_projection.item_def_id()
1054 && ecx
1055 .probe(|_| ProbeKind::ProjectionCompatibility)
1056 .enter(|ecx| -> Result<_, NoSolution> {
1057 ecx.enter_forall(target_projection, |ecx, target_projection| {
1058 let source_projection =
1059 ecx.instantiate_binder_with_infer(source_projection);
1060 ecx.eq(param_env, source_projection, target_projection)?;
1061 ecx.try_evaluate_added_goals()
1062 })
1063 })
1064 .is_ok()
1065 };
1066
1067 self.probe_trait_candidate(source).enter(|ecx| {
1068 for bound in b_data.iter() {
1069 match bound.skip_binder() {
1070 ty::ExistentialPredicate::Trait(target_principal) => {
1073 let source_principal = upcast_principal.unwrap();
1074 let target_principal = bound.rebind(target_principal);
1075 ecx.enter_forall(target_principal, |ecx, target_principal| {
1076 let source_principal =
1077 ecx.instantiate_binder_with_infer(source_principal);
1078 ecx.eq(param_env, source_principal, target_principal)?;
1079 ecx.try_evaluate_added_goals()
1080 })?;
1081 }
1082 ty::ExistentialPredicate::Projection(target_projection) => {
1088 let target_projection = bound.rebind(target_projection);
1089 let mut matching_projections =
1090 a_data.projection_bounds().into_iter().filter(|source_projection| {
1091 projection_may_match(ecx, *source_projection, target_projection)
1092 });
1093 let Some(source_projection) = matching_projections.next() else {
1094 return Err(NoSolution);
1095 };
1096 if matching_projections.next().is_some() {
1097 return ecx.evaluate_added_goals_and_make_canonical_response(
1098 Certainty::AMBIGUOUS,
1099 );
1100 }
1101 ecx.enter_forall(target_projection, |ecx, target_projection| {
1102 let source_projection =
1103 ecx.instantiate_binder_with_infer(source_projection);
1104 ecx.eq(param_env, source_projection, target_projection)?;
1105 ecx.try_evaluate_added_goals()
1106 })?;
1107 }
1108 ty::ExistentialPredicate::AutoTrait(def_id) => {
1110 if !a_auto_traits.contains(&def_id) {
1111 return Err(NoSolution);
1112 }
1113 }
1114 }
1115 }
1116
1117 ecx.add_goal(
1119 GoalSource::ImplWhereBound,
1120 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1121 );
1122
1123 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1124 })
1125 }
1126
1127 fn consider_builtin_array_unsize(
1136 &mut self,
1137 goal: Goal<I, (I::Ty, I::Ty)>,
1138 a_elem_ty: I::Ty,
1139 b_elem_ty: I::Ty,
1140 ) -> Result<Candidate<I>, NoSolution> {
1141 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1142 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1143 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1144 }
1145
1146 fn consider_builtin_struct_unsize(
1160 &mut self,
1161 goal: Goal<I, (I::Ty, I::Ty)>,
1162 def: I::AdtDef,
1163 a_args: I::GenericArgs,
1164 b_args: I::GenericArgs,
1165 ) -> Result<Candidate<I>, NoSolution> {
1166 let cx = self.cx();
1167 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1168
1169 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1170 if unsizing_params.is_empty() {
1173 return Err(NoSolution);
1174 }
1175
1176 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1177
1178 let a_tail_ty = tail_field_ty.instantiate(cx, a_args);
1179 let b_tail_ty = tail_field_ty.instantiate(cx, b_args);
1180
1181 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1185 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1186 }));
1187 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1188
1189 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1192 self.add_goal(
1193 GoalSource::ImplWhereBound,
1194 goal.with(
1195 cx,
1196 ty::TraitRef::new(
1197 cx,
1198 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1199 [a_tail_ty, b_tail_ty],
1200 ),
1201 ),
1202 );
1203 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1204 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1205 }
1206
1207 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1212 &mut self,
1213 goal: Goal<I, TraitPredicate<I>>,
1214 ) -> Option<Result<Candidate<I>, NoSolution>> {
1215 let self_ty = goal.predicate.self_ty();
1216 let check_impls = || {
1217 let mut disqualifying_impl = None;
1218 self.cx().for_each_relevant_impl(
1219 goal.predicate.def_id(),
1220 goal.predicate.self_ty(),
1221 |impl_def_id| {
1222 disqualifying_impl = Some(impl_def_id);
1223 },
1224 );
1225 if let Some(def_id) = disqualifying_impl {
1226 {
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:1226",
"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(1226u32),
::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");
1227 return Some(Err(NoSolution));
1230 } else {
1231 None
1232 }
1233 };
1234
1235 match self_ty.kind() {
1236 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1242 Some(self.forced_ambiguity(MaybeCause::Ambiguity))
1243 }
1244
1245 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1248
1249 ty::Dynamic(..)
1252 | ty::Param(..)
1253 | ty::Foreign(..)
1254 | ty::Alias(ty::AliasTy {
1255 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1256 ..
1257 })
1258 | ty::Placeholder(..) => Some(Err(NoSolution)),
1259
1260 ty::Infer(_) | ty::Bound(_, _) => {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`"),
1261
1262 ty::Coroutine(def_id, _)
1266 if self
1267 .cx()
1268 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1269 {
1270 match self.cx().coroutine_movability(def_id) {
1271 Movability::Static => Some(Err(NoSolution)),
1272 Movability::Movable => Some(
1273 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1274 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1275 }),
1276 ),
1277 }
1278 }
1279
1280 ty::Alias(..) => None,
1285
1286 ty::Bool
1293 | ty::Char
1294 | ty::Int(_)
1295 | ty::Uint(_)
1296 | ty::Float(_)
1297 | ty::Str
1298 | ty::Array(_, _)
1299 | ty::Pat(_, _)
1300 | ty::Slice(_)
1301 | ty::RawPtr(_, _)
1302 | ty::Ref(_, _, _)
1303 | ty::FnDef(_, _)
1304 | ty::FnPtr(..)
1305 | ty::Closure(..)
1306 | ty::CoroutineClosure(..)
1307 | ty::Coroutine(_, _)
1308 | ty::CoroutineWitness(..)
1309 | ty::Never
1310 | ty::Tuple(_)
1311 | ty::Adt(_, _)
1312 | ty::UnsafeBinder(_) => check_impls(),
1313 ty::Error(_) => None,
1314 }
1315 }
1316
1317 fn probe_and_evaluate_goal_for_constituent_tys(
1322 &mut self,
1323 source: CandidateSource<I>,
1324 goal: Goal<I, TraitPredicate<I>>,
1325 constituent_tys: impl Fn(
1326 &EvalCtxt<'_, D>,
1327 I::Ty,
1328 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1329 ) -> Result<Candidate<I>, NoSolution> {
1330 self.probe_trait_candidate(source).enter(|ecx| {
1331 let goals =
1332 ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| {
1333 tys.into_iter()
1334 .map(|ty| {
1335 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1336 })
1337 .collect::<Vec<_>>()
1338 });
1339 ecx.add_goals(GoalSource::ImplWhereBound, goals);
1340 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1341 })
1342 }
1343}
1344
1345#[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)]
1356pub(super) enum TraitGoalProvenVia {
1357 Misc,
1363 ParamEnv,
1364 AliasBound,
1365}
1366
1367impl<D, I> EvalCtxt<'_, D>
1368where
1369 D: SolverDelegate<Interner = I>,
1370 I: Interner,
1371{
1372 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1385 match self.typing_mode() {
1386 TypingMode::Coherence => return,
1387 TypingMode::Analysis { .. }
1388 | TypingMode::Borrowck { .. }
1389 | TypingMode::PostBorrowckAnalysis { .. }
1390 | TypingMode::PostAnalysis => {}
1391 }
1392
1393 if candidates
1394 .iter()
1395 .find(|c| {
1396 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1397 })
1398 .is_some_and(|c| has_only_region_constraints(c.result))
1399 {
1400 candidates.retain(|c| {
1401 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1402 {
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:1402",
"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(1402u32),
::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");
1403 false
1404 } else {
1405 true
1406 }
1407 });
1408 }
1409 }
1410
1411 x;#[instrument(level = "debug", skip(self), ret)]
1412 pub(super) fn merge_trait_candidates(
1413 &mut self,
1414 candidate_preference_mode: CandidatePreferenceMode,
1415 mut candidates: Vec<Candidate<I>>,
1416 failed_candidate_info: FailedCandidateInfo,
1417 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1418 if let TypingMode::Coherence = self.typing_mode() {
1419 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1420 Ok((response, Some(TraitGoalProvenVia::Misc)))
1421 } else {
1422 self.flounder(&candidates).map(|r| (r, None))
1423 };
1424 }
1425
1426 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1431 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1432 });
1433 if let Some(candidate) = trivial_builtin_impls.next() {
1434 assert!(trivial_builtin_impls.next().is_none());
1437 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1438 }
1439
1440 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1443 && candidates.iter().any(|c| {
1444 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1445 })
1446 {
1447 let alias_bounds: Vec<_> = candidates
1448 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1449 .collect();
1450 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1451 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1452 } else {
1453 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1454 };
1455 }
1456
1457 let has_non_global_where_bounds = candidates
1460 .iter()
1461 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1462 if has_non_global_where_bounds {
1463 let where_bounds: Vec<_> = candidates
1464 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1465 .collect();
1466 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1467 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1468 };
1469 match info {
1470 MergeCandidateInfo::AlwaysApplicable(i) => {
1486 for (j, c) in where_bounds.into_iter().enumerate() {
1487 if i != j {
1488 self.ignore_candidate_head_usages(c.head_usages)
1489 }
1490 }
1491 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1495 }
1496 MergeCandidateInfo::EqualResponse => {}
1497 }
1498 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1499 }
1500
1501 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1503 let alias_bounds: Vec<_> = candidates
1504 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1505 .collect();
1506 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1507 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1508 } else {
1509 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1510 };
1511 }
1512
1513 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1514 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1515
1516 let proven_via = if candidates
1521 .iter()
1522 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1523 {
1524 TraitGoalProvenVia::ParamEnv
1525 } else {
1526 candidates
1527 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1528 TraitGoalProvenVia::Misc
1529 };
1530
1531 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1532 Ok((response, Some(proven_via)))
1533 } else {
1534 self.flounder(&candidates).map(|r| (r, None))
1535 }
1536 }
1537
1538 #[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(1538u32),
::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))]
1539 pub(super) fn compute_trait_goal(
1540 &mut self,
1541 goal: Goal<I, TraitPredicate<I>>,
1542 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1543 let (candidates, failed_candidate_info) =
1544 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1545 let candidate_preference_mode =
1546 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1547 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1548 }
1549
1550 fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
1551 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1552 match self.typing_mode() {
1553 TypingMode::Analysis {
1554 defining_opaque_types_and_generators: stalled_generators,
1555 } => {
1556 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1557 {
1558 return Some(self.forced_ambiguity(MaybeCause::Ambiguity));
1559 }
1560 }
1561 TypingMode::Coherence
1562 | TypingMode::PostAnalysis
1563 | TypingMode::Borrowck { defining_opaque_types: _ }
1564 | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
1565 }
1566 }
1567
1568 None
1569 }
1570}