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