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 match self.tcx().coroutine_movability(coroutine_def_id) {
800 hir::Movability::Static => {
801 }
804 hir::Movability::Movable => {
805 candidates.vec.push(BuiltinCandidate);
808 }
809 }
810 } else {
811 if self.should_stall_coroutine(coroutine_def_id) {
812 candidates.ambiguous = true;
813 } else {
814 candidates.vec.push(AutoImplCandidate);
816 }
817 }
818 }
819
820 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
821 bug!(
822 "asked to assemble auto trait candidates of unexpected type: {:?}",
823 self_ty
824 );
825 }
826
827 ty::Alias(ty::Opaque, alias) => {
828 if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
829 } else if let TypingMode::Coherence = self.infcx.typing_mode() {
839 candidates.ambiguous = true;
842 } else if self.infcx.can_define_opaque_ty(alias.def_id) {
843 candidates.ambiguous = true;
847 } else {
848 candidates.vec.push(AutoImplCandidate)
849 }
850 }
851
852 ty::CoroutineWitness(..) => {
853 candidates.vec.push(AutoImplCandidate);
854 }
855
856 ty::Bool
857 | ty::Char
858 | ty::Int(_)
859 | ty::Uint(_)
860 | ty::Float(_)
861 | ty::Str
862 | ty::Array(_, _)
863 | ty::Pat(_, _)
864 | ty::Slice(_)
865 | ty::Adt(..)
866 | ty::RawPtr(_, _)
867 | ty::Ref(..)
868 | ty::FnDef(..)
869 | ty::FnPtr(..)
870 | ty::Closure(..)
871 | ty::CoroutineClosure(..)
872 | ty::Never
873 | ty::Tuple(_)
874 | ty::UnsafeBinder(_) => {
875 if self.tcx().trait_def(def_id).safety.is_unsafe()
878 && self_ty.has_unsafe_fields()
879 {
880 return;
881 }
882
883 check_impls();
884 }
885 ty::Error(_) => {
886 candidates.vec.push(AutoImplCandidate);
887 }
888 }
889 }
890 }
891
892 fn assemble_candidates_from_object_ty(
894 &mut self,
895 obligation: &PolyTraitObligation<'tcx>,
896 candidates: &mut SelectionCandidateSet<'tcx>,
897 ) {
898 debug!(
899 self_ty = ?obligation.self_ty().skip_binder(),
900 "assemble_candidates_from_object_ty",
901 );
902
903 if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
904 return;
905 }
906
907 self.infcx.probe(|_snapshot| {
908 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
909 self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
910 let self_ty = placeholder_trait_predicate.self_ty();
911 let principal_trait_ref = match self_ty.kind() {
912 ty::Dynamic(data, ..) => {
913 if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
914 debug!(
915 "assemble_candidates_from_object_ty: matched builtin bound, \
916 pushing candidate"
917 );
918 candidates.vec.push(BuiltinObjectCandidate);
919 return;
920 }
921
922 if let Some(principal) = data.principal() {
923 principal.with_self_ty(self.tcx(), self_ty)
924 } else {
925 return;
927 }
928 }
929 ty::Infer(ty::TyVar(_)) => {
930 debug!("assemble_candidates_from_object_ty: ambiguous");
931 candidates.ambiguous = true; return;
933 }
934 _ => return,
935 };
936
937 debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
938
939 let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
945 .enumerate()
946 .filter(|&(_, upcast_trait_ref)| {
947 self.infcx.probe(|_| {
948 self.match_normalize_trait_ref(
949 obligation,
950 placeholder_trait_predicate.trait_ref,
951 upcast_trait_ref,
952 )
953 .is_ok()
954 })
955 })
956 .map(|(idx, _)| ObjectCandidate(idx));
957
958 candidates.vec.extend(candidate_supertraits);
959 })
960 })
961 }
962
963 fn assemble_candidates_for_unsizing(
965 &mut self,
966 obligation: &PolyTraitObligation<'tcx>,
967 candidates: &mut SelectionCandidateSet<'tcx>,
968 ) {
969 let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
984 return;
986 };
987 let source = trait_pred.self_ty();
988 let target = trait_pred.trait_ref.args.type_at(1);
989
990 debug!(?source, ?target, "assemble_candidates_for_unsizing");
991
992 match (source.kind(), target.kind()) {
993 (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => {
995 let principal_def_id_a = a_data.principal_def_id();
1007 let principal_def_id_b = b_data.principal_def_id();
1008 if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
1009 let a_auto_traits: FxIndexSet<DefId> = a_data
1013 .auto_traits()
1014 .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
1015 elaborate::supertrait_def_ids(self.tcx(), principal_def_id)
1016 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
1017 }))
1018 .collect();
1019 let auto_traits_compatible = b_data
1020 .auto_traits()
1021 .all(|b| a_auto_traits.contains(&b));
1023 if auto_traits_compatible {
1024 candidates.vec.push(BuiltinUnsizeCandidate);
1025 }
1026 } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
1027 let principal_a = a_data.principal().unwrap();
1029 let target_trait_did = principal_def_id_b.unwrap();
1030 let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
1031
1032 for (idx, upcast_trait_ref) in
1033 util::supertraits(self.tcx(), source_trait_ref).enumerate()
1034 {
1035 self.infcx.probe(|_| {
1036 if upcast_trait_ref.def_id() == target_trait_did
1037 && let Ok(nested) = self.match_upcast_principal(
1038 obligation,
1039 upcast_trait_ref,
1040 a_data,
1041 b_data,
1042 a_region,
1043 b_region,
1044 )
1045 {
1046 if nested.is_none() {
1047 candidates.ambiguous = true;
1048 }
1049 candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
1050 }
1051 })
1052 }
1053 }
1054 }
1055
1056 (_, &ty::Dynamic(_, _, ty::Dyn)) => {
1058 candidates.vec.push(BuiltinUnsizeCandidate);
1059 }
1060
1061 (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
1065 debug!("assemble_candidates_for_unsizing: ambiguous");
1066 candidates.ambiguous = true;
1067 }
1068
1069 (&ty::Array(..), &ty::Slice(_)) => {
1071 candidates.vec.push(BuiltinUnsizeCandidate);
1072 }
1073
1074 (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
1076 if def_id_a == def_id_b {
1077 candidates.vec.push(BuiltinUnsizeCandidate);
1078 }
1079 }
1080
1081 _ => {}
1082 };
1083 }
1084
1085 #[instrument(level = "debug", skip(self, obligation, candidates))]
1086 fn assemble_candidates_for_transmutability(
1087 &mut self,
1088 obligation: &PolyTraitObligation<'tcx>,
1089 candidates: &mut SelectionCandidateSet<'tcx>,
1090 ) {
1091 if obligation.predicate.has_non_region_param() {
1092 return;
1093 }
1094
1095 if obligation.has_non_region_infer() {
1096 candidates.ambiguous = true;
1097 return;
1098 }
1099
1100 candidates.vec.push(TransmutabilityCandidate);
1101 }
1102
1103 #[instrument(level = "debug", skip(self, obligation, candidates))]
1104 fn assemble_candidates_for_trait_alias(
1105 &mut self,
1106 obligation: &PolyTraitObligation<'tcx>,
1107 candidates: &mut SelectionCandidateSet<'tcx>,
1108 ) {
1109 let self_ty = obligation.self_ty().skip_binder();
1111 debug!(?self_ty);
1112
1113 let def_id = obligation.predicate.def_id();
1114
1115 if self.tcx().is_trait_alias(def_id) {
1116 candidates.vec.push(TraitAliasCandidate);
1117 }
1118 }
1119
1120 #[instrument(level = "debug", skip(self, candidates))]
1123 fn assemble_builtin_copy_clone_candidate(
1124 &mut self,
1125 self_ty: Ty<'tcx>,
1126 candidates: &mut SelectionCandidateSet<'tcx>,
1127 ) {
1128 match *self_ty.kind() {
1129 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) | ty::Tuple(..) | ty::Pat(..) => {
1132 candidates.vec.push(BuiltinCandidate);
1133 }
1134
1135 ty::Uint(_)
1137 | ty::Int(_)
1138 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1139 | ty::Bool
1140 | ty::Float(_)
1141 | ty::Char
1142 | ty::RawPtr(..)
1143 | ty::Never
1144 | ty::Ref(_, _, hir::Mutability::Not)
1145 | ty::Array(..) => {}
1146
1147 ty::UnsafeBinder(_) => {}
1150
1151 ty::Dynamic(..) | ty::Str | ty::Slice(..) | ty::Foreign(..) => {}
1153
1154 ty::Ref(_, _, hir::Mutability::Mut) => {}
1156
1157 ty::Coroutine(coroutine_def_id, args) => {
1158 if self.should_stall_coroutine(coroutine_def_id) {
1159 candidates.ambiguous = true;
1160 return;
1161 }
1162
1163 match self.tcx().coroutine_movability(coroutine_def_id) {
1164 hir::Movability::Static => {}
1165 hir::Movability::Movable => {
1166 if self.tcx().features().coroutine_clone() {
1167 let resolved_upvars =
1168 self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
1169 let resolved_witness =
1170 self.infcx.shallow_resolve(args.as_coroutine().witness());
1171 if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
1172 candidates.ambiguous = true;
1174 } else {
1175 candidates.vec.push(BuiltinCandidate);
1176 }
1177 }
1178 }
1179 }
1180 }
1181
1182 ty::Closure(_, args) => {
1183 let resolved_upvars =
1184 self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
1185 if resolved_upvars.is_ty_var() {
1186 candidates.ambiguous = true;
1188 } else {
1189 candidates.vec.push(BuiltinCandidate);
1190 }
1191 }
1192
1193 ty::CoroutineClosure(_, args) => {
1194 let resolved_upvars =
1195 self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
1196 if resolved_upvars.is_ty_var() {
1197 candidates.ambiguous = true;
1199 } else {
1200 candidates.vec.push(BuiltinCandidate);
1201 }
1202 }
1203
1204 ty::CoroutineWitness(..) => {
1205 candidates.vec.push(SizedCandidate);
1206 }
1207
1208 ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {}
1210
1211 ty::Infer(ty::TyVar(_)) => {
1212 candidates.ambiguous = true;
1213 }
1214
1215 ty::Bound(..) => {}
1217
1218 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1219 bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
1220 }
1221 }
1222 }
1223
1224 #[instrument(level = "debug", skip(self, candidates))]
1226 fn assemble_builtin_sized_candidate(
1227 &mut self,
1228 self_ty: Ty<'tcx>,
1229 candidates: &mut SelectionCandidateSet<'tcx>,
1230 sizedness: SizedTraitKind,
1231 ) {
1232 match *self_ty.kind() {
1233 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1235 | ty::Uint(_)
1236 | ty::Int(_)
1237 | ty::Bool
1238 | ty::Float(_)
1239 | ty::FnDef(..)
1240 | ty::FnPtr(..)
1241 | ty::RawPtr(..)
1242 | ty::Char
1243 | ty::Ref(..)
1244 | ty::Array(..)
1245 | ty::Closure(..)
1246 | ty::CoroutineClosure(..)
1247 | ty::Never
1248 | ty::Error(_) => {
1249 candidates.vec.push(SizedCandidate);
1250 }
1251
1252 ty::Coroutine(coroutine_def_id, _) => {
1253 if self.should_stall_coroutine(coroutine_def_id) {
1254 candidates.ambiguous = true;
1255 } else {
1256 candidates.vec.push(SizedCandidate);
1257 }
1258 }
1259
1260 ty::CoroutineWitness(..) => {
1261 candidates.vec.push(SizedCandidate);
1262 }
1263
1264 ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
1266 candidates.vec.push(SizedCandidate);
1267 }
1268
1269 ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
1271 SizedTraitKind::Sized => {}
1272 SizedTraitKind::MetaSized => {
1273 candidates.vec.push(SizedCandidate);
1274 }
1275 },
1276
1277 ty::Foreign(..) => {}
1279
1280 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => {}
1281
1282 ty::Infer(ty::TyVar(_)) => {
1283 candidates.ambiguous = true;
1284 }
1285
1286 ty::Bound(..) => {}
1288
1289 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1290 bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
1291 }
1292 }
1293 }
1294
1295 fn assemble_const_destruct_candidates(
1296 &mut self,
1297 _obligation: &PolyTraitObligation<'tcx>,
1298 candidates: &mut SelectionCandidateSet<'tcx>,
1299 ) {
1300 candidates.vec.push(BuiltinCandidate);
1301 }
1302
1303 fn assemble_candidate_for_tuple(
1304 &mut self,
1305 obligation: &PolyTraitObligation<'tcx>,
1306 candidates: &mut SelectionCandidateSet<'tcx>,
1307 ) {
1308 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1309 match self_ty.kind() {
1310 ty::Tuple(_) => {
1311 candidates.vec.push(BuiltinCandidate);
1312 }
1313 ty::Infer(ty::TyVar(_)) => {
1314 candidates.ambiguous = true;
1315 }
1316 ty::Bool
1317 | ty::Char
1318 | ty::Int(_)
1319 | ty::Uint(_)
1320 | ty::Float(_)
1321 | ty::Adt(_, _)
1322 | ty::Foreign(_)
1323 | ty::Str
1324 | ty::Array(_, _)
1325 | ty::Slice(_)
1326 | ty::RawPtr(_, _)
1327 | ty::Ref(_, _, _)
1328 | ty::FnDef(_, _)
1329 | ty::Pat(_, _)
1330 | ty::FnPtr(..)
1331 | ty::UnsafeBinder(_)
1332 | ty::Dynamic(_, _, _)
1333 | ty::Closure(..)
1334 | ty::CoroutineClosure(..)
1335 | ty::Coroutine(_, _)
1336 | ty::CoroutineWitness(..)
1337 | ty::Never
1338 | ty::Alias(..)
1339 | ty::Param(_)
1340 | ty::Bound(_, _)
1341 | ty::Error(_)
1342 | ty::Infer(_)
1343 | ty::Placeholder(_) => {}
1344 }
1345 }
1346
1347 fn assemble_candidates_for_fn_ptr_trait(
1348 &mut self,
1349 obligation: &PolyTraitObligation<'tcx>,
1350 candidates: &mut SelectionCandidateSet<'tcx>,
1351 ) {
1352 let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
1353
1354 match self_ty.skip_binder().kind() {
1355 ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate),
1356 ty::Bool
1357 | ty::Char
1358 | ty::Int(_)
1359 | ty::Uint(_)
1360 | ty::Float(_)
1361 | ty::Adt(..)
1362 | ty::Foreign(..)
1363 | ty::Str
1364 | ty::Array(..)
1365 | ty::Pat(..)
1366 | ty::Slice(_)
1367 | ty::RawPtr(_, _)
1368 | ty::Ref(..)
1369 | ty::FnDef(..)
1370 | ty::Placeholder(..)
1371 | ty::Dynamic(..)
1372 | ty::Closure(..)
1373 | ty::CoroutineClosure(..)
1374 | ty::Coroutine(..)
1375 | ty::CoroutineWitness(..)
1376 | ty::UnsafeBinder(_)
1377 | ty::Never
1378 | ty::Tuple(..)
1379 | ty::Alias(..)
1380 | ty::Param(..)
1381 | ty::Bound(..)
1382 | ty::Error(_)
1383 | ty::Infer(
1384 ty::InferTy::IntVar(_)
1385 | ty::InferTy::FloatVar(_)
1386 | ty::InferTy::FreshIntTy(_)
1387 | ty::InferTy::FreshFloatTy(_),
1388 ) => {}
1389 ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
1390 candidates.ambiguous = true;
1391 }
1392 }
1393 }
1394
1395 fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
1396 &mut self,
1397 obligation: &PolyTraitObligation<'tcx>,
1398 candidates: &mut SelectionCandidateSet<'tcx>,
1399 ) {
1400 match obligation.predicate.self_ty().skip_binder().kind() {
1401 ty::Ref(..)
1402 | ty::Adt(..)
1403 | ty::Tuple(_)
1404 | ty::Array(..)
1405 | ty::FnDef(..)
1406 | ty::FnPtr(..)
1407 | ty::Error(_)
1408 | ty::Uint(_)
1409 | ty::Int(_)
1410 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1411 | ty::Bool
1412 | ty::Float(_)
1413 | ty::Char
1414 | ty::RawPtr(..)
1415 | ty::Never
1416 | ty::Pat(..)
1417 | ty::Dynamic(..)
1418 | ty::Str
1419 | ty::Slice(_)
1420 | ty::Foreign(..)
1421 | ty::Alias(..)
1422 | ty::Param(_)
1423 | ty::Placeholder(..)
1424 | ty::Closure(..)
1425 | ty::CoroutineClosure(..)
1426 | ty::Coroutine(..)
1427 | ty::UnsafeBinder(_)
1428 | ty::CoroutineWitness(..)
1429 | ty::Bound(..) => {
1430 candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
1431 }
1432
1433 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1434 candidates.ambiguous = true;
1435 }
1436 }
1437 }
1438}