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, SizedTraitKind, 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(
91 obligation,
92 &mut candidates,
93 SizedTraitKind::Sized,
94 );
95 }
96 Some(LangItem::MetaSized) => {
97 self.assemble_builtin_sized_candidate(
98 obligation,
99 &mut candidates,
100 SizedTraitKind::MetaSized,
101 );
102 }
103 Some(LangItem::PointeeSized) => {
104 bug!("`PointeeSized` is removed during lowering");
105 }
106 Some(LangItem::Unsize) => {
107 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
108 }
109 Some(LangItem::Destruct) => {
110 self.assemble_const_destruct_candidates(obligation, &mut candidates);
111 }
112 Some(LangItem::TransmuteTrait) => {
113 self.assemble_candidates_from_impls(obligation, &mut candidates);
115 self.assemble_candidates_for_transmutability(obligation, &mut candidates);
116 }
117 Some(LangItem::Tuple) => {
118 self.assemble_candidate_for_tuple(obligation, &mut candidates);
119 }
120 Some(LangItem::FnPtrTrait) => {
121 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
122 }
123 Some(LangItem::BikeshedGuaranteedNoDrop) => {
124 self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
125 obligation,
126 &mut candidates,
127 );
128 }
129 _ => {
130 match lang_item {
134 Some(LangItem::Coroutine) => {
135 self.assemble_coroutine_candidates(obligation, &mut candidates);
136 }
137 Some(LangItem::Future) => {
138 self.assemble_future_candidates(obligation, &mut candidates);
139 }
140 Some(LangItem::Iterator) => {
141 self.assemble_iterator_candidates(obligation, &mut candidates);
142 }
143 Some(LangItem::FusedIterator) => {
144 self.assemble_fused_iterator_candidates(obligation, &mut candidates);
145 }
146 Some(LangItem::AsyncIterator) => {
147 self.assemble_async_iterator_candidates(obligation, &mut candidates);
148 }
149 Some(LangItem::AsyncFnKindHelper) => {
150 self.assemble_async_fn_kind_helper_candidates(
151 obligation,
152 &mut candidates,
153 );
154 }
155 Some(LangItem::AsyncFn | LangItem::AsyncFnMut | LangItem::AsyncFnOnce) => {
156 self.assemble_async_closure_candidates(obligation, &mut candidates);
157 }
158 Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
159 self.assemble_closure_candidates(obligation, &mut candidates);
160 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
161 }
162 _ => {}
163 }
164
165 self.assemble_candidates_from_impls(obligation, &mut candidates);
166 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
167 }
168 }
169
170 self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
171 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
172 self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
173 }
174 debug!("candidate list size: {}", candidates.vec.len());
175 Ok(candidates)
176 }
177
178 #[instrument(level = "debug", skip(self, candidates))]
179 fn assemble_candidates_from_projected_tys(
180 &mut self,
181 obligation: &PolyTraitObligation<'tcx>,
182 candidates: &mut SelectionCandidateSet<'tcx>,
183 ) {
184 match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
187 ty::Alias(ty::Projection | ty::Opaque, _) => {}
189 ty::Infer(ty::TyVar(_)) => {
190 span_bug!(
191 obligation.cause.span,
192 "Self=_ should have been handled by assemble_candidates"
193 );
194 }
195 _ => return,
196 }
197
198 self.infcx.probe(|_| {
199 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
200 let placeholder_trait_predicate =
201 self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
202
203 let mut distinct_normalized_bounds = FxHashSet::default();
207 let _ = self.for_each_item_bound::<!>(
208 placeholder_trait_predicate.self_ty(),
209 |selcx, bound, idx| {
210 let Some(bound) = bound.as_trait_clause() else {
211 return ControlFlow::Continue(());
212 };
213 if bound.polarity() != placeholder_trait_predicate.polarity {
214 return ControlFlow::Continue(());
215 }
216
217 selcx.infcx.probe(|_| {
218 let bound = util::lazily_elaborate_sizedness_candidate(
219 selcx.infcx,
220 obligation,
221 bound,
222 );
223
224 match selcx.match_normalize_trait_ref(
226 obligation,
227 placeholder_trait_predicate.trait_ref,
228 bound.map_bound(|pred| pred.trait_ref),
229 ) {
230 Ok(None) => {
231 candidates.vec.push(ProjectionCandidate(idx));
232 }
233 Ok(Some(normalized_trait))
234 if distinct_normalized_bounds.insert(normalized_trait) =>
235 {
236 candidates.vec.push(ProjectionCandidate(idx));
237 }
238 _ => {}
239 }
240 });
241
242 ControlFlow::Continue(())
243 },
244 || candidates.ambiguous = true,
246 );
247 });
248 }
249
250 #[instrument(level = "debug", skip(self, stack, candidates))]
255 fn assemble_candidates_from_caller_bounds<'o>(
256 &mut self,
257 stack: &TraitObligationStack<'o, 'tcx>,
258 candidates: &mut SelectionCandidateSet<'tcx>,
259 ) -> Result<(), SelectionError<'tcx>> {
260 debug!(?stack.obligation);
261
262 let bounds = stack
263 .obligation
264 .param_env
265 .caller_bounds()
266 .iter()
267 .filter_map(|p| p.as_trait_clause())
268 .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
270
271 let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
272 let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
273 for bound in bounds {
275 let bound =
276 util::lazily_elaborate_sizedness_candidate(self.infcx, stack.obligation, bound);
277
278 if bound.def_id() != stack.obligation.predicate.def_id() {
280 continue;
281 }
282
283 let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
284 if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
285 continue;
286 }
287 let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
288 if wc.may_apply() {
289 candidates.vec.push(ParamCandidate(bound));
290 }
291 }
292
293 Ok(())
294 }
295
296 fn assemble_coroutine_candidates(
297 &mut self,
298 obligation: &PolyTraitObligation<'tcx>,
299 candidates: &mut SelectionCandidateSet<'tcx>,
300 ) {
301 let self_ty = obligation.self_ty().skip_binder();
305 match self_ty.kind() {
306 ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => {
309 debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
310
311 candidates.vec.push(CoroutineCandidate);
312 }
313 ty::Infer(ty::TyVar(_)) => {
314 debug!("assemble_coroutine_candidates: ambiguous self-type");
315 candidates.ambiguous = true;
316 }
317 _ => {}
318 }
319 }
320
321 fn assemble_future_candidates(
322 &mut self,
323 obligation: &PolyTraitObligation<'tcx>,
324 candidates: &mut SelectionCandidateSet<'tcx>,
325 ) {
326 let self_ty = obligation.self_ty().skip_binder();
327 if let ty::Coroutine(did, ..) = self_ty.kind() {
328 if self.tcx().coroutine_is_async(*did) {
331 debug!(?self_ty, ?obligation, "assemble_future_candidates",);
332
333 candidates.vec.push(FutureCandidate);
334 }
335 }
336 }
337
338 fn assemble_iterator_candidates(
339 &mut self,
340 obligation: &PolyTraitObligation<'tcx>,
341 candidates: &mut SelectionCandidateSet<'tcx>,
342 ) {
343 let self_ty = obligation.self_ty().skip_binder();
344 if let ty::Coroutine(did, ..) = self_ty.kind()
347 && self.tcx().coroutine_is_gen(*did)
348 {
349 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
350
351 candidates.vec.push(IteratorCandidate);
352 }
353 }
354
355 fn assemble_fused_iterator_candidates(
356 &mut self,
357 obligation: &PolyTraitObligation<'tcx>,
358 candidates: &mut SelectionCandidateSet<'tcx>,
359 ) {
360 let self_ty = obligation.self_ty().skip_binder();
361 if let ty::Coroutine(did, ..) = self_ty.kind()
364 && self.tcx().coroutine_is_gen(*did)
365 {
366 debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
367
368 candidates.vec.push(BuiltinCandidate { has_nested: false });
369 }
370 }
371
372 fn assemble_async_iterator_candidates(
373 &mut self,
374 obligation: &PolyTraitObligation<'tcx>,
375 candidates: &mut SelectionCandidateSet<'tcx>,
376 ) {
377 let self_ty = obligation.self_ty().skip_binder();
378 if let ty::Coroutine(did, args) = *self_ty.kind() {
379 if self.tcx().coroutine_is_async_gen(did) {
382 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
383
384 let ty::Adt(_poll_def, args) = *args.as_coroutine().yield_ty().kind() else {
387 candidates.ambiguous = true;
388 return;
389 };
390 let ty::Adt(_option_def, _) = *args.type_at(0).kind() else {
391 candidates.ambiguous = true;
392 return;
393 };
394
395 candidates.vec.push(AsyncIteratorCandidate);
396 }
397 }
398 }
399
400 fn assemble_closure_candidates(
407 &mut self,
408 obligation: &PolyTraitObligation<'tcx>,
409 candidates: &mut SelectionCandidateSet<'tcx>,
410 ) {
411 let kind = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
412
413 let self_ty = obligation.self_ty().skip_binder();
417 match *self_ty.kind() {
418 ty::Closure(def_id, _) => {
419 let is_const = self.tcx().is_const_fn(def_id);
420 debug!(?kind, ?obligation, "assemble_unboxed_candidates");
421 match self.infcx.closure_kind(self_ty) {
422 Some(closure_kind) => {
423 debug!(?closure_kind, "assemble_unboxed_candidates");
424 if closure_kind.extends(kind) {
425 candidates.vec.push(ClosureCandidate { is_const });
426 }
427 }
428 None => {
429 if kind == ty::ClosureKind::FnOnce {
430 candidates.vec.push(ClosureCandidate { is_const });
431 } else {
432 candidates.ambiguous = true;
433 }
434 }
435 }
436 }
437 ty::CoroutineClosure(def_id, args) => {
438 let args = args.as_coroutine_closure();
439 let is_const = self.tcx().is_const_fn(def_id);
440 if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
441 && !args.tupled_upvars_ty().is_ty_var()
443 {
444 if closure_kind.extends(kind) && !args.has_self_borrows() {
449 candidates.vec.push(ClosureCandidate { is_const });
450 } else if kind == ty::ClosureKind::FnOnce {
451 candidates.vec.push(ClosureCandidate { is_const });
452 }
453 } else if kind == ty::ClosureKind::FnOnce {
454 candidates.vec.push(ClosureCandidate { is_const });
455 } else {
456 candidates.ambiguous = true;
458 }
459 }
460 ty::Infer(ty::TyVar(_)) => {
461 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
462 candidates.ambiguous = true;
463 }
464 _ => {}
465 }
466 }
467
468 #[instrument(level = "debug", skip(self, candidates))]
469 fn assemble_async_closure_candidates(
470 &mut self,
471 obligation: &PolyTraitObligation<'tcx>,
472 candidates: &mut SelectionCandidateSet<'tcx>,
473 ) {
474 let goal_kind =
475 self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
476
477 debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind());
478 match *obligation.self_ty().skip_binder().kind() {
479 ty::CoroutineClosure(def_id, args) => {
480 if let Some(closure_kind) =
481 args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
482 && !closure_kind.extends(goal_kind)
483 {
484 return;
485 }
486
487 let Some(coroutine_kind) =
489 self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id))
490 else {
491 bug!("coroutine with no kind");
492 };
493
494 debug!(?coroutine_kind);
495 match coroutine_kind {
496 CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
497 candidates.vec.push(AsyncClosureCandidate);
498 }
499 _ => (),
500 }
501 }
502 ty::Closure(_, args) => {
505 if let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind()
506 && !closure_kind.extends(goal_kind)
507 {
508 return;
509 }
510 candidates.vec.push(AsyncClosureCandidate);
511 }
512 ty::FnPtr(sig_tys, hdr) => {
514 if sig_tys.with(hdr).is_fn_trait_compatible() {
515 candidates.vec.push(AsyncClosureCandidate);
516 }
517 }
518 ty::FnDef(def_id, _) => {
520 let tcx = self.tcx();
521 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
522 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
523 {
524 candidates.vec.push(AsyncClosureCandidate);
525 }
526 }
527 _ => {}
528 }
529 }
530
531 fn assemble_async_fn_kind_helper_candidates(
532 &mut self,
533 obligation: &PolyTraitObligation<'tcx>,
534 candidates: &mut SelectionCandidateSet<'tcx>,
535 ) {
536 let self_ty = obligation.self_ty().skip_binder();
537 let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
538
539 if !(self_ty.is_integral() || self_ty.is_ty_var()) {
541 return;
542 }
543 if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) {
544 return;
545 }
546
547 if let Some(closure_kind) = self_ty.to_opt_closure_kind()
550 && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
551 && closure_kind.extends(goal_kind)
552 {
553 candidates.vec.push(AsyncFnKindHelperCandidate);
554 }
555 }
556
557 fn assemble_fn_pointer_candidates(
559 &mut self,
560 obligation: &PolyTraitObligation<'tcx>,
561 candidates: &mut SelectionCandidateSet<'tcx>,
562 ) {
563 let self_ty = obligation.self_ty().skip_binder();
568 match *self_ty.kind() {
569 ty::Infer(ty::TyVar(_)) => {
570 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
571 candidates.ambiguous = true; }
573 ty::FnPtr(sig_tys, hdr) => {
575 if sig_tys.with(hdr).is_fn_trait_compatible() {
576 candidates.vec.push(FnPointerCandidate);
577 }
578 }
579 ty::FnDef(def_id, _) => {
581 let tcx = self.tcx();
582 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
583 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
584 {
585 candidates.vec.push(FnPointerCandidate);
586 }
587 }
588 _ => {}
589 }
590 }
591
592 #[instrument(level = "debug", skip(self, candidates))]
594 fn assemble_candidates_from_impls(
595 &mut self,
596 obligation: &PolyTraitObligation<'tcx>,
597 candidates: &mut SelectionCandidateSet<'tcx>,
598 ) {
599 let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
600 let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
601 self.tcx().for_each_relevant_impl(
602 obligation.predicate.def_id(),
603 obligation.predicate.skip_binder().trait_ref.self_ty(),
604 |impl_def_id| {
605 let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
609 if !drcx
610 .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
611 {
612 return;
613 }
614
615 if self.tcx().defaultness(impl_def_id).is_default() {
619 return;
620 }
621
622 if self.reject_fn_ptr_impls(
623 impl_def_id,
624 obligation,
625 impl_trait_header.trait_ref.skip_binder().self_ty(),
626 ) {
627 return;
628 }
629
630 self.infcx.probe(|_| {
631 if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_header, obligation) {
632 candidates.vec.push(ImplCandidate(impl_def_id));
633 }
634 });
635 },
636 );
637 }
638
639 #[instrument(level = "trace", skip(self), ret)]
644 fn reject_fn_ptr_impls(
645 &mut self,
646 impl_def_id: DefId,
647 obligation: &PolyTraitObligation<'tcx>,
648 impl_self_ty: Ty<'tcx>,
649 ) -> bool {
650 if !matches!(impl_self_ty.kind(), ty::Param(..)) {
652 return false;
653 }
654 let Some(fn_ptr_trait) = self.tcx().lang_items().fn_ptr_trait() else {
655 return false;
656 };
657
658 for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
659 let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
660 if fn_ptr_trait != pred.trait_ref.def_id {
661 continue;
662 }
663 trace!(?pred);
664 if pred.self_ty() != impl_self_ty {
666 continue;
667 }
668
669 let self_ty = obligation.self_ty().skip_binder();
670 match self_ty.kind() {
671 ty::FnPtr(..) => return false,
674
675 ty::Placeholder(..)
677 | ty::Dynamic(_, _, _)
678 | ty::Alias(_, _)
679 | ty::Infer(_)
680 | ty::Param(..)
681 | ty::Bound(_, _) => {}
682
683 ty::Bool
686 | ty::Char
687 | ty::Int(_)
688 | ty::Uint(_)
689 | ty::Float(_)
690 | ty::Adt(_, _)
691 | ty::Foreign(_)
692 | ty::Str
693 | ty::Array(_, _)
694 | ty::Pat(_, _)
695 | ty::Slice(_)
696 | ty::RawPtr(_, _)
697 | ty::Ref(_, _, _)
698 | ty::Closure(..)
699 | ty::CoroutineClosure(..)
700 | ty::Coroutine(_, _)
701 | ty::CoroutineWitness(..)
702 | ty::UnsafeBinder(_)
703 | ty::Never
704 | ty::Tuple(_)
705 | ty::Error(_) => return true,
706 ty::FnDef(_, _) => return true,
709 }
710
711 let obligation = Obligation::new(
714 self.tcx(),
715 obligation.cause.clone(),
716 obligation.param_env,
717 self.tcx().mk_predicate(obligation.predicate.map_bound(|mut pred| {
718 pred.trait_ref =
719 ty::TraitRef::new(self.tcx(), fn_ptr_trait, [pred.trait_ref.self_ty()]);
720 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
721 })),
722 );
723 if let Ok(r) = self.evaluate_root_obligation(&obligation) {
724 if !r.may_apply() {
725 return true;
726 }
727 }
728 }
729 false
730 }
731
732 fn assemble_candidates_from_auto_impls(
733 &mut self,
734 obligation: &PolyTraitObligation<'tcx>,
735 candidates: &mut SelectionCandidateSet<'tcx>,
736 ) {
737 let self_ty = obligation.self_ty().skip_binder();
739 debug!(?self_ty, "assemble_candidates_from_auto_impls");
740
741 let def_id = obligation.predicate.def_id();
742
743 let mut check_impls = || {
744 let mut has_impl = false;
754 self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
755 if !has_impl {
756 candidates.vec.push(AutoImplCandidate)
757 }
758 };
759
760 if self.tcx().trait_is_auto(def_id) {
761 match *self_ty.kind() {
762 ty::Dynamic(..) => {
763 }
768 ty::Foreign(..) => {
769 if self.tcx().is_default_trait(def_id) {
777 check_impls()
778 }
779 }
780 ty::Param(..)
781 | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
782 | ty::Placeholder(..)
783 | ty::Bound(..) => {
784 }
798 ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
799 candidates.ambiguous = true;
801 }
802 ty::Coroutine(coroutine_def_id, _)
803 if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
804 {
805 match self.tcx().coroutine_movability(coroutine_def_id) {
806 hir::Movability::Static => {
807 }
810 hir::Movability::Movable => {
811 candidates.vec.push(BuiltinCandidate { has_nested: false });
814 }
815 }
816 }
817
818 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
819 bug!(
820 "asked to assemble auto trait candidates of unexpected type: {:?}",
821 self_ty
822 );
823 }
824
825 ty::Alias(ty::Opaque, alias) => {
826 if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
827 } else if let TypingMode::Coherence = self.infcx.typing_mode() {
837 candidates.ambiguous = true;
840 } else if self.infcx.can_define_opaque_ty(alias.def_id) {
841 candidates.ambiguous = true;
845 } else {
846 candidates.vec.push(AutoImplCandidate)
847 }
848 }
849
850 ty::Bool
851 | ty::Char
852 | ty::Int(_)
853 | ty::Uint(_)
854 | ty::Float(_)
855 | ty::Str
856 | ty::Array(_, _)
857 | ty::Pat(_, _)
858 | ty::Slice(_)
859 | ty::Adt(..)
860 | ty::RawPtr(_, _)
861 | ty::Ref(..)
862 | ty::FnDef(..)
863 | ty::FnPtr(..)
864 | ty::Closure(..)
865 | ty::CoroutineClosure(..)
866 | ty::Coroutine(..)
867 | ty::Never
868 | ty::Tuple(_)
869 | ty::CoroutineWitness(..)
870 | ty::UnsafeBinder(_) => {
871 if self.tcx().trait_def(def_id).safety.is_unsafe()
874 && self_ty.has_unsafe_fields()
875 {
876 return;
877 }
878
879 check_impls();
880 }
881 ty::Error(_) => {
882 candidates.vec.push(AutoImplCandidate);
883 }
884 }
885 }
886 }
887
888 fn assemble_candidates_from_object_ty(
890 &mut self,
891 obligation: &PolyTraitObligation<'tcx>,
892 candidates: &mut SelectionCandidateSet<'tcx>,
893 ) {
894 debug!(
895 self_ty = ?obligation.self_ty().skip_binder(),
896 "assemble_candidates_from_object_ty",
897 );
898
899 if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
900 return;
901 }
902
903 self.infcx.probe(|_snapshot| {
904 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
905 self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
906 let self_ty = placeholder_trait_predicate.self_ty();
907 let principal_trait_ref = match self_ty.kind() {
908 ty::Dynamic(data, ..) => {
909 if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
910 debug!(
911 "assemble_candidates_from_object_ty: matched builtin bound, \
912 pushing candidate"
913 );
914 candidates.vec.push(BuiltinObjectCandidate);
915 return;
916 }
917
918 if let Some(principal) = data.principal() {
919 principal.with_self_ty(self.tcx(), self_ty)
920 } else {
921 return;
923 }
924 }
925 ty::Infer(ty::TyVar(_)) => {
926 debug!("assemble_candidates_from_object_ty: ambiguous");
927 candidates.ambiguous = true; return;
929 }
930 _ => return,
931 };
932
933 debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
934
935 let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
941 .enumerate()
942 .filter(|&(_, upcast_trait_ref)| {
943 self.infcx.probe(|_| {
944 self.match_normalize_trait_ref(
945 obligation,
946 placeholder_trait_predicate.trait_ref,
947 upcast_trait_ref,
948 )
949 .is_ok()
950 })
951 })
952 .map(|(idx, _)| ObjectCandidate(idx));
953
954 candidates.vec.extend(candidate_supertraits);
955 })
956 })
957 }
958
959 fn assemble_candidates_for_unsizing(
961 &mut self,
962 obligation: &PolyTraitObligation<'tcx>,
963 candidates: &mut SelectionCandidateSet<'tcx>,
964 ) {
965 let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
980 return;
982 };
983 let source = trait_pred.self_ty();
984 let target = trait_pred.trait_ref.args.type_at(1);
985
986 debug!(?source, ?target, "assemble_candidates_for_unsizing");
987
988 match (source.kind(), target.kind()) {
989 (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => {
991 let principal_def_id_a = a_data.principal_def_id();
1003 let principal_def_id_b = b_data.principal_def_id();
1004 if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
1005 let a_auto_traits: FxIndexSet<DefId> = a_data
1009 .auto_traits()
1010 .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
1011 elaborate::supertrait_def_ids(self.tcx(), principal_def_id)
1012 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
1013 }))
1014 .collect();
1015 let auto_traits_compatible = b_data
1016 .auto_traits()
1017 .all(|b| a_auto_traits.contains(&b));
1019 if auto_traits_compatible {
1020 candidates.vec.push(BuiltinUnsizeCandidate);
1021 }
1022 } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
1023 let principal_a = a_data.principal().unwrap();
1025 let target_trait_did = principal_def_id_b.unwrap();
1026 let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
1027
1028 for (idx, upcast_trait_ref) in
1029 util::supertraits(self.tcx(), source_trait_ref).enumerate()
1030 {
1031 self.infcx.probe(|_| {
1032 if upcast_trait_ref.def_id() == target_trait_did
1033 && let Ok(nested) = self.match_upcast_principal(
1034 obligation,
1035 upcast_trait_ref,
1036 a_data,
1037 b_data,
1038 a_region,
1039 b_region,
1040 )
1041 {
1042 if nested.is_none() {
1043 candidates.ambiguous = true;
1044 }
1045 candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
1046 }
1047 })
1048 }
1049 }
1050 }
1051
1052 (_, &ty::Dynamic(_, _, ty::Dyn)) => {
1054 candidates.vec.push(BuiltinUnsizeCandidate);
1055 }
1056
1057 (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
1061 debug!("assemble_candidates_for_unsizing: ambiguous");
1062 candidates.ambiguous = true;
1063 }
1064
1065 (&ty::Array(..), &ty::Slice(_)) => {
1067 candidates.vec.push(BuiltinUnsizeCandidate);
1068 }
1069
1070 (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
1072 if def_id_a == def_id_b {
1073 candidates.vec.push(BuiltinUnsizeCandidate);
1074 }
1075 }
1076
1077 _ => {}
1078 };
1079 }
1080
1081 #[instrument(level = "debug", skip(self, obligation, candidates))]
1082 fn assemble_candidates_for_transmutability(
1083 &mut self,
1084 obligation: &PolyTraitObligation<'tcx>,
1085 candidates: &mut SelectionCandidateSet<'tcx>,
1086 ) {
1087 if obligation.predicate.has_non_region_param() {
1088 return;
1089 }
1090
1091 if obligation.has_non_region_infer() {
1092 candidates.ambiguous = true;
1093 return;
1094 }
1095
1096 candidates.vec.push(TransmutabilityCandidate);
1097 }
1098
1099 #[instrument(level = "debug", skip(self, obligation, candidates))]
1100 fn assemble_candidates_for_trait_alias(
1101 &mut self,
1102 obligation: &PolyTraitObligation<'tcx>,
1103 candidates: &mut SelectionCandidateSet<'tcx>,
1104 ) {
1105 let self_ty = obligation.self_ty().skip_binder();
1107 debug!(?self_ty);
1108
1109 let def_id = obligation.predicate.def_id();
1110
1111 if self.tcx().is_trait_alias(def_id) {
1112 candidates.vec.push(TraitAliasCandidate);
1113 }
1114 }
1115
1116 #[instrument(level = "debug", skip(self, candidates))]
1118 fn assemble_builtin_sized_candidate(
1119 &mut self,
1120 obligation: &PolyTraitObligation<'tcx>,
1121 candidates: &mut SelectionCandidateSet<'tcx>,
1122 sizedness: SizedTraitKind,
1123 ) {
1124 match self.sizedness_conditions(obligation, sizedness) {
1125 BuiltinImplConditions::Where(nested) => {
1126 candidates
1127 .vec
1128 .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
1129 }
1130 BuiltinImplConditions::None => {}
1131 BuiltinImplConditions::Ambiguous => {
1132 candidates.ambiguous = true;
1133 }
1134 }
1135 }
1136
1137 #[instrument(level = "debug", skip(self, candidates))]
1140 fn assemble_builtin_bound_candidates(
1141 &mut self,
1142 conditions: BuiltinImplConditions<'tcx>,
1143 candidates: &mut SelectionCandidateSet<'tcx>,
1144 ) {
1145 match conditions {
1146 BuiltinImplConditions::Where(nested) => {
1147 candidates
1148 .vec
1149 .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
1150 }
1151 BuiltinImplConditions::None => {}
1152 BuiltinImplConditions::Ambiguous => {
1153 candidates.ambiguous = true;
1154 }
1155 }
1156 }
1157
1158 fn assemble_const_destruct_candidates(
1159 &mut self,
1160 _obligation: &PolyTraitObligation<'tcx>,
1161 candidates: &mut SelectionCandidateSet<'tcx>,
1162 ) {
1163 candidates.vec.push(BuiltinCandidate { has_nested: false });
1164 }
1165
1166 fn assemble_candidate_for_tuple(
1167 &mut self,
1168 obligation: &PolyTraitObligation<'tcx>,
1169 candidates: &mut SelectionCandidateSet<'tcx>,
1170 ) {
1171 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1172 match self_ty.kind() {
1173 ty::Tuple(_) => {
1174 candidates.vec.push(BuiltinCandidate { has_nested: false });
1175 }
1176 ty::Infer(ty::TyVar(_)) => {
1177 candidates.ambiguous = true;
1178 }
1179 ty::Bool
1180 | ty::Char
1181 | ty::Int(_)
1182 | ty::Uint(_)
1183 | ty::Float(_)
1184 | ty::Adt(_, _)
1185 | ty::Foreign(_)
1186 | ty::Str
1187 | ty::Array(_, _)
1188 | ty::Slice(_)
1189 | ty::RawPtr(_, _)
1190 | ty::Ref(_, _, _)
1191 | ty::FnDef(_, _)
1192 | ty::Pat(_, _)
1193 | ty::FnPtr(..)
1194 | ty::UnsafeBinder(_)
1195 | ty::Dynamic(_, _, _)
1196 | ty::Closure(..)
1197 | ty::CoroutineClosure(..)
1198 | ty::Coroutine(_, _)
1199 | ty::CoroutineWitness(..)
1200 | ty::Never
1201 | ty::Alias(..)
1202 | ty::Param(_)
1203 | ty::Bound(_, _)
1204 | ty::Error(_)
1205 | ty::Infer(_)
1206 | ty::Placeholder(_) => {}
1207 }
1208 }
1209
1210 fn assemble_candidates_for_fn_ptr_trait(
1211 &mut self,
1212 obligation: &PolyTraitObligation<'tcx>,
1213 candidates: &mut SelectionCandidateSet<'tcx>,
1214 ) {
1215 let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
1216
1217 match self_ty.skip_binder().kind() {
1218 ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
1219 ty::Bool
1220 | ty::Char
1221 | ty::Int(_)
1222 | ty::Uint(_)
1223 | ty::Float(_)
1224 | ty::Adt(..)
1225 | ty::Foreign(..)
1226 | ty::Str
1227 | ty::Array(..)
1228 | ty::Pat(..)
1229 | ty::Slice(_)
1230 | ty::RawPtr(_, _)
1231 | ty::Ref(..)
1232 | ty::FnDef(..)
1233 | ty::Placeholder(..)
1234 | ty::Dynamic(..)
1235 | ty::Closure(..)
1236 | ty::CoroutineClosure(..)
1237 | ty::Coroutine(..)
1238 | ty::CoroutineWitness(..)
1239 | ty::UnsafeBinder(_)
1240 | ty::Never
1241 | ty::Tuple(..)
1242 | ty::Alias(..)
1243 | ty::Param(..)
1244 | ty::Bound(..)
1245 | ty::Error(_)
1246 | ty::Infer(
1247 ty::InferTy::IntVar(_)
1248 | ty::InferTy::FloatVar(_)
1249 | ty::InferTy::FreshIntTy(_)
1250 | ty::InferTy::FreshFloatTy(_),
1251 ) => {}
1252 ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
1253 candidates.ambiguous = true;
1254 }
1255 }
1256 }
1257
1258 fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
1259 &mut self,
1260 obligation: &PolyTraitObligation<'tcx>,
1261 candidates: &mut SelectionCandidateSet<'tcx>,
1262 ) {
1263 match obligation.predicate.self_ty().skip_binder().kind() {
1264 ty::Ref(..)
1265 | ty::Adt(..)
1266 | ty::Tuple(_)
1267 | ty::Array(..)
1268 | ty::FnDef(..)
1269 | ty::FnPtr(..)
1270 | ty::Error(_)
1271 | ty::Uint(_)
1272 | ty::Int(_)
1273 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1274 | ty::Bool
1275 | ty::Float(_)
1276 | ty::Char
1277 | ty::RawPtr(..)
1278 | ty::Never
1279 | ty::Pat(..)
1280 | ty::Dynamic(..)
1281 | ty::Str
1282 | ty::Slice(_)
1283 | ty::Foreign(..)
1284 | ty::Alias(..)
1285 | ty::Param(_)
1286 | ty::Placeholder(..)
1287 | ty::Closure(..)
1288 | ty::CoroutineClosure(..)
1289 | ty::Coroutine(..)
1290 | ty::UnsafeBinder(_)
1291 | ty::CoroutineWitness(..)
1292 | ty::Bound(..) => {
1293 candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
1294 }
1295
1296 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1297 candidates.ambiguous = true;
1298 }
1299 }
1300 }
1301}