1use std::ops::ControlFlow;
10
11use hir::LangItem;
12use hir::def_id::DefId;
13use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
14use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
15use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
16use rustc_middle::ty::fast_reject::DeepRejectCtxt;
17use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate};
18use rustc_middle::{bug, span_bug};
19use tracing::{debug, instrument, trace};
20
21use super::SelectionCandidate::*;
22use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
23use crate::traits::util;
24
25impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
26 #[instrument(skip(self, stack), level = "debug")]
27 pub(super) fn assemble_candidates<'o>(
28 &mut self,
29 stack: &TraitObligationStack<'o, 'tcx>,
30 ) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
31 let TraitObligationStack { obligation, .. } = *stack;
32 let obligation = &Obligation {
33 param_env: obligation.param_env,
34 cause: obligation.cause.clone(),
35 recursion_depth: obligation.recursion_depth,
36 predicate: self.infcx.resolve_vars_if_possible(obligation.predicate),
37 };
38
39 if obligation.predicate.skip_binder().self_ty().is_ty_var() {
40 debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type");
41 return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
51 }
52
53 let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
54
55 if obligation.polarity() == ty::PredicatePolarity::Negative {
57 self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
58 self.assemble_candidates_from_impls(obligation, &mut candidates);
59 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
60 } else {
61 self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
62
63 let def_id = obligation.predicate.def_id();
66 let tcx = self.tcx();
67
68 let lang_item = tcx.as_lang_item(def_id);
69 match lang_item {
70 Some(LangItem::Copy | LangItem::Clone) => {
71 debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
72
73 self.assemble_candidates_from_impls(obligation, &mut candidates);
76
77 let copy_conditions = self.copy_clone_conditions(obligation);
79 self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
80 }
81 Some(LangItem::DiscriminantKind) => {
82 candidates.vec.push(BuiltinCandidate { has_nested: false });
84 }
85 Some(LangItem::PointeeTrait) => {
86 candidates.vec.push(BuiltinCandidate { has_nested: false });
88 }
89 Some(LangItem::Sized) => {
90 self.assemble_builtin_sized_candidate(obligation, &mut candidates);
91 }
92 Some(LangItem::Unsize) => {
93 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
94 }
95 Some(LangItem::Destruct) => {
96 self.assemble_const_destruct_candidates(obligation, &mut candidates);
97 }
98 Some(LangItem::TransmuteTrait) => {
99 self.assemble_candidates_from_impls(obligation, &mut candidates);
101 self.assemble_candidates_for_transmutability(obligation, &mut candidates);
102 }
103 Some(LangItem::Tuple) => {
104 self.assemble_candidate_for_tuple(obligation, &mut candidates);
105 }
106 Some(LangItem::FnPtrTrait) => {
107 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
108 }
109 Some(LangItem::BikeshedGuaranteedNoDrop) => {
110 self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
111 obligation,
112 &mut candidates,
113 );
114 }
115 _ => {
116 match lang_item {
120 Some(LangItem::Coroutine) => {
121 self.assemble_coroutine_candidates(obligation, &mut candidates);
122 }
123 Some(LangItem::Future) => {
124 self.assemble_future_candidates(obligation, &mut candidates);
125 }
126 Some(LangItem::Iterator) => {
127 self.assemble_iterator_candidates(obligation, &mut candidates);
128 }
129 Some(LangItem::FusedIterator) => {
130 self.assemble_fused_iterator_candidates(obligation, &mut candidates);
131 }
132 Some(LangItem::AsyncIterator) => {
133 self.assemble_async_iterator_candidates(obligation, &mut candidates);
134 }
135 Some(LangItem::AsyncFnKindHelper) => {
136 self.assemble_async_fn_kind_helper_candidates(
137 obligation,
138 &mut candidates,
139 );
140 }
141 Some(LangItem::AsyncFn | LangItem::AsyncFnMut | LangItem::AsyncFnOnce) => {
142 self.assemble_async_closure_candidates(obligation, &mut candidates);
143 }
144 Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
145 self.assemble_closure_candidates(obligation, &mut candidates);
146 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
147 }
148 _ => {}
149 }
150
151 self.assemble_candidates_from_impls(obligation, &mut candidates);
152 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
153 }
154 }
155
156 self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
157 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
158 self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
159 }
160 debug!("candidate list size: {}", candidates.vec.len());
161 Ok(candidates)
162 }
163
164 #[instrument(level = "debug", skip(self, candidates))]
165 fn assemble_candidates_from_projected_tys(
166 &mut self,
167 obligation: &PolyTraitObligation<'tcx>,
168 candidates: &mut SelectionCandidateSet<'tcx>,
169 ) {
170 match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
173 ty::Alias(ty::Projection | ty::Opaque, _) => {}
175 ty::Infer(ty::TyVar(_)) => {
176 span_bug!(
177 obligation.cause.span,
178 "Self=_ should have been handled by assemble_candidates"
179 );
180 }
181 _ => return,
182 }
183
184 self.infcx.probe(|_| {
185 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
186 let placeholder_trait_predicate =
187 self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
188
189 let mut distinct_normalized_bounds = FxHashSet::default();
193 let _ = self.for_each_item_bound::<!>(
194 placeholder_trait_predicate.self_ty(),
195 |selcx, bound, idx| {
196 let Some(bound) = bound.as_trait_clause() else {
197 return ControlFlow::Continue(());
198 };
199 if bound.polarity() != placeholder_trait_predicate.polarity {
200 return ControlFlow::Continue(());
201 }
202
203 selcx.infcx.probe(|_| {
204 match selcx.match_normalize_trait_ref(
206 obligation,
207 placeholder_trait_predicate.trait_ref,
208 bound.map_bound(|pred| pred.trait_ref),
209 ) {
210 Ok(None) => {
211 candidates.vec.push(ProjectionCandidate(idx));
212 }
213 Ok(Some(normalized_trait))
214 if distinct_normalized_bounds.insert(normalized_trait) =>
215 {
216 candidates.vec.push(ProjectionCandidate(idx));
217 }
218 _ => {}
219 }
220 });
221
222 ControlFlow::Continue(())
223 },
224 || candidates.ambiguous = true,
226 );
227 });
228 }
229
230 #[instrument(level = "debug", skip(self, stack, candidates))]
235 fn assemble_candidates_from_caller_bounds<'o>(
236 &mut self,
237 stack: &TraitObligationStack<'o, 'tcx>,
238 candidates: &mut SelectionCandidateSet<'tcx>,
239 ) -> Result<(), SelectionError<'tcx>> {
240 debug!(?stack.obligation);
241
242 let bounds = stack
243 .obligation
244 .param_env
245 .caller_bounds()
246 .iter()
247 .filter_map(|p| p.as_trait_clause())
248 .filter(|p| p.def_id() == stack.obligation.predicate.def_id())
250 .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
251
252 let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
253 let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
254 for bound in bounds {
256 let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
257 if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
258 continue;
259 }
260 let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
261 if wc.may_apply() {
262 candidates.vec.push(ParamCandidate(bound));
263 }
264 }
265
266 Ok(())
267 }
268
269 fn assemble_coroutine_candidates(
270 &mut self,
271 obligation: &PolyTraitObligation<'tcx>,
272 candidates: &mut SelectionCandidateSet<'tcx>,
273 ) {
274 let self_ty = obligation.self_ty().skip_binder();
278 match self_ty.kind() {
279 ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => {
282 debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
283
284 candidates.vec.push(CoroutineCandidate);
285 }
286 ty::Infer(ty::TyVar(_)) => {
287 debug!("assemble_coroutine_candidates: ambiguous self-type");
288 candidates.ambiguous = true;
289 }
290 _ => {}
291 }
292 }
293
294 fn assemble_future_candidates(
295 &mut self,
296 obligation: &PolyTraitObligation<'tcx>,
297 candidates: &mut SelectionCandidateSet<'tcx>,
298 ) {
299 let self_ty = obligation.self_ty().skip_binder();
300 if let ty::Coroutine(did, ..) = self_ty.kind() {
301 if self.tcx().coroutine_is_async(*did) {
304 debug!(?self_ty, ?obligation, "assemble_future_candidates",);
305
306 candidates.vec.push(FutureCandidate);
307 }
308 }
309 }
310
311 fn assemble_iterator_candidates(
312 &mut self,
313 obligation: &PolyTraitObligation<'tcx>,
314 candidates: &mut SelectionCandidateSet<'tcx>,
315 ) {
316 let self_ty = obligation.self_ty().skip_binder();
317 if let ty::Coroutine(did, ..) = self_ty.kind()
320 && self.tcx().coroutine_is_gen(*did)
321 {
322 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
323
324 candidates.vec.push(IteratorCandidate);
325 }
326 }
327
328 fn assemble_fused_iterator_candidates(
329 &mut self,
330 obligation: &PolyTraitObligation<'tcx>,
331 candidates: &mut SelectionCandidateSet<'tcx>,
332 ) {
333 let self_ty = obligation.self_ty().skip_binder();
334 if let ty::Coroutine(did, ..) = self_ty.kind()
337 && self.tcx().coroutine_is_gen(*did)
338 {
339 debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
340
341 candidates.vec.push(BuiltinCandidate { has_nested: false });
342 }
343 }
344
345 fn assemble_async_iterator_candidates(
346 &mut self,
347 obligation: &PolyTraitObligation<'tcx>,
348 candidates: &mut SelectionCandidateSet<'tcx>,
349 ) {
350 let self_ty = obligation.self_ty().skip_binder();
351 if let ty::Coroutine(did, args) = *self_ty.kind() {
352 if self.tcx().coroutine_is_async_gen(did) {
355 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
356
357 let ty::Adt(_poll_def, args) = *args.as_coroutine().yield_ty().kind() else {
360 candidates.ambiguous = true;
361 return;
362 };
363 let ty::Adt(_option_def, _) = *args.type_at(0).kind() else {
364 candidates.ambiguous = true;
365 return;
366 };
367
368 candidates.vec.push(AsyncIteratorCandidate);
369 }
370 }
371 }
372
373 fn assemble_closure_candidates(
380 &mut self,
381 obligation: &PolyTraitObligation<'tcx>,
382 candidates: &mut SelectionCandidateSet<'tcx>,
383 ) {
384 let kind = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
385
386 let self_ty = obligation.self_ty().skip_binder();
390 match *self_ty.kind() {
391 ty::Closure(def_id, _) => {
392 let is_const = self.tcx().is_const_fn(def_id);
393 debug!(?kind, ?obligation, "assemble_unboxed_candidates");
394 match self.infcx.closure_kind(self_ty) {
395 Some(closure_kind) => {
396 debug!(?closure_kind, "assemble_unboxed_candidates");
397 if closure_kind.extends(kind) {
398 candidates.vec.push(ClosureCandidate { is_const });
399 }
400 }
401 None => {
402 if kind == ty::ClosureKind::FnOnce {
403 candidates.vec.push(ClosureCandidate { is_const });
404 } else {
405 candidates.ambiguous = true;
406 }
407 }
408 }
409 }
410 ty::CoroutineClosure(def_id, args) => {
411 let args = args.as_coroutine_closure();
412 let is_const = self.tcx().is_const_fn(def_id);
413 if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
414 && !args.tupled_upvars_ty().is_ty_var()
416 {
417 if closure_kind.extends(kind) && !args.has_self_borrows() {
422 candidates.vec.push(ClosureCandidate { is_const });
423 } else if kind == ty::ClosureKind::FnOnce {
424 candidates.vec.push(ClosureCandidate { is_const });
425 }
426 } else if kind == ty::ClosureKind::FnOnce {
427 candidates.vec.push(ClosureCandidate { is_const });
428 } else {
429 candidates.ambiguous = true;
431 }
432 }
433 ty::Infer(ty::TyVar(_)) => {
434 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
435 candidates.ambiguous = true;
436 }
437 _ => {}
438 }
439 }
440
441 #[instrument(level = "debug", skip(self, candidates))]
442 fn assemble_async_closure_candidates(
443 &mut self,
444 obligation: &PolyTraitObligation<'tcx>,
445 candidates: &mut SelectionCandidateSet<'tcx>,
446 ) {
447 let goal_kind =
448 self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
449
450 debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind());
451 match *obligation.self_ty().skip_binder().kind() {
452 ty::CoroutineClosure(def_id, args) => {
453 if let Some(closure_kind) =
454 args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
455 && !closure_kind.extends(goal_kind)
456 {
457 return;
458 }
459
460 let Some(coroutine_kind) =
462 self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id))
463 else {
464 bug!("coroutine with no kind");
465 };
466
467 debug!(?coroutine_kind);
468 match coroutine_kind {
469 CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
470 candidates.vec.push(AsyncClosureCandidate);
471 }
472 _ => (),
473 }
474 }
475 ty::Closure(_, args) => {
478 if let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind()
479 && !closure_kind.extends(goal_kind)
480 {
481 return;
482 }
483 candidates.vec.push(AsyncClosureCandidate);
484 }
485 ty::FnPtr(sig_tys, hdr) => {
487 if sig_tys.with(hdr).is_fn_trait_compatible() {
488 candidates.vec.push(AsyncClosureCandidate);
489 }
490 }
491 ty::FnDef(def_id, _) => {
493 let tcx = self.tcx();
494 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
495 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
496 {
497 candidates.vec.push(AsyncClosureCandidate);
498 }
499 }
500 _ => {}
501 }
502 }
503
504 fn assemble_async_fn_kind_helper_candidates(
505 &mut self,
506 obligation: &PolyTraitObligation<'tcx>,
507 candidates: &mut SelectionCandidateSet<'tcx>,
508 ) {
509 let self_ty = obligation.self_ty().skip_binder();
510 let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
511
512 if !(self_ty.is_integral() || self_ty.is_ty_var()) {
514 return;
515 }
516 if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) {
517 return;
518 }
519
520 if let Some(closure_kind) = self_ty.to_opt_closure_kind()
523 && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
524 && closure_kind.extends(goal_kind)
525 {
526 candidates.vec.push(AsyncFnKindHelperCandidate);
527 }
528 }
529
530 fn assemble_fn_pointer_candidates(
532 &mut self,
533 obligation: &PolyTraitObligation<'tcx>,
534 candidates: &mut SelectionCandidateSet<'tcx>,
535 ) {
536 let self_ty = obligation.self_ty().skip_binder();
541 match *self_ty.kind() {
542 ty::Infer(ty::TyVar(_)) => {
543 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
544 candidates.ambiguous = true; }
546 ty::FnPtr(sig_tys, hdr) => {
548 if sig_tys.with(hdr).is_fn_trait_compatible() {
549 candidates.vec.push(FnPointerCandidate);
550 }
551 }
552 ty::FnDef(def_id, _) => {
554 let tcx = self.tcx();
555 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
556 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
557 {
558 candidates.vec.push(FnPointerCandidate);
559 }
560 }
561 _ => {}
562 }
563 }
564
565 #[instrument(level = "debug", skip(self, candidates))]
567 fn assemble_candidates_from_impls(
568 &mut self,
569 obligation: &PolyTraitObligation<'tcx>,
570 candidates: &mut SelectionCandidateSet<'tcx>,
571 ) {
572 let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
573 let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
574 self.tcx().for_each_relevant_impl(
575 obligation.predicate.def_id(),
576 obligation.predicate.skip_binder().trait_ref.self_ty(),
577 |impl_def_id| {
578 let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
582 if !drcx
583 .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
584 {
585 return;
586 }
587
588 if self.tcx().defaultness(impl_def_id).is_default() {
592 return;
593 }
594
595 if self.reject_fn_ptr_impls(
596 impl_def_id,
597 obligation,
598 impl_trait_header.trait_ref.skip_binder().self_ty(),
599 ) {
600 return;
601 }
602
603 self.infcx.probe(|_| {
604 if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_header, obligation) {
605 candidates.vec.push(ImplCandidate(impl_def_id));
606 }
607 });
608 },
609 );
610 }
611
612 #[instrument(level = "trace", skip(self), ret)]
617 fn reject_fn_ptr_impls(
618 &mut self,
619 impl_def_id: DefId,
620 obligation: &PolyTraitObligation<'tcx>,
621 impl_self_ty: Ty<'tcx>,
622 ) -> bool {
623 if !matches!(impl_self_ty.kind(), ty::Param(..)) {
625 return false;
626 }
627 let Some(fn_ptr_trait) = self.tcx().lang_items().fn_ptr_trait() else {
628 return false;
629 };
630
631 for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
632 let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
633 if fn_ptr_trait != pred.trait_ref.def_id {
634 continue;
635 }
636 trace!(?pred);
637 if pred.self_ty() != impl_self_ty {
639 continue;
640 }
641
642 let self_ty = obligation.self_ty().skip_binder();
643 match self_ty.kind() {
644 ty::FnPtr(..) => return false,
647
648 ty::Placeholder(..)
650 | ty::Dynamic(_, _, _)
651 | ty::Alias(_, _)
652 | ty::Infer(_)
653 | ty::Param(..)
654 | ty::Bound(_, _) => {}
655
656 ty::Bool
659 | ty::Char
660 | ty::Int(_)
661 | ty::Uint(_)
662 | ty::Float(_)
663 | ty::Adt(_, _)
664 | ty::Foreign(_)
665 | ty::Str
666 | ty::Array(_, _)
667 | ty::Pat(_, _)
668 | ty::Slice(_)
669 | ty::RawPtr(_, _)
670 | ty::Ref(_, _, _)
671 | ty::Closure(..)
672 | ty::CoroutineClosure(..)
673 | ty::Coroutine(_, _)
674 | ty::CoroutineWitness(..)
675 | ty::UnsafeBinder(_)
676 | ty::Never
677 | ty::Tuple(_)
678 | ty::Error(_) => return true,
679 ty::FnDef(_, _) => return true,
682 }
683
684 let obligation = Obligation::new(
687 self.tcx(),
688 obligation.cause.clone(),
689 obligation.param_env,
690 self.tcx().mk_predicate(obligation.predicate.map_bound(|mut pred| {
691 pred.trait_ref =
692 ty::TraitRef::new(self.tcx(), fn_ptr_trait, [pred.trait_ref.self_ty()]);
693 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
694 })),
695 );
696 if let Ok(r) = self.evaluate_root_obligation(&obligation) {
697 if !r.may_apply() {
698 return true;
699 }
700 }
701 }
702 false
703 }
704
705 fn assemble_candidates_from_auto_impls(
706 &mut self,
707 obligation: &PolyTraitObligation<'tcx>,
708 candidates: &mut SelectionCandidateSet<'tcx>,
709 ) {
710 let self_ty = obligation.self_ty().skip_binder();
712 debug!(?self_ty, "assemble_candidates_from_auto_impls");
713
714 let def_id = obligation.predicate.def_id();
715
716 let mut check_impls = || {
717 let mut has_impl = false;
727 self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
728 if !has_impl {
729 candidates.vec.push(AutoImplCandidate)
730 }
731 };
732
733 if self.tcx().trait_is_auto(def_id) {
734 match *self_ty.kind() {
735 ty::Dynamic(..) => {
736 }
741 ty::Foreign(..) => {
742 if self.tcx().is_default_trait(def_id) {
750 check_impls()
751 }
752 }
753 ty::Param(..)
754 | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
755 | ty::Placeholder(..)
756 | ty::Bound(..) => {
757 }
771 ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
772 candidates.ambiguous = true;
774 }
775 ty::Coroutine(coroutine_def_id, _)
776 if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
777 {
778 match self.tcx().coroutine_movability(coroutine_def_id) {
779 hir::Movability::Static => {
780 }
783 hir::Movability::Movable => {
784 candidates.vec.push(BuiltinCandidate { has_nested: false });
787 }
788 }
789 }
790
791 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
792 bug!(
793 "asked to assemble auto trait candidates of unexpected type: {:?}",
794 self_ty
795 );
796 }
797
798 ty::Alias(ty::Opaque, alias) => {
799 if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
800 } else if let TypingMode::Coherence = self.infcx.typing_mode() {
810 candidates.ambiguous = true;
813 } else if self.infcx.can_define_opaque_ty(alias.def_id) {
814 candidates.ambiguous = true;
818 } else {
819 candidates.vec.push(AutoImplCandidate)
820 }
821 }
822
823 ty::Bool
824 | ty::Char
825 | ty::Int(_)
826 | ty::Uint(_)
827 | ty::Float(_)
828 | ty::Str
829 | ty::Array(_, _)
830 | ty::Pat(_, _)
831 | ty::Slice(_)
832 | ty::Adt(..)
833 | ty::RawPtr(_, _)
834 | ty::Ref(..)
835 | ty::FnDef(..)
836 | ty::FnPtr(..)
837 | ty::Closure(..)
838 | ty::CoroutineClosure(..)
839 | ty::Coroutine(..)
840 | ty::Never
841 | ty::Tuple(_)
842 | ty::CoroutineWitness(..)
843 | ty::UnsafeBinder(_) => {
844 if self.tcx().trait_def(def_id).safety.is_unsafe()
847 && self_ty.has_unsafe_fields()
848 {
849 return;
850 }
851
852 check_impls();
853 }
854 ty::Error(_) => {
855 candidates.vec.push(AutoImplCandidate);
856 }
857 }
858 }
859 }
860
861 fn assemble_candidates_from_object_ty(
863 &mut self,
864 obligation: &PolyTraitObligation<'tcx>,
865 candidates: &mut SelectionCandidateSet<'tcx>,
866 ) {
867 debug!(
868 self_ty = ?obligation.self_ty().skip_binder(),
869 "assemble_candidates_from_object_ty",
870 );
871
872 if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
873 return;
874 }
875
876 self.infcx.probe(|_snapshot| {
877 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
878 self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
879 let self_ty = placeholder_trait_predicate.self_ty();
880 let principal_trait_ref = match self_ty.kind() {
881 ty::Dynamic(data, ..) => {
882 if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
883 debug!(
884 "assemble_candidates_from_object_ty: matched builtin bound, \
885 pushing candidate"
886 );
887 candidates.vec.push(BuiltinObjectCandidate);
888 return;
889 }
890
891 if let Some(principal) = data.principal() {
892 principal.with_self_ty(self.tcx(), self_ty)
893 } else {
894 return;
896 }
897 }
898 ty::Infer(ty::TyVar(_)) => {
899 debug!("assemble_candidates_from_object_ty: ambiguous");
900 candidates.ambiguous = true; return;
902 }
903 _ => return,
904 };
905
906 debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
907
908 let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
914 .enumerate()
915 .filter(|&(_, upcast_trait_ref)| {
916 self.infcx.probe(|_| {
917 self.match_normalize_trait_ref(
918 obligation,
919 placeholder_trait_predicate.trait_ref,
920 upcast_trait_ref,
921 )
922 .is_ok()
923 })
924 })
925 .map(|(idx, _)| ObjectCandidate(idx));
926
927 candidates.vec.extend(candidate_supertraits);
928 })
929 })
930 }
931
932 fn assemble_candidates_for_unsizing(
934 &mut self,
935 obligation: &PolyTraitObligation<'tcx>,
936 candidates: &mut SelectionCandidateSet<'tcx>,
937 ) {
938 let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
953 return;
955 };
956 let source = trait_pred.self_ty();
957 let target = trait_pred.trait_ref.args.type_at(1);
958
959 debug!(?source, ?target, "assemble_candidates_for_unsizing");
960
961 match (source.kind(), target.kind()) {
962 (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => {
964 let principal_def_id_a = a_data.principal_def_id();
976 let principal_def_id_b = b_data.principal_def_id();
977 if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
978 let a_auto_traits: FxIndexSet<DefId> = a_data
982 .auto_traits()
983 .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
984 elaborate::supertrait_def_ids(self.tcx(), principal_def_id)
985 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
986 }))
987 .collect();
988 let auto_traits_compatible = b_data
989 .auto_traits()
990 .all(|b| a_auto_traits.contains(&b));
992 if auto_traits_compatible {
993 candidates.vec.push(BuiltinUnsizeCandidate);
994 }
995 } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
996 let principal_a = a_data.principal().unwrap();
998 let target_trait_did = principal_def_id_b.unwrap();
999 let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
1000
1001 for (idx, upcast_trait_ref) in
1002 util::supertraits(self.tcx(), source_trait_ref).enumerate()
1003 {
1004 self.infcx.probe(|_| {
1005 if upcast_trait_ref.def_id() == target_trait_did
1006 && let Ok(nested) = self.match_upcast_principal(
1007 obligation,
1008 upcast_trait_ref,
1009 a_data,
1010 b_data,
1011 a_region,
1012 b_region,
1013 )
1014 {
1015 if nested.is_none() {
1016 candidates.ambiguous = true;
1017 }
1018 candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
1019 }
1020 })
1021 }
1022 }
1023 }
1024
1025 (_, &ty::Dynamic(_, _, ty::Dyn)) => {
1027 candidates.vec.push(BuiltinUnsizeCandidate);
1028 }
1029
1030 (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
1034 debug!("assemble_candidates_for_unsizing: ambiguous");
1035 candidates.ambiguous = true;
1036 }
1037
1038 (&ty::Array(..), &ty::Slice(_)) => {
1040 candidates.vec.push(BuiltinUnsizeCandidate);
1041 }
1042
1043 (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
1045 if def_id_a == def_id_b {
1046 candidates.vec.push(BuiltinUnsizeCandidate);
1047 }
1048 }
1049
1050 _ => {}
1051 };
1052 }
1053
1054 #[instrument(level = "debug", skip(self, obligation, candidates))]
1055 fn assemble_candidates_for_transmutability(
1056 &mut self,
1057 obligation: &PolyTraitObligation<'tcx>,
1058 candidates: &mut SelectionCandidateSet<'tcx>,
1059 ) {
1060 if obligation.predicate.has_non_region_param() {
1061 return;
1062 }
1063
1064 if obligation.has_non_region_infer() {
1065 candidates.ambiguous = true;
1066 return;
1067 }
1068
1069 candidates.vec.push(TransmutabilityCandidate);
1070 }
1071
1072 #[instrument(level = "debug", skip(self, obligation, candidates))]
1073 fn assemble_candidates_for_trait_alias(
1074 &mut self,
1075 obligation: &PolyTraitObligation<'tcx>,
1076 candidates: &mut SelectionCandidateSet<'tcx>,
1077 ) {
1078 let self_ty = obligation.self_ty().skip_binder();
1080 debug!(?self_ty);
1081
1082 let def_id = obligation.predicate.def_id();
1083
1084 if self.tcx().is_trait_alias(def_id) {
1085 candidates.vec.push(TraitAliasCandidate);
1086 }
1087 }
1088
1089 #[instrument(level = "debug", skip(self, candidates))]
1092 fn assemble_builtin_sized_candidate(
1093 &mut self,
1094 obligation: &PolyTraitObligation<'tcx>,
1095 candidates: &mut SelectionCandidateSet<'tcx>,
1096 ) {
1097 match self.sized_conditions(obligation) {
1098 BuiltinImplConditions::Where(nested) => {
1099 candidates
1100 .vec
1101 .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
1102 }
1103 BuiltinImplConditions::None => {}
1104 BuiltinImplConditions::Ambiguous => {
1105 candidates.ambiguous = true;
1106 }
1107 }
1108 }
1109
1110 #[instrument(level = "debug", skip(self, candidates))]
1113 fn assemble_builtin_bound_candidates(
1114 &mut self,
1115 conditions: BuiltinImplConditions<'tcx>,
1116 candidates: &mut SelectionCandidateSet<'tcx>,
1117 ) {
1118 match conditions {
1119 BuiltinImplConditions::Where(nested) => {
1120 candidates
1121 .vec
1122 .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
1123 }
1124 BuiltinImplConditions::None => {}
1125 BuiltinImplConditions::Ambiguous => {
1126 candidates.ambiguous = true;
1127 }
1128 }
1129 }
1130
1131 fn assemble_const_destruct_candidates(
1132 &mut self,
1133 _obligation: &PolyTraitObligation<'tcx>,
1134 candidates: &mut SelectionCandidateSet<'tcx>,
1135 ) {
1136 candidates.vec.push(BuiltinCandidate { has_nested: false });
1137 }
1138
1139 fn assemble_candidate_for_tuple(
1140 &mut self,
1141 obligation: &PolyTraitObligation<'tcx>,
1142 candidates: &mut SelectionCandidateSet<'tcx>,
1143 ) {
1144 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1145 match self_ty.kind() {
1146 ty::Tuple(_) => {
1147 candidates.vec.push(BuiltinCandidate { has_nested: false });
1148 }
1149 ty::Infer(ty::TyVar(_)) => {
1150 candidates.ambiguous = true;
1151 }
1152 ty::Bool
1153 | ty::Char
1154 | ty::Int(_)
1155 | ty::Uint(_)
1156 | ty::Float(_)
1157 | ty::Adt(_, _)
1158 | ty::Foreign(_)
1159 | ty::Str
1160 | ty::Array(_, _)
1161 | ty::Slice(_)
1162 | ty::RawPtr(_, _)
1163 | ty::Ref(_, _, _)
1164 | ty::FnDef(_, _)
1165 | ty::Pat(_, _)
1166 | ty::FnPtr(..)
1167 | ty::UnsafeBinder(_)
1168 | ty::Dynamic(_, _, _)
1169 | ty::Closure(..)
1170 | ty::CoroutineClosure(..)
1171 | ty::Coroutine(_, _)
1172 | ty::CoroutineWitness(..)
1173 | ty::Never
1174 | ty::Alias(..)
1175 | ty::Param(_)
1176 | ty::Bound(_, _)
1177 | ty::Error(_)
1178 | ty::Infer(_)
1179 | ty::Placeholder(_) => {}
1180 }
1181 }
1182
1183 fn assemble_candidates_for_fn_ptr_trait(
1184 &mut self,
1185 obligation: &PolyTraitObligation<'tcx>,
1186 candidates: &mut SelectionCandidateSet<'tcx>,
1187 ) {
1188 let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
1189
1190 match self_ty.skip_binder().kind() {
1191 ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
1192 ty::Bool
1193 | ty::Char
1194 | ty::Int(_)
1195 | ty::Uint(_)
1196 | ty::Float(_)
1197 | ty::Adt(..)
1198 | ty::Foreign(..)
1199 | ty::Str
1200 | ty::Array(..)
1201 | ty::Pat(..)
1202 | ty::Slice(_)
1203 | ty::RawPtr(_, _)
1204 | ty::Ref(..)
1205 | ty::FnDef(..)
1206 | ty::Placeholder(..)
1207 | ty::Dynamic(..)
1208 | ty::Closure(..)
1209 | ty::CoroutineClosure(..)
1210 | ty::Coroutine(..)
1211 | ty::CoroutineWitness(..)
1212 | ty::UnsafeBinder(_)
1213 | ty::Never
1214 | ty::Tuple(..)
1215 | ty::Alias(..)
1216 | ty::Param(..)
1217 | ty::Bound(..)
1218 | ty::Error(_)
1219 | ty::Infer(
1220 ty::InferTy::IntVar(_)
1221 | ty::InferTy::FloatVar(_)
1222 | ty::InferTy::FreshIntTy(_)
1223 | ty::InferTy::FreshFloatTy(_),
1224 ) => {}
1225 ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
1226 candidates.ambiguous = true;
1227 }
1228 }
1229 }
1230
1231 fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
1232 &mut self,
1233 obligation: &PolyTraitObligation<'tcx>,
1234 candidates: &mut SelectionCandidateSet<'tcx>,
1235 ) {
1236 match obligation.predicate.self_ty().skip_binder().kind() {
1237 ty::Ref(..)
1238 | ty::Adt(..)
1239 | ty::Tuple(_)
1240 | ty::Array(..)
1241 | ty::FnDef(..)
1242 | ty::FnPtr(..)
1243 | ty::Error(_)
1244 | ty::Uint(_)
1245 | ty::Int(_)
1246 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1247 | ty::Bool
1248 | ty::Float(_)
1249 | ty::Char
1250 | ty::RawPtr(..)
1251 | ty::Never
1252 | ty::Pat(..)
1253 | ty::Dynamic(..)
1254 | ty::Str
1255 | ty::Slice(_)
1256 | ty::Foreign(..)
1257 | ty::Alias(..)
1258 | ty::Param(_)
1259 | ty::Placeholder(..)
1260 | ty::Closure(..)
1261 | ty::CoroutineClosure(..)
1262 | ty::Coroutine(..)
1263 | ty::UnsafeBinder(_)
1264 | ty::CoroutineWitness(..)
1265 | ty::Bound(..) => {
1266 candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
1267 }
1268
1269 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1270 candidates.ambiguous = true;
1271 }
1272 }
1273 }
1274}