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::{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 self.assemble_builtin_copy_clone_candidate(
79 obligation.predicate.self_ty().skip_binder(),
80 &mut candidates,
81 );
82 }
83 Some(LangItem::DiscriminantKind) => {
84 candidates.vec.push(BuiltinCandidate);
86 }
87 Some(LangItem::PointeeTrait) => {
88 candidates.vec.push(BuiltinCandidate);
90 }
91 Some(LangItem::Sized) => {
92 self.assemble_builtin_sized_candidate(
93 obligation.predicate.self_ty().skip_binder(),
94 &mut candidates,
95 SizedTraitKind::Sized,
96 );
97 }
98 Some(LangItem::MetaSized) => {
99 self.assemble_builtin_sized_candidate(
100 obligation.predicate.self_ty().skip_binder(),
101 &mut candidates,
102 SizedTraitKind::MetaSized,
103 );
104 }
105 Some(LangItem::PointeeSized) => {
106 bug!("`PointeeSized` is removed during lowering");
107 }
108 Some(LangItem::Unsize) => {
109 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
110 }
111 Some(LangItem::Destruct) => {
112 self.assemble_const_destruct_candidates(obligation, &mut candidates);
113 }
114 Some(LangItem::TransmuteTrait) => {
115 self.assemble_candidates_from_impls(obligation, &mut candidates);
117 self.assemble_candidates_for_transmutability(obligation, &mut candidates);
118 }
119 Some(LangItem::Tuple) => {
120 self.assemble_candidate_for_tuple(obligation, &mut candidates);
121 }
122 Some(LangItem::FnPtrTrait) => {
123 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
124 }
125 Some(LangItem::BikeshedGuaranteedNoDrop) => {
126 self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
127 obligation,
128 &mut candidates,
129 );
130 }
131 _ => {
132 match lang_item {
136 Some(LangItem::Coroutine) => {
137 self.assemble_coroutine_candidates(obligation, &mut candidates);
138 }
139 Some(LangItem::Future) => {
140 self.assemble_future_candidates(obligation, &mut candidates);
141 }
142 Some(LangItem::Iterator) => {
143 self.assemble_iterator_candidates(obligation, &mut candidates);
144 }
145 Some(LangItem::FusedIterator) => {
146 self.assemble_fused_iterator_candidates(obligation, &mut candidates);
147 }
148 Some(LangItem::AsyncIterator) => {
149 self.assemble_async_iterator_candidates(obligation, &mut candidates);
150 }
151 Some(LangItem::AsyncFnKindHelper) => {
152 self.assemble_async_fn_kind_helper_candidates(
153 obligation,
154 &mut candidates,
155 );
156 }
157 Some(LangItem::AsyncFn | LangItem::AsyncFnMut | LangItem::AsyncFnOnce) => {
158 self.assemble_async_closure_candidates(obligation, &mut candidates);
159 }
160 Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
161 self.assemble_closure_candidates(obligation, &mut candidates);
162 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
163 }
164 _ => {}
165 }
166
167 self.assemble_candidates_from_impls(obligation, &mut candidates);
168 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
169 }
170 }
171
172 self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
173 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
174 self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
175 }
176 debug!("candidate list size: {}", candidates.vec.len());
177 Ok(candidates)
178 }
179
180 #[instrument(level = "debug", skip(self, candidates))]
181 fn assemble_candidates_from_projected_tys(
182 &mut self,
183 obligation: &PolyTraitObligation<'tcx>,
184 candidates: &mut SelectionCandidateSet<'tcx>,
185 ) {
186 match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
189 ty::Alias(ty::Projection | ty::Opaque, _) => {}
191 ty::Infer(ty::TyVar(_)) => {
192 span_bug!(
193 obligation.cause.span,
194 "Self=_ should have been handled by assemble_candidates"
195 );
196 }
197 _ => return,
198 }
199
200 self.infcx.probe(|_| {
201 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
202 let placeholder_trait_predicate =
203 self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
204
205 let mut distinct_normalized_bounds = FxHashSet::default();
209 let _ = self.for_each_item_bound::<!>(
210 placeholder_trait_predicate.self_ty(),
211 |selcx, bound, idx| {
212 let Some(bound) = bound.as_trait_clause() else {
213 return ControlFlow::Continue(());
214 };
215 if bound.polarity() != placeholder_trait_predicate.polarity {
216 return ControlFlow::Continue(());
217 }
218
219 selcx.infcx.probe(|_| {
220 let bound = util::lazily_elaborate_sizedness_candidate(
221 selcx.infcx,
222 obligation,
223 bound,
224 );
225
226 match selcx.match_normalize_trait_ref(
228 obligation,
229 placeholder_trait_predicate.trait_ref,
230 bound.map_bound(|pred| pred.trait_ref),
231 ) {
232 Ok(None) => {
233 candidates.vec.push(ProjectionCandidate(idx));
234 }
235 Ok(Some(normalized_trait))
236 if distinct_normalized_bounds.insert(normalized_trait) =>
237 {
238 candidates.vec.push(ProjectionCandidate(idx));
239 }
240 _ => {}
241 }
242 });
243
244 ControlFlow::Continue(())
245 },
246 || candidates.ambiguous = true,
248 );
249 });
250 }
251
252 #[instrument(level = "debug", skip(self, stack, candidates))]
257 fn assemble_candidates_from_caller_bounds<'o>(
258 &mut self,
259 stack: &TraitObligationStack<'o, 'tcx>,
260 candidates: &mut SelectionCandidateSet<'tcx>,
261 ) -> Result<(), SelectionError<'tcx>> {
262 debug!(?stack.obligation);
263
264 let bounds = stack
265 .obligation
266 .param_env
267 .caller_bounds()
268 .iter()
269 .filter_map(|p| p.as_trait_clause())
270 .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
272
273 let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
274 let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
275 for bound in bounds {
277 let bound =
278 util::lazily_elaborate_sizedness_candidate(self.infcx, stack.obligation, bound);
279
280 if bound.def_id() != stack.obligation.predicate.def_id() {
282 continue;
283 }
284
285 let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
286 if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
287 continue;
288 }
289 let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
290 if wc.may_apply() {
291 candidates.vec.push(ParamCandidate(bound));
292 }
293 }
294
295 Ok(())
296 }
297
298 fn assemble_coroutine_candidates(
299 &mut self,
300 obligation: &PolyTraitObligation<'tcx>,
301 candidates: &mut SelectionCandidateSet<'tcx>,
302 ) {
303 let self_ty = obligation.self_ty().skip_binder();
307 match self_ty.kind() {
308 ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => {
311 debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
312
313 candidates.vec.push(CoroutineCandidate);
314 }
315 ty::Infer(ty::TyVar(_)) => {
316 debug!("assemble_coroutine_candidates: ambiguous self-type");
317 candidates.ambiguous = true;
318 }
319 _ => {}
320 }
321 }
322
323 fn assemble_future_candidates(
324 &mut self,
325 obligation: &PolyTraitObligation<'tcx>,
326 candidates: &mut SelectionCandidateSet<'tcx>,
327 ) {
328 let self_ty = obligation.self_ty().skip_binder();
329 if let ty::Coroutine(did, ..) = self_ty.kind() {
330 if self.tcx().coroutine_is_async(*did) {
333 debug!(?self_ty, ?obligation, "assemble_future_candidates",);
334
335 candidates.vec.push(FutureCandidate);
336 }
337 }
338 }
339
340 fn assemble_iterator_candidates(
341 &mut self,
342 obligation: &PolyTraitObligation<'tcx>,
343 candidates: &mut SelectionCandidateSet<'tcx>,
344 ) {
345 let self_ty = obligation.self_ty().skip_binder();
346 if let ty::Coroutine(did, ..) = self_ty.kind()
349 && self.tcx().coroutine_is_gen(*did)
350 {
351 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
352
353 candidates.vec.push(IteratorCandidate);
354 }
355 }
356
357 fn assemble_fused_iterator_candidates(
358 &mut self,
359 obligation: &PolyTraitObligation<'tcx>,
360 candidates: &mut SelectionCandidateSet<'tcx>,
361 ) {
362 if self.coroutine_is_gen(obligation.self_ty().skip_binder()) {
363 candidates.vec.push(BuiltinCandidate);
364 }
365 }
366
367 fn assemble_async_iterator_candidates(
368 &mut self,
369 obligation: &PolyTraitObligation<'tcx>,
370 candidates: &mut SelectionCandidateSet<'tcx>,
371 ) {
372 let self_ty = obligation.self_ty().skip_binder();
373 if let ty::Coroutine(did, args) = *self_ty.kind() {
374 if self.tcx().coroutine_is_async_gen(did) {
377 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
378
379 let ty::Adt(_poll_def, args) = *args.as_coroutine().yield_ty().kind() else {
382 candidates.ambiguous = true;
383 return;
384 };
385 let ty::Adt(_option_def, _) = *args.type_at(0).kind() else {
386 candidates.ambiguous = true;
387 return;
388 };
389
390 candidates.vec.push(AsyncIteratorCandidate);
391 }
392 }
393 }
394
395 fn assemble_closure_candidates(
402 &mut self,
403 obligation: &PolyTraitObligation<'tcx>,
404 candidates: &mut SelectionCandidateSet<'tcx>,
405 ) {
406 let kind = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
407
408 let self_ty = obligation.self_ty().skip_binder();
412 match *self_ty.kind() {
413 ty::Closure(def_id, _) => {
414 let is_const = self.tcx().is_const_fn(def_id);
415 debug!(?kind, ?obligation, "assemble_unboxed_candidates");
416 match self.infcx.closure_kind(self_ty) {
417 Some(closure_kind) => {
418 debug!(?closure_kind, "assemble_unboxed_candidates");
419 if closure_kind.extends(kind) {
420 candidates.vec.push(ClosureCandidate { is_const });
421 }
422 }
423 None => {
424 if kind == ty::ClosureKind::FnOnce {
425 candidates.vec.push(ClosureCandidate { is_const });
426 } else {
427 candidates.ambiguous = true;
428 }
429 }
430 }
431 }
432 ty::CoroutineClosure(def_id, args) => {
433 let args = args.as_coroutine_closure();
434 let is_const = self.tcx().is_const_fn(def_id);
435 if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
436 && !args.tupled_upvars_ty().is_ty_var()
438 {
439 if closure_kind.extends(kind) && !args.has_self_borrows() {
444 candidates.vec.push(ClosureCandidate { is_const });
445 } else if kind == ty::ClosureKind::FnOnce {
446 candidates.vec.push(ClosureCandidate { is_const });
447 }
448 } else if kind == ty::ClosureKind::FnOnce {
449 candidates.vec.push(ClosureCandidate { is_const });
450 } else {
451 candidates.ambiguous = true;
453 }
454 }
455 ty::Infer(ty::TyVar(_)) => {
456 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
457 candidates.ambiguous = true;
458 }
459 _ => {}
460 }
461 }
462
463 #[instrument(level = "debug", skip(self, candidates))]
464 fn assemble_async_closure_candidates(
465 &mut self,
466 obligation: &PolyTraitObligation<'tcx>,
467 candidates: &mut SelectionCandidateSet<'tcx>,
468 ) {
469 let goal_kind =
470 self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
471
472 debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind());
473 match *obligation.self_ty().skip_binder().kind() {
474 ty::CoroutineClosure(def_id, args) => {
475 if let Some(closure_kind) =
476 args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
477 && !closure_kind.extends(goal_kind)
478 {
479 return;
480 }
481
482 let Some(coroutine_kind) =
484 self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id))
485 else {
486 bug!("coroutine with no kind");
487 };
488
489 debug!(?coroutine_kind);
490 match coroutine_kind {
491 CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
492 candidates.vec.push(AsyncClosureCandidate);
493 }
494 _ => (),
495 }
496 }
497 ty::Closure(_, args) => {
500 if let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind()
501 && !closure_kind.extends(goal_kind)
502 {
503 return;
504 }
505 candidates.vec.push(AsyncClosureCandidate);
506 }
507 ty::FnPtr(sig_tys, hdr) => {
509 if sig_tys.with(hdr).is_fn_trait_compatible() {
510 candidates.vec.push(AsyncClosureCandidate);
511 }
512 }
513 ty::FnDef(def_id, _) => {
515 let tcx = self.tcx();
516 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
517 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
518 {
519 candidates.vec.push(AsyncClosureCandidate);
520 }
521 }
522 _ => {}
523 }
524 }
525
526 fn assemble_async_fn_kind_helper_candidates(
527 &mut self,
528 obligation: &PolyTraitObligation<'tcx>,
529 candidates: &mut SelectionCandidateSet<'tcx>,
530 ) {
531 let self_ty = obligation.self_ty().skip_binder();
532 let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
533
534 if !(self_ty.is_integral() || self_ty.is_ty_var()) {
536 return;
537 }
538 if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) {
539 return;
540 }
541
542 if let Some(closure_kind) = self_ty.to_opt_closure_kind()
545 && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
546 && closure_kind.extends(goal_kind)
547 {
548 candidates.vec.push(AsyncFnKindHelperCandidate);
549 }
550 }
551
552 fn assemble_fn_pointer_candidates(
554 &mut self,
555 obligation: &PolyTraitObligation<'tcx>,
556 candidates: &mut SelectionCandidateSet<'tcx>,
557 ) {
558 let self_ty = obligation.self_ty().skip_binder();
563 match *self_ty.kind() {
564 ty::Infer(ty::TyVar(_)) => {
565 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
566 candidates.ambiguous = true; }
568 ty::FnPtr(sig_tys, hdr) => {
570 if sig_tys.with(hdr).is_fn_trait_compatible() {
571 candidates.vec.push(FnPointerCandidate);
572 }
573 }
574 ty::FnDef(def_id, _) => {
576 let tcx = self.tcx();
577 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
578 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
579 {
580 candidates.vec.push(FnPointerCandidate);
581 }
582 }
583 _ => {}
584 }
585 }
586
587 #[instrument(level = "debug", skip(self, candidates))]
589 fn assemble_candidates_from_impls(
590 &mut self,
591 obligation: &PolyTraitObligation<'tcx>,
592 candidates: &mut SelectionCandidateSet<'tcx>,
593 ) {
594 let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
595 let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
596 self.tcx().for_each_relevant_impl(
597 obligation.predicate.def_id(),
598 obligation.predicate.skip_binder().trait_ref.self_ty(),
599 |impl_def_id| {
600 let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
604 if !drcx
605 .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
606 {
607 return;
608 }
609
610 if self.tcx().defaultness(impl_def_id).is_default() {
614 return;
615 }
616
617 if self.reject_fn_ptr_impls(
618 impl_def_id,
619 obligation,
620 impl_trait_header.trait_ref.skip_binder().self_ty(),
621 ) {
622 return;
623 }
624
625 self.infcx.probe(|_| {
626 if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_header, obligation) {
627 candidates.vec.push(ImplCandidate(impl_def_id));
628 }
629 });
630 },
631 );
632 }
633
634 #[instrument(level = "trace", skip(self), ret)]
639 fn reject_fn_ptr_impls(
640 &mut self,
641 impl_def_id: DefId,
642 obligation: &PolyTraitObligation<'tcx>,
643 impl_self_ty: Ty<'tcx>,
644 ) -> bool {
645 if !matches!(impl_self_ty.kind(), ty::Param(..)) {
647 return false;
648 }
649 let Some(fn_ptr_trait) = self.tcx().lang_items().fn_ptr_trait() else {
650 return false;
651 };
652
653 for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
654 let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
655 if fn_ptr_trait != pred.trait_ref.def_id {
656 continue;
657 }
658 trace!(?pred);
659 if pred.self_ty() != impl_self_ty {
661 continue;
662 }
663
664 let self_ty = obligation.self_ty().skip_binder();
665 match self_ty.kind() {
666 ty::FnPtr(..) => return false,
669
670 ty::Placeholder(..)
672 | ty::Dynamic(_, _, _)
673 | ty::Alias(_, _)
674 | ty::Infer(_)
675 | ty::Param(..)
676 | ty::Bound(_, _) => {}
677
678 ty::Bool
681 | ty::Char
682 | ty::Int(_)
683 | ty::Uint(_)
684 | ty::Float(_)
685 | ty::Adt(_, _)
686 | ty::Foreign(_)
687 | ty::Str
688 | ty::Array(_, _)
689 | ty::Pat(_, _)
690 | ty::Slice(_)
691 | ty::RawPtr(_, _)
692 | ty::Ref(_, _, _)
693 | ty::Closure(..)
694 | ty::CoroutineClosure(..)
695 | ty::Coroutine(_, _)
696 | ty::CoroutineWitness(..)
697 | ty::UnsafeBinder(_)
698 | ty::Never
699 | ty::Tuple(_)
700 | ty::Error(_) => return true,
701 ty::FnDef(_, _) => return true,
704 }
705
706 let obligation = Obligation::new(
709 self.tcx(),
710 obligation.cause.clone(),
711 obligation.param_env,
712 self.tcx().mk_predicate(obligation.predicate.map_bound(|mut pred| {
713 pred.trait_ref =
714 ty::TraitRef::new(self.tcx(), fn_ptr_trait, [pred.trait_ref.self_ty()]);
715 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
716 })),
717 );
718 if let Ok(r) = self.evaluate_root_obligation(&obligation) {
719 if !r.may_apply() {
720 return true;
721 }
722 }
723 }
724 false
725 }
726
727 fn assemble_candidates_from_auto_impls(
728 &mut self,
729 obligation: &PolyTraitObligation<'tcx>,
730 candidates: &mut SelectionCandidateSet<'tcx>,
731 ) {
732 let self_ty = obligation.self_ty().skip_binder();
734 debug!(?self_ty, "assemble_candidates_from_auto_impls");
735
736 let def_id = obligation.predicate.def_id();
737
738 let mut check_impls = || {
739 let mut has_impl = false;
749 self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
750 if !has_impl {
751 candidates.vec.push(AutoImplCandidate)
752 }
753 };
754
755 if self.tcx().trait_is_auto(def_id) {
756 match *self_ty.kind() {
757 ty::Dynamic(..) => {
758 }
763 ty::Foreign(..) => {
764 if self.tcx().is_default_trait(def_id) {
772 check_impls()
773 }
774 }
775 ty::Param(..)
776 | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
777 | ty::Placeholder(..)
778 | ty::Bound(..) => {
779 }
793 ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
794 candidates.ambiguous = true;
796 }
797 ty::Coroutine(coroutine_def_id, _)
798 if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
799 {
800 match self.tcx().coroutine_movability(coroutine_def_id) {
801 hir::Movability::Static => {
802 }
805 hir::Movability::Movable => {
806 candidates.vec.push(BuiltinCandidate);
809 }
810 }
811 }
812
813 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
814 bug!(
815 "asked to assemble auto trait candidates of unexpected type: {:?}",
816 self_ty
817 );
818 }
819
820 ty::Alias(ty::Opaque, alias) => {
821 if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
822 } else if let TypingMode::Coherence = self.infcx.typing_mode() {
832 candidates.ambiguous = true;
835 } else if self.infcx.can_define_opaque_ty(alias.def_id) {
836 candidates.ambiguous = true;
840 } else {
841 candidates.vec.push(AutoImplCandidate)
842 }
843 }
844
845 ty::CoroutineWitness(def_id, _) => {
846 if self.should_stall_coroutine_witness(def_id) {
847 candidates.ambiguous = true;
848 } else {
849 candidates.vec.push(AutoImplCandidate);
850 }
851 }
852
853 ty::Bool
854 | ty::Char
855 | ty::Int(_)
856 | ty::Uint(_)
857 | ty::Float(_)
858 | ty::Str
859 | ty::Array(_, _)
860 | ty::Pat(_, _)
861 | ty::Slice(_)
862 | ty::Adt(..)
863 | ty::RawPtr(_, _)
864 | ty::Ref(..)
865 | ty::FnDef(..)
866 | ty::FnPtr(..)
867 | ty::Closure(..)
868 | ty::CoroutineClosure(..)
869 | ty::Coroutine(..)
870 | ty::Never
871 | ty::Tuple(_)
872 | ty::UnsafeBinder(_) => {
873 if self.tcx().trait_def(def_id).safety.is_unsafe()
876 && self_ty.has_unsafe_fields()
877 {
878 return;
879 }
880
881 check_impls();
882 }
883 ty::Error(_) => {
884 candidates.vec.push(AutoImplCandidate);
885 }
886 }
887 }
888 }
889
890 fn assemble_candidates_from_object_ty(
892 &mut self,
893 obligation: &PolyTraitObligation<'tcx>,
894 candidates: &mut SelectionCandidateSet<'tcx>,
895 ) {
896 debug!(
897 self_ty = ?obligation.self_ty().skip_binder(),
898 "assemble_candidates_from_object_ty",
899 );
900
901 if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
902 return;
903 }
904
905 self.infcx.probe(|_snapshot| {
906 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
907 self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
908 let self_ty = placeholder_trait_predicate.self_ty();
909 let principal_trait_ref = match self_ty.kind() {
910 ty::Dynamic(data, ..) => {
911 if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
912 debug!(
913 "assemble_candidates_from_object_ty: matched builtin bound, \
914 pushing candidate"
915 );
916 candidates.vec.push(BuiltinObjectCandidate);
917 return;
918 }
919
920 if let Some(principal) = data.principal() {
921 principal.with_self_ty(self.tcx(), self_ty)
922 } else {
923 return;
925 }
926 }
927 ty::Infer(ty::TyVar(_)) => {
928 debug!("assemble_candidates_from_object_ty: ambiguous");
929 candidates.ambiguous = true; return;
931 }
932 _ => return,
933 };
934
935 debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
936
937 let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
943 .enumerate()
944 .filter(|&(_, upcast_trait_ref)| {
945 self.infcx.probe(|_| {
946 self.match_normalize_trait_ref(
947 obligation,
948 placeholder_trait_predicate.trait_ref,
949 upcast_trait_ref,
950 )
951 .is_ok()
952 })
953 })
954 .map(|(idx, _)| ObjectCandidate(idx));
955
956 candidates.vec.extend(candidate_supertraits);
957 })
958 })
959 }
960
961 fn assemble_candidates_for_unsizing(
963 &mut self,
964 obligation: &PolyTraitObligation<'tcx>,
965 candidates: &mut SelectionCandidateSet<'tcx>,
966 ) {
967 let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
982 return;
984 };
985 let source = trait_pred.self_ty();
986 let target = trait_pred.trait_ref.args.type_at(1);
987
988 debug!(?source, ?target, "assemble_candidates_for_unsizing");
989
990 match (source.kind(), target.kind()) {
991 (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => {
993 let principal_def_id_a = a_data.principal_def_id();
1005 let principal_def_id_b = b_data.principal_def_id();
1006 if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
1007 let a_auto_traits: FxIndexSet<DefId> = a_data
1011 .auto_traits()
1012 .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
1013 elaborate::supertrait_def_ids(self.tcx(), principal_def_id)
1014 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
1015 }))
1016 .collect();
1017 let auto_traits_compatible = b_data
1018 .auto_traits()
1019 .all(|b| a_auto_traits.contains(&b));
1021 if auto_traits_compatible {
1022 candidates.vec.push(BuiltinUnsizeCandidate);
1023 }
1024 } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
1025 let principal_a = a_data.principal().unwrap();
1027 let target_trait_did = principal_def_id_b.unwrap();
1028 let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
1029
1030 for (idx, upcast_trait_ref) in
1031 util::supertraits(self.tcx(), source_trait_ref).enumerate()
1032 {
1033 self.infcx.probe(|_| {
1034 if upcast_trait_ref.def_id() == target_trait_did
1035 && let Ok(nested) = self.match_upcast_principal(
1036 obligation,
1037 upcast_trait_ref,
1038 a_data,
1039 b_data,
1040 a_region,
1041 b_region,
1042 )
1043 {
1044 if nested.is_none() {
1045 candidates.ambiguous = true;
1046 }
1047 candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
1048 }
1049 })
1050 }
1051 }
1052 }
1053
1054 (_, &ty::Dynamic(_, _, ty::Dyn)) => {
1056 candidates.vec.push(BuiltinUnsizeCandidate);
1057 }
1058
1059 (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
1063 debug!("assemble_candidates_for_unsizing: ambiguous");
1064 candidates.ambiguous = true;
1065 }
1066
1067 (&ty::Array(..), &ty::Slice(_)) => {
1069 candidates.vec.push(BuiltinUnsizeCandidate);
1070 }
1071
1072 (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
1074 if def_id_a == def_id_b {
1075 candidates.vec.push(BuiltinUnsizeCandidate);
1076 }
1077 }
1078
1079 _ => {}
1080 };
1081 }
1082
1083 #[instrument(level = "debug", skip(self, obligation, candidates))]
1084 fn assemble_candidates_for_transmutability(
1085 &mut self,
1086 obligation: &PolyTraitObligation<'tcx>,
1087 candidates: &mut SelectionCandidateSet<'tcx>,
1088 ) {
1089 if obligation.predicate.has_non_region_param() {
1090 return;
1091 }
1092
1093 if obligation.has_non_region_infer() {
1094 candidates.ambiguous = true;
1095 return;
1096 }
1097
1098 candidates.vec.push(TransmutabilityCandidate);
1099 }
1100
1101 #[instrument(level = "debug", skip(self, obligation, candidates))]
1102 fn assemble_candidates_for_trait_alias(
1103 &mut self,
1104 obligation: &PolyTraitObligation<'tcx>,
1105 candidates: &mut SelectionCandidateSet<'tcx>,
1106 ) {
1107 let self_ty = obligation.self_ty().skip_binder();
1109 debug!(?self_ty);
1110
1111 let def_id = obligation.predicate.def_id();
1112
1113 if self.tcx().is_trait_alias(def_id) {
1114 candidates.vec.push(TraitAliasCandidate);
1115 }
1116 }
1117
1118 #[instrument(level = "debug", skip(self, candidates))]
1121 fn assemble_builtin_copy_clone_candidate(
1122 &mut self,
1123 self_ty: Ty<'tcx>,
1124 candidates: &mut SelectionCandidateSet<'tcx>,
1125 ) {
1126 match *self_ty.kind() {
1127 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) | ty::Tuple(..) | ty::Pat(..) => {
1130 candidates.vec.push(BuiltinCandidate);
1131 }
1132
1133 ty::Uint(_)
1135 | ty::Int(_)
1136 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1137 | ty::Bool
1138 | ty::Float(_)
1139 | ty::Char
1140 | ty::RawPtr(..)
1141 | ty::Never
1142 | ty::Ref(_, _, hir::Mutability::Not)
1143 | ty::Array(..) => {}
1144
1145 ty::UnsafeBinder(_) => {}
1148
1149 ty::Dynamic(..) | ty::Str | ty::Slice(..) | ty::Foreign(..) => {}
1151
1152 ty::Ref(_, _, hir::Mutability::Mut) => {}
1154
1155 ty::Coroutine(coroutine_def_id, args) => {
1156 match self.tcx().coroutine_movability(coroutine_def_id) {
1157 hir::Movability::Static => {}
1158 hir::Movability::Movable => {
1159 if self.tcx().features().coroutine_clone() {
1160 let resolved_upvars =
1161 self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
1162 let resolved_witness =
1163 self.infcx.shallow_resolve(args.as_coroutine().witness());
1164 if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
1165 candidates.ambiguous = true;
1167 } else {
1168 candidates.vec.push(BuiltinCandidate);
1169 }
1170 }
1171 }
1172 }
1173 }
1174
1175 ty::Closure(_, args) => {
1176 let resolved_upvars =
1177 self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
1178 if resolved_upvars.is_ty_var() {
1179 candidates.ambiguous = true;
1181 } else {
1182 candidates.vec.push(BuiltinCandidate);
1183 }
1184 }
1185
1186 ty::CoroutineClosure(_, args) => {
1187 let resolved_upvars =
1188 self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
1189 if resolved_upvars.is_ty_var() {
1190 candidates.ambiguous = true;
1192 } else {
1193 candidates.vec.push(BuiltinCandidate);
1194 }
1195 }
1196
1197 ty::CoroutineWitness(coroutine_def_id, _) => {
1198 if self.should_stall_coroutine_witness(coroutine_def_id) {
1199 candidates.ambiguous = true;
1200 } else {
1201 candidates.vec.push(SizedCandidate);
1202 }
1203 }
1204
1205 ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {}
1207
1208 ty::Infer(ty::TyVar(_)) => {
1209 candidates.ambiguous = true;
1210 }
1211
1212 ty::Bound(..) => {}
1214
1215 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1216 bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
1217 }
1218 }
1219 }
1220
1221 #[instrument(level = "debug", skip(self, candidates))]
1223 fn assemble_builtin_sized_candidate(
1224 &mut self,
1225 self_ty: Ty<'tcx>,
1226 candidates: &mut SelectionCandidateSet<'tcx>,
1227 sizedness: SizedTraitKind,
1228 ) {
1229 match *self_ty.kind() {
1230 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1232 | ty::Uint(_)
1233 | ty::Int(_)
1234 | ty::Bool
1235 | ty::Float(_)
1236 | ty::FnDef(..)
1237 | ty::FnPtr(..)
1238 | ty::RawPtr(..)
1239 | ty::Char
1240 | ty::Ref(..)
1241 | ty::Coroutine(..)
1242 | ty::Array(..)
1243 | ty::Closure(..)
1244 | ty::CoroutineClosure(..)
1245 | ty::Never
1246 | ty::Error(_) => {
1247 candidates.vec.push(SizedCandidate);
1248 }
1249
1250 ty::CoroutineWitness(coroutine_def_id, _) => {
1251 if self.should_stall_coroutine_witness(coroutine_def_id) {
1252 candidates.ambiguous = true;
1253 } else {
1254 candidates.vec.push(SizedCandidate);
1255 }
1256 }
1257
1258 ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
1260 candidates.vec.push(SizedCandidate);
1261 }
1262
1263 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
1265 SizedTraitKind::Sized => {}
1266 SizedTraitKind::MetaSized => {
1267 candidates.vec.push(SizedCandidate);
1268 }
1269 },
1270
1271 ty::Foreign(..) => {}
1273
1274 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => {}
1275
1276 ty::Infer(ty::TyVar(_)) => {
1277 candidates.ambiguous = true;
1278 }
1279
1280 ty::Bound(..) => {}
1282
1283 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1284 bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
1285 }
1286 }
1287 }
1288
1289 fn assemble_const_destruct_candidates(
1290 &mut self,
1291 _obligation: &PolyTraitObligation<'tcx>,
1292 candidates: &mut SelectionCandidateSet<'tcx>,
1293 ) {
1294 candidates.vec.push(BuiltinCandidate);
1295 }
1296
1297 fn assemble_candidate_for_tuple(
1298 &mut self,
1299 obligation: &PolyTraitObligation<'tcx>,
1300 candidates: &mut SelectionCandidateSet<'tcx>,
1301 ) {
1302 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1303 match self_ty.kind() {
1304 ty::Tuple(_) => {
1305 candidates.vec.push(BuiltinCandidate);
1306 }
1307 ty::Infer(ty::TyVar(_)) => {
1308 candidates.ambiguous = true;
1309 }
1310 ty::Bool
1311 | ty::Char
1312 | ty::Int(_)
1313 | ty::Uint(_)
1314 | ty::Float(_)
1315 | ty::Adt(_, _)
1316 | ty::Foreign(_)
1317 | ty::Str
1318 | ty::Array(_, _)
1319 | ty::Slice(_)
1320 | ty::RawPtr(_, _)
1321 | ty::Ref(_, _, _)
1322 | ty::FnDef(_, _)
1323 | ty::Pat(_, _)
1324 | ty::FnPtr(..)
1325 | ty::UnsafeBinder(_)
1326 | ty::Dynamic(_, _, _)
1327 | ty::Closure(..)
1328 | ty::CoroutineClosure(..)
1329 | ty::Coroutine(_, _)
1330 | ty::CoroutineWitness(..)
1331 | ty::Never
1332 | ty::Alias(..)
1333 | ty::Param(_)
1334 | ty::Bound(_, _)
1335 | ty::Error(_)
1336 | ty::Infer(_)
1337 | ty::Placeholder(_) => {}
1338 }
1339 }
1340
1341 fn assemble_candidates_for_fn_ptr_trait(
1342 &mut self,
1343 obligation: &PolyTraitObligation<'tcx>,
1344 candidates: &mut SelectionCandidateSet<'tcx>,
1345 ) {
1346 let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
1347
1348 match self_ty.skip_binder().kind() {
1349 ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate),
1350 ty::Bool
1351 | ty::Char
1352 | ty::Int(_)
1353 | ty::Uint(_)
1354 | ty::Float(_)
1355 | ty::Adt(..)
1356 | ty::Foreign(..)
1357 | ty::Str
1358 | ty::Array(..)
1359 | ty::Pat(..)
1360 | ty::Slice(_)
1361 | ty::RawPtr(_, _)
1362 | ty::Ref(..)
1363 | ty::FnDef(..)
1364 | ty::Placeholder(..)
1365 | ty::Dynamic(..)
1366 | ty::Closure(..)
1367 | ty::CoroutineClosure(..)
1368 | ty::Coroutine(..)
1369 | ty::CoroutineWitness(..)
1370 | ty::UnsafeBinder(_)
1371 | ty::Never
1372 | ty::Tuple(..)
1373 | ty::Alias(..)
1374 | ty::Param(..)
1375 | ty::Bound(..)
1376 | ty::Error(_)
1377 | ty::Infer(
1378 ty::InferTy::IntVar(_)
1379 | ty::InferTy::FloatVar(_)
1380 | ty::InferTy::FreshIntTy(_)
1381 | ty::InferTy::FreshFloatTy(_),
1382 ) => {}
1383 ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
1384 candidates.ambiguous = true;
1385 }
1386 }
1387 }
1388
1389 fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
1390 &mut self,
1391 obligation: &PolyTraitObligation<'tcx>,
1392 candidates: &mut SelectionCandidateSet<'tcx>,
1393 ) {
1394 match obligation.predicate.self_ty().skip_binder().kind() {
1395 ty::Ref(..)
1396 | ty::Adt(..)
1397 | ty::Tuple(_)
1398 | ty::Array(..)
1399 | ty::FnDef(..)
1400 | ty::FnPtr(..)
1401 | ty::Error(_)
1402 | ty::Uint(_)
1403 | ty::Int(_)
1404 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1405 | ty::Bool
1406 | ty::Float(_)
1407 | ty::Char
1408 | ty::RawPtr(..)
1409 | ty::Never
1410 | ty::Pat(..)
1411 | ty::Dynamic(..)
1412 | ty::Str
1413 | ty::Slice(_)
1414 | ty::Foreign(..)
1415 | ty::Alias(..)
1416 | ty::Param(_)
1417 | ty::Placeholder(..)
1418 | ty::Closure(..)
1419 | ty::CoroutineClosure(..)
1420 | ty::Coroutine(..)
1421 | ty::UnsafeBinder(_)
1422 | ty::CoroutineWitness(..)
1423 | ty::Bound(..) => {
1424 candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
1425 }
1426
1427 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1428 candidates.ambiguous = true;
1429 }
1430 }
1431 }
1432}