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, FieldInfo, Interner, MayBeErased, Movability, PredicatePolarity, TraitPredicate,
14 TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, elaborate,
15};
16use tracing::{debug, instrument, trace, warn};
17
18use crate::delegate::SolverDelegate;
19use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
20use crate::solve::assembly::{
21 self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate, FailedCandidateInfo,
22};
23use crate::solve::inspect::ProbeKind;
24use crate::solve::{
25 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
26 MergeCandidateInfo, NoSolution, ParamEnvSource, StalledOnCoroutines,
27 has_only_region_constraints,
28};
29
30impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
31where
32 D: SolverDelegate<Interner = I>,
33 I: Interner,
34{
35 fn self_ty(self) -> I::Ty {
36 self.self_ty()
37 }
38
39 fn trait_ref(self, _: I) -> ty::TraitRef<I> {
40 self.trait_ref
41 }
42
43 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
44 self.with_replaced_self_ty(cx, self_ty)
45 }
46
47 fn trait_def_id(self, _: I) -> I::TraitId {
48 self.def_id()
49 }
50
51 fn consider_additional_alias_assumptions(
52 _ecx: &mut EvalCtxt<'_, D>,
53 _goal: Goal<I, Self>,
54 _alias_ty: ty::AliasTy<I>,
55 ) -> Vec<Candidate<I>> {
56 ::alloc::vec::Vec::new()vec![]
57 }
58
59 fn consider_impl_candidate(
60 ecx: &mut EvalCtxt<'_, D>,
61 goal: Goal<I, TraitPredicate<I>>,
62 impl_def_id: I::ImplId,
63 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
64 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
65 let cx = ecx.cx();
66
67 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
68 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
69 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
70 {
71 return Err(NoSolution.into());
72 }
73
74 let impl_polarity = cx.impl_polarity(impl_def_id);
77 let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
78 (ty::ImplPolarity::Reservation, _) => {
80 if ecx.typing_mode().is_coherence() {
81 Certainty::AMBIGUOUS
82 } else {
83 return Err(NoSolution.into());
84 }
85 }
86
87 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
89 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => Certainty::Yes,
90
91 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative)
93 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Positive) => {
94 return Err(NoSolution.into());
95 }
96 };
97
98 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
99 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
100 ecx.record_impl_args(impl_args);
101 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
102
103 ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
104 let where_clause_bounds = cx
105 .predicates_of(impl_def_id.into())
106 .iter_instantiated(cx, impl_args)
107 .map(Unnormalized::skip_norm_wip)
108 .map(|pred| goal.with(cx, pred));
109 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
110
111 ecx.add_goals(
115 GoalSource::Misc,
116 cx.impl_super_outlives(impl_def_id)
117 .iter_instantiated(cx, impl_args)
118 .map(Unnormalized::skip_norm_wip)
119 .map(|pred| goal.with(cx, pred)),
120 );
121
122 then(ecx, maximal_certainty).map_err(Into::into)
123 })
124 }
125
126 fn consider_error_guaranteed_candidate(
127 ecx: &mut EvalCtxt<'_, D>,
128 _goal: Goal<I, Self>,
129 _guar: I::ErrorGuaranteed,
130 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
131 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
132 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
133 }
134
135 fn fast_reject_assumption(
136 ecx: &mut EvalCtxt<'_, D>,
137 goal: Goal<I, Self>,
138 assumption: I::Clause,
139 ) -> Result<(), NoSolution> {
140 fn trait_def_id_matches<I: Interner>(
141 cx: I,
142 clause_def_id: I::TraitId,
143 goal_def_id: I::TraitId,
144 polarity: PredicatePolarity,
145 ) -> bool {
146 clause_def_id == goal_def_id
147 || (polarity == PredicatePolarity::Positive
152 && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized)
153 && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized))
154 }
155
156 if let Some(trait_clause) = assumption.as_trait_clause()
157 && trait_clause.polarity() == goal.predicate.polarity
158 && trait_def_id_matches(
159 ecx.cx(),
160 trait_clause.def_id(),
161 goal.predicate.def_id(),
162 goal.predicate.polarity,
163 )
164 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
165 goal.predicate.trait_ref.args,
166 trait_clause.skip_binder().trait_ref.args,
167 )
168 {
169 return Ok(());
170 } else {
171 Err(NoSolution)
172 }
173 }
174
175 fn match_assumption(
176 ecx: &mut EvalCtxt<'_, D>,
177 goal: Goal<I, Self>,
178 assumption: I::Clause,
179 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
180 ) -> QueryResultOrRerunNonErased<I> {
181 let trait_clause = assumption.as_trait_clause().unwrap();
182
183 if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
189 && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
190 {
191 let meta_sized_clause =
192 trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
193 return Self::match_assumption(ecx, goal, meta_sized_clause, then);
194 }
195
196 let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
197 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
198
199 then(ecx)
200 }
201
202 fn consider_auto_trait_candidate(
203 ecx: &mut EvalCtxt<'_, D>,
204 goal: Goal<I, Self>,
205 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
206 let cx = ecx.cx();
207 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
208 return Err(NoSolution.into());
209 }
210
211 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
212 return result;
213 }
214
215 if cx.trait_is_unsafe(goal.predicate.def_id())
218 && goal.predicate.self_ty().has_unsafe_fields()
219 {
220 return Err(NoSolution.into());
221 }
222
223 if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) =
239 goal.predicate.self_ty().kind()
240 {
241 if ecx.opaque_accesses.might_rerun() {
242 ecx.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)?;
243 return Err(NoSolution.into());
244 }
245
246 if true {
if !ecx.opaque_type_is_rigid(def_id) {
::core::panicking::panic("assertion failed: ecx.opaque_type_is_rigid(def_id)")
};
};debug_assert!(ecx.opaque_type_is_rigid(def_id));
247 for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() {
248 if item_bound
249 .as_trait_clause()
250 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
251 {
252 return Err(NoSolution.into());
253 }
254 }
255 }
256
257 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
259 return cand;
260 }
261
262 ecx.probe_and_evaluate_goal_for_constituent_tys(
263 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
264 goal,
265 structural_traits::instantiate_constituent_tys_for_auto_trait,
266 )
267 }
268
269 fn consider_trait_alias_candidate(
270 ecx: &mut EvalCtxt<'_, D>,
271 goal: Goal<I, Self>,
272 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
273 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
274 return Err(NoSolution.into());
275 }
276
277 let cx = ecx.cx();
278
279 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
280 let nested_obligations = cx
281 .predicates_of(goal.predicate.def_id().into())
282 .iter_instantiated(cx, goal.predicate.trait_ref.args)
283 .map(Unnormalized::skip_norm_wip)
284 .map(|p| goal.with(cx, p));
285 ecx.add_goals(GoalSource::Misc, nested_obligations);
291 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
292 })
293 }
294
295 fn consider_builtin_sizedness_candidates(
296 ecx: &mut EvalCtxt<'_, D>,
297 goal: Goal<I, Self>,
298 sizedness: SizedTraitKind,
299 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
300 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
301 return Err(NoSolution.into());
302 }
303
304 ecx.probe_and_evaluate_goal_for_constituent_tys(
305 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
306 goal,
307 |ecx, ty| {
308 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
309 ecx, sizedness, ty,
310 )
311 },
312 )
313 }
314
315 fn consider_builtin_copy_clone_candidate(
316 ecx: &mut EvalCtxt<'_, D>,
317 goal: Goal<I, Self>,
318 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
319 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
320 return Err(NoSolution.into());
321 }
322
323 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
325 return cand;
326 }
327
328 ecx.probe_and_evaluate_goal_for_constituent_tys(
329 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
330 goal,
331 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
332 )
333 }
334
335 fn consider_builtin_fn_ptr_trait_candidate(
336 ecx: &mut EvalCtxt<'_, D>,
337 goal: Goal<I, Self>,
338 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
339 let self_ty = goal.predicate.self_ty();
340 match goal.predicate.polarity {
341 ty::PredicatePolarity::Positive => {
343 if self_ty.is_fn_ptr() {
344 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
345 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
346 })
347 } else {
348 Err(NoSolution.into())
349 }
350 }
351 ty::PredicatePolarity::Negative => {
353 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
356 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
357 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
358 })
359 } else {
360 Err(NoSolution.into())
361 }
362 }
363 }
364 }
365
366 fn consider_builtin_fn_trait_candidates(
367 ecx: &mut EvalCtxt<'_, D>,
368 goal: Goal<I, Self>,
369 goal_kind: ty::ClosureKind,
370 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
371 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
372 return Err(NoSolution.into());
373 }
374
375 let cx = ecx.cx();
376 let Some(tupled_inputs_and_output) =
377 structural_traits::extract_tupled_inputs_and_output_from_callable(
378 cx,
379 goal.predicate.self_ty(),
380 goal_kind,
381 )?
382 else {
383 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
384 };
385 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
386
387 let output_is_sized_pred =
390 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
391
392 let pred =
393 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
394 .upcast(cx);
395 Self::probe_and_consider_implied_clause(
396 ecx,
397 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
398 goal,
399 pred,
400 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
401 )
402 .map_err(Into::into)
403 }
404
405 fn consider_builtin_async_fn_trait_candidates(
406 ecx: &mut EvalCtxt<'_, D>,
407 goal: Goal<I, Self>,
408 goal_kind: ty::ClosureKind,
409 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
410 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
411 return Err(NoSolution.into());
412 }
413
414 let cx = ecx.cx();
415 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
416 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
417 cx,
418 goal.predicate.self_ty(),
419 goal_kind,
420 Region::new_static(cx),
422 )?;
423 let AsyncCallableRelevantTypes {
424 tupled_inputs_ty,
425 output_coroutine_ty,
426 coroutine_return_ty: _,
427 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
428
429 let output_is_sized_pred = ty::TraitRef::new(
432 cx,
433 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
434 [output_coroutine_ty],
435 );
436
437 let pred = ty::TraitRef::new(
438 cx,
439 goal.predicate.def_id(),
440 [goal.predicate.self_ty(), tupled_inputs_ty],
441 )
442 .upcast(cx);
443 Self::probe_and_consider_implied_clause(
444 ecx,
445 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
446 goal,
447 pred,
448 [goal.with(cx, output_is_sized_pred)]
449 .into_iter()
450 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
451 .map(|goal| (GoalSource::ImplWhereBound, goal)),
452 )
453 .map_err(Into::into)
454 }
455
456 fn consider_builtin_async_fn_kind_helper_candidate(
457 ecx: &mut EvalCtxt<'_, D>,
458 goal: Goal<I, Self>,
459 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
460 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
461 ::core::panicking::panic("explicit panic");panic!();
462 };
463
464 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
465 return Err(NoSolution.into());
467 };
468 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
469 if closure_kind.extends(goal_kind) {
470 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
471 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
472 } else {
473 Err(NoSolution.into())
474 }
475 }
476
477 fn consider_builtin_tuple_candidate(
484 ecx: &mut EvalCtxt<'_, D>,
485 goal: Goal<I, Self>,
486 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
487 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
488 return Err(NoSolution.into());
489 }
490
491 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
492 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
493 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
494 } else {
495 Err(NoSolution.into())
496 }
497 }
498
499 fn consider_builtin_pointee_candidate(
500 ecx: &mut EvalCtxt<'_, D>,
501 goal: Goal<I, Self>,
502 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
503 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
504 return Err(NoSolution.into());
505 }
506
507 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
508 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
509 }
510
511 fn consider_builtin_future_candidate(
512 ecx: &mut EvalCtxt<'_, D>,
513 goal: Goal<I, Self>,
514 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
515 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
516 return Err(NoSolution.into());
517 }
518
519 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
520 return Err(NoSolution.into());
521 };
522
523 let cx = ecx.cx();
525 if !cx.coroutine_is_async(def_id) {
526 return Err(NoSolution.into());
527 }
528
529 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
533 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
534 }
535
536 fn consider_builtin_iterator_candidate(
537 ecx: &mut EvalCtxt<'_, D>,
538 goal: Goal<I, Self>,
539 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
540 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
541 return Err(NoSolution.into());
542 }
543
544 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
545 return Err(NoSolution.into());
546 };
547
548 let cx = ecx.cx();
550 if !cx.coroutine_is_gen(def_id) {
551 return Err(NoSolution.into());
552 }
553
554 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
558 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
559 }
560
561 fn consider_builtin_fused_iterator_candidate(
562 ecx: &mut EvalCtxt<'_, D>,
563 goal: Goal<I, Self>,
564 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
565 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
566 return Err(NoSolution.into());
567 }
568
569 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
570 return Err(NoSolution.into());
571 };
572
573 let cx = ecx.cx();
575 if !cx.coroutine_is_gen(def_id) {
576 return Err(NoSolution.into());
577 }
578
579 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
581 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
582 }
583
584 fn consider_builtin_async_iterator_candidate(
585 ecx: &mut EvalCtxt<'_, D>,
586 goal: Goal<I, Self>,
587 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
588 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
589 return Err(NoSolution.into());
590 }
591
592 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
593 return Err(NoSolution.into());
594 };
595
596 let cx = ecx.cx();
598 if !cx.coroutine_is_async_gen(def_id) {
599 return Err(NoSolution.into());
600 }
601
602 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
606 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
607 }
608
609 fn consider_builtin_coroutine_candidate(
610 ecx: &mut EvalCtxt<'_, D>,
611 goal: Goal<I, Self>,
612 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
613 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
614 return Err(NoSolution.into());
615 }
616
617 let self_ty = goal.predicate.self_ty();
618 let ty::Coroutine(def_id, args) = self_ty.kind() else {
619 return Err(NoSolution.into());
620 };
621
622 let cx = ecx.cx();
624 if !cx.is_general_coroutine(def_id) {
625 return Err(NoSolution.into());
626 }
627
628 let coroutine = args.as_coroutine();
629 Self::probe_and_consider_implied_clause(
630 ecx,
631 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
632 goal,
633 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
634 .upcast(cx),
635 [],
638 )
639 }
640
641 fn consider_builtin_discriminant_kind_candidate(
642 ecx: &mut EvalCtxt<'_, D>,
643 goal: Goal<I, Self>,
644 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
645 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
646 return Err(NoSolution.into());
647 }
648
649 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
651 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
652 }
653
654 fn consider_builtin_destruct_candidate(
655 ecx: &mut EvalCtxt<'_, D>,
656 goal: Goal<I, Self>,
657 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
658 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
659 return Err(NoSolution.into());
660 }
661
662 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
665 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
666 }
667
668 fn consider_builtin_transmute_candidate(
669 ecx: &mut EvalCtxt<'_, D>,
670 goal: Goal<I, Self>,
671 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
672 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
673 return Err(NoSolution.into());
674 }
675
676 if goal.predicate.has_non_region_placeholders() {
678 return Err(NoSolution.into());
679 }
680
681 if goal.has_non_region_infer() {
684 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
685 }
686
687 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(
688 |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
689 let assume = ecx.structurally_normalize_const(
690 goal.param_env,
691 goal.predicate.trait_ref.args.const_at(2),
692 )?;
693
694 let certainty = ecx.is_transmutable(
695 goal.predicate.trait_ref.args.type_at(0),
696 goal.predicate.trait_ref.args.type_at(1),
697 assume,
698 )?;
699 ecx.evaluate_added_goals_and_make_canonical_response(certainty).map_err(Into::into)
700 },
701 )
702 }
703
704 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
717 ecx: &mut EvalCtxt<'_, D>,
718 goal: Goal<I, Self>,
719 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
720 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
721 return Err(NoSolution.into());
722 }
723
724 let cx = ecx.cx();
725 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
726 let ty = goal.predicate.self_ty();
727 match ty.kind() {
728 ty::Ref(..) => {}
730 ty::Adt(def, _) if def.is_manually_drop() => {}
732 ty::Tuple(tys) => {
735 ecx.add_goals(
736 GoalSource::ImplWhereBound,
737 tys.iter().map(|elem_ty| {
738 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
739 }),
740 );
741 }
742 ty::Array(elem_ty, _) => {
743 ecx.add_goal(
744 GoalSource::ImplWhereBound,
745 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
746 );
747 }
748
749 ty::FnDef(..)
753 | ty::FnPtr(..)
754 | ty::Error(_)
755 | ty::Uint(_)
756 | ty::Int(_)
757 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
758 | ty::Bool
759 | ty::Float(_)
760 | ty::Char
761 | ty::RawPtr(..)
762 | ty::Never
763 | ty::Pat(..)
764 | ty::Dynamic(..)
765 | ty::Str
766 | ty::Slice(_)
767 | ty::Foreign(..)
768 | ty::Adt(..)
769 | ty::Alias(..)
770 | ty::Param(_)
771 | ty::Placeholder(..)
772 | ty::Closure(..)
773 | ty::CoroutineClosure(..)
774 | ty::Coroutine(..)
775 | ty::UnsafeBinder(_)
776 | ty::CoroutineWitness(..) => {
777 ecx.add_goal(
778 GoalSource::ImplWhereBound,
779 goal.with(
780 cx,
781 ty::TraitRef::new(
782 cx,
783 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
784 [ty],
785 ),
786 ),
787 );
788 }
789
790 ty::Bound(..)
791 | ty::Infer(
792 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
793 ) => {
794 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
795 }
796 }
797
798 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
799 })
800 }
801
802 fn consider_structural_builtin_unsize_candidates(
810 ecx: &mut EvalCtxt<'_, D>,
811 goal: Goal<I, Self>,
812 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
813 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
814 return Ok(::alloc::vec::Vec::new()vec![]);
815 }
816
817 let result = ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(
818 |ecx| -> Result<Vec<Candidate<I>>, NoSolutionOrRerunNonErased> {
819 let a_ty = goal.predicate.self_ty();
820 let b_ty = ecx.structurally_normalize_ty(
823 goal.param_env,
824 goal.predicate.trait_ref.args.type_at(1),
825 )?;
826
827 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
828 match (a_ty.kind(), b_ty.kind()) {
829 (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:?}"),
830
831 (_, ty::Infer(ty::TyVar(..))) => {
832 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)?])
833 }
834
835 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => Ok(ecx
837 .consider_builtin_dyn_upcast_candidates(
838 goal, a_data, a_region, b_data, b_region,
839 )),
840
841 (_, 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![
843 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data)?,
844 ]),
845
846 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
848 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)?])
849 }
850
851 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
853 if a_def.is_struct() && a_def == b_def =>
854 {
855 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)?])
856 }
857
858 _ => Err(NoSolution.into()),
859 }
860 },
861 );
862
863 match result.map_err_to_rerun()? {
864 Ok(resp) => Ok(resp),
865 Err(NoSolution) => Ok(::alloc::vec::Vec::new()vec![]),
866 }
867 }
868
869 fn consider_builtin_field_candidate(
870 ecx: &mut EvalCtxt<'_, D>,
871 goal: Goal<I, Self>,
872 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
873 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
874 return Err(NoSolution.into());
875 }
876 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
877 && let Some(FieldInfo { base, ty, .. }) =
878 def.field_representing_type_info(ecx.cx(), args)
879 && {
880 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
881 ecx.add_goal(
889 GoalSource::ImplWhereBound,
890 Goal {
891 param_env: goal.param_env,
892 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
893 },
894 );
895 ecx.add_goal(
896 GoalSource::ImplWhereBound,
897 Goal {
898 param_env: goal.param_env,
899 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
900 },
901 );
902 ecx.try_evaluate_added_goals()? == Certainty::Yes
905 }
906 && match base.kind() {
907 ty::Adt(def, _) => def.is_struct() && !def.is_packed(),
908 ty::Tuple(..) => true,
909 _ => false,
910 }
911 {
912 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
913 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
914 } else {
915 Err(NoSolution.into())
916 }
917 }
918}
919
920#[inline(always)]
926fn trait_predicate_with_def_id<I: Interner>(
927 cx: I,
928 clause: ty::Binder<I, ty::TraitPredicate<I>>,
929 did: I::TraitId,
930) -> I::Clause {
931 clause
932 .map_bound(|c| TraitPredicate {
933 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
934 polarity: c.polarity,
935 })
936 .upcast(cx)
937}
938
939impl<D, I> EvalCtxt<'_, D>
940where
941 D: SolverDelegate<Interner = I>,
942 I: Interner,
943{
944 fn consider_builtin_dyn_upcast_candidates(
954 &mut self,
955 goal: Goal<I, (I::Ty, I::Ty)>,
956 a_data: I::BoundExistentialPredicates,
957 a_region: I::Region,
958 b_data: I::BoundExistentialPredicates,
959 b_region: I::Region,
960 ) -> Vec<Candidate<I>> {
961 let cx = self.cx();
962 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
963
964 let mut responses = ::alloc::vec::Vec::new()vec![];
965 let b_principal_def_id = b_data.principal_def_id();
968 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
969 responses.extend(self.consider_builtin_upcast_to_principal(
970 goal,
971 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
972 a_data,
973 a_region,
974 b_data,
975 b_region,
976 a_data.principal(),
977 ));
978 } else if let Some(a_principal) = a_data.principal() {
979 for (idx, new_a_principal) in
980 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
981 .enumerate()
982 .skip(1)
983 {
984 responses.extend(self.consider_builtin_upcast_to_principal(
985 goal,
986 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
987 a_data,
988 a_region,
989 b_data,
990 b_region,
991 Some(new_a_principal.map_bound(|trait_ref| {
992 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
993 })),
994 ));
995 }
996 }
997
998 responses
999 }
1000
1001 fn consider_builtin_unsize_to_dyn_candidate(
1002 &mut self,
1003 goal: Goal<I, (I::Ty, I::Ty)>,
1004 b_data: I::BoundExistentialPredicates,
1005 b_region: I::Region,
1006 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1007 let cx = self.cx();
1008 let Goal { predicate: (a_ty, _), .. } = goal;
1009
1010 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1012 return Err(NoSolution.into());
1013 }
1014
1015 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1016 ecx.add_goals(
1019 GoalSource::ImplWhereBound,
1020 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1021 );
1022
1023 ecx.add_goal(
1025 GoalSource::ImplWhereBound,
1026 goal.with(
1027 cx,
1028 ty::TraitRef::new(
1029 cx,
1030 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1031 [a_ty],
1032 ),
1033 ),
1034 );
1035
1036 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)));
1038 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1039 })
1040 }
1041
1042 fn consider_builtin_upcast_to_principal(
1043 &mut self,
1044 goal: Goal<I, (I::Ty, I::Ty)>,
1045 source: CandidateSource<I>,
1046 a_data: I::BoundExistentialPredicates,
1047 a_region: I::Region,
1048 b_data: I::BoundExistentialPredicates,
1049 b_region: I::Region,
1050 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1051 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1052 let param_env = goal.param_env;
1053
1054 let a_auto_traits: IndexSet<I::TraitId> = a_data
1058 .auto_traits()
1059 .into_iter()
1060 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1061 elaborate::supertrait_def_ids(self.cx(), principal_def_id)
1062 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1063 }))
1064 .collect();
1065
1066 let projection_may_match =
1071 |ecx: &mut EvalCtxt<'_, D>,
1072 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1073 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
1074 source_projection.item_def_id() == target_projection.item_def_id()
1075 && ecx
1076 .probe(|_| ProbeKind::ProjectionCompatibility)
1077 .enter(|ecx| {
1078 ecx.enter_forall_with_assumptions(
1079 target_projection,
1080 param_env,
1081 |ecx, target_projection| {
1082 let source_projection =
1083 ecx.instantiate_binder_with_infer(source_projection);
1084 ecx.eq(param_env, source_projection, target_projection)?;
1085 ecx.try_evaluate_added_goals()
1086 },
1087 )
1088 .map_err(Into::into)
1089 })
1090 .is_ok()
1091 };
1092
1093 self.probe_trait_candidate(source).enter(|ecx| {
1094 for bound in b_data.iter() {
1095 match bound.skip_binder() {
1096 ty::ExistentialPredicate::Trait(target_principal) => {
1099 let source_principal = upcast_principal.unwrap();
1100 let target_principal = bound.rebind(target_principal);
1101 ecx.enter_forall_with_assumptions(
1102 target_principal,
1103 param_env,
1104 |ecx, target_principal| {
1105 let source_principal =
1106 ecx.instantiate_binder_with_infer(source_principal);
1107 ecx.eq(param_env, source_principal, target_principal)?;
1108 ecx.try_evaluate_added_goals()
1109 },
1110 )?;
1111 }
1112 ty::ExistentialPredicate::Projection(target_projection) => {
1118 let target_projection = bound.rebind(target_projection);
1119 let mut matching_projections =
1120 a_data.projection_bounds().into_iter().filter(|source_projection| {
1121 projection_may_match(ecx, *source_projection, target_projection)
1122 });
1123 let Some(source_projection) = matching_projections.next() else {
1124 return Err(NoSolution.into());
1125 };
1126 if matching_projections.next().is_some() {
1127 return ecx
1128 .evaluate_added_goals_and_make_canonical_response(
1129 Certainty::AMBIGUOUS,
1130 )
1131 .map_err(Into::into);
1132 }
1133 ecx.enter_forall_with_assumptions(
1134 target_projection,
1135 param_env,
1136 |ecx, target_projection| {
1137 let source_projection =
1138 ecx.instantiate_binder_with_infer(source_projection);
1139 ecx.eq(param_env, source_projection, target_projection)?;
1140 ecx.try_evaluate_added_goals()
1141 },
1142 )?;
1143 }
1144 ty::ExistentialPredicate::AutoTrait(def_id) => {
1146 if !a_auto_traits.contains(&def_id) {
1147 return Err(NoSolution.into());
1148 }
1149 }
1150 }
1151 }
1152
1153 ecx.add_goal(
1155 GoalSource::ImplWhereBound,
1156 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
1157 );
1158
1159 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into)
1160 })
1161 }
1162
1163 fn consider_builtin_array_unsize(
1172 &mut self,
1173 goal: Goal<I, (I::Ty, I::Ty)>,
1174 a_elem_ty: I::Ty,
1175 b_elem_ty: I::Ty,
1176 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1177 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1178 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1179 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1180 }
1181
1182 fn consider_builtin_struct_unsize(
1196 &mut self,
1197 goal: Goal<I, (I::Ty, I::Ty)>,
1198 def: I::AdtDef,
1199 a_args: I::GenericArgs,
1200 b_args: I::GenericArgs,
1201 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1202 let cx = self.cx();
1203 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1204
1205 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1206 if unsizing_params.is_empty() {
1209 return Err(NoSolution.into());
1210 }
1211
1212 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1213
1214 let a_tail_ty = tail_field_ty.instantiate(cx, a_args).skip_norm_wip();
1215 let b_tail_ty = tail_field_ty.instantiate(cx, b_args).skip_norm_wip();
1216
1217 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1221 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1222 }));
1223 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1224
1225 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1228 self.add_goal(
1229 GoalSource::ImplWhereBound,
1230 goal.with(
1231 cx,
1232 ty::TraitRef::new(
1233 cx,
1234 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1235 [a_tail_ty, b_tail_ty],
1236 ),
1237 ),
1238 );
1239 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1240 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1241 }
1242
1243 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1248 &mut self,
1249 goal: Goal<I, TraitPredicate<I>>,
1250 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1251 let self_ty = goal.predicate.self_ty();
1252 let check_impls = || {
1253 let mut disqualifying_impl = None;
1254 self.cx().for_each_relevant_impl(
1255 goal.predicate.def_id(),
1256 goal.predicate.self_ty(),
1257 |impl_def_id| {
1258 disqualifying_impl = Some(impl_def_id);
1259 },
1260 );
1261 if let Some(def_id) = disqualifying_impl {
1262 {
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:1262",
"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(1262u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message", "def_id",
"goal"], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("disqualified auto-trait implementation")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&def_id) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&goal) as
&dyn Value))])
});
} else { ; }
};trace!(?def_id, ?goal, "disqualified auto-trait implementation");
1263 return Some(Err(NoSolution.into()));
1266 } else {
1267 None
1268 }
1269 };
1270
1271 match self_ty.kind() {
1272 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1278 Some(self.forced_ambiguity(MaybeInfo::AMBIGUOUS))
1279 }
1280
1281 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1284
1285 ty::Dynamic(..)
1288 | ty::Param(..)
1289 | ty::Foreign(..)
1290 | ty::Alias(ty::AliasTy {
1291 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1292 ..
1293 })
1294 | ty::Placeholder(..) => Some(Err(NoSolution.into())),
1295
1296 ty::Infer(_) | ty::Bound(_, _) => {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`"),
1297
1298 ty::Coroutine(def_id, _)
1302 if self
1303 .cx()
1304 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1305 {
1306 match self.cx().coroutine_movability(def_id) {
1307 Movability::Static => Some(Err(NoSolution.into())),
1308 Movability::Movable => Some(
1309 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1310 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1311 }),
1312 ),
1313 }
1314 }
1315
1316 ty::Alias(..) => None,
1321
1322 ty::Bool
1329 | ty::Char
1330 | ty::Int(_)
1331 | ty::Uint(_)
1332 | ty::Float(_)
1333 | ty::Str
1334 | ty::Array(_, _)
1335 | ty::Pat(_, _)
1336 | ty::Slice(_)
1337 | ty::RawPtr(_, _)
1338 | ty::Ref(_, _, _)
1339 | ty::FnDef(_, _)
1340 | ty::FnPtr(..)
1341 | ty::Closure(..)
1342 | ty::CoroutineClosure(..)
1343 | ty::Coroutine(_, _)
1344 | ty::CoroutineWitness(..)
1345 | ty::Never
1346 | ty::Tuple(_)
1347 | ty::Adt(_, _)
1348 | ty::UnsafeBinder(_) => check_impls(),
1349 ty::Error(_) => None,
1350 }
1351 }
1352
1353 fn probe_and_evaluate_goal_for_constituent_tys(
1358 &mut self,
1359 source: CandidateSource<I>,
1360 goal: Goal<I, TraitPredicate<I>>,
1361 constituent_tys: impl Fn(
1362 &EvalCtxt<'_, D>,
1363 I::Ty,
1364 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1365 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1366 self.probe_trait_candidate(source).enter(|ecx| {
1367 let goals = ecx.enter_forall_with_assumptions(
1368 constituent_tys(ecx, goal.predicate.self_ty())?,
1369 goal.param_env,
1370 |ecx, tys| {
1371 tys.into_iter()
1372 .map(|ty| {
1373 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1374 })
1375 .collect::<Vec<_>>()
1376 },
1377 );
1378 ecx.add_goals(GoalSource::ImplWhereBound, goals);
1379 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1380 })
1381 }
1382}
1383
1384#[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)]
1395pub(super) enum TraitGoalProvenVia {
1396 Misc,
1402 ParamEnv,
1403 AliasBound,
1404}
1405
1406impl<D, I> EvalCtxt<'_, D>
1407where
1408 D: SolverDelegate<Interner = I>,
1409 I: Interner,
1410{
1411 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1424 if self.typing_mode().is_coherence() {
1425 return;
1426 }
1427
1428 if candidates
1429 .iter()
1430 .find(|c| {
1431 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1432 })
1433 .is_some_and(|c| has_only_region_constraints(c.result))
1434 {
1435 candidates.retain(|c| {
1436 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1437 {
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:1437",
"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(1437u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message", "c"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("unsoundly dropping impl in favor of builtin dyn-candidate")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&c) as
&dyn Value))])
});
} else { ; }
};debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
1438 false
1439 } else {
1440 true
1441 }
1442 });
1443 }
1444 }
1445
1446 x;#[instrument(level = "debug", skip(self), ret)]
1447 pub(super) fn merge_trait_candidates(
1448 &mut self,
1449 candidate_preference_mode: CandidatePreferenceMode,
1450 mut candidates: Vec<Candidate<I>>,
1451 failed_candidate_info: FailedCandidateInfo,
1452 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1453 if self.typing_mode().is_coherence() {
1454 return if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1455 Ok((response, Some(TraitGoalProvenVia::Misc)))
1456 } else {
1457 self.flounder(&candidates).map(|r| (r, None))
1458 };
1459 }
1460
1461 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1466 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1467 });
1468 if let Some(candidate) = trivial_builtin_impls.next() {
1469 assert!(trivial_builtin_impls.next().is_none());
1472 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1473 }
1474
1475 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1478 && candidates.iter().any(|c| {
1479 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1480 })
1481 {
1482 let alias_bounds: Vec<_> = candidates
1483 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1484 .collect();
1485 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1486 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1487 } else {
1488 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1489 };
1490 }
1491
1492 let has_non_global_where_bounds = candidates
1495 .iter()
1496 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1497 if has_non_global_where_bounds {
1498 let where_bounds: Vec<_> = candidates
1499 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1500 .collect();
1501 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1502 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1503 };
1504 match info {
1505 MergeCandidateInfo::AlwaysApplicable(i) => {
1521 for (j, c) in where_bounds.into_iter().enumerate() {
1522 if i != j {
1523 self.ignore_candidate_head_usages(c.head_usages)
1524 }
1525 }
1526 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1530 }
1531 MergeCandidateInfo::EqualResponse => {}
1532 }
1533 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1534 }
1535
1536 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1538 let alias_bounds: Vec<_> = candidates
1539 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1540 .collect();
1541 return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1542 Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1543 } else {
1544 Ok((self.bail_with_ambiguity(&alias_bounds), None))
1545 };
1546 }
1547
1548 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1549 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1550
1551 let proven_via = if candidates
1556 .iter()
1557 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)))
1558 {
1559 TraitGoalProvenVia::ParamEnv
1560 } else {
1561 candidates
1562 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1563 TraitGoalProvenVia::Misc
1564 };
1565
1566 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
1567 Ok((response, Some(proven_via)))
1568 } else {
1569 self.flounder(&candidates).map(|r| (r, None))
1570 }
1571 }
1572
1573 #[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(1573u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["goal"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
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))]
1574 pub(super) fn compute_trait_goal(
1575 &mut self,
1576 goal: Goal<I, TraitPredicate<I>>,
1577 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1578 {
1579 let (candidates, failed_candidate_info) =
1580 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
1581 let candidate_preference_mode =
1582 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1583 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1584 .map_err(Into::into)
1585 }
1586
1587 fn try_stall_coroutine(
1588 &mut self,
1589 self_ty: I::Ty,
1590 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1591 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1592 match self.typing_mode() {
1593 TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => {
1594 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1595 {
1596 return Some(self.forced_ambiguity(MaybeInfo {
1597 cause: MaybeCause::Ambiguity,
1598 opaque_types_jank: OpaqueTypesJank::AllGood,
1599 stalled_on_coroutines: StalledOnCoroutines::Yes,
1600 }));
1601 }
1602 }
1603 TypingMode::ErasedNotCoherence(MayBeErased) => {
1604 return Some(
1606 match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1607 Err(e) => Err(e.into()),
1608 },
1609 );
1610 }
1611 TypingMode::Coherence
1612 | TypingMode::PostAnalysis
1613 | TypingMode::Codegen
1614 | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ }
1615 | TypingMode::PostBorrowck { defined_opaque_types: _ } => {}
1616 }
1617 }
1618
1619 None
1620 }
1621}