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 if tcx.is_lang_item(def_id, LangItem::Copy) {
69 debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
70
71 self.assemble_candidates_from_impls(obligation, &mut candidates);
74
75 let copy_conditions = self.copy_clone_conditions(obligation);
77 self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
78 } else if tcx.is_lang_item(def_id, LangItem::DiscriminantKind) {
79 candidates.vec.push(BuiltinCandidate { has_nested: false });
81 } else if tcx.is_lang_item(def_id, LangItem::PointeeTrait) {
82 candidates.vec.push(BuiltinCandidate { has_nested: false });
84 } else if tcx.is_lang_item(def_id, LangItem::Sized) {
85 self.assemble_builtin_sized_candidate(obligation, &mut candidates);
86 } else if tcx.is_lang_item(def_id, LangItem::Unsize) {
87 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
88 } else if tcx.is_lang_item(def_id, LangItem::Destruct) {
89 self.assemble_const_destruct_candidates(obligation, &mut candidates);
90 } else if tcx.is_lang_item(def_id, LangItem::TransmuteTrait) {
91 self.assemble_candidates_from_impls(obligation, &mut candidates);
93 self.assemble_candidates_for_transmutability(obligation, &mut candidates);
94 } else if tcx.is_lang_item(def_id, LangItem::Tuple) {
95 self.assemble_candidate_for_tuple(obligation, &mut candidates);
96 } else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
97 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
98 } else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) {
99 self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
100 obligation,
101 &mut candidates,
102 );
103 } else {
104 if tcx.is_lang_item(def_id, LangItem::Clone) {
105 let clone_conditions = self.copy_clone_conditions(obligation);
109 self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
110 }
111
112 if tcx.is_lang_item(def_id, LangItem::Coroutine) {
113 self.assemble_coroutine_candidates(obligation, &mut candidates);
114 } else if tcx.is_lang_item(def_id, LangItem::Future) {
115 self.assemble_future_candidates(obligation, &mut candidates);
116 } else if tcx.is_lang_item(def_id, LangItem::Iterator) {
117 self.assemble_iterator_candidates(obligation, &mut candidates);
118 } else if tcx.is_lang_item(def_id, LangItem::FusedIterator) {
119 self.assemble_fused_iterator_candidates(obligation, &mut candidates);
120 } else if tcx.is_lang_item(def_id, LangItem::AsyncIterator) {
121 self.assemble_async_iterator_candidates(obligation, &mut candidates);
122 } else if tcx.is_lang_item(def_id, LangItem::AsyncFnKindHelper) {
123 self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates);
124 }
125
126 self.assemble_closure_candidates(obligation, &mut candidates);
128 self.assemble_async_closure_candidates(obligation, &mut candidates);
129 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
130
131 self.assemble_candidates_from_impls(obligation, &mut candidates);
132 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
133 }
134
135 self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
136 self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
137 self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
138 }
139 debug!("candidate list size: {}", candidates.vec.len());
140 Ok(candidates)
141 }
142
143 #[instrument(level = "debug", skip(self, candidates))]
144 fn assemble_candidates_from_projected_tys(
145 &mut self,
146 obligation: &PolyTraitObligation<'tcx>,
147 candidates: &mut SelectionCandidateSet<'tcx>,
148 ) {
149 match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
152 ty::Alias(ty::Projection | ty::Opaque, _) => {}
154 ty::Infer(ty::TyVar(_)) => {
155 span_bug!(
156 obligation.cause.span,
157 "Self=_ should have been handled by assemble_candidates"
158 );
159 }
160 _ => return,
161 }
162
163 self.infcx.probe(|_| {
164 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
165 let placeholder_trait_predicate =
166 self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
167
168 let mut distinct_normalized_bounds = FxHashSet::default();
172 let _ = self.for_each_item_bound::<!>(
173 placeholder_trait_predicate.self_ty(),
174 |selcx, bound, idx| {
175 let Some(bound) = bound.as_trait_clause() else {
176 return ControlFlow::Continue(());
177 };
178 if bound.polarity() != placeholder_trait_predicate.polarity {
179 return ControlFlow::Continue(());
180 }
181
182 selcx.infcx.probe(|_| {
183 match selcx.match_normalize_trait_ref(
185 obligation,
186 placeholder_trait_predicate.trait_ref,
187 bound.map_bound(|pred| pred.trait_ref),
188 ) {
189 Ok(None) => {
190 candidates.vec.push(ProjectionCandidate(idx));
191 }
192 Ok(Some(normalized_trait))
193 if distinct_normalized_bounds.insert(normalized_trait) =>
194 {
195 candidates.vec.push(ProjectionCandidate(idx));
196 }
197 _ => {}
198 }
199 });
200
201 ControlFlow::Continue(())
202 },
203 || candidates.ambiguous = true,
205 );
206 });
207 }
208
209 #[instrument(level = "debug", skip(self, stack, candidates))]
214 fn assemble_candidates_from_caller_bounds<'o>(
215 &mut self,
216 stack: &TraitObligationStack<'o, 'tcx>,
217 candidates: &mut SelectionCandidateSet<'tcx>,
218 ) -> Result<(), SelectionError<'tcx>> {
219 debug!(?stack.obligation);
220
221 let bounds = stack
222 .obligation
223 .param_env
224 .caller_bounds()
225 .iter()
226 .filter_map(|p| p.as_trait_clause())
227 .filter(|p| p.def_id() == stack.obligation.predicate.def_id())
229 .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
230
231 let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
232 let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
233 for bound in bounds {
235 let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
236 if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
237 continue;
238 }
239 let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
240 if wc.may_apply() {
241 candidates.vec.push(ParamCandidate(bound));
242 }
243 }
244
245 Ok(())
246 }
247
248 fn assemble_coroutine_candidates(
249 &mut self,
250 obligation: &PolyTraitObligation<'tcx>,
251 candidates: &mut SelectionCandidateSet<'tcx>,
252 ) {
253 let self_ty = obligation.self_ty().skip_binder();
257 match self_ty.kind() {
258 ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => {
261 debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
262
263 candidates.vec.push(CoroutineCandidate);
264 }
265 ty::Infer(ty::TyVar(_)) => {
266 debug!("assemble_coroutine_candidates: ambiguous self-type");
267 candidates.ambiguous = true;
268 }
269 _ => {}
270 }
271 }
272
273 fn assemble_future_candidates(
274 &mut self,
275 obligation: &PolyTraitObligation<'tcx>,
276 candidates: &mut SelectionCandidateSet<'tcx>,
277 ) {
278 let self_ty = obligation.self_ty().skip_binder();
279 if let ty::Coroutine(did, ..) = self_ty.kind() {
280 if self.tcx().coroutine_is_async(*did) {
283 debug!(?self_ty, ?obligation, "assemble_future_candidates",);
284
285 candidates.vec.push(FutureCandidate);
286 }
287 }
288 }
289
290 fn assemble_iterator_candidates(
291 &mut self,
292 obligation: &PolyTraitObligation<'tcx>,
293 candidates: &mut SelectionCandidateSet<'tcx>,
294 ) {
295 let self_ty = obligation.self_ty().skip_binder();
296 if let ty::Coroutine(did, ..) = self_ty.kind()
299 && self.tcx().coroutine_is_gen(*did)
300 {
301 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
302
303 candidates.vec.push(IteratorCandidate);
304 }
305 }
306
307 fn assemble_fused_iterator_candidates(
308 &mut self,
309 obligation: &PolyTraitObligation<'tcx>,
310 candidates: &mut SelectionCandidateSet<'tcx>,
311 ) {
312 let self_ty = obligation.self_ty().skip_binder();
313 if let ty::Coroutine(did, ..) = self_ty.kind()
316 && self.tcx().coroutine_is_gen(*did)
317 {
318 debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
319
320 candidates.vec.push(BuiltinCandidate { has_nested: false });
321 }
322 }
323
324 fn assemble_async_iterator_candidates(
325 &mut self,
326 obligation: &PolyTraitObligation<'tcx>,
327 candidates: &mut SelectionCandidateSet<'tcx>,
328 ) {
329 let self_ty = obligation.self_ty().skip_binder();
330 if let ty::Coroutine(did, args) = *self_ty.kind() {
331 if self.tcx().coroutine_is_async_gen(did) {
334 debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
335
336 let ty::Adt(_poll_def, args) = *args.as_coroutine().yield_ty().kind() else {
339 candidates.ambiguous = true;
340 return;
341 };
342 let ty::Adt(_option_def, _) = *args.type_at(0).kind() else {
343 candidates.ambiguous = true;
344 return;
345 };
346
347 candidates.vec.push(AsyncIteratorCandidate);
348 }
349 }
350 }
351
352 fn assemble_closure_candidates(
359 &mut self,
360 obligation: &PolyTraitObligation<'tcx>,
361 candidates: &mut SelectionCandidateSet<'tcx>,
362 ) {
363 let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
364 return;
365 };
366
367 let self_ty = obligation.self_ty().skip_binder();
371 match *self_ty.kind() {
372 ty::Closure(def_id, _) => {
373 let is_const = self.tcx().is_const_fn(def_id);
374 debug!(?kind, ?obligation, "assemble_unboxed_candidates");
375 match self.infcx.closure_kind(self_ty) {
376 Some(closure_kind) => {
377 debug!(?closure_kind, "assemble_unboxed_candidates");
378 if closure_kind.extends(kind) {
379 candidates.vec.push(ClosureCandidate { is_const });
380 }
381 }
382 None => {
383 if kind == ty::ClosureKind::FnOnce {
384 candidates.vec.push(ClosureCandidate { is_const });
385 } else {
386 candidates.ambiguous = true;
387 }
388 }
389 }
390 }
391 ty::CoroutineClosure(def_id, args) => {
392 let args = args.as_coroutine_closure();
393 let is_const = self.tcx().is_const_fn(def_id);
394 if let Some(closure_kind) = self.infcx.closure_kind(self_ty)
395 && !args.tupled_upvars_ty().is_ty_var()
397 {
398 if closure_kind.extends(kind) && !args.has_self_borrows() {
403 candidates.vec.push(ClosureCandidate { is_const });
404 } else if kind == ty::ClosureKind::FnOnce {
405 candidates.vec.push(ClosureCandidate { is_const });
406 }
407 } else if kind == ty::ClosureKind::FnOnce {
408 candidates.vec.push(ClosureCandidate { is_const });
409 } else {
410 candidates.ambiguous = true;
412 }
413 }
414 ty::Infer(ty::TyVar(_)) => {
415 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
416 candidates.ambiguous = true;
417 }
418 _ => {}
419 }
420 }
421
422 fn assemble_async_closure_candidates(
423 &mut self,
424 obligation: &PolyTraitObligation<'tcx>,
425 candidates: &mut SelectionCandidateSet<'tcx>,
426 ) {
427 let Some(goal_kind) =
428 self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id())
429 else {
430 return;
431 };
432
433 match *obligation.self_ty().skip_binder().kind() {
434 ty::CoroutineClosure(_, args) => {
435 if let Some(closure_kind) =
436 args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
437 && !closure_kind.extends(goal_kind)
438 {
439 return;
440 }
441 candidates.vec.push(AsyncClosureCandidate);
442 }
443 ty::Closure(_, args) => {
446 if let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind()
447 && !closure_kind.extends(goal_kind)
448 {
449 return;
450 }
451 candidates.vec.push(AsyncClosureCandidate);
452 }
453 ty::FnPtr(sig_tys, hdr) => {
455 if sig_tys.with(hdr).is_fn_trait_compatible() {
456 candidates.vec.push(AsyncClosureCandidate);
457 }
458 }
459 ty::FnDef(def_id, _) => {
461 let tcx = self.tcx();
462 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
463 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
464 {
465 candidates.vec.push(AsyncClosureCandidate);
466 }
467 }
468 _ => {}
469 }
470 }
471
472 fn assemble_async_fn_kind_helper_candidates(
473 &mut self,
474 obligation: &PolyTraitObligation<'tcx>,
475 candidates: &mut SelectionCandidateSet<'tcx>,
476 ) {
477 let self_ty = obligation.self_ty().skip_binder();
478 let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
479
480 if !(self_ty.is_integral() || self_ty.is_ty_var()) {
482 return;
483 }
484 if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) {
485 return;
486 }
487
488 if let Some(closure_kind) = self_ty.to_opt_closure_kind()
491 && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
492 && closure_kind.extends(goal_kind)
493 {
494 candidates.vec.push(AsyncFnKindHelperCandidate);
495 }
496 }
497
498 fn assemble_fn_pointer_candidates(
500 &mut self,
501 obligation: &PolyTraitObligation<'tcx>,
502 candidates: &mut SelectionCandidateSet<'tcx>,
503 ) {
504 if !self.tcx().is_fn_trait(obligation.predicate.def_id()) {
506 return;
507 }
508
509 let self_ty = obligation.self_ty().skip_binder();
514 match *self_ty.kind() {
515 ty::Infer(ty::TyVar(_)) => {
516 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
517 candidates.ambiguous = true; }
519 ty::FnPtr(sig_tys, hdr) => {
521 if sig_tys.with(hdr).is_fn_trait_compatible() {
522 candidates.vec.push(FnPointerCandidate);
523 }
524 }
525 ty::FnDef(def_id, _) => {
527 let tcx = self.tcx();
528 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
529 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
530 {
531 candidates.vec.push(FnPointerCandidate);
532 }
533 }
534 _ => {}
535 }
536 }
537
538 #[instrument(level = "debug", skip(self, candidates))]
540 fn assemble_candidates_from_impls(
541 &mut self,
542 obligation: &PolyTraitObligation<'tcx>,
543 candidates: &mut SelectionCandidateSet<'tcx>,
544 ) {
545 let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
546 let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
547 self.tcx().for_each_relevant_impl(
548 obligation.predicate.def_id(),
549 obligation.predicate.skip_binder().trait_ref.self_ty(),
550 |impl_def_id| {
551 let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
555 if !drcx
556 .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
557 {
558 return;
559 }
560
561 if self.tcx().defaultness(impl_def_id).is_default() {
565 return;
566 }
567
568 if self.reject_fn_ptr_impls(
569 impl_def_id,
570 obligation,
571 impl_trait_header.trait_ref.skip_binder().self_ty(),
572 ) {
573 return;
574 }
575
576 self.infcx.probe(|_| {
577 if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_header, obligation) {
578 candidates.vec.push(ImplCandidate(impl_def_id));
579 }
580 });
581 },
582 );
583 }
584
585 #[instrument(level = "trace", skip(self), ret)]
590 fn reject_fn_ptr_impls(
591 &mut self,
592 impl_def_id: DefId,
593 obligation: &PolyTraitObligation<'tcx>,
594 impl_self_ty: Ty<'tcx>,
595 ) -> bool {
596 if !matches!(impl_self_ty.kind(), ty::Param(..)) {
598 return false;
599 }
600 let Some(fn_ptr_trait) = self.tcx().lang_items().fn_ptr_trait() else {
601 return false;
602 };
603
604 for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
605 let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
606 if fn_ptr_trait != pred.trait_ref.def_id {
607 continue;
608 }
609 trace!(?pred);
610 if pred.self_ty() != impl_self_ty {
612 continue;
613 }
614
615 let self_ty = obligation.self_ty().skip_binder();
616 match self_ty.kind() {
617 ty::FnPtr(..) => return false,
620
621 ty::Placeholder(..)
623 | ty::Dynamic(_, _, _)
624 | ty::Alias(_, _)
625 | ty::Infer(_)
626 | ty::Param(..)
627 | ty::Bound(_, _) => {}
628
629 ty::Bool
632 | ty::Char
633 | ty::Int(_)
634 | ty::Uint(_)
635 | ty::Float(_)
636 | ty::Adt(_, _)
637 | ty::Foreign(_)
638 | ty::Str
639 | ty::Array(_, _)
640 | ty::Pat(_, _)
641 | ty::Slice(_)
642 | ty::RawPtr(_, _)
643 | ty::Ref(_, _, _)
644 | ty::Closure(..)
645 | ty::CoroutineClosure(..)
646 | ty::Coroutine(_, _)
647 | ty::CoroutineWitness(..)
648 | ty::UnsafeBinder(_)
649 | ty::Never
650 | ty::Tuple(_)
651 | ty::Error(_) => return true,
652 ty::FnDef(_, _) => return true,
655 }
656
657 let obligation = Obligation::new(
660 self.tcx(),
661 obligation.cause.clone(),
662 obligation.param_env,
663 self.tcx().mk_predicate(obligation.predicate.map_bound(|mut pred| {
664 pred.trait_ref =
665 ty::TraitRef::new(self.tcx(), fn_ptr_trait, [pred.trait_ref.self_ty()]);
666 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
667 })),
668 );
669 if let Ok(r) = self.evaluate_root_obligation(&obligation) {
670 if !r.may_apply() {
671 return true;
672 }
673 }
674 }
675 false
676 }
677
678 fn assemble_candidates_from_auto_impls(
679 &mut self,
680 obligation: &PolyTraitObligation<'tcx>,
681 candidates: &mut SelectionCandidateSet<'tcx>,
682 ) {
683 let self_ty = obligation.self_ty().skip_binder();
685 debug!(?self_ty, "assemble_candidates_from_auto_impls");
686
687 let def_id = obligation.predicate.def_id();
688
689 let mut check_impls = || {
690 let mut has_impl = false;
700 self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
701 if !has_impl {
702 candidates.vec.push(AutoImplCandidate)
703 }
704 };
705
706 if self.tcx().trait_is_auto(def_id) {
707 match *self_ty.kind() {
708 ty::Dynamic(..) => {
709 }
714 ty::Foreign(..) => {
715 if self.tcx().is_default_trait(def_id) {
723 check_impls()
724 }
725 }
726 ty::Param(..)
727 | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..)
728 | ty::Placeholder(..)
729 | ty::Bound(..) => {
730 }
744 ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
745 candidates.ambiguous = true;
747 }
748 ty::Coroutine(coroutine_def_id, _)
749 if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
750 {
751 match self.tcx().coroutine_movability(coroutine_def_id) {
752 hir::Movability::Static => {
753 }
756 hir::Movability::Movable => {
757 candidates.vec.push(BuiltinCandidate { has_nested: false });
760 }
761 }
762 }
763
764 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
765 bug!(
766 "asked to assemble auto trait candidates of unexpected type: {:?}",
767 self_ty
768 );
769 }
770
771 ty::Alias(ty::Opaque, alias) => {
772 if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
773 } else if let TypingMode::Coherence = self.infcx.typing_mode() {
783 candidates.ambiguous = true;
786 } else if self.infcx.can_define_opaque_ty(alias.def_id) {
787 candidates.ambiguous = true;
791 } else {
792 candidates.vec.push(AutoImplCandidate)
793 }
794 }
795
796 ty::Bool
797 | ty::Char
798 | ty::Int(_)
799 | ty::Uint(_)
800 | ty::Float(_)
801 | ty::Str
802 | ty::Array(_, _)
803 | ty::Pat(_, _)
804 | ty::Slice(_)
805 | ty::Adt(..)
806 | ty::RawPtr(_, _)
807 | ty::Ref(..)
808 | ty::FnDef(..)
809 | ty::FnPtr(..)
810 | ty::Closure(..)
811 | ty::CoroutineClosure(..)
812 | ty::Coroutine(..)
813 | ty::Never
814 | ty::Tuple(_)
815 | ty::CoroutineWitness(..)
816 | ty::UnsafeBinder(_) => {
817 if self.tcx().trait_def(def_id).safety.is_unsafe()
820 && self_ty.has_unsafe_fields()
821 {
822 return;
823 }
824
825 check_impls();
826 }
827 ty::Error(_) => {
828 candidates.vec.push(AutoImplCandidate);
829 }
830 }
831 }
832 }
833
834 fn assemble_candidates_from_object_ty(
836 &mut self,
837 obligation: &PolyTraitObligation<'tcx>,
838 candidates: &mut SelectionCandidateSet<'tcx>,
839 ) {
840 debug!(
841 self_ty = ?obligation.self_ty().skip_binder(),
842 "assemble_candidates_from_object_ty",
843 );
844
845 if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
846 return;
847 }
848
849 self.infcx.probe(|_snapshot| {
850 let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
851 self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
852 let self_ty = placeholder_trait_predicate.self_ty();
853 let principal_trait_ref = match self_ty.kind() {
854 ty::Dynamic(data, ..) => {
855 if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
856 debug!(
857 "assemble_candidates_from_object_ty: matched builtin bound, \
858 pushing candidate"
859 );
860 candidates.vec.push(BuiltinObjectCandidate);
861 return;
862 }
863
864 if let Some(principal) = data.principal() {
865 principal.with_self_ty(self.tcx(), self_ty)
866 } else {
867 return;
869 }
870 }
871 ty::Infer(ty::TyVar(_)) => {
872 debug!("assemble_candidates_from_object_ty: ambiguous");
873 candidates.ambiguous = true; return;
875 }
876 _ => return,
877 };
878
879 debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
880
881 let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
887 .enumerate()
888 .filter(|&(_, upcast_trait_ref)| {
889 self.infcx.probe(|_| {
890 self.match_normalize_trait_ref(
891 obligation,
892 placeholder_trait_predicate.trait_ref,
893 upcast_trait_ref,
894 )
895 .is_ok()
896 })
897 })
898 .map(|(idx, _)| ObjectCandidate(idx));
899
900 candidates.vec.extend(candidate_supertraits);
901 })
902 })
903 }
904
905 fn assemble_candidates_for_unsizing(
907 &mut self,
908 obligation: &PolyTraitObligation<'tcx>,
909 candidates: &mut SelectionCandidateSet<'tcx>,
910 ) {
911 let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
926 return;
928 };
929 let source = trait_pred.self_ty();
930 let target = trait_pred.trait_ref.args.type_at(1);
931
932 debug!(?source, ?target, "assemble_candidates_for_unsizing");
933
934 match (source.kind(), target.kind()) {
935 (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => {
937 let principal_def_id_a = a_data.principal_def_id();
949 let principal_def_id_b = b_data.principal_def_id();
950 if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
951 let a_auto_traits: FxIndexSet<DefId> = a_data
955 .auto_traits()
956 .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
957 elaborate::supertrait_def_ids(self.tcx(), principal_def_id)
958 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
959 }))
960 .collect();
961 let auto_traits_compatible = b_data
962 .auto_traits()
963 .all(|b| a_auto_traits.contains(&b));
965 if auto_traits_compatible {
966 candidates.vec.push(BuiltinUnsizeCandidate);
967 }
968 } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
969 let principal_a = a_data.principal().unwrap();
971 let target_trait_did = principal_def_id_b.unwrap();
972 let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
973
974 for (idx, upcast_trait_ref) in
975 util::supertraits(self.tcx(), source_trait_ref).enumerate()
976 {
977 self.infcx.probe(|_| {
978 if upcast_trait_ref.def_id() == target_trait_did
979 && let Ok(nested) = self.match_upcast_principal(
980 obligation,
981 upcast_trait_ref,
982 a_data,
983 b_data,
984 a_region,
985 b_region,
986 )
987 {
988 if nested.is_none() {
989 candidates.ambiguous = true;
990 }
991 candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
992 }
993 })
994 }
995 }
996 }
997
998 (_, &ty::Dynamic(_, _, ty::Dyn)) => {
1000 candidates.vec.push(BuiltinUnsizeCandidate);
1001 }
1002
1003 (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
1007 debug!("assemble_candidates_for_unsizing: ambiguous");
1008 candidates.ambiguous = true;
1009 }
1010
1011 (&ty::Array(..), &ty::Slice(_)) => {
1013 candidates.vec.push(BuiltinUnsizeCandidate);
1014 }
1015
1016 (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
1018 if def_id_a == def_id_b {
1019 candidates.vec.push(BuiltinUnsizeCandidate);
1020 }
1021 }
1022
1023 _ => {}
1024 };
1025 }
1026
1027 #[instrument(level = "debug", skip(self, obligation, candidates))]
1028 fn assemble_candidates_for_transmutability(
1029 &mut self,
1030 obligation: &PolyTraitObligation<'tcx>,
1031 candidates: &mut SelectionCandidateSet<'tcx>,
1032 ) {
1033 if obligation.predicate.has_non_region_param() {
1034 return;
1035 }
1036
1037 if obligation.has_non_region_infer() {
1038 candidates.ambiguous = true;
1039 return;
1040 }
1041
1042 candidates.vec.push(TransmutabilityCandidate);
1043 }
1044
1045 #[instrument(level = "debug", skip(self, obligation, candidates))]
1046 fn assemble_candidates_for_trait_alias(
1047 &mut self,
1048 obligation: &PolyTraitObligation<'tcx>,
1049 candidates: &mut SelectionCandidateSet<'tcx>,
1050 ) {
1051 let self_ty = obligation.self_ty().skip_binder();
1053 debug!(?self_ty);
1054
1055 let def_id = obligation.predicate.def_id();
1056
1057 if self.tcx().is_trait_alias(def_id) {
1058 candidates.vec.push(TraitAliasCandidate);
1059 }
1060 }
1061
1062 #[instrument(level = "debug", skip(self, candidates))]
1065 fn assemble_builtin_sized_candidate(
1066 &mut self,
1067 obligation: &PolyTraitObligation<'tcx>,
1068 candidates: &mut SelectionCandidateSet<'tcx>,
1069 ) {
1070 match self.sized_conditions(obligation) {
1071 BuiltinImplConditions::Where(nested) => {
1072 candidates
1073 .vec
1074 .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
1075 }
1076 BuiltinImplConditions::None => {}
1077 BuiltinImplConditions::Ambiguous => {
1078 candidates.ambiguous = true;
1079 }
1080 }
1081 }
1082
1083 #[instrument(level = "debug", skip(self, candidates))]
1086 fn assemble_builtin_bound_candidates(
1087 &mut self,
1088 conditions: BuiltinImplConditions<'tcx>,
1089 candidates: &mut SelectionCandidateSet<'tcx>,
1090 ) {
1091 match conditions {
1092 BuiltinImplConditions::Where(nested) => {
1093 candidates
1094 .vec
1095 .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
1096 }
1097 BuiltinImplConditions::None => {}
1098 BuiltinImplConditions::Ambiguous => {
1099 candidates.ambiguous = true;
1100 }
1101 }
1102 }
1103
1104 fn assemble_const_destruct_candidates(
1105 &mut self,
1106 _obligation: &PolyTraitObligation<'tcx>,
1107 candidates: &mut SelectionCandidateSet<'tcx>,
1108 ) {
1109 candidates.vec.push(BuiltinCandidate { has_nested: false });
1110 }
1111
1112 fn assemble_candidate_for_tuple(
1113 &mut self,
1114 obligation: &PolyTraitObligation<'tcx>,
1115 candidates: &mut SelectionCandidateSet<'tcx>,
1116 ) {
1117 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
1118 match self_ty.kind() {
1119 ty::Tuple(_) => {
1120 candidates.vec.push(BuiltinCandidate { has_nested: false });
1121 }
1122 ty::Infer(ty::TyVar(_)) => {
1123 candidates.ambiguous = true;
1124 }
1125 ty::Bool
1126 | ty::Char
1127 | ty::Int(_)
1128 | ty::Uint(_)
1129 | ty::Float(_)
1130 | ty::Adt(_, _)
1131 | ty::Foreign(_)
1132 | ty::Str
1133 | ty::Array(_, _)
1134 | ty::Slice(_)
1135 | ty::RawPtr(_, _)
1136 | ty::Ref(_, _, _)
1137 | ty::FnDef(_, _)
1138 | ty::Pat(_, _)
1139 | ty::FnPtr(..)
1140 | ty::UnsafeBinder(_)
1141 | ty::Dynamic(_, _, _)
1142 | ty::Closure(..)
1143 | ty::CoroutineClosure(..)
1144 | ty::Coroutine(_, _)
1145 | ty::CoroutineWitness(..)
1146 | ty::Never
1147 | ty::Alias(..)
1148 | ty::Param(_)
1149 | ty::Bound(_, _)
1150 | ty::Error(_)
1151 | ty::Infer(_)
1152 | ty::Placeholder(_) => {}
1153 }
1154 }
1155
1156 fn assemble_candidates_for_fn_ptr_trait(
1157 &mut self,
1158 obligation: &PolyTraitObligation<'tcx>,
1159 candidates: &mut SelectionCandidateSet<'tcx>,
1160 ) {
1161 let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
1162
1163 match self_ty.skip_binder().kind() {
1164 ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
1165 ty::Bool
1166 | ty::Char
1167 | ty::Int(_)
1168 | ty::Uint(_)
1169 | ty::Float(_)
1170 | ty::Adt(..)
1171 | ty::Foreign(..)
1172 | ty::Str
1173 | ty::Array(..)
1174 | ty::Pat(..)
1175 | ty::Slice(_)
1176 | ty::RawPtr(_, _)
1177 | ty::Ref(..)
1178 | ty::FnDef(..)
1179 | ty::Placeholder(..)
1180 | ty::Dynamic(..)
1181 | ty::Closure(..)
1182 | ty::CoroutineClosure(..)
1183 | ty::Coroutine(..)
1184 | ty::CoroutineWitness(..)
1185 | ty::UnsafeBinder(_)
1186 | ty::Never
1187 | ty::Tuple(..)
1188 | ty::Alias(..)
1189 | ty::Param(..)
1190 | ty::Bound(..)
1191 | ty::Error(_)
1192 | ty::Infer(
1193 ty::InferTy::IntVar(_)
1194 | ty::InferTy::FloatVar(_)
1195 | ty::InferTy::FreshIntTy(_)
1196 | ty::InferTy::FreshFloatTy(_),
1197 ) => {}
1198 ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
1199 candidates.ambiguous = true;
1200 }
1201 }
1202 }
1203
1204 fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
1205 &mut self,
1206 obligation: &PolyTraitObligation<'tcx>,
1207 candidates: &mut SelectionCandidateSet<'tcx>,
1208 ) {
1209 match obligation.predicate.self_ty().skip_binder().kind() {
1210 ty::Ref(..)
1211 | ty::Adt(..)
1212 | ty::Tuple(_)
1213 | ty::Array(..)
1214 | ty::FnDef(..)
1215 | ty::FnPtr(..)
1216 | ty::Error(_)
1217 | ty::Uint(_)
1218 | ty::Int(_)
1219 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1220 | ty::Bool
1221 | ty::Float(_)
1222 | ty::Char
1223 | ty::RawPtr(..)
1224 | ty::Never
1225 | ty::Pat(..)
1226 | ty::Dynamic(..)
1227 | ty::Str
1228 | ty::Slice(_)
1229 | ty::Foreign(..)
1230 | ty::Alias(..)
1231 | ty::Param(_)
1232 | ty::Placeholder(..)
1233 | ty::Closure(..)
1234 | ty::CoroutineClosure(..)
1235 | ty::Coroutine(..)
1236 | ty::UnsafeBinder(_)
1237 | ty::CoroutineWitness(..)
1238 | ty::Bound(..) => {
1239 candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
1240 }
1241
1242 ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1243 candidates.ambiguous = true;
1244 }
1245 }
1246 }
1247}