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::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
234 if true {
if !ecx.opaque_type_is_rigid(opaque_ty.def_id) {
::core::panicking::panic("assertion failed: ecx.opaque_type_is_rigid(opaque_ty.def_id)")
};
};debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
235 for item_bound in cx.item_self_bounds(opaque_ty.def_id).skip_binder() {
236 if item_bound
237 .as_trait_clause()
238 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
239 {
240 return Err(NoSolution);
241 }
242 }
243 }
244
245 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
247 return cand;
248 }
249
250 ecx.probe_and_evaluate_goal_for_constituent_tys(
251 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
252 goal,
253 structural_traits::instantiate_constituent_tys_for_auto_trait,
254 )
255 }
256
257 fn consider_trait_alias_candidate(
258 ecx: &mut EvalCtxt<'_, D>,
259 goal: Goal<I, Self>,
260 ) -> Result<Candidate<I>, NoSolution> {
261 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
262 return Err(NoSolution);
263 }
264
265 let cx = ecx.cx();
266
267 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
268 let nested_obligations = cx
269 .predicates_of(goal.predicate.def_id().into())
270 .iter_instantiated(cx, goal.predicate.trait_ref.args)
271 .map(|p| goal.with(cx, p));
272 ecx.add_goals(GoalSource::Misc, nested_obligations);
278 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
279 })
280 }
281
282 fn consider_builtin_sizedness_candidates(
283 ecx: &mut EvalCtxt<'_, D>,
284 goal: Goal<I, Self>,
285 sizedness: SizedTraitKind,
286 ) -> Result<Candidate<I>, NoSolution> {
287 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
288 return Err(NoSolution);
289 }
290
291 ecx.probe_and_evaluate_goal_for_constituent_tys(
292 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
293 goal,
294 |ecx, ty| {
295 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
296 ecx, sizedness, ty,
297 )
298 },
299 )
300 }
301
302 fn consider_builtin_copy_clone_candidate(
303 ecx: &mut EvalCtxt<'_, D>,
304 goal: Goal<I, Self>,
305 ) -> Result<Candidate<I>, NoSolution> {
306 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
307 return Err(NoSolution);
308 }
309
310 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
312 return cand;
313 }
314
315 ecx.probe_and_evaluate_goal_for_constituent_tys(
316 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
317 goal,
318 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
319 )
320 }
321
322 fn consider_builtin_fn_ptr_trait_candidate(
323 ecx: &mut EvalCtxt<'_, D>,
324 goal: Goal<I, Self>,
325 ) -> Result<Candidate<I>, NoSolution> {
326 let self_ty = goal.predicate.self_ty();
327 match goal.predicate.polarity {
328 ty::PredicatePolarity::Positive => {
330 if self_ty.is_fn_ptr() {
331 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
332 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
333 })
334 } else {
335 Err(NoSolution)
336 }
337 }
338 ty::PredicatePolarity::Negative => {
340 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
343 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
344 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
345 })
346 } else {
347 Err(NoSolution)
348 }
349 }
350 }
351 }
352
353 fn consider_builtin_fn_trait_candidates(
354 ecx: &mut EvalCtxt<'_, D>,
355 goal: Goal<I, Self>,
356 goal_kind: ty::ClosureKind,
357 ) -> Result<Candidate<I>, NoSolution> {
358 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
359 return Err(NoSolution);
360 }
361
362 let cx = ecx.cx();
363 let Some(tupled_inputs_and_output) =
364 structural_traits::extract_tupled_inputs_and_output_from_callable(
365 cx,
366 goal.predicate.self_ty(),
367 goal_kind,
368 )?
369 else {
370 return ecx.forced_ambiguity(MaybeCause::Ambiguity);
371 };
372 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
373
374 let output_is_sized_pred =
377 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
378
379 let pred =
380 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
381 .upcast(cx);
382 Self::probe_and_consider_implied_clause(
383 ecx,
384 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
385 goal,
386 pred,
387 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
388 )
389 }
390
391 fn consider_builtin_async_fn_trait_candidates(
392 ecx: &mut EvalCtxt<'_, D>,
393 goal: Goal<I, Self>,
394 goal_kind: ty::ClosureKind,
395 ) -> Result<Candidate<I>, NoSolution> {
396 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
397 return Err(NoSolution);
398 }
399
400 let cx = ecx.cx();
401 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
402 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
403 cx,
404 goal.predicate.self_ty(),
405 goal_kind,
406 Region::new_static(cx),
408 )?;
409 let AsyncCallableRelevantTypes {
410 tupled_inputs_ty,
411 output_coroutine_ty,
412 coroutine_return_ty: _,
413 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
414
415 let output_is_sized_pred = ty::TraitRef::new(
418 cx,
419 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
420 [output_coroutine_ty],
421 );
422
423 let pred = ty::TraitRef::new(
424 cx,
425 goal.predicate.def_id(),
426 [goal.predicate.self_ty(), tupled_inputs_ty],
427 )
428 .upcast(cx);
429 Self::probe_and_consider_implied_clause(
430 ecx,
431 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
432 goal,
433 pred,
434 [goal.with(cx, output_is_sized_pred)]
435 .into_iter()
436 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
437 .map(|goal| (GoalSource::ImplWhereBound, goal)),
438 )
439 }
440
441 fn consider_builtin_async_fn_kind_helper_candidate(
442 ecx: &mut EvalCtxt<'_, D>,
443 goal: Goal<I, Self>,
444 ) -> Result<Candidate<I>, NoSolution> {
445 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
446 ::core::panicking::panic("explicit panic");panic!();
447 };
448
449 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
450 return Err(NoSolution);
452 };
453 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
454 if closure_kind.extends(goal_kind) {
455 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
456 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
457 } else {
458 Err(NoSolution)
459 }
460 }
461
462 fn consider_builtin_tuple_candidate(
469 ecx: &mut EvalCtxt<'_, D>,
470 goal: Goal<I, Self>,
471 ) -> Result<Candidate<I>, NoSolution> {
472 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
473 return Err(NoSolution);
474 }
475
476 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
477 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
478 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
479 } else {
480 Err(NoSolution)
481 }
482 }
483
484 fn consider_builtin_pointee_candidate(
485 ecx: &mut EvalCtxt<'_, D>,
486 goal: Goal<I, Self>,
487 ) -> Result<Candidate<I>, NoSolution> {
488 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
489 return Err(NoSolution);
490 }
491
492 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
493 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
494 }
495
496 fn consider_builtin_future_candidate(
497 ecx: &mut EvalCtxt<'_, D>,
498 goal: Goal<I, Self>,
499 ) -> Result<Candidate<I>, NoSolution> {
500 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
501 return Err(NoSolution);
502 }
503
504 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
505 return Err(NoSolution);
506 };
507
508 let cx = ecx.cx();
510 if !cx.coroutine_is_async(def_id) {
511 return Err(NoSolution);
512 }
513
514 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
518 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
519 }
520
521 fn consider_builtin_iterator_candidate(
522 ecx: &mut EvalCtxt<'_, D>,
523 goal: Goal<I, Self>,
524 ) -> Result<Candidate<I>, NoSolution> {
525 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
526 return Err(NoSolution);
527 }
528
529 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
530 return Err(NoSolution);
531 };
532
533 let cx = ecx.cx();
535 if !cx.coroutine_is_gen(def_id) {
536 return Err(NoSolution);
537 }
538
539 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
543 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
544 }
545
546 fn consider_builtin_fused_iterator_candidate(
547 ecx: &mut EvalCtxt<'_, D>,
548 goal: Goal<I, Self>,
549 ) -> Result<Candidate<I>, NoSolution> {
550 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
551 return Err(NoSolution);
552 }
553
554 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
555 return Err(NoSolution);
556 };
557
558 let cx = ecx.cx();
560 if !cx.coroutine_is_gen(def_id) {
561 return Err(NoSolution);
562 }
563
564 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
566 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
567 }
568
569 fn consider_builtin_async_iterator_candidate(
570 ecx: &mut EvalCtxt<'_, D>,
571 goal: Goal<I, Self>,
572 ) -> Result<Candidate<I>, NoSolution> {
573 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
574 return Err(NoSolution);
575 }
576
577 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
578 return Err(NoSolution);
579 };
580
581 let cx = ecx.cx();
583 if !cx.coroutine_is_async_gen(def_id) {
584 return Err(NoSolution);
585 }
586
587 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
591 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
592 }
593
594 fn consider_builtin_coroutine_candidate(
595 ecx: &mut EvalCtxt<'_, D>,
596 goal: Goal<I, Self>,
597 ) -> Result<Candidate<I>, NoSolution> {
598 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
599 return Err(NoSolution);
600 }
601
602 let self_ty = goal.predicate.self_ty();
603 let ty::Coroutine(def_id, args) = self_ty.kind() else {
604 return Err(NoSolution);
605 };
606
607 let cx = ecx.cx();
609 if !cx.is_general_coroutine(def_id) {
610 return Err(NoSolution);
611 }
612
613 let coroutine = args.as_coroutine();
614 Self::probe_and_consider_implied_clause(
615 ecx,
616 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
617 goal,
618 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
619 .upcast(cx),
620 [],
623 )
624 }
625
626 fn consider_builtin_discriminant_kind_candidate(
627 ecx: &mut EvalCtxt<'_, D>,
628 goal: Goal<I, Self>,
629 ) -> Result<Candidate<I>, NoSolution> {
630 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
631 return Err(NoSolution);
632 }
633
634 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
636 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
637 }
638
639 fn consider_builtin_destruct_candidate(
640 ecx: &mut EvalCtxt<'_, D>,
641 goal: Goal<I, Self>,
642 ) -> Result<Candidate<I>, NoSolution> {
643 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
644 return Err(NoSolution);
645 }
646
647 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
650 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
651 }
652
653 fn consider_builtin_transmute_candidate(
654 ecx: &mut EvalCtxt<'_, D>,
655 goal: Goal<I, Self>,
656 ) -> Result<Candidate<I>, NoSolution> {
657 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
658 return Err(NoSolution);
659 }
660
661 if goal.predicate.has_non_region_placeholders() {
663 return Err(NoSolution);
664 }
665
666 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
667 let assume = ecx.structurally_normalize_const(
668 goal.param_env,
669 goal.predicate.trait_ref.args.const_at(2),
670 )?;
671
672 let certainty = ecx.is_transmutable(
673 goal.predicate.trait_ref.args.type_at(0),
674 goal.predicate.trait_ref.args.type_at(1),
675 assume,
676 )?;
677 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
678 })
679 }
680
681 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
694 ecx: &mut EvalCtxt<'_, D>,
695 goal: Goal<I, Self>,
696 ) -> Result<Candidate<I>, NoSolution> {
697 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
698 return Err(NoSolution);
699 }
700
701 let cx = ecx.cx();
702 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
703 let ty = goal.predicate.self_ty();
704 match ty.kind() {
705 ty::Ref(..) => {}
707 ty::Adt(def, _) if def.is_manually_drop() => {}
709 ty::Tuple(tys) => {
712 ecx.add_goals(
713 GoalSource::ImplWhereBound,
714 tys.iter().map(|elem_ty| {
715 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
716 }),
717 );
718 }
719 ty::Array(elem_ty, _) => {
720 ecx.add_goal(
721 GoalSource::ImplWhereBound,
722 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
723 );
724 }
725
726 ty::FnDef(..)
730 | ty::FnPtr(..)
731 | ty::Error(_)
732 | ty::Uint(_)
733 | ty::Int(_)
734 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
735 | ty::Bool
736 | ty::Float(_)
737 | ty::Char
738 | ty::RawPtr(..)
739 | ty::Never
740 | ty::Pat(..)
741 | ty::Dynamic(..)
742 | ty::Str
743 | ty::Slice(_)
744 | ty::Foreign(..)
745 | ty::Adt(..)
746 | ty::Alias(..)
747 | ty::Param(_)
748 | ty::Placeholder(..)
749 | ty::Closure(..)
750 | ty::CoroutineClosure(..)
751 | ty::Coroutine(..)
752 | ty::UnsafeBinder(_)
753 | ty::CoroutineWitness(..) => {
754 ecx.add_goal(
755 GoalSource::ImplWhereBound,
756 goal.with(
757 cx,
758 ty::TraitRef::new(
759 cx,
760 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
761 [ty],
762 ),
763 ),
764 );
765 }
766
767 ty::Bound(..)
768 | ty::Infer(
769 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
770 ) => {
771 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
772 }
773 }
774
775 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
776 })
777 }
778
779 fn consider_structural_builtin_unsize_candidates(
787 ecx: &mut EvalCtxt<'_, D>,
788 goal: Goal<I, Self>,
789 ) -> Vec<Candidate<I>> {
790 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
791 return ::alloc::vec::Vec::new()vec![];
792 }
793
794 let result_to_single = |result| match result {
795 Ok(resp) => ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[resp]))vec![resp],
796 Err(NoSolution) => ::alloc::vec::Vec::new()vec![],
797 };
798
799 ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| {
800 let a_ty = goal.predicate.self_ty();
801 let Ok(b_ty) = ecx.structurally_normalize_ty(
804 goal.param_env,
805 goal.predicate.trait_ref.args.type_at(1),
806 ) else {
807 return ::alloc::vec::Vec::new()vec![];
808 };
809
810 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
811 match (a_ty.kind(), b_ty.kind()) {
812 (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:?}"),
813
814 (_, ty::Infer(ty::TyVar(..))) => {
815 result_to_single(ecx.forced_ambiguity(MaybeCause::Ambiguity))
816 }
817
818 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => ecx
820 .consider_builtin_dyn_upcast_candidates(
821 goal, a_data, a_region, b_data, b_region,
822 ),
823
824 (_, ty::Dynamic(b_region, b_data)) => result_to_single(
826 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data),
827 ),
828
829 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
831 result_to_single(ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty))
832 }
833
834 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
836 if a_def.is_struct() && a_def == b_def =>
837 {
838 result_to_single(
839 ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args),
840 )
841 }
842
843 _ => ::alloc::vec::Vec::new()vec![],
844 }
845 })
846 }
847
848 fn consider_builtin_field_candidate(
849 ecx: &mut EvalCtxt<'_, D>,
850 goal: Goal<I, Self>,
851 ) -> Result<Candidate<I>, NoSolution> {
852 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
853 return Err(NoSolution);
854 }
855 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
856 && let Some(FieldInfo { base, ty, .. }) =
857 def.field_representing_type_info(ecx.cx(), args)
858 && {
859 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
860 ecx.add_goal(
868 GoalSource::ImplWhereBound,
869 Goal {
870 param_env: goal.param_env,
871 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
872 },
873 );
874 ecx.add_goal(
875 GoalSource::ImplWhereBound,
876 Goal {
877 param_env: goal.param_env,
878 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
879 },
880 );
881 ecx.try_evaluate_added_goals()? == Certainty::Yes
882 }
883 && match base.kind() {
884 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
885 ty::Tuple(..) => true,
886 _ => false,
887 }
888 {
889 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
890 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
891 } else {
892 Err(NoSolution)
893 }
894 }
895}
896
897#[inline(always)]
903fn trait_predicate_with_def_id<I: Interner>(
904 cx: I,
905 clause: ty::Binder<I, ty::TraitPredicate<I>>,
906 did: I::TraitId,
907) -> I::Clause {
908 clause
909 .map_bound(|c| TraitPredicate {
910 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
911 polarity: c.polarity,
912 })
913 .upcast(cx)
914}
915
916impl<D, I> EvalCtxt<'_, D>
917where
918 D: SolverDelegate<Interner = I>,
919 I: Interner,
920{
921 fn consider_builtin_dyn_upcast_candidates(
931 &mut self,
932 goal: Goal<I, (I::Ty, I::Ty)>,
933 a_data: I::BoundExistentialPredicates,
934 a_region: I::Region,
935 b_data: I::BoundExistentialPredicates,
936 b_region: I::Region,
937 ) -> Vec<Candidate<I>> {
938 let cx = self.cx();
939 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
940
941 let mut responses = ::alloc::vec::Vec::new()vec![];
942 let b_principal_def_id = b_data.principal_def_id();
945 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
946 responses.extend(self.consider_builtin_upcast_to_principal(
947 goal,
948 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
949 a_data,
950 a_region,
951 b_data,
952 b_region,
953 a_data.principal(),
954 ));
955 } else if let Some(a_principal) = a_data.principal() {
956 for (idx, new_a_principal) in
957 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
958 .enumerate()
959 .skip(1)
960 {
961 responses.extend(self.consider_builtin_upcast_to_principal(
962 goal,
963 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
964 a_data,
965 a_region,
966 b_data,
967 b_region,
968 Some(new_a_principal.map_bound(|trait_ref| {
969 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
970 })),
971 ));
972 }
973 }
974
975 responses
976 }
977
978 fn consider_builtin_unsize_to_dyn_candidate(
979 &mut self,
980 goal: Goal<I, (I::Ty, I::Ty)>,
981 b_data: I::BoundExistentialPredicates,
982 b_region: I::Region,
983 ) -> Result<Candidate<I>, NoSolution> {
984 let cx = self.cx();
985 let Goal { predicate: (a_ty, _), .. } = goal;
986
987 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
989 return Err(NoSolution);
990 }
991
992 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
993 ecx.add_goals(
996 GoalSource::ImplWhereBound,
997 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
998 );
999
1000 ecx.add_goal(
1002 GoalSource::ImplWhereBound,
1003 goal.with(
1004 cx,
1005 ty::TraitRef::new(
1006 cx,
1007 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1008 [a_ty],
1009 ),
1010 ),
1011 );
1012
1013 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)));
1015 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1016 })
1017 }
1018
1019 fn consider_builtin_upcast_to_principal(
1020 &mut self,
1021 goal: Goal<I, (I::Ty, I::Ty)>,
1022 source: CandidateSource<I>,
1023 a_data: I::BoundExistentialPredicates,
1024 a_region: I::Region,
1025 b_data: I::BoundExistentialPredicates,
1026 b_region: I::Region,
1027 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1028 ) -> Result<Candidate<I>, NoSolution> {
1029 let param_env = goal.param_env;
1030
1031 let a_auto_traits: IndexSet<I::TraitId> = a_data
1035 .auto_traits()
1036 .into_iter()
1037 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1038 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1039 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1040 }))
1041 .collect();
1042
1043 let projection_may_match =
1048 |ecx: &mut EvalCtxt<'_, D>,
1049 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1050 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1051 source_projection.item_def_id() == target_projection.item_def_id()
1052 && ecx
1053 .probe(|_| ProbeKind::ProjectionCompatibility)
1054 .enter(|ecx| -> Result<_, NoSolution> {
1055 ecx.enter_forall(target_projection, |ecx, target_projection| {
1056 let source_projection =
1057 ecx.instantiate_binder_with_infer(source_projection);
1058 ecx.eq(param_env, source_projection, target_projection)?;
1059 ecx.try_evaluate_added_goals()
1060 })
1061 })
1062 .is_ok()
1063 };
1064
1065 self.probe_trait_candidate(source).enter(|ecx| {
1066 for bound in b_data.iter() {
1067 match bound.skip_binder() {
1068 ty::ExistentialPredicate::Trait(target_principal) => {
1071 let source_principal = upcast_principal.unwrap();
1072 let target_principal = bound.rebind(target_principal);
1073 ecx.enter_forall(target_principal, |ecx, target_principal| {
1074 let source_principal =
1075 ecx.instantiate_binder_with_infer(source_principal);
1076 ecx.eq(param_env, source_principal, target_principal)?;
1077 ecx.try_evaluate_added_goals()
1078 })?;
1079 }
1080 ty::ExistentialPredicate::Projection(target_projection) => {
1086 let target_projection = bound.rebind(target_projection);
1087 let mut matching_projections =
1088 a_data.projection_bounds().into_iter().filter(|source_projection| {
1089 projection_may_match(ecx, *source_projection, target_projection)
1090 });
1091 let Some(source_projection) = matching_projections.next() else {
1092 return Err(NoSolution);
1093 };
1094 if matching_projections.next().is_some() {
1095 return ecx.evaluate_added_goals_and_make_canonical_response(
1096 Certainty::AMBIGUOUS,
1097 );
1098 }
1099 ecx.enter_forall(target_projection, |ecx, target_projection| {
1100 let source_projection =
1101 ecx.instantiate_binder_with_infer(source_projection);
1102 ecx.eq(param_env, source_projection, target_projection)?;
1103 ecx.try_evaluate_added_goals()
1104 })?;
1105 }
1106 ty::ExistentialPredicate::AutoTrait(def_id) => {
1108 if !a_auto_traits.contains(&def_id) {
1109 return Err(NoSolution);
1110 }
1111 }
1112 }
1113 }
1114
1115 ecx.add_goal(
1117 GoalSource::ImplWhereBound,
1118 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1119 );
1120
1121 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1122 })
1123 }
1124
1125 fn consider_builtin_array_unsize(
1134 &mut self,
1135 goal: Goal<I, (I::Ty, I::Ty)>,
1136 a_elem_ty: I::Ty,
1137 b_elem_ty: I::Ty,
1138 ) -> Result<Candidate<I>, NoSolution> {
1139 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1140 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1141 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1142 }
1143
1144 fn consider_builtin_struct_unsize(
1158 &mut self,
1159 goal: Goal<I, (I::Ty, I::Ty)>,
1160 def: I::AdtDef,
1161 a_args: I::GenericArgs,
1162 b_args: I::GenericArgs,
1163 ) -> Result<Candidate<I>, NoSolution> {
1164 let cx = self.cx();
1165 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1166
1167 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1168 if unsizing_params.is_empty() {
1171 return Err(NoSolution);
1172 }
1173
1174 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1175
1176 let a_tail_ty = tail_field_ty.instantiate(cx, a_args);
1177 let b_tail_ty = tail_field_ty.instantiate(cx, b_args);
1178
1179 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1183 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1184 }));
1185 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1186
1187 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1190 self.add_goal(
1191 GoalSource::ImplWhereBound,
1192 goal.with(
1193 cx,
1194 ty::TraitRef::new(
1195 cx,
1196 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1197 [a_tail_ty, b_tail_ty],
1198 ),
1199 ),
1200 );
1201 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1202 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1203 }
1204
1205 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1210 &mut self,
1211 goal: Goal<I, TraitPredicate<I>>,
1212 ) -> Option<Result<Candidate<I>, NoSolution>> {
1213 let self_ty = goal.predicate.self_ty();
1214 let check_impls = || {
1215 let mut disqualifying_impl = None;
1216 self.cx().for_each_relevant_impl(
1217 goal.predicate.def_id(),
1218 goal.predicate.self_ty(),
1219 |impl_def_id| {
1220 disqualifying_impl = Some(impl_def_id);
1221 },
1222 );
1223 if let Some(def_id) = disqualifying_impl {
1224 {
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:1224",
"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(1224u32),
::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");
1225 return Some(Err(NoSolution));
1228 } else {
1229 None
1230 }
1231 };
1232
1233 match self_ty.kind() {
1234 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1240 Some(self.forced_ambiguity(MaybeCause::Ambiguity))
1241 }
1242
1243 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1246
1247 ty::Dynamic(..)
1250 | ty::Param(..)
1251 | ty::Foreign(..)
1252 | ty::Alias(ty::Projection | ty::Free | ty::Inherent, ..)
1253 | ty::Placeholder(..) => Some(Err(NoSolution)),
1254
1255 ty::Infer(_) | ty::Bound(_, _) => {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`"),
1256
1257 ty::Coroutine(def_id, _)
1261 if self
1262 .cx()
1263 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1264 {
1265 match self.cx().coroutine_movability(def_id) {
1266 Movability::Static => Some(Err(NoSolution)),
1267 Movability::Movable => Some(
1268 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1269 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1270 }),
1271 ),
1272 }
1273 }
1274
1275 ty::Alias(..) => None,
1280
1281 ty::Bool
1288 | ty::Char
1289 | ty::Int(_)
1290 | ty::Uint(_)
1291 | ty::Float(_)
1292 | ty::Str
1293 | ty::Array(_, _)
1294 | ty::Pat(_, _)
1295 | ty::Slice(_)
1296 | ty::RawPtr(_, _)
1297 | ty::Ref(_, _, _)
1298 | ty::FnDef(_, _)
1299 | ty::FnPtr(..)
1300 | ty::Closure(..)
1301 | ty::CoroutineClosure(..)
1302 | ty::Coroutine(_, _)
1303 | ty::CoroutineWitness(..)
1304 | ty::Never
1305 | ty::Tuple(_)
1306 | ty::Adt(_, _)
1307 | ty::UnsafeBinder(_) => check_impls(),
1308 ty::Error(_) => None,
1309 }
1310 }
1311
1312 fn probe_and_evaluate_goal_for_constituent_tys(
1317 &mut self,
1318 source: CandidateSource<I>,
1319 goal: Goal<I, TraitPredicate<I>>,
1320 constituent_tys: impl Fn(
1321 &EvalCtxt<'_, D>,
1322 I::Ty,
1323 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1324 ) -> Result<Candidate<I>, NoSolution> {
1325 self.probe_trait_candidate(source).enter(|ecx| {
1326 let goals =
1327 ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| {
1328 tys.into_iter()
1329 .map(|ty| {
1330 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1331 })
1332 .collect::<Vec<_>>()
1333 });
1334 ecx.add_goals(GoalSource::ImplWhereBound, goals);
1335 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1336 })
1337 }
1338}
1339
1340#[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)]
1351pub(super) enum TraitGoalProvenVia {
1352 Misc,
1358 ParamEnv,
1359 AliasBound,
1360}
1361
1362impl<D, I> EvalCtxt<'_, D>
1363where
1364 D: SolverDelegate<Interner = I>,
1365 I: Interner,
1366{
1367 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1380 match self.typing_mode() {
1381 TypingMode::Coherence => return,
1382 TypingMode::Analysis { .. }
1383 | TypingMode::Borrowck { .. }
1384 | TypingMode::PostBorrowckAnalysis { .. }
1385 | TypingMode::PostAnalysis => {}
1386 }
1387
1388 if candidates
1389 .iter()
1390 .find(|c| {
1391 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1392 })
1393 .is_some_and(|c| has_only_region_constraints(c.result))
1394 {
1395 candidates.retain(|c| {
1396 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1397 {
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:1397",
"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(1397u32),
::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");
1398 false
1399 } else {
1400 true
1401 }
1402 });
1403 }
1404 }
1405
1406 x;#[instrument(level = "debug", skip(self), ret)]
1407 pub(super) fn merge_trait_candidates(
1408 &mut self,
1409 candidate_preference_mode: CandidatePreferenceMode,
1410 mut candidates: Vec<Candidate<I>>,
1411 failed_candidate_info: FailedCandidateInfo,
1412 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1413 if let TypingMode::Coherence = self.typing_mode() {
1414 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1415 Ok((response, Some(TraitGoalProvenVia::Misc)))
1416 } else {
1417 self.flounder(&candidates).map(|r| (r, None))
1418 };
1419 }
1420
1421 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1426 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1427 });
1428 if let Some(candidate) = trivial_builtin_impls.next() {
1429 assert!(trivial_builtin_impls.next().is_none());
1432 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1433 }
1434
1435 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1438 && candidates.iter().any(|c| {
1439 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1440 })
1441 {
1442 let alias_bounds: Vec<_> = candidates
1443 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1444 .collect();
1445 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1446 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1447 } else {
1448 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1449 };
1450 }
1451
1452 let has_non_global_where_bounds = candidates
1455 .iter()
1456 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1457 if has_non_global_where_bounds {
1458 let where_bounds: Vec<_> = candidates
1459 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1460 .collect();
1461 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1462 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1463 };
1464 match info {
1465 MergeCandidateInfo::AlwaysApplicable(i) => {
1481 for (j, c) in where_bounds.into_iter().enumerate() {
1482 if i != j {
1483 self.ignore_candidate_head_usages(c.head_usages)
1484 }
1485 }
1486 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1490 }
1491 MergeCandidateInfo::EqualResponse => {}
1492 }
1493 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1494 }
1495
1496 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1498 let alias_bounds: Vec<_> = candidates
1499 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1500 .collect();
1501 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1502 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1503 } else {
1504 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1505 };
1506 }
1507
1508 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1509 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1510
1511 let proven_via = if candidates
1516 .iter()
1517 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1518 {
1519 TraitGoalProvenVia::ParamEnv
1520 } else {
1521 candidates
1522 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1523 TraitGoalProvenVia::Misc
1524 };
1525
1526 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1527 Ok((response, Some(proven_via)))
1528 } else {
1529 self.flounder(&candidates).map(|r| (r, None))
1530 }
1531 }
1532
1533 #[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(1533u32),
::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))]
1534 pub(super) fn compute_trait_goal(
1535 &mut self,
1536 goal: Goal<I, TraitPredicate<I>>,
1537 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1538 let (candidates, failed_candidate_info) =
1539 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1540 let candidate_preference_mode =
1541 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1542 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1543 }
1544
1545 fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
1546 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1547 match self.typing_mode() {
1548 TypingMode::Analysis {
1549 defining_opaque_types_and_generators: stalled_generators,
1550 } => {
1551 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1552 {
1553 return Some(self.forced_ambiguity(MaybeCause::Ambiguity));
1554 }
1555 }
1556 TypingMode::Coherence
1557 | TypingMode::PostAnalysis
1558 | TypingMode::Borrowck { defining_opaque_types: _ }
1559 | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
1560 }
1561 }
1562
1563 None
1564 }
1565}