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