1use rustc_type_ir::data_structures::IndexSet;
4use rustc_type_ir::fast_reject::DeepRejectCtxt;
5use rustc_type_ir::inherent::*;
6use rustc_type_ir::lang_items::SolverTraitLangItem;
7use rustc_type_ir::solve::{
8 AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, MaybeInfo,
9 NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunNonErased,
10 RerunReason, RerunResultExt, SizedTraitKind,
11};
12use rustc_type_ir::{
13 self as ty, ExistentialPredicate, FieldInfo, Interner, MayBeErased, Movability,
14 PredicatePolarity, Region, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
15 Unnormalized, Upcast as _, elaborate,
16};
17use tracing::{debug, instrument, trace, warn};
18
19use crate::delegate::SolverDelegate;
20use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
21use crate::solve::assembly::{
22 self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate, FailedCandidateInfo,
23};
24use crate::solve::inspect::ProbeKind;
25use crate::solve::{
26 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
27 MergeCandidateInfo, NoSolution, ParamEnvSource, StalledOnCoroutines,
28 has_only_region_constraints,
29};
30
31impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
32where
33 D: SolverDelegate<Interner = I>,
34 I: Interner,
35{
36 fn self_ty(self) -> I::Ty {
37 self.self_ty()
38 }
39
40 fn trait_ref(self, _: I) -> ty::TraitRef<I> {
41 self.trait_ref
42 }
43
44 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
45 self.with_replaced_self_ty(cx, self_ty)
46 }
47
48 fn trait_def_id(self, _: I) -> I::TraitId {
49 self.def_id()
50 }
51
52 fn consider_additional_alias_assumptions(
53 _ecx: &mut EvalCtxt<'_, D>,
54 _goal: Goal<I, Self>,
55 _alias_ty: ty::AliasTy<I>,
56 ) -> Vec<Candidate<I>> {
57 ::alloc::vec::Vec::new()vec![]
58 }
59
60 fn consider_impl_candidate(
61 ecx: &mut EvalCtxt<'_, D>,
62 goal: Goal<I, TraitPredicate<I>>,
63 impl_def_id: I::ImplId,
64 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
65 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
66 let cx = ecx.cx();
67
68 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
69 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
70 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
71 {
72 return Err(NoSolution.into());
73 }
74
75 let impl_polarity = cx.impl_polarity(impl_def_id);
78 let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
79 (ty::ImplPolarity::Reservation, _) => {
81 if ecx.typing_mode().is_coherence() {
82 Certainty::AMBIGUOUS
83 } else {
84 return Err(NoSolution.into());
85 }
86 }
87
88 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
90 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {
91 if ecx.typing_mode().is_reflection()
92 && !cx.is_fully_generic_for_reflection(impl_def_id)
93 {
94 return Err(NoSolution.into());
95 } else {
96 Certainty::Yes
97 }
98 }
99
100 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative)
102 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Positive) => {
103 return Err(NoSolution.into());
104 }
105 };
106
107 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
108 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
109 ecx.record_impl_args(impl_args);
110 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
111
112 ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
113 let where_clause_bounds = cx
114 .predicates_of(impl_def_id.into())
115 .iter_instantiated(cx, impl_args)
116 .map(Unnormalized::skip_norm_wip)
117 .map(|pred| goal.with(cx, pred));
118 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
119
120 ecx.add_goals(
124 GoalSource::Misc,
125 cx.impl_super_outlives(impl_def_id)
126 .iter_instantiated(cx, impl_args)
127 .map(Unnormalized::skip_norm_wip)
128 .map(|pred| goal.with(cx, pred)),
129 )?;
130
131 then(ecx, maximal_certainty)
132 })
133 }
134
135 fn consider_error_guaranteed_candidate(
136 ecx: &mut EvalCtxt<'_, D>,
137 _goal: Goal<I, Self>,
138 _guar: I::ErrorGuaranteed,
139 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
140 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
141 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
142 }
143
144 fn fast_reject_assumption(
145 ecx: &mut EvalCtxt<'_, D>,
146 goal: Goal<I, Self>,
147 assumption: I::Clause,
148 ) -> Result<(), NoSolution> {
149 fn trait_def_id_matches<I: Interner>(
150 cx: I,
151 clause_def_id: I::TraitId,
152 goal_def_id: I::TraitId,
153 polarity: PredicatePolarity,
154 ) -> bool {
155 clause_def_id == goal_def_id
156 || (polarity == PredicatePolarity::Positive
161 && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
162 && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
163 }
164
165 if let Some(trait_clause) = assumption.as_trait_clause()
166 && trait_clause.polarity() == goal.predicate.polarity
167 && trait_def_id_matches(
168 ecx.cx(),
169 trait_clause.def_id(),
170 goal.predicate.def_id(),
171 goal.predicate.polarity,
172 )
173 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
174 goal.predicate.trait_ref.args,
175 trait_clause.skip_binder().trait_ref.args,
176 )
177 {
178 return Ok(());
179 } else {
180 Err(NoSolution)
181 }
182 }
183
184 fn match_assumption(
185 ecx: &mut EvalCtxt<'_, D>,
186 goal: Goal<I, Self>,
187 assumption: I::Clause,
188 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
189 ) -> QueryResultOrRerunNonErased<I> {
190 let trait_clause = assumption.as_trait_clause().unwrap();
191
192 if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
198 && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
199 {
200 let meta_sized_clause =
201 trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
202 return Self::match_assumption(ecx, goal, meta_sized_clause, then);
203 }
204
205 let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
206 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
207
208 then(ecx)
209 }
210
211 fn consider_auto_trait_candidate(
212 ecx: &mut EvalCtxt<'_, D>,
213 goal: Goal<I, Self>,
214 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
215 let cx = ecx.cx();
216 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
217 return Err(NoSolution.into());
218 }
219
220 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
221 return result;
222 }
223
224 if cx.trait_is_unsafe(goal.predicate.def_id())
227 && goal.predicate.self_ty().has_unsafe_fields()
228 {
229 return Err(NoSolution.into());
230 }
231
232 if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) =
248 goal.predicate.self_ty().kind()
249 {
250 if true {
if !(is_rigid == ty::IsRigid::Yes) {
::core::panicking::panic("assertion failed: is_rigid == ty::IsRigid::Yes")
};
};debug_assert!(is_rigid == ty::IsRigid::Yes);
251 if ecx.opaque_accesses.might_rerun() {
252 ecx.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)?;
253 return Err(NoSolution.into());
254 }
255
256 for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() {
257 if item_bound
258 .as_trait_clause()
259 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
260 {
261 return Err(NoSolution.into());
262 }
263 }
264 }
265
266 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
268 return cand;
269 }
270
271 ecx.probe_and_evaluate_goal_for_constituent_tys(
272 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
273 goal,
274 structural_traits::instantiate_constituent_tys_for_auto_trait,
275 )
276 }
277
278 fn consider_trait_alias_candidate(
279 ecx: &mut EvalCtxt<'_, D>,
280 goal: Goal<I, Self>,
281 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
282 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
283 return Err(NoSolution.into());
284 }
285
286 let cx = ecx.cx();
287
288 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
289 let nested_obligations = cx
290 .predicates_of(goal.predicate.def_id().into())
291 .iter_instantiated(cx, goal.predicate.trait_ref.args)
292 .map(Unnormalized::skip_norm_wip)
293 .map(|p| goal.with(cx, p));
294 ecx.add_goals(GoalSource::Misc, nested_obligations)?;
300 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
301 })
302 }
303
304 fn consider_builtin_sizedness_candidates(
305 ecx: &mut EvalCtxt<'_, D>,
306 goal: Goal<I, Self>,
307 sizedness: SizedTraitKind,
308 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
309 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
310 return Err(NoSolution.into());
311 }
312
313 ecx.probe_and_evaluate_goal_for_constituent_tys(
314 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
315 goal,
316 |ecx, ty| {
317 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
318 ecx, sizedness, ty,
319 )
320 },
321 )
322 }
323
324 fn consider_builtin_copy_clone_candidate(
325 ecx: &mut EvalCtxt<'_, D>,
326 goal: Goal<I, Self>,
327 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
328 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
329 return Err(NoSolution.into());
330 }
331
332 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
334 return cand;
335 }
336
337 ecx.probe_and_evaluate_goal_for_constituent_tys(
338 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
339 goal,
340 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
341 )
342 }
343
344 fn consider_builtin_fn_ptr_trait_candidate(
345 ecx: &mut EvalCtxt<'_, D>,
346 goal: Goal<I, Self>,
347 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
348 let self_ty = goal.predicate.self_ty();
349 match goal.predicate.polarity {
350 ty::PredicatePolarity::Positive => {
352 if self_ty.is_fn_ptr() {
353 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
354 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
355 })
356 } else {
357 Err(NoSolution.into())
358 }
359 }
360 ty::PredicatePolarity::Negative => {
362 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
365 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
366 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
367 })
368 } else {
369 Err(NoSolution.into())
370 }
371 }
372 }
373 }
374
375 fn consider_builtin_fn_trait_candidates(
376 ecx: &mut EvalCtxt<'_, D>,
377 goal: Goal<I, Self>,
378 goal_kind: ty::ClosureKind,
379 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
380 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
381 return Err(NoSolution.into());
382 }
383
384 let cx = ecx.cx();
385 let Some(tupled_inputs_and_output) =
386 structural_traits::extract_tupled_inputs_and_output_from_callable(
387 cx,
388 goal.predicate.self_ty(),
389 goal_kind,
390 )?
391 else {
392 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
393 };
394 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
395
396 let output_is_sized_pred =
399 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
400
401 let pred =
402 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
403 .upcast(cx);
404 Self::probe_and_consider_implied_clause(
405 ecx,
406 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
407 goal,
408 pred,
409 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
410 )
411 }
412
413 fn consider_builtin_async_fn_trait_candidates(
414 ecx: &mut EvalCtxt<'_, D>,
415 goal: Goal<I, Self>,
416 goal_kind: ty::ClosureKind,
417 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
418 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
419 return Err(NoSolution.into());
420 }
421
422 let cx = ecx.cx();
423 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
424 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
425 cx,
426 goal.predicate.self_ty(),
427 goal_kind,
428 Region::new_static(cx),
430 )?;
431 let AsyncCallableRelevantTypes {
432 tupled_inputs_ty,
433 output_coroutine_ty,
434 coroutine_return_ty: _,
435 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
436
437 let output_is_sized_pred = ty::TraitRef::new(
440 cx,
441 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
442 [output_coroutine_ty],
443 );
444
445 let pred = ty::TraitRef::new(
446 cx,
447 goal.predicate.def_id(),
448 [goal.predicate.self_ty(), tupled_inputs_ty],
449 )
450 .upcast(cx);
451 Self::probe_and_consider_implied_clause(
452 ecx,
453 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
454 goal,
455 pred,
456 [goal.with(cx, output_is_sized_pred)]
457 .into_iter()
458 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
459 .map(|goal| (GoalSource::ImplWhereBound, goal)),
460 )
461 }
462
463 fn consider_builtin_async_fn_kind_helper_candidate(
464 ecx: &mut EvalCtxt<'_, D>,
465 goal: Goal<I, Self>,
466 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
467 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
468 ::core::panicking::panic("explicit panic");panic!();
469 };
470
471 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
472 return Err(NoSolution.into());
474 };
475 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
476 if closure_kind.extends(goal_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.into())
481 }
482 }
483
484 fn consider_builtin_tuple_candidate(
491 ecx: &mut EvalCtxt<'_, D>,
492 goal: Goal<I, Self>,
493 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
494 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
495 return Err(NoSolution.into());
496 }
497
498 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
499 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
500 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
501 } else {
502 Err(NoSolution.into())
503 }
504 }
505
506 fn consider_builtin_pointee_candidate(
507 ecx: &mut EvalCtxt<'_, D>,
508 goal: Goal<I, Self>,
509 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
510 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
511 return Err(NoSolution.into());
512 }
513
514 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
515 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
516 }
517
518 fn consider_builtin_future_candidate(
519 ecx: &mut EvalCtxt<'_, D>,
520 goal: Goal<I, Self>,
521 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
522 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
523 return Err(NoSolution.into());
524 }
525
526 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
527 return Err(NoSolution.into());
528 };
529
530 let cx = ecx.cx();
532 if !cx.coroutine_is_async(def_id) {
533 return Err(NoSolution.into());
534 }
535
536 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
540 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
541 }
542
543 fn consider_builtin_iterator_candidate(
544 ecx: &mut EvalCtxt<'_, D>,
545 goal: Goal<I, Self>,
546 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
547 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
548 return Err(NoSolution.into());
549 }
550
551 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
552 return Err(NoSolution.into());
553 };
554
555 let cx = ecx.cx();
557 if !cx.coroutine_is_gen(def_id) {
558 return Err(NoSolution.into());
559 }
560
561 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
565 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
566 }
567
568 fn consider_builtin_fused_iterator_candidate(
569 ecx: &mut EvalCtxt<'_, D>,
570 goal: Goal<I, Self>,
571 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
572 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
573 return Err(NoSolution.into());
574 }
575
576 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
577 return Err(NoSolution.into());
578 };
579
580 let cx = ecx.cx();
582 if !cx.coroutine_is_gen(def_id) {
583 return Err(NoSolution.into());
584 }
585
586 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
588 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
589 }
590
591 fn consider_builtin_async_iterator_candidate(
592 ecx: &mut EvalCtxt<'_, D>,
593 goal: Goal<I, Self>,
594 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
595 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
596 return Err(NoSolution.into());
597 }
598
599 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
600 return Err(NoSolution.into());
601 };
602
603 let cx = ecx.cx();
605 if !cx.coroutine_is_async_gen(def_id) {
606 return Err(NoSolution.into());
607 }
608
609 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
613 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
614 }
615
616 fn consider_builtin_coroutine_candidate(
617 ecx: &mut EvalCtxt<'_, D>,
618 goal: Goal<I, Self>,
619 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
620 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
621 return Err(NoSolution.into());
622 }
623
624 let self_ty = goal.predicate.self_ty();
625 let ty::Coroutine(def_id, args) = self_ty.kind() else {
626 return Err(NoSolution.into());
627 };
628
629 let cx = ecx.cx();
631 if !cx.is_general_coroutine(def_id) {
632 return Err(NoSolution.into());
633 }
634
635 let coroutine = args.as_coroutine();
636 Self::probe_and_consider_implied_clause(
637 ecx,
638 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
639 goal,
640 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
641 .upcast(cx),
642 [],
645 )
646 }
647
648 fn consider_builtin_discriminant_kind_candidate(
649 ecx: &mut EvalCtxt<'_, D>,
650 goal: Goal<I, Self>,
651 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
652 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
653 return Err(NoSolution.into());
654 }
655
656 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
658 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
659 }
660
661 fn consider_builtin_destruct_candidate(
662 ecx: &mut EvalCtxt<'_, D>,
663 goal: Goal<I, Self>,
664 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
665 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
666 return Err(NoSolution.into());
667 }
668
669 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
672 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
673 }
674
675 fn consider_builtin_transmute_candidate(
676 ecx: &mut EvalCtxt<'_, D>,
677 goal: Goal<I, Self>,
678 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
679 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
680 return Err(NoSolution.into());
681 }
682
683 if goal.predicate.has_non_region_placeholders() {
685 return Err(NoSolution.into());
686 }
687
688 if goal.has_non_region_infer() {
691 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
692 }
693
694 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(
695 |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
696 let assume = ecx.structurally_normalize_const(
697 goal.param_env,
698 goal.predicate.trait_ref.args.const_at(2),
699 )?;
700
701 let certainty = ecx.is_transmutable(
702 goal.predicate.trait_ref.args.type_at(0),
703 goal.predicate.trait_ref.args.type_at(1),
704 assume,
705 )?;
706 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
707 },
708 )
709 }
710
711 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
724 ecx: &mut EvalCtxt<'_, D>,
725 goal: Goal<I, Self>,
726 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
727 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
728 return Err(NoSolution.into());
729 }
730
731 let cx = ecx.cx();
732 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
733 let ty = goal.predicate.self_ty();
734 match ty.kind() {
735 ty::Ref(..) => {}
737 ty::Adt(def, _) if def.is_manually_drop() => {}
739 ty::Tuple(tys) => {
742 ecx.add_goals(
743 GoalSource::ImplWhereBound,
744 tys.iter().map(|elem_ty| {
745 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
746 }),
747 )?;
748 }
749 ty::Array(elem_ty, _) => {
750 ecx.add_goal(
751 GoalSource::ImplWhereBound,
752 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
753 )?;
754 }
755
756 ty::FnDef(..)
760 | ty::FnPtr(..)
761 | ty::Error(_)
762 | ty::Uint(_)
763 | ty::Int(_)
764 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
765 | ty::Bool
766 | ty::Float(_)
767 | ty::Char
768 | ty::RawPtr(..)
769 | ty::Never
770 | ty::Pat(..)
771 | ty::Dynamic(..)
772 | ty::Str
773 | ty::Slice(_)
774 | ty::Foreign(..)
775 | ty::Adt(..)
776 | ty::Alias(..)
777 | ty::Param(_)
778 | ty::Placeholder(..)
779 | ty::Closure(..)
780 | ty::CoroutineClosure(..)
781 | ty::Coroutine(..)
782 | ty::UnsafeBinder(_)
783 | ty::CoroutineWitness(..) => {
784 ecx.add_goal(
785 GoalSource::ImplWhereBound,
786 goal.with(
787 cx,
788 ty::TraitRef::new(
789 cx,
790 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
791 [ty],
792 ),
793 ),
794 )?;
795 }
796
797 ty::Bound(..)
798 | ty::Infer(
799 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
800 ) => {
801 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
802 }
803 }
804
805 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
806 })
807 }
808
809 fn consider_structural_builtin_unsize_candidates(
817 ecx: &mut EvalCtxt<'_, D>,
818 goal: Goal<I, Self>,
819 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
820 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
821 return Ok(::alloc::vec::Vec::new()vec![]);
822 }
823
824 let result = ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(
825 |ecx| -> Result<Vec<Candidate<I>>, NoSolutionOrRerunNonErased> {
826 let a_ty = goal.predicate.self_ty();
827 let b_ty = ecx.structurally_normalize_ty(
830 goal.param_env,
831 goal.predicate.trait_ref.args.type_at(1),
832 )?;
833
834 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
835 match (a_ty.kind(), b_ty.kind()) {
836 (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:?}"),
837
838 (_, ty::Infer(ty::TyVar(..))) => {
839 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?]))vec![ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?])
840 }
841
842 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => Ok(ecx
844 .consider_builtin_dyn_upcast_candidates(
845 goal, a_data, a_region, b_data, b_region,
846 )),
847
848 (_, ty::Dynamic(b_region, b_data)) => Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region,
b_data)?]))vec![
850 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data)?,
851 ]),
852
853 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
855 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?]))vec![ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?])
856 }
857
858 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
860 if a_def.is_struct() && a_def == b_def =>
861 {
862 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?]))vec![ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?])
863 }
864
865 _ => Err(NoSolution.into()),
866 }
867 },
868 );
869
870 match result.map_err_to_rerun()? {
871 Ok(resp) => Ok(resp),
872 Err(NoSolution) => Ok(::alloc::vec::Vec::new()vec![]),
873 }
874 }
875
876 fn consider_builtin_try_as_dyn_candidate(
877 ecx: &mut EvalCtxt<'_, D>,
878 goal: Goal<I, Self>,
879 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
880 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
881 return Err(NoSolution.into());
882 }
883 let cx = ecx.cx();
884
885 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
886 let self_ty = goal.predicate.self_ty();
887 let ty_lifetime = goal.predicate.trait_ref.args.region_at(1);
888 match self_ty.kind() {
889 ty::Dynamic(bounds, lifetime) => {
890 for bound in bounds.iter() {
891 match bound.skip_binder() {
892 ExistentialPredicate::Trait(_) => {}
893 ExistentialPredicate::Projection(_) => return Err(NoSolution.into()),
895 ExistentialPredicate::AutoTrait(_) => {}
898 }
899 }
900 ecx.add_goal(
901 GoalSource::Misc,
902 goal.with(cx, ty::OutlivesPredicate(ty_lifetime, lifetime)),
903 )?;
904 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
905 }
906
907 ty::Bound(..)
908 | ty::Infer(
909 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
910 ) => {
911 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
912 }
913
914 _ => Err(NoSolution.into()),
915 }
916 })
917 }
918
919 fn consider_builtin_field_candidate(
920 ecx: &mut EvalCtxt<'_, D>,
921 goal: Goal<I, Self>,
922 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
923 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
924 return Err(NoSolution.into());
925 }
926 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
927 && let Some(FieldInfo { base, ty, .. }) =
928 def.field_representing_type_info(ecx.cx(), args)
929 && {
930 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
931 ecx.add_goal(
939 GoalSource::ImplWhereBound,
940 Goal {
941 param_env: goal.param_env,
942 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
943 },
944 )?;
945 ecx.add_goal(
946 GoalSource::ImplWhereBound,
947 Goal {
948 param_env: goal.param_env,
949 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
950 },
951 )?;
952 ecx.try_evaluate_added_goals()? == Certainty::Yes
955 }
956 && match base.kind() {
957 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
958 ty::Tuple(..) => true,
959 _ => false,
960 }
961 {
962 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
963 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
964 } else {
965 Err(NoSolution.into())
966 }
967 }
968}
969
970#[inline(always)]
976fn trait_predicate_with_def_id<I: Interner>(
977 cx: I,
978 clause: ty::Binder<I, ty::TraitPredicate<I>>,
979 did: I::TraitId,
980) -> I::Clause {
981 clause
982 .map_bound(|c| TraitPredicate {
983 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
984 polarity: c.polarity,
985 })
986 .upcast(cx)
987}
988
989impl<D, I> EvalCtxt<'_, D>
990where
991 D: SolverDelegate<Interner = I>,
992 I: Interner,
993{
994 fn consider_builtin_dyn_upcast_candidates(
1004 &mut self,
1005 goal: Goal<I, (I::Ty, I::Ty)>,
1006 a_data: I::BoundExistentialPredicates,
1007 a_region: Region<I>,
1008 b_data: I::BoundExistentialPredicates,
1009 b_region: Region<I>,
1010 ) -> Vec<Candidate<I>> {
1011 let cx = self.cx();
1012 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
1013
1014 let mut responses = ::alloc::vec::Vec::new()vec![];
1015 let b_principal_def_id = b_data.principal_def_id();
1018 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
1019 responses.extend(self.consider_builtin_upcast_to_principal(
1020 goal,
1021 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
1022 a_data,
1023 a_region,
1024 b_data,
1025 b_region,
1026 a_data.principal(),
1027 ));
1028 } else if let Some(a_principal) = a_data.principal() {
1029 for (idx, new_a_principal) in
1030 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
1031 .enumerate()
1032 .skip(1)
1033 {
1034 responses.extend(self.consider_builtin_upcast_to_principal(
1035 goal,
1036 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
1037 a_data,
1038 a_region,
1039 b_data,
1040 b_region,
1041 Some(new_a_principal.map_bound(|trait_ref| {
1042 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
1043 })),
1044 ));
1045 }
1046 }
1047
1048 responses
1049 }
1050
1051 fn consider_builtin_unsize_to_dyn_candidate(
1052 &mut self,
1053 goal: Goal<I, (I::Ty, I::Ty)>,
1054 b_data: I::BoundExistentialPredicates,
1055 b_region: Region<I>,
1056 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1057 let cx = self.cx();
1058 let Goal { predicate: (a_ty, _), .. } = goal;
1059
1060 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1062 return Err(NoSolution.into());
1063 }
1064
1065 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1066 ecx.add_goals(
1069 GoalSource::ImplWhereBound,
1070 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1071 )?;
1072
1073 ecx.add_goal(
1075 GoalSource::ImplWhereBound,
1076 goal.with(
1077 cx,
1078 ty::TraitRef::new(
1079 cx,
1080 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1081 [a_ty],
1082 ),
1083 ),
1084 )?;
1085
1086 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)))?;
1088 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1089 })
1090 }
1091
1092 fn consider_builtin_upcast_to_principal(
1093 &mut self,
1094 goal: Goal<I, (I::Ty, I::Ty)>,
1095 source: CandidateSource<I>,
1096 a_data: I::BoundExistentialPredicates,
1097 a_region: Region<I>,
1098 b_data: I::BoundExistentialPredicates,
1099 b_region: Region<I>,
1100 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1101 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1102 let param_env = goal.param_env;
1103
1104 let a_auto_traits: IndexSet<I::TraitId> = a_data
1108 .auto_traits()
1109 .into_iter()
1110 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1111 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1112 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1113 }))
1114 .collect();
1115
1116 let projection_may_match =
1121 |ecx: &mut EvalCtxt<'_, D>,
1122 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1123 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1124 source_projection.item_def_id() == target_projection.item_def_id()
1125 && ecx
1126 .probe(|_| ProbeKind::ProjectionCompatibility)
1127 .enter(|ecx| {
1128 ecx.enter_forall_with_assumptions(
1129 target_projection,
1130 param_env,
1131 |ecx, target_projection| {
1132 let source_projection =
1133 ecx.instantiate_binder_with_infer(source_projection);
1134 ecx.eq(param_env, source_projection, target_projection)?;
1135 ecx.try_evaluate_added_goals()
1136 },
1137 )
1138 })
1139 .is_ok()
1140 };
1141
1142 self.probe_trait_candidate(source).enter(|ecx| {
1143 for bound in b_data.iter() {
1144 match bound.skip_binder() {
1145 ty::ExistentialPredicate::Trait(target_principal) => {
1148 let source_principal = upcast_principal.unwrap();
1149 let target_principal = bound.rebind(target_principal);
1150 ecx.enter_forall_with_assumptions(
1151 target_principal,
1152 param_env,
1153 |ecx, target_principal| {
1154 let source_principal =
1155 ecx.instantiate_binder_with_infer(source_principal);
1156 ecx.eq(param_env, source_principal, target_principal)?;
1157 ecx.try_evaluate_added_goals()
1158 },
1159 )?;
1160 }
1161 ty::ExistentialPredicate::Projection(target_projection) => {
1167 let target_projection = bound.rebind(target_projection);
1168 let mut matching_projections =
1169 a_data.projection_bounds().into_iter().filter(|source_projection| {
1170 projection_may_match(ecx, *source_projection, target_projection)
1171 });
1172 let Some(source_projection) = matching_projections.next() else {
1173 return Err(NoSolution.into());
1174 };
1175 if matching_projections.next().is_some() {
1176 return ecx.evaluate_added_goals_and_make_canonical_response(
1177 Certainty::AMBIGUOUS,
1178 );
1179 }
1180 ecx.enter_forall_with_assumptions(
1181 target_projection,
1182 param_env,
1183 |ecx, target_projection| {
1184 let source_projection =
1185 ecx.instantiate_binder_with_infer(source_projection);
1186 ecx.eq(param_env, source_projection, target_projection)?;
1187 ecx.try_evaluate_added_goals()
1188 },
1189 )?;
1190 }
1191 ty::ExistentialPredicate::AutoTrait(def_id) => {
1193 if !a_auto_traits.contains(&def_id) {
1194 return Err(NoSolution.into());
1195 }
1196 }
1197 }
1198 }
1199
1200 ecx.add_goal(
1202 GoalSource::ImplWhereBound,
1203 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1204 )?;
1205
1206 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1207 })
1208 }
1209
1210 fn consider_builtin_array_unsize(
1219 &mut self,
1220 goal: Goal<I, (I::Ty, I::Ty)>,
1221 a_elem_ty: I::Ty,
1222 b_elem_ty: I::Ty,
1223 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1224 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1225 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1226 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1227 }
1228
1229 fn consider_builtin_struct_unsize(
1243 &mut self,
1244 goal: Goal<I, (I::Ty, I::Ty)>,
1245 def: I::AdtDef,
1246 a_args: I::GenericArgs,
1247 b_args: I::GenericArgs,
1248 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1249 let cx = self.cx();
1250 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1251
1252 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1253 if unsizing_params.is_empty() {
1256 return Err(NoSolution.into());
1257 }
1258
1259 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1260
1261 let a_tail_ty = tail_field_ty.instantiate(cx, a_args).skip_norm_wip();
1262 let b_tail_ty = tail_field_ty.instantiate(cx, b_args).skip_norm_wip();
1263
1264 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1268 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1269 }));
1270 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1271
1272 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1275 self.add_goal(
1276 GoalSource::ImplWhereBound,
1277 goal.with(
1278 cx,
1279 ty::TraitRef::new(
1280 cx,
1281 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1282 [a_tail_ty, b_tail_ty],
1283 ),
1284 ),
1285 )?;
1286 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1287 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1288 }
1289
1290 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1295 &mut self,
1296 goal: Goal<I, TraitPredicate<I>>,
1297 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1298 let self_ty = goal.predicate.self_ty();
1299 let check_impls = || {
1300 let mut disqualifying_impl = None;
1301 self.cx().for_each_relevant_impl(goal.predicate.trait_ref, |impl_def_id| {
1302 disqualifying_impl = Some(impl_def_id);
1303 });
1304 if let Some(def_id) = disqualifying_impl {
1305 {
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:1305",
"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(1305u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("disqualified auto-trait implementation")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(?def_id, ?goal, "disqualified auto-trait implementation");
1306 return Some(Err(NoSolution.into()));
1309 } else {
1310 None
1311 }
1312 };
1313
1314 match self_ty.kind() {
1315 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1321 Some(self.forced_ambiguity(MaybeInfo::AMBIGUOUS))
1322 }
1323
1324 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1327
1328 ty::Dynamic(..)
1331 | ty::Param(..)
1332 | ty::Foreign(..)
1333 | ty::Alias(
1334 ty::IsRigid::Yes,
1335 ty::AliasTy {
1336 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1337 ..
1338 },
1339 )
1340 | ty::Placeholder(..) => Some(Err(NoSolution.into())),
1341
1342 ty::Coroutine(def_id, _)
1346 if self
1347 .cx()
1348 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1349 {
1350 match self.cx().coroutine_movability(def_id) {
1351 Movability::Static => Some(Err(NoSolution.into())),
1352 Movability::Movable => Some(
1353 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1354 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1355 }),
1356 ),
1357 }
1358 }
1359
1360 ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => None,
1365
1366 ty::Bool
1373 | ty::Char
1374 | ty::Int(_)
1375 | ty::Uint(_)
1376 | ty::Float(_)
1377 | ty::Str
1378 | ty::Array(_, _)
1379 | ty::Pat(_, _)
1380 | ty::Slice(_)
1381 | ty::RawPtr(_, _)
1382 | ty::Ref(_, _, _)
1383 | ty::FnDef(_, _)
1384 | ty::FnPtr(..)
1385 | ty::Closure(..)
1386 | ty::CoroutineClosure(..)
1387 | ty::Coroutine(_, _)
1388 | ty::CoroutineWitness(..)
1389 | ty::Never
1390 | ty::Tuple(_)
1391 | ty::Adt(_, _)
1392 | ty::UnsafeBinder(_) => check_impls(),
1393 ty::Error(_) => None,
1394
1395 ty::Infer(_) | ty::Alias(ty::IsRigid::No, _) | ty::Bound(_, _) => {
1396 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
1397 }
1398 }
1399 }
1400
1401 fn probe_and_evaluate_goal_for_constituent_tys(
1406 &mut self,
1407 source: CandidateSource<I>,
1408 goal: Goal<I, TraitPredicate<I>>,
1409 constituent_tys: impl Fn(
1410 &EvalCtxt<'_, D>,
1411 I::Ty,
1412 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1413 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1414 self.probe_trait_candidate(source).enter(|ecx| {
1415 let goals = ecx.enter_forall_with_assumptions(
1416 constituent_tys(ecx, goal.predicate.self_ty())?,
1417 goal.param_env,
1418 |ecx, tys| {
1419 tys.into_iter()
1420 .map(|ty| {
1421 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1422 })
1423 .collect::<Vec<_>>()
1424 },
1425 );
1426 ecx.add_goals(GoalSource::ImplWhereBound, goals)?;
1427 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1428 })
1429 }
1430}
1431
1432#[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)]
1443pub(super) enum TraitGoalProvenVia {
1444 Misc,
1450 ParamEnv,
1451 AliasBound,
1452}
1453
1454impl<D, I> EvalCtxt<'_, D>
1455where
1456 D: SolverDelegate<Interner = I>,
1457 I: Interner,
1458{
1459 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1472 if self.typing_mode().is_coherence() {
1473 return;
1474 }
1475
1476 if candidates
1477 .iter()
1478 .find(|c| {
1479 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1480 })
1481 .is_some_and(|c| has_only_region_constraints(c.result))
1482 {
1483 candidates.retain(|c| {
1484 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1485 {
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:1485",
"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(1485u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("c")
}> =
::tracing::__macro_support::FieldName::new("c");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("unsoundly dropping impl in favor of builtin dyn-candidate")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&c)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
1486 false
1487 } else {
1488 true
1489 }
1490 });
1491 }
1492 }
1493
1494 x;#[instrument(level = "debug", skip(self), ret)]
1495 pub(super) fn merge_trait_candidates(
1496 &mut self,
1497 candidate_preference_mode: CandidatePreferenceMode,
1498 mut candidates: Vec<Candidate<I>>,
1499 failed_candidate_info: FailedCandidateInfo,
1500 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1501 if self.typing_mode().is_coherence() {
1502 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1503 Ok((response, Some(TraitGoalProvenVia::Misc)))
1504 } else {
1505 self.flounder(&candidates).map(|r| (r, None))
1506 };
1507 }
1508
1509 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1514 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1515 });
1516 if let Some(candidate) = trivial_builtin_impls.next() {
1517 assert!(trivial_builtin_impls.next().is_none());
1520 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1521 }
1522
1523 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1526 && candidates.iter().any(|c| {
1527 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1528 })
1529 {
1530 let alias_bounds: Vec<_> = candidates
1531 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1532 .collect();
1533 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1534 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1535 } else {
1536 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1537 };
1538 }
1539
1540 let has_non_global_where_bounds = candidates
1543 .iter()
1544 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1545 if has_non_global_where_bounds {
1546 let where_bounds: Vec<_> = candidates
1547 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1548 .collect();
1549 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1550 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1551 };
1552 match info {
1553 MergeCandidateInfo::AlwaysApplicable(i) => {
1569 for (j, c) in where_bounds.into_iter().enumerate() {
1570 if i != j {
1571 self.ignore_candidate_head_usages(c.head_usages)
1572 }
1573 }
1574 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1578 }
1579 MergeCandidateInfo::EqualResponse => {}
1580 }
1581 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1582 }
1583
1584 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1586 let alias_bounds: Vec<_> = candidates
1587 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1588 .collect();
1589 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1590 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1591 } else {
1592 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1593 };
1594 }
1595
1596 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1597 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1598
1599 let proven_via = if candidates
1604 .iter()
1605 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1606 {
1607 TraitGoalProvenVia::ParamEnv
1608 } else {
1609 candidates
1610 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1611 TraitGoalProvenVia::Misc
1612 };
1613
1614 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1615 Ok((response, Some(proven_via)))
1616 } else {
1617 self.flounder(&candidates).map(|r| (r, None))
1618 }
1619 }
1620
1621 #[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(1621u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn ::tracing::field::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>),
NoSolutionOrRerunNonErased> = 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).map_err(Into::into)
}
}
}#[instrument(level = "trace", skip(self))]
1622 pub(super) fn compute_trait_goal(
1623 &mut self,
1624 goal: Goal<I, TraitPredicate<I>>,
1625 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1626 {
1627 let (candidates, failed_candidate_info) =
1628 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
1629 let candidate_preference_mode =
1630 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1631 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1632 .map_err(Into::into)
1633 }
1634
1635 fn try_stall_coroutine(
1636 &mut self,
1637 self_ty: I::Ty,
1638 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1639 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1640 match self.typing_mode() {
1641 TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => {
1642 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1643 {
1644 return Some(self.forced_ambiguity(MaybeInfo {
1645 cause: MaybeCause::Ambiguity,
1646 opaque_types_jank: OpaqueTypesJank::AllGood,
1647 stalled_on_coroutines: StalledOnCoroutines::Yes,
1648 }));
1649 }
1650 }
1651 TypingMode::ErasedNotCoherence(MayBeErased) => {
1652 return Some(
1654 match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1655 Err(e) => Err(e.into()),
1656 },
1657 );
1658 }
1659 TypingMode::Coherence
1660 | TypingMode::PostAnalysis
1661 | TypingMode::Reflection
1662 | TypingMode::Codegen
1663 | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ }
1664 | TypingMode::PostBorrowck { defined_opaque_types: _ } => {}
1665 }
1666 }
1667
1668 None
1669 }
1670}