1use std::ops::ControlFlow;
10
11use hir::LangItem;
12use hir::def_id::DefId;
13use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
14use rustc_hir as hir;
15use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
16use rustc_middle::ty::fast_reject::DeepRejectCtxt;
17use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
18use rustc_middle::{bug, span_bug};
19use rustc_type_ir::{Interner, elaborate};
20use tracing::{debug, instrument, trace};
21
22use super::SelectionCandidate::*;
23use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
24use crate::traits::util;
25
26impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
27 #[instrument(skip(self, stack), level = "debug")]
28 pub(super) fn assemble_candidates<'o>(
29 &mut self,
30 stack: &TraitObligationStack<'o, 'tcx>,
31 ) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
32 let TraitObligationStack { obligation, .. } = *stack;
33 let obligation = &Obligation {
34 param_env: obligation.param_env,
35 cause: obligation.cause.clone(),
36 recursion_depth: obligation.recursion_depth,
37 predicate: self.infcx.resolve_vars_if_possible(obligation.predicate),
38 };
39
40 if obligation.predicate.skip_binder().self_ty().is_ty_var() {
41 debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type");
42 return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
52 }
53
54 let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
55
56 if obligation.polarity() == ty::PredicatePolarity::Negative {
58 self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
59 self.assemble_candidates_from_impls(obligation, &mut candidates);
60 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
61 } else {
62 self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
63
64 let def_id = obligation.predicate.def_id();
67 let tcx = self.tcx();
68
69 if tcx.is_lang_item(def_id, LangItem::Copy) {
70 debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
71
72 self.assemble_candidates_from_impls(obligation, &mut candidates);
75
76 let copy_conditions = self.copy_clone_conditions(obligation);
78 self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
79 } else if tcx.is_lang_item(def_id, LangItem::DiscriminantKind) {
80 candidates.vec.push(BuiltinCandidate { has_nested: false });
82 } else if tcx.is_lang_item(def_id, LangItem::AsyncDestruct) {
83 candidates.vec.push(BuiltinCandidate { has_nested: false });
85 } else if tcx.is_lang_item(def_id, LangItem::PointeeTrait) {
86 candidates.vec.push(BuiltinCandidate { has_nested: false });
88 } else if tcx.is_lang_item(def_id, LangItem::Sized) {
89 let sized_conditions = self.sized_conditions(obligation);
92 self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
93 } else if tcx.is_lang_item(def_id, LangItem::Unsize) {
94 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
95 } else if tcx.is_lang_item(def_id, LangItem::Destruct) {
96 self.assemble_const_destruct_candidates(obligation, &mut candidates);
97 } else if tcx.is_lang_item(def_id, LangItem::TransmuteTrait) {
98 self.assemble_candidates_from_impls(obligation, &mut candidates);
100 self.assemble_candidates_for_transmutability(obligation, &mut candidates);
101 } else if tcx.is_lang_item(def_id, LangItem::Tuple) {
102 self.assemble_candidate_for_tuple(obligation, &mut candidates);
103 } else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
104 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
105 } else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) {
106 self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
107 obligation,
108 &mut candidates,
109 );
110 } else {
111 if tcx.is_lang_item(def_id, LangItem::Clone) {
112 let clone_conditions = self.copy_clone_conditions(obligation);
116 self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
117 }
118
119 if tcx.is_lang_item(def_id, LangItem::Coroutine) {
120 self.assemble_coroutine_candidates(obligation, &mut candidates);
121 } else if tcx.is_lang_item(def_id, LangItem::Future) {
122 self.assemble_future_candidates(obligation, &mut candidates);
123 } else if tcx.is_lang_item(def_id, LangItem::Iterator) {
124 self.assemble_iterator_candidates(obligation, &mut candidates);
125 } else if tcx.is_lang_item(def_id, LangItem::FusedIterator) {
126 self.assemble_fused_iterator_candidates(obligation, &mut candidates);
127 } else if tcx.is_lang_item(def_id, LangItem::AsyncIterator) {
128 self.assemble_async_iterator_candidates(obligation, &mut candidates);
129 } else if tcx.is_lang_item(def_id, LangItem::AsyncFnKindHelper) {
130 self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates);
131 }
132
133 self.assemble_closure_candidates(obligation, &mut candidates);
135 self.assemble_async_closure_candidates(obligation, &mut candidates);
136 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
137
138 self.assemble_candidates_from_impls(obligation, &mut candidates);
139 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
140 }
141
142 self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
143 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
144 self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
145 }
146 debug!("candidate list size: {}", candidates.vec.len());
147 Ok(candidates)
148 }
149
150 #[instrument(level = "debug", skip(self, candidates))]
151 fn assemble_candidates_from_projected_tys(
152 &mut self,
153 obligation: &PolyTraitObligation<'tcx>,
154 candidates: &mut SelectionCandidateSet<'tcx>,
155 ) {
156 match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
159 ty::Alias(ty::Projection | ty::Opaque, _) => {}
161 ty::Infer(ty::TyVar(_)) => {
162 span_bug!(
163 obligation.cause.span,
164 "Self=_ should have been handled by assemble_candidates"
165 );
166 }
167 _ => return,
168 }
169
170 self.infcx.probe(|_| {
171 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
172 let placeholder_trait_predicate =
173 self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
174
175 let mut distinct_normalized_bounds = FxHashSet::default();
179 self.for_each_item_bound::<!>(
180 placeholder_trait_predicate.self_ty(),
181 |selcx, bound, idx| {
182 let Some(bound) = bound.as_trait_clause() else {
183 return ControlFlow::Continue(());
184 };
185 if bound.polarity() != placeholder_trait_predicate.polarity {
186 return ControlFlow::Continue(());
187 }
188
189 selcx.infcx.probe(|_| {
190 match selcx.match_normalize_trait_ref(
192 obligation,
193 placeholder_trait_predicate.trait_ref,
194 bound.map_bound(|pred| pred.trait_ref),
195 ) {
196 Ok(None) => {
197 candidates.vec.push(ProjectionCandidate(idx));
198 }
199 Ok(Some(normalized_trait))
200 if distinct_normalized_bounds.insert(normalized_trait) =>
201 {
202 candidates.vec.push(ProjectionCandidate(idx));
203 }
204 _ => {}
205 }
206 });
207
208 ControlFlow::Continue(())
209 },
210 || candidates.ambiguous = true,
212 );
213 });
214 }
215
216 #[instrument(level = "debug", skip(self, stack, candidates))]
221 fn assemble_candidates_from_caller_bounds<'o>(
222 &mut self,
223 stack: &TraitObligationStack<'o, 'tcx>,
224 candidates: &mut SelectionCandidateSet<'tcx>,
225 ) -> Result<(), SelectionError<'tcx>> {
226 debug!(?stack.obligation);
227
228 let bounds = stack
229 .obligation
230 .param_env
231 .caller_bounds()
232 .iter()
233 .filter_map(|p| p.as_trait_clause())
234 .filter(|p| p.def_id() == stack.obligation.predicate.def_id())
236 .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
237
238 let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
239 let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
240 for bound in bounds {
242 let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
243 if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
244 continue;
245 }
246 let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
249 if wc.may_apply() {
250 candidates.vec.push(ParamCandidate(bound));
251 }
252 }
253
254 Ok(())
255 }
256
257 fn assemble_coroutine_candidates(
258 &mut self,
259 obligation: &PolyTraitObligation<'tcx>,
260 candidates: &mut SelectionCandidateSet<'tcx>,
261 ) {
262 let self_ty = obligation.self_ty().skip_binder();
266 match self_ty.kind() {
267 ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => {
270 debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
271
272 candidates.vec.push(CoroutineCandidate);
273 }
274 ty::Infer(ty::TyVar(_)) => {
275 debug!("assemble_coroutine_candidates: ambiguous self-type");
276 candidates.ambiguous = true;
277 }
278 _ => {}
279 }
280 }
281
282 fn assemble_future_candidates(
283 &mut self,
284 obligation: &PolyTraitObligation<'tcx>,
285 candidates: &mut SelectionCandidateSet<'tcx>,
286 ) {
287 let self_ty = obligation.self_ty().skip_binder();
288 if let ty::Coroutine(did, ..) = self_ty.kind() {
289 if self.tcx().coroutine_is_async(*did) {
292 debug!(?self_ty, ?obligation, "assemble_future_candidates",);
293
294 candidates.vec.push(FutureCandidate);
295 }
296 }
297 }
298
299 fn assemble_iterator_candidates(
300 &mut self,
301 obligation: &PolyTraitObligation<'tcx>,
302 candidates: &mut SelectionCandidateSet<'tcx>,
303 ) {
304 let self_ty = obligation.self_ty().skip_binder();
305 if let ty::Coroutine(did, ..) = self_ty.kind()
308 && self.tcx().coroutine_is_gen(*did)
309 {
310 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
311
312 candidates.vec.push(IteratorCandidate);
313 }
314 }
315
316 fn assemble_fused_iterator_candidates(
317 &mut self,
318 obligation: &PolyTraitObligation<'tcx>,
319 candidates: &mut SelectionCandidateSet<'tcx>,
320 ) {
321 let self_ty = obligation.self_ty().skip_binder();
322 if let ty::Coroutine(did, ..) = self_ty.kind()
325 && self.tcx().coroutine_is_gen(*did)
326 {
327 debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
328
329 candidates.vec.push(BuiltinCandidate { has_nested: false });
330 }
331 }
332
333 fn assemble_async_iterator_candidates(
334 &mut self,
335 obligation: &PolyTraitObligation<'tcx>,
336 candidates: &mut SelectionCandidateSet<'tcx>,
337 ) {
338 let self_ty = obligation.self_ty().skip_binder();
339 if let ty::Coroutine(did, args) = *self_ty.kind() {
340 if self.tcx().coroutine_is_async_gen(did) {
343 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
344
345 let ty::Adt(_poll_def, args) = *args.as_coroutine().yield_ty().kind() else {
348 candidates.ambiguous = true;
349 return;
350 };
351 let ty::Adt(_option_def, _) = *args.type_at(0).kind() else {
352 candidates.ambiguous = true;
353 return;
354 };
355
356 candidates.vec.push(AsyncIteratorCandidate);
357 }
358 }
359 }
360
361 fn assemble_closure_candidates(
368 &mut self,
369 obligation: &PolyTraitObligation<'tcx>,
370 candidates: &mut SelectionCandidateSet<'tcx>,
371 ) {
372 let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
373 return;
374 };
375
376 let self_ty = obligation.self_ty().skip_binder();
380 match *self_ty.kind() {
381 ty::Closure(def_id, _) => {
382 let is_const = self.tcx().is_const_fn(def_id);
383 debug!(?kind, ?obligation, "assemble_unboxed_candidates");
384 match self.infcx.closure_kind(self_ty) {
385 Some(closure_kind) => {
386 debug!(?closure_kind, "assemble_unboxed_candidates");
387 if closure_kind.extends(kind) {
388 candidates.vec.push(ClosureCandidate { is_const });
389 }
390 }
391 None => {
392 if kind == ty::ClosureKind::FnOnce {
393 candidates.vec.push(ClosureCandidate { is_const });
394 } else {
395 candidates.ambiguous = true;
396 }
397 }
398 }
399 }
400 ty::CoroutineClosure(def_id, args) => {
401 let args = args.as_coroutine_closure();
402 let is_const = self.tcx().is_const_fn(def_id);
403 if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
404 && !args.tupled_upvars_ty().is_ty_var()
406 {
407 if closure_kind.extends(kind) && !args.has_self_borrows() {
412 candidates.vec.push(ClosureCandidate { is_const });
413 } else if kind == ty::ClosureKind::FnOnce {
414 candidates.vec.push(ClosureCandidate { is_const });
415 }
416 } else if kind == ty::ClosureKind::FnOnce {
417 candidates.vec.push(ClosureCandidate { is_const });
418 } else {
419 candidates.ambiguous = true;
421 }
422 }
423 ty::Infer(ty::TyVar(_)) => {
424 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
425 candidates.ambiguous = true;
426 }
427 _ => {}
428 }
429 }
430
431 fn assemble_async_closure_candidates(
432 &mut self,
433 obligation: &PolyTraitObligation<'tcx>,
434 candidates: &mut SelectionCandidateSet<'tcx>,
435 ) {
436 let Some(goal_kind) =
437 self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id())
438 else {
439 return;
440 };
441
442 match *obligation.self_ty().skip_binder().kind() {
443 ty::CoroutineClosure(_, args) => {
444 if let Some(closure_kind) =
445 args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
446 && !closure_kind.extends(goal_kind)
447 {
448 return;
449 }
450 candidates.vec.push(AsyncClosureCandidate);
451 }
452 ty::Closure(_, args) => {
455 if let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind()
456 && !closure_kind.extends(goal_kind)
457 {
458 return;
459 }
460 candidates.vec.push(AsyncClosureCandidate);
461 }
462 ty::FnPtr(sig_tys, hdr) => {
464 if sig_tys.with(hdr).is_fn_trait_compatible() {
465 candidates.vec.push(AsyncClosureCandidate);
466 }
467 }
468 ty::FnDef(def_id, _) => {
470 let tcx = self.tcx();
471 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
472 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
473 {
474 candidates.vec.push(AsyncClosureCandidate);
475 }
476 }
477 _ => {}
478 }
479 }
480
481 fn assemble_async_fn_kind_helper_candidates(
482 &mut self,
483 obligation: &PolyTraitObligation<'tcx>,
484 candidates: &mut SelectionCandidateSet<'tcx>,
485 ) {
486 let self_ty = obligation.self_ty().skip_binder();
487 let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
488
489 if !(self_ty.is_integral() || self_ty.is_ty_var()) {
491 return;
492 }
493 if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) {
494 return;
495 }
496
497 if let Some(closure_kind) = self_ty.to_opt_closure_kind()
500 && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
501 && closure_kind.extends(goal_kind)
502 {
503 candidates.vec.push(AsyncFnKindHelperCandidate);
504 }
505 }
506
507 fn assemble_fn_pointer_candidates(
509 &mut self,
510 obligation: &PolyTraitObligation<'tcx>,
511 candidates: &mut SelectionCandidateSet<'tcx>,
512 ) {
513 if !self.tcx().is_fn_trait(obligation.predicate.def_id()) {
515 return;
516 }
517
518 let self_ty = obligation.self_ty().skip_binder();
523 match *self_ty.kind() {
524 ty::Infer(ty::TyVar(_)) => {
525 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
526 candidates.ambiguous = true; }
528 ty::FnPtr(sig_tys, hdr) => {
530 if sig_tys.with(hdr).is_fn_trait_compatible() {
531 candidates.vec.push(FnPointerCandidate);
532 }
533 }
534 ty::FnDef(def_id, _) => {
536 let tcx = self.tcx();
537 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
538 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
539 {
540 candidates.vec.push(FnPointerCandidate);
541 }
542 }
543 _ => {}
544 }
545 }
546
547 #[instrument(level = "debug", skip(self, candidates))]
549 fn assemble_candidates_from_impls(
550 &mut self,
551 obligation: &PolyTraitObligation<'tcx>,
552 candidates: &mut SelectionCandidateSet<'tcx>,
553 ) {
554 let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
555 let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
556 self.tcx().for_each_relevant_impl(
557 obligation.predicate.def_id(),
558 obligation.predicate.skip_binder().trait_ref.self_ty(),
559 |impl_def_id| {
560 let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
564 if !drcx
565 .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
566 {
567 return;
568 }
569
570 if self.tcx().defaultness(impl_def_id).is_default() {
574 return;
575 }
576
577 if self.reject_fn_ptr_impls(
578 impl_def_id,
579 obligation,
580 impl_trait_header.trait_ref.skip_binder().self_ty(),
581 ) {
582 return;
583 }
584
585 self.infcx.probe(|_| {
586 if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_header, obligation) {
587 candidates.vec.push(ImplCandidate(impl_def_id));
588 }
589 });
590 },
591 );
592 }
593
594 #[instrument(level = "trace", skip(self), ret)]
599 fn reject_fn_ptr_impls(
600 &mut self,
601 impl_def_id: DefId,
602 obligation: &PolyTraitObligation<'tcx>,
603 impl_self_ty: Ty<'tcx>,
604 ) -> bool {
605 if !matches!(impl_self_ty.kind(), ty::Param(..)) {
607 return false;
608 }
609 let Some(fn_ptr_trait) = self.tcx().lang_items().fn_ptr_trait() else {
610 return false;
611 };
612
613 for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
614 let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
615 if fn_ptr_trait != pred.trait_ref.def_id {
616 continue;
617 }
618 trace!(?pred);
619 if pred.self_ty() != impl_self_ty {
621 continue;
622 }
623
624 let self_ty = obligation.self_ty().skip_binder();
625 match self_ty.kind() {
626 ty::FnPtr(..) => return false,
629
630 ty::Placeholder(..)
632 | ty::Dynamic(_, _, _)
633 | ty::Alias(_, _)
634 | ty::Infer(_)
635 | ty::Param(..)
636 | ty::Bound(_, _) => {}
637
638 ty::Bool
641 | ty::Char
642 | ty::Int(_)
643 | ty::Uint(_)
644 | ty::Float(_)
645 | ty::Adt(_, _)
646 | ty::Foreign(_)
647 | ty::Str
648 | ty::Array(_, _)
649 | ty::Pat(_, _)
650 | ty::Slice(_)
651 | ty::RawPtr(_, _)
652 | ty::Ref(_, _, _)
653 | ty::Closure(..)
654 | ty::CoroutineClosure(..)
655 | ty::Coroutine(_, _)
656 | ty::CoroutineWitness(..)
657 | ty::UnsafeBinder(_)
658 | ty::Never
659 | ty::Tuple(_)
660 | ty::Error(_) => return true,
661 ty::FnDef(_, _) => return true,
664 }
665
666 let obligation = Obligation::new(
669 self.tcx(),
670 obligation.cause.clone(),
671 obligation.param_env,
672 self.tcx().mk_predicate(obligation.predicate.map_bound(|mut pred| {
673 pred.trait_ref =
674 ty::TraitRef::new(self.tcx(), fn_ptr_trait, [pred.trait_ref.self_ty()]);
675 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
676 })),
677 );
678 if let Ok(r) = self.evaluate_root_obligation(&obligation) {
679 if !r.may_apply() {
680 return true;
681 }
682 }
683 }
684 false
685 }
686
687 fn assemble_candidates_from_auto_impls(
688 &mut self,
689 obligation: &PolyTraitObligation<'tcx>,
690 candidates: &mut SelectionCandidateSet<'tcx>,
691 ) {
692 let self_ty = obligation.self_ty().skip_binder();
694 debug!(?self_ty, "assemble_candidates_from_auto_impls");
695
696 let def_id = obligation.predicate.def_id();
697
698 if self.tcx().trait_is_auto(def_id) {
699 match *self_ty.kind() {
700 ty::Dynamic(..) => {
701 }
706 ty::Foreign(..) => {
707 }
712 ty::Param(..)
713 | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
714 | ty::Placeholder(..)
715 | ty::Bound(..) => {
716 }
730 ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
731 candidates.ambiguous = true;
733 }
734 ty::Coroutine(coroutine_def_id, _)
735 if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
736 {
737 match self.tcx().coroutine_movability(coroutine_def_id) {
738 hir::Movability::Static => {
739 }
742 hir::Movability::Movable => {
743 candidates.vec.push(BuiltinCandidate { has_nested: false });
746 }
747 }
748 }
749
750 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
751 bug!(
752 "asked to assemble auto trait candidates of unexpected type: {:?}",
753 self_ty
754 );
755 }
756
757 ty::Alias(ty::Opaque, alias) => {
758 if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
759 } else if let TypingMode::Coherence = self.infcx.typing_mode() {
769 candidates.ambiguous = true;
772 } else if self.infcx.can_define_opaque_ty(alias.def_id) {
773 candidates.ambiguous = true;
777 } else {
778 candidates.vec.push(AutoImplCandidate)
779 }
780 }
781
782 ty::Bool
783 | ty::Char
784 | ty::Int(_)
785 | ty::Uint(_)
786 | ty::Float(_)
787 | ty::Str
788 | ty::Array(_, _)
789 | ty::Pat(_, _)
790 | ty::Slice(_)
791 | ty::Adt(..)
792 | ty::RawPtr(_, _)
793 | ty::Ref(..)
794 | ty::FnDef(..)
795 | ty::FnPtr(..)
796 | ty::Closure(..)
797 | ty::CoroutineClosure(..)
798 | ty::Coroutine(..)
799 | ty::Never
800 | ty::Tuple(_)
801 | ty::CoroutineWitness(..)
802 | ty::UnsafeBinder(_) => {
803 if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
806 return;
807 }
808
809 let mut has_impl = false;
819 self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
820 if !has_impl {
821 candidates.vec.push(AutoImplCandidate)
822 }
823 }
824 ty::Error(_) => {
825 candidates.vec.push(AutoImplCandidate);
826 }
827 }
828 }
829 }
830
831 fn assemble_candidates_from_object_ty(
833 &mut self,
834 obligation: &PolyTraitObligation<'tcx>,
835 candidates: &mut SelectionCandidateSet<'tcx>,
836 ) {
837 debug!(
838 self_ty = ?obligation.self_ty().skip_binder(),
839 "assemble_candidates_from_object_ty",
840 );
841
842 if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
843 return;
844 }
845
846 self.infcx.probe(|_snapshot| {
847 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
848 self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
849 let self_ty = placeholder_trait_predicate.self_ty();
850 let principal_trait_ref = match self_ty.kind() {
851 ty::Dynamic(data, ..) => {
852 if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
853 debug!(
854 "assemble_candidates_from_object_ty: matched builtin bound, \
855 pushing candidate"
856 );
857 candidates.vec.push(BuiltinObjectCandidate);
858 return;
859 }
860
861 if let Some(principal) = data.principal() {
862 if !self.infcx.tcx.features().dyn_compatible_for_dispatch() {
863 principal.with_self_ty(self.tcx(), self_ty)
864 } else if self.tcx().is_dyn_compatible(principal.def_id()) {
865 principal.with_self_ty(self.tcx(), self_ty)
866 } else {
867 return;
868 }
869 } else {
870 return;
872 }
873 }
874 ty::Infer(ty::TyVar(_)) => {
875 debug!("assemble_candidates_from_object_ty: ambiguous");
876 candidates.ambiguous = true; return;
878 }
879 _ => return,
880 };
881
882 debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
883
884 let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
890 .enumerate()
891 .filter(|&(_, upcast_trait_ref)| {
892 self.infcx.probe(|_| {
893 self.match_normalize_trait_ref(
894 obligation,
895 placeholder_trait_predicate.trait_ref,
896 upcast_trait_ref,
897 )
898 .is_ok()
899 })
900 })
901 .map(|(idx, _)| ObjectCandidate(idx));
902
903 candidates.vec.extend(candidate_supertraits);
904 })
905 })
906 }
907
908 fn assemble_candidates_for_unsizing(
910 &mut self,
911 obligation: &PolyTraitObligation<'tcx>,
912 candidates: &mut SelectionCandidateSet<'tcx>,
913 ) {
914 let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
929 return;
931 };
932 let source = trait_pred.self_ty();
933 let target = trait_pred.trait_ref.args.type_at(1);
934
935 debug!(?source, ?target, "assemble_candidates_for_unsizing");
936
937 match (source.kind(), target.kind()) {
938 (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => {
940 let principal_def_id_a = a_data.principal_def_id();
952 let principal_def_id_b = b_data.principal_def_id();
953 if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
954 let a_auto_traits: FxIndexSet<DefId> = a_data
958 .auto_traits()
959 .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
960 elaborate::supertrait_def_ids(self.tcx(), principal_def_id)
961 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
962 }))
963 .collect();
964 let auto_traits_compatible = b_data
965 .auto_traits()
966 .all(|b| a_auto_traits.contains(&b));
968 if auto_traits_compatible {
969 candidates.vec.push(BuiltinUnsizeCandidate);
970 }
971 } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
972 let principal_a = a_data.principal().unwrap();
974 let target_trait_did = principal_def_id_b.unwrap();
975 let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
976
977 for (idx, upcast_trait_ref) in
978 util::supertraits(self.tcx(), source_trait_ref).enumerate()
979 {
980 self.infcx.probe(|_| {
981 if upcast_trait_ref.def_id() == target_trait_did
982 && let Ok(nested) = self.match_upcast_principal(
983 obligation,
984 upcast_trait_ref,
985 a_data,
986 b_data,
987 a_region,
988 b_region,
989 )
990 {
991 if nested.is_none() {
992 candidates.ambiguous = true;
993 }
994 candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
995 }
996 })
997 }
998 }
999 }
1000
1001 (_, &ty::Dynamic(_, _, ty::Dyn)) => {
1003 candidates.vec.push(BuiltinUnsizeCandidate);
1004 }
1005
1006 (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
1010 debug!("assemble_candidates_for_unsizing: ambiguous");
1011 candidates.ambiguous = true;
1012 }
1013
1014 (&ty::Array(..), &ty::Slice(_)) => {
1016 candidates.vec.push(BuiltinUnsizeCandidate);
1017 }
1018
1019 (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
1021 if def_id_a == def_id_b {
1022 candidates.vec.push(BuiltinUnsizeCandidate);
1023 }
1024 }
1025
1026 (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
1028 if tys_a.len() == tys_b.len() {
1029 candidates.vec.push(BuiltinUnsizeCandidate);
1030 }
1031 }
1032
1033 _ => {}
1034 };
1035 }
1036
1037 #[instrument(level = "debug", skip(self, obligation, candidates))]
1038 fn assemble_candidates_for_transmutability(
1039 &mut self,
1040 obligation: &PolyTraitObligation<'tcx>,
1041 candidates: &mut SelectionCandidateSet<'tcx>,
1042 ) {
1043 if obligation.predicate.has_non_region_param() {
1044 return;
1045 }
1046
1047 if obligation.has_non_region_infer() {
1048 candidates.ambiguous = true;
1049 return;
1050 }
1051
1052 candidates.vec.push(TransmutabilityCandidate);
1053 }
1054
1055 #[instrument(level = "debug", skip(self, obligation, candidates))]
1056 fn assemble_candidates_for_trait_alias(
1057 &mut self,
1058 obligation: &PolyTraitObligation<'tcx>,
1059 candidates: &mut SelectionCandidateSet<'tcx>,
1060 ) {
1061 let self_ty = obligation.self_ty().skip_binder();
1063 debug!(?self_ty);
1064
1065 let def_id = obligation.predicate.def_id();
1066
1067 if self.tcx().is_trait_alias(def_id) {
1068 candidates.vec.push(TraitAliasCandidate);
1069 }
1070 }
1071
1072 #[instrument(level = "debug", skip(self, candidates))]
1075 fn assemble_builtin_bound_candidates(
1076 &mut self,
1077 conditions: BuiltinImplConditions<'tcx>,
1078 candidates: &mut SelectionCandidateSet<'tcx>,
1079 ) {
1080 match conditions {
1081 BuiltinImplConditions::Where(nested) => {
1082 candidates
1083 .vec
1084 .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
1085 }
1086 BuiltinImplConditions::None => {}
1087 BuiltinImplConditions::Ambiguous => {
1088 candidates.ambiguous = true;
1089 }
1090 }
1091 }
1092
1093 fn assemble_const_destruct_candidates(
1094 &mut self,
1095 _obligation: &PolyTraitObligation<'tcx>,
1096 candidates: &mut SelectionCandidateSet<'tcx>,
1097 ) {
1098 candidates.vec.push(BuiltinCandidate { has_nested: false });
1099 }
1100
1101 fn assemble_candidate_for_tuple(
1102 &mut self,
1103 obligation: &PolyTraitObligation<'tcx>,
1104 candidates: &mut SelectionCandidateSet<'tcx>,
1105 ) {
1106 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1107 match self_ty.kind() {
1108 ty::Tuple(_) => {
1109 candidates.vec.push(BuiltinCandidate { has_nested: false });
1110 }
1111 ty::Infer(ty::TyVar(_)) => {
1112 candidates.ambiguous = true;
1113 }
1114 ty::Bool
1115 | ty::Char
1116 | ty::Int(_)
1117 | ty::Uint(_)
1118 | ty::Float(_)
1119 | ty::Adt(_, _)
1120 | ty::Foreign(_)
1121 | ty::Str
1122 | ty::Array(_, _)
1123 | ty::Slice(_)
1124 | ty::RawPtr(_, _)
1125 | ty::Ref(_, _, _)
1126 | ty::FnDef(_, _)
1127 | ty::Pat(_, _)
1128 | ty::FnPtr(..)
1129 | ty::UnsafeBinder(_)
1130 | ty::Dynamic(_, _, _)
1131 | ty::Closure(..)
1132 | ty::CoroutineClosure(..)
1133 | ty::Coroutine(_, _)
1134 | ty::CoroutineWitness(..)
1135 | ty::Never
1136 | ty::Alias(..)
1137 | ty::Param(_)
1138 | ty::Bound(_, _)
1139 | ty::Error(_)
1140 | ty::Infer(_)
1141 | ty::Placeholder(_) => {}
1142 }
1143 }
1144
1145 fn assemble_candidates_for_fn_ptr_trait(
1146 &mut self,
1147 obligation: &PolyTraitObligation<'tcx>,
1148 candidates: &mut SelectionCandidateSet<'tcx>,
1149 ) {
1150 let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
1151
1152 match self_ty.skip_binder().kind() {
1153 ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
1154 ty::Bool
1155 | ty::Char
1156 | ty::Int(_)
1157 | ty::Uint(_)
1158 | ty::Float(_)
1159 | ty::Adt(..)
1160 | ty::Foreign(..)
1161 | ty::Str
1162 | ty::Array(..)
1163 | ty::Pat(..)
1164 | ty::Slice(_)
1165 | ty::RawPtr(_, _)
1166 | ty::Ref(..)
1167 | ty::FnDef(..)
1168 | ty::Placeholder(..)
1169 | ty::Dynamic(..)
1170 | ty::Closure(..)
1171 | ty::CoroutineClosure(..)
1172 | ty::Coroutine(..)
1173 | ty::CoroutineWitness(..)
1174 | ty::UnsafeBinder(_)
1175 | ty::Never
1176 | ty::Tuple(..)
1177 | ty::Alias(..)
1178 | ty::Param(..)
1179 | ty::Bound(..)
1180 | ty::Error(_)
1181 | ty::Infer(
1182 ty::InferTy::IntVar(_)
1183 | ty::InferTy::FloatVar(_)
1184 | ty::InferTy::FreshIntTy(_)
1185 | ty::InferTy::FreshFloatTy(_),
1186 ) => {}
1187 ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
1188 candidates.ambiguous = true;
1189 }
1190 }
1191 }
1192
1193 fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
1194 &mut self,
1195 obligation: &PolyTraitObligation<'tcx>,
1196 candidates: &mut SelectionCandidateSet<'tcx>,
1197 ) {
1198 match obligation.predicate.self_ty().skip_binder().kind() {
1199 ty::Ref(..)
1200 | ty::Adt(..)
1201 | ty::Tuple(_)
1202 | ty::Array(..)
1203 | ty::FnDef(..)
1204 | ty::FnPtr(..)
1205 | ty::Error(_)
1206 | ty::Uint(_)
1207 | ty::Int(_)
1208 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1209 | ty::Bool
1210 | ty::Float(_)
1211 | ty::Char
1212 | ty::RawPtr(..)
1213 | ty::Never
1214 | ty::Pat(..)
1215 | ty::Dynamic(..)
1216 | ty::Str
1217 | ty::Slice(_)
1218 | ty::Foreign(..)
1219 | ty::Alias(..)
1220 | ty::Param(_)
1221 | ty::Placeholder(..)
1222 | ty::Closure(..)
1223 | ty::CoroutineClosure(..)
1224 | ty::Coroutine(..)
1225 | ty::UnsafeBinder(_)
1226 | ty::CoroutineWitness(..)
1227 | ty::Bound(..) => {
1228 candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
1229 }
1230
1231 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1232 candidates.ambiguous = true;
1233 }
1234 }
1235 }
1236}