]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_trait_selection/src/traits/select/confirmation.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / select / confirmation.rs
1 //! Confirmation.
2 //!
3 //! Confirmation unifies the output type parameters of the trait
4 //! with the values found in the obligation, possibly yielding a
5 //! type error. See the [rustc dev guide] for more details.
6 //!
7 //! [rustc dev guide]:
8 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
9 use rustc_ast::Mutability;
10 use rustc_data_structures::stack::ensure_sufficient_stack;
11 use rustc_hir::lang_items::LangItem;
12 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
13 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
14 use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
15 use rustc_middle::ty::{
16 self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
17 TraitPredicate, Ty, TyCtxt, TypeVisitableExt,
18 };
19 use rustc_span::def_id::DefId;
20
21 use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
22 use crate::traits::util::{self, closure_trait_ref_and_return_type};
23 use crate::traits::vtable::{
24 count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
25 VtblSegment,
26 };
27 use crate::traits::{
28 BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
29 ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
30 OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection,
31 SelectionError, TraitNotObjectSafe, Unimplemented,
32 };
33
34 use super::BuiltinImplConditions;
35 use super::SelectionCandidate::{self, *};
36 use super::SelectionContext;
37
38 use std::iter;
39 use std::ops::ControlFlow;
40
41 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
42 #[instrument(level = "debug", skip(self))]
43 pub(super) fn confirm_candidate(
44 &mut self,
45 obligation: &PolyTraitObligation<'tcx>,
46 candidate: SelectionCandidate<'tcx>,
47 ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
48 let mut impl_src = match candidate {
49 BuiltinCandidate { has_nested } => {
50 let data = self.confirm_builtin_candidate(obligation, has_nested);
51 ImplSource::Builtin(BuiltinImplSource::Misc, data)
52 }
53
54 TransmutabilityCandidate => {
55 let data = self.confirm_transmutability_candidate(obligation)?;
56 ImplSource::Builtin(BuiltinImplSource::Misc, data)
57 }
58
59 ParamCandidate(param) => {
60 let obligations =
61 self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
62 ImplSource::Param(obligations)
63 }
64
65 ImplCandidate(impl_def_id) => {
66 ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
67 }
68
69 AutoImplCandidate => {
70 let data = self.confirm_auto_impl_candidate(obligation)?;
71 ImplSource::Builtin(BuiltinImplSource::Misc, data)
72 }
73
74 ProjectionCandidate(idx, _) => {
75 let obligations = self.confirm_projection_candidate(obligation, idx)?;
76 ImplSource::Param(obligations)
77 }
78
79 ObjectCandidate(idx) => self.confirm_object_candidate(obligation, idx)?,
80
81 ClosureCandidate { .. } => {
82 let vtable_closure = self.confirm_closure_candidate(obligation)?;
83 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure)
84 }
85
86 GeneratorCandidate => {
87 let vtable_generator = self.confirm_generator_candidate(obligation)?;
88 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_generator)
89 }
90
91 FutureCandidate => {
92 let vtable_future = self.confirm_future_candidate(obligation)?;
93 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_future)
94 }
95
96 FnPointerCandidate { is_const } => {
97 let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
98 ImplSource::Builtin(BuiltinImplSource::Misc, data)
99 }
100
101 TraitAliasCandidate => {
102 let data = self.confirm_trait_alias_candidate(obligation);
103 ImplSource::Builtin(BuiltinImplSource::Misc, data)
104 }
105
106 BuiltinObjectCandidate => {
107 // This indicates something like `Trait + Send: Send`. In this case, we know that
108 // this holds because that's what the object type is telling us, and there's really
109 // no additional obligations to prove and no types in particular to unify, etc.
110 ImplSource::Builtin(BuiltinImplSource::Misc, Vec::new())
111 }
112
113 BuiltinUnsizeCandidate => self.confirm_builtin_unsize_candidate(obligation)?,
114
115 TraitUpcastingUnsizeCandidate(idx) => {
116 self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
117 }
118
119 ConstDestructCandidate(def_id) => {
120 let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
121 ImplSource::Builtin(BuiltinImplSource::Misc, data)
122 }
123 };
124
125 // The obligations returned by confirmation are recursively evaluated
126 // so we need to make sure they have the correct depth.
127 for subobligation in impl_src.borrow_nested_obligations_mut() {
128 subobligation.set_depth_from_parent(obligation.recursion_depth);
129 }
130
131 Ok(impl_src)
132 }
133
134 fn confirm_projection_candidate(
135 &mut self,
136 obligation: &PolyTraitObligation<'tcx>,
137 idx: usize,
138 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
139 let tcx = self.tcx();
140
141 let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
142 let placeholder_trait_predicate =
143 self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
144 let placeholder_self_ty = placeholder_trait_predicate.self_ty();
145 let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
146 let (def_id, args) = match *placeholder_self_ty.kind() {
147 // Excluding IATs and type aliases here as they don't have meaningful item bounds.
148 ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
149 (def_id, args)
150 }
151 _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
152 };
153
154 let candidate_predicate =
155 tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args);
156 let candidate = candidate_predicate
157 .as_trait_clause()
158 .expect("projection candidate is not a trait predicate")
159 .map_bound(|t| t.trait_ref);
160 let mut obligations = Vec::new();
161 let candidate = normalize_with_depth_to(
162 self,
163 obligation.param_env,
164 obligation.cause.clone(),
165 obligation.recursion_depth + 1,
166 candidate,
167 &mut obligations,
168 );
169
170 obligations.extend(self.infcx.commit_if_ok(|_| {
171 self.infcx
172 .at(&obligation.cause, obligation.param_env)
173 .sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
174 .map(|InferOk { obligations, .. }| obligations)
175 .map_err(|_| Unimplemented)
176 })?);
177
178 if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
179 let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
180 for (predicate, _) in predicates {
181 let normalized = normalize_with_depth_to(
182 self,
183 obligation.param_env,
184 obligation.cause.clone(),
185 obligation.recursion_depth + 1,
186 predicate,
187 &mut obligations,
188 );
189 obligations.push(Obligation::with_depth(
190 self.tcx(),
191 obligation.cause.clone(),
192 obligation.recursion_depth + 1,
193 obligation.param_env,
194 normalized,
195 ));
196 }
197 }
198
199 Ok(obligations)
200 }
201
202 fn confirm_param_candidate(
203 &mut self,
204 obligation: &PolyTraitObligation<'tcx>,
205 param: ty::PolyTraitRef<'tcx>,
206 ) -> Vec<PredicateObligation<'tcx>> {
207 debug!(?obligation, ?param, "confirm_param_candidate");
208
209 // During evaluation, we already checked that this
210 // where-clause trait-ref could be unified with the obligation
211 // trait-ref. Repeat that unification now without any
212 // transactional boundary; it should not fail.
213 match self.match_where_clause_trait_ref(obligation, param) {
214 Ok(obligations) => obligations,
215 Err(()) => {
216 bug!(
217 "Where clause `{:?}` was applicable to `{:?}` but now is not",
218 param,
219 obligation
220 );
221 }
222 }
223 }
224
225 fn confirm_builtin_candidate(
226 &mut self,
227 obligation: &PolyTraitObligation<'tcx>,
228 has_nested: bool,
229 ) -> Vec<PredicateObligation<'tcx>> {
230 debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
231
232 let lang_items = self.tcx().lang_items();
233 let obligations = if has_nested {
234 let trait_def = obligation.predicate.def_id();
235 let conditions = if Some(trait_def) == lang_items.sized_trait() {
236 self.sized_conditions(obligation)
237 } else if Some(trait_def) == lang_items.copy_trait() {
238 self.copy_clone_conditions(obligation)
239 } else if Some(trait_def) == lang_items.clone_trait() {
240 self.copy_clone_conditions(obligation)
241 } else {
242 bug!("unexpected builtin trait {:?}", trait_def)
243 };
244 let BuiltinImplConditions::Where(nested) = conditions else {
245 bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
246 };
247
248 let cause = obligation.derived_cause(BuiltinDerivedObligation);
249 self.collect_predicates_for_types(
250 obligation.param_env,
251 cause,
252 obligation.recursion_depth + 1,
253 trait_def,
254 nested,
255 )
256 } else {
257 vec![]
258 };
259
260 debug!(?obligations);
261
262 obligations
263 }
264
265 #[instrument(level = "debug", skip(self))]
266 fn confirm_transmutability_candidate(
267 &mut self,
268 obligation: &PolyTraitObligation<'tcx>,
269 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
270 use rustc_transmute::{Answer, Condition};
271 #[instrument(level = "debug", skip(tcx, obligation, predicate))]
272 fn flatten_answer_tree<'tcx>(
273 tcx: TyCtxt<'tcx>,
274 obligation: &PolyTraitObligation<'tcx>,
275 predicate: TraitPredicate<'tcx>,
276 cond: Condition<rustc_transmute::layout::rustc::Ref<'tcx>>,
277 ) -> Vec<PredicateObligation<'tcx>> {
278 match cond {
279 // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll`
280 // Not possible until the trait solver supports disjunctions of obligations
281 Condition::IfAll(conds) | Condition::IfAny(conds) => conds
282 .into_iter()
283 .flat_map(|cond| flatten_answer_tree(tcx, obligation, predicate, cond))
284 .collect(),
285 Condition::IfTransmutable { src, dst } => {
286 let trait_def_id = obligation.predicate.def_id();
287 let scope = predicate.trait_ref.args.type_at(2);
288 let assume_const = predicate.trait_ref.args.const_at(3);
289 let make_obl = |from_ty, to_ty| {
290 let trait_ref1 = ty::TraitRef::new(
291 tcx,
292 trait_def_id,
293 [
294 ty::GenericArg::from(to_ty),
295 ty::GenericArg::from(from_ty),
296 ty::GenericArg::from(scope),
297 ty::GenericArg::from(assume_const),
298 ],
299 );
300 Obligation::with_depth(
301 tcx,
302 obligation.cause.clone(),
303 obligation.recursion_depth + 1,
304 obligation.param_env,
305 trait_ref1,
306 )
307 };
308
309 // If Dst is mutable, check bidirectionally.
310 // For example, transmuting bool -> u8 is OK as long as you can't update that u8
311 // to be > 1, because you could later transmute the u8 back to a bool and get UB.
312 match dst.mutability {
313 Mutability::Not => vec![make_obl(src.ty, dst.ty)],
314 Mutability::Mut => vec![make_obl(src.ty, dst.ty), make_obl(dst.ty, src.ty)],
315 }
316 }
317 }
318 }
319
320 // We erase regions here because transmutability calls layout queries,
321 // which does not handle inference regions and doesn't particularly
322 // care about other regions. Erasing late-bound regions is equivalent
323 // to instantiating the binder with placeholders then erasing those
324 // placeholder regions.
325 let predicate =
326 self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate));
327
328 let Some(assume) = rustc_transmute::Assume::from_const(
329 self.infcx.tcx,
330 obligation.param_env,
331 predicate.trait_ref.args.const_at(3),
332 ) else {
333 return Err(Unimplemented);
334 };
335
336 let dst = predicate.trait_ref.args.type_at(0);
337 let src = predicate.trait_ref.args.type_at(1);
338 debug!(?src, ?dst);
339 let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
340 let maybe_transmutable = transmute_env.is_transmutable(
341 obligation.cause.clone(),
342 rustc_transmute::Types { dst, src },
343 predicate.trait_ref.args.type_at(2),
344 assume,
345 );
346
347 let fully_flattened = match maybe_transmutable {
348 Answer::No(_) => Err(Unimplemented)?,
349 Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, predicate, cond),
350 Answer::Yes => vec![],
351 };
352
353 debug!(?fully_flattened);
354 Ok(fully_flattened)
355 }
356
357 /// This handles the case where an `auto trait Foo` impl is being used.
358 /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
359 ///
360 /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
361 /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
362 fn confirm_auto_impl_candidate(
363 &mut self,
364 obligation: &PolyTraitObligation<'tcx>,
365 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
366 debug!(?obligation, "confirm_auto_impl_candidate");
367
368 let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
369 let types = self.constituent_types_for_ty(self_ty)?;
370 Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
371 }
372
373 /// See `confirm_auto_impl_candidate`.
374 fn vtable_auto_impl(
375 &mut self,
376 obligation: &PolyTraitObligation<'tcx>,
377 trait_def_id: DefId,
378 nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
379 ) -> Vec<PredicateObligation<'tcx>> {
380 debug!(?nested, "vtable_auto_impl");
381 ensure_sufficient_stack(|| {
382 let cause = obligation.derived_cause(BuiltinDerivedObligation);
383
384 let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
385 let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref);
386 let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations(
387 &cause,
388 obligation.recursion_depth + 1,
389 obligation.param_env,
390 trait_def_id,
391 &trait_ref.args,
392 obligation.predicate,
393 );
394
395 let mut obligations = self.collect_predicates_for_types(
396 obligation.param_env,
397 cause,
398 obligation.recursion_depth + 1,
399 trait_def_id,
400 nested,
401 );
402
403 // Adds the predicates from the trait. Note that this contains a `Self: Trait`
404 // predicate as usual. It won't have any effect since auto traits are coinductive.
405 obligations.extend(trait_obligations);
406
407 debug!(?obligations, "vtable_auto_impl");
408
409 obligations
410 })
411 }
412
413 fn confirm_impl_candidate(
414 &mut self,
415 obligation: &PolyTraitObligation<'tcx>,
416 impl_def_id: DefId,
417 ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
418 debug!(?obligation, ?impl_def_id, "confirm_impl_candidate");
419
420 // First, create the substitutions by matching the impl again,
421 // this time not in a probe.
422 let args = self.rematch_impl(impl_def_id, obligation);
423 debug!(?args, "impl args");
424 ensure_sufficient_stack(|| {
425 self.vtable_impl(
426 impl_def_id,
427 args,
428 &obligation.cause,
429 obligation.recursion_depth + 1,
430 obligation.param_env,
431 obligation.predicate,
432 )
433 })
434 }
435
436 fn vtable_impl(
437 &mut self,
438 impl_def_id: DefId,
439 args: Normalized<'tcx, GenericArgsRef<'tcx>>,
440 cause: &ObligationCause<'tcx>,
441 recursion_depth: usize,
442 param_env: ty::ParamEnv<'tcx>,
443 parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
444 ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
445 debug!(?impl_def_id, ?args, ?recursion_depth, "vtable_impl");
446
447 let mut impl_obligations = self.impl_or_trait_obligations(
448 cause,
449 recursion_depth,
450 param_env,
451 impl_def_id,
452 &args.value,
453 parent_trait_pred,
454 );
455
456 debug!(?impl_obligations, "vtable_impl");
457
458 // Because of RFC447, the impl-trait-ref and obligations
459 // are sufficient to determine the impl args, without
460 // relying on projections in the impl-trait-ref.
461 //
462 // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
463 impl_obligations.extend(args.obligations);
464
465 ImplSourceUserDefinedData { impl_def_id, args: args.value, nested: impl_obligations }
466 }
467
468 fn confirm_object_candidate(
469 &mut self,
470 obligation: &PolyTraitObligation<'tcx>,
471 index: usize,
472 ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
473 let tcx = self.tcx();
474 debug!(?obligation, ?index, "confirm_object_candidate");
475
476 let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
477 let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
478 let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
479 let ty::Dynamic(data, ..) = *self_ty.kind() else {
480 span_bug!(obligation.cause.span, "object candidate with non-object");
481 };
482
483 let object_trait_ref = data.principal().unwrap_or_else(|| {
484 span_bug!(obligation.cause.span, "object candidate with no principal")
485 });
486 let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
487 obligation.cause.span,
488 HigherRankedType,
489 object_trait_ref,
490 );
491 let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty);
492
493 let mut nested = vec![];
494
495 let mut supertraits = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref));
496 let unnormalized_upcast_trait_ref =
497 supertraits.nth(index).expect("supertraits iterator no longer has as many elements");
498
499 let upcast_trait_ref = normalize_with_depth_to(
500 self,
501 obligation.param_env,
502 obligation.cause.clone(),
503 obligation.recursion_depth + 1,
504 unnormalized_upcast_trait_ref,
505 &mut nested,
506 );
507
508 nested.extend(self.infcx.commit_if_ok(|_| {
509 self.infcx
510 .at(&obligation.cause, obligation.param_env)
511 .sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref)
512 .map(|InferOk { obligations, .. }| obligations)
513 .map_err(|_| Unimplemented)
514 })?);
515
516 // Check supertraits hold. This is so that their associated type bounds
517 // will be checked in the code below.
518 for super_trait in tcx
519 .super_predicates_of(trait_predicate.def_id())
520 .instantiate(tcx, trait_predicate.trait_ref.args)
521 .predicates
522 .into_iter()
523 {
524 let normalized_super_trait = normalize_with_depth_to(
525 self,
526 obligation.param_env,
527 obligation.cause.clone(),
528 obligation.recursion_depth + 1,
529 super_trait,
530 &mut nested,
531 );
532 nested.push(obligation.with(tcx, normalized_super_trait));
533 }
534
535 let assoc_types: Vec<_> = tcx
536 .associated_items(trait_predicate.def_id())
537 .in_definition_order()
538 // Associated types that require `Self: Sized` do not show up in the built-in
539 // implementation of `Trait for dyn Trait`, and can be dropped here.
540 .filter(|item| !tcx.generics_require_sized_self(item.def_id))
541 .filter_map(
542 |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
543 )
544 .collect();
545
546 for assoc_type in assoc_types {
547 let defs: &ty::Generics = tcx.generics_of(assoc_type);
548
549 if !defs.params.is_empty() && !tcx.features().generic_associated_types_extended {
550 tcx.sess.delay_span_bug(
551 obligation.cause.span,
552 "GATs in trait object shouldn't have been considered",
553 );
554 return Err(SelectionError::TraitNotObjectSafe(trait_predicate.trait_ref.def_id));
555 }
556
557 // This maybe belongs in wf, but that can't (doesn't) handle
558 // higher-ranked things.
559 // Prevent, e.g., `dyn Iterator<Item = str>`.
560 for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
561 let subst_bound = if defs.count() == 0 {
562 bound.instantiate(tcx, trait_predicate.trait_ref.args)
563 } else {
564 let mut args = smallvec::SmallVec::with_capacity(defs.count());
565 args.extend(trait_predicate.trait_ref.args.iter());
566 let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
567 smallvec::SmallVec::with_capacity(
568 bound.skip_binder().kind().bound_vars().len() + defs.count(),
569 );
570 bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
571 GenericArgs::fill_single(&mut args, defs, &mut |param, _| match param.kind {
572 GenericParamDefKind::Type { .. } => {
573 let kind = ty::BoundTyKind::Param(param.def_id, param.name);
574 let bound_var = ty::BoundVariableKind::Ty(kind);
575 bound_vars.push(bound_var);
576 Ty::new_bound(
577 tcx,
578 ty::INNERMOST,
579 ty::BoundTy {
580 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
581 kind,
582 },
583 )
584 .into()
585 }
586 GenericParamDefKind::Lifetime => {
587 let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
588 let bound_var = ty::BoundVariableKind::Region(kind);
589 bound_vars.push(bound_var);
590 ty::Region::new_late_bound(
591 tcx,
592 ty::INNERMOST,
593 ty::BoundRegion {
594 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
595 kind,
596 },
597 )
598 .into()
599 }
600 GenericParamDefKind::Const { .. } => {
601 let bound_var = ty::BoundVariableKind::Const;
602 bound_vars.push(bound_var);
603 ty::Const::new_bound(
604 tcx,
605 ty::INNERMOST,
606 ty::BoundVar::from_usize(bound_vars.len() - 1),
607 tcx.type_of(param.def_id)
608 .no_bound_vars()
609 .expect("const parameter types cannot be generic"),
610 )
611 .into()
612 }
613 });
614 let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
615 let assoc_ty_args = tcx.mk_args(&args);
616 let bound =
617 bound.map_bound(|b| b.kind().skip_binder()).instantiate(tcx, assoc_ty_args);
618 ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
619 };
620 let normalized_bound = normalize_with_depth_to(
621 self,
622 obligation.param_env,
623 obligation.cause.clone(),
624 obligation.recursion_depth + 1,
625 subst_bound,
626 &mut nested,
627 );
628 nested.push(obligation.with(tcx, normalized_bound));
629 }
630 }
631
632 debug!(?nested, "object nested obligations");
633
634 let vtable_base = vtable_trait_first_method_offset(
635 tcx,
636 (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
637 );
638
639 Ok(ImplSource::Builtin(BuiltinImplSource::Object { vtable_base: vtable_base }, nested))
640 }
641
642 fn confirm_fn_pointer_candidate(
643 &mut self,
644 obligation: &PolyTraitObligation<'tcx>,
645 // FIXME(effects)
646 _is_const: bool,
647 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
648 debug!(?obligation, "confirm_fn_pointer_candidate");
649
650 let tcx = self.tcx();
651
652 let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else {
653 // FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
654 // but we do not currently. Luckily, such a bound is not
655 // particularly useful, so we don't expect users to write
656 // them often.
657 return Err(SelectionError::Unimplemented);
658 };
659
660 let sig = self_ty.fn_sig(tcx);
661 let trait_ref = closure_trait_ref_and_return_type(
662 tcx,
663 obligation.predicate.def_id(),
664 self_ty,
665 sig,
666 util::TupleArgumentsFlag::Yes,
667 )
668 .map_bound(|(trait_ref, _)| trait_ref);
669
670 let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
671 let cause = obligation.derived_cause(BuiltinDerivedObligation);
672
673 // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
674 let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
675 let output_ty = normalize_with_depth_to(
676 self,
677 obligation.param_env,
678 cause.clone(),
679 obligation.recursion_depth,
680 output_ty,
681 &mut nested,
682 );
683 let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]);
684 nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
685
686 Ok(nested)
687 }
688
689 fn confirm_trait_alias_candidate(
690 &mut self,
691 obligation: &PolyTraitObligation<'tcx>,
692 ) -> Vec<PredicateObligation<'tcx>> {
693 debug!(?obligation, "confirm_trait_alias_candidate");
694
695 let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
696 let trait_ref = predicate.trait_ref;
697 let trait_def_id = trait_ref.def_id;
698 let args = trait_ref.args;
699
700 let trait_obligations = self.impl_or_trait_obligations(
701 &obligation.cause,
702 obligation.recursion_depth,
703 obligation.param_env,
704 trait_def_id,
705 &args,
706 obligation.predicate,
707 );
708
709 debug!(?trait_def_id, ?trait_obligations, "trait alias obligations");
710
711 trait_obligations
712 }
713
714 fn confirm_generator_candidate(
715 &mut self,
716 obligation: &PolyTraitObligation<'tcx>,
717 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
718 // Okay to skip binder because the args on generator types never
719 // touch bound regions, they just capture the in-scope
720 // type/region parameters.
721 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
722 let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
723 bug!("closure candidate for non-closure {:?}", obligation);
724 };
725
726 debug!(?obligation, ?generator_def_id, ?args, "confirm_generator_candidate");
727
728 let gen_sig = args.as_generator().poly_sig();
729
730 // NOTE: The self-type is a generator type and hence is
731 // in fact unparameterized (or at least does not reference any
732 // regions bound in the obligation).
733 let self_ty = obligation
734 .predicate
735 .self_ty()
736 .no_bound_vars()
737 .expect("unboxed closure type should not capture bound vars from the predicate");
738
739 let trait_ref = super::util::generator_trait_ref_and_outputs(
740 self.tcx(),
741 obligation.predicate.def_id(),
742 self_ty,
743 gen_sig,
744 )
745 .map_bound(|(trait_ref, ..)| trait_ref);
746
747 let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
748 debug!(?trait_ref, ?nested, "generator candidate obligations");
749
750 Ok(nested)
751 }
752
753 fn confirm_future_candidate(
754 &mut self,
755 obligation: &PolyTraitObligation<'tcx>,
756 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
757 // Okay to skip binder because the args on generator types never
758 // touch bound regions, they just capture the in-scope
759 // type/region parameters.
760 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
761 let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
762 bug!("closure candidate for non-closure {:?}", obligation);
763 };
764
765 debug!(?obligation, ?generator_def_id, ?args, "confirm_future_candidate");
766
767 let gen_sig = args.as_generator().poly_sig();
768
769 let trait_ref = super::util::future_trait_ref_and_outputs(
770 self.tcx(),
771 obligation.predicate.def_id(),
772 obligation.predicate.no_bound_vars().expect("future has no bound vars").self_ty(),
773 gen_sig,
774 )
775 .map_bound(|(trait_ref, ..)| trait_ref);
776
777 let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
778 debug!(?trait_ref, ?nested, "future candidate obligations");
779
780 Ok(nested)
781 }
782
783 #[instrument(skip(self), level = "debug")]
784 fn confirm_closure_candidate(
785 &mut self,
786 obligation: &PolyTraitObligation<'tcx>,
787 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
788 let kind = self
789 .tcx()
790 .fn_trait_kind_from_def_id(obligation.predicate.def_id())
791 .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
792
793 // Okay to skip binder because the args on closure types never
794 // touch bound regions, they just capture the in-scope
795 // type/region parameters.
796 let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
797 let ty::Closure(closure_def_id, args) = *self_ty.kind() else {
798 bug!("closure candidate for non-closure {:?}", obligation);
799 };
800
801 let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
802 let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
803
804 debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
805
806 nested.push(obligation.with(
807 self.tcx(),
808 ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)),
809 ));
810
811 Ok(nested)
812 }
813
814 /// In the case of closure types and fn pointers,
815 /// we currently treat the input type parameters on the trait as
816 /// outputs. This means that when we have a match we have only
817 /// considered the self type, so we have to go back and make sure
818 /// to relate the argument types too. This is kind of wrong, but
819 /// since we control the full set of impls, also not that wrong,
820 /// and it DOES yield better error messages (since we don't report
821 /// errors as if there is no applicable impl, but rather report
822 /// errors are about mismatched argument types.
823 ///
824 /// Here is an example. Imagine we have a closure expression
825 /// and we desugared it so that the type of the expression is
826 /// `Closure`, and `Closure` expects `i32` as argument. Then it
827 /// is "as if" the compiler generated this impl:
828 /// ```ignore (illustrative)
829 /// impl Fn(i32) for Closure { ... }
830 /// ```
831 /// Now imagine our obligation is `Closure: Fn(usize)`. So far
832 /// we have matched the self type `Closure`. At this point we'll
833 /// compare the `i32` to `usize` and generate an error.
834 ///
835 /// Note that this checking occurs *after* the impl has selected,
836 /// because these output type parameters should not affect the
837 /// selection of the impl. Therefore, if there is a mismatch, we
838 /// report an error to the user.
839 #[instrument(skip(self), level = "trace")]
840 fn confirm_poly_trait_refs(
841 &mut self,
842 obligation: &PolyTraitObligation<'tcx>,
843 self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
844 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
845 let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
846 // Normalize the obligation and expected trait refs together, because why not
847 let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } =
848 ensure_sufficient_stack(|| {
849 normalize_with_depth(
850 self,
851 obligation.param_env,
852 obligation.cause.clone(),
853 obligation.recursion_depth + 1,
854 (obligation_trait_ref, self_ty_trait_ref),
855 )
856 });
857
858 // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
859 self.infcx
860 .at(&obligation.cause, obligation.param_env)
861 .sup(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref)
862 .map(|InferOk { mut obligations, .. }| {
863 obligations.extend(nested);
864 obligations
865 })
866 .map_err(|terr| {
867 OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch {
868 expected_trait_ref: obligation_trait_ref,
869 found_trait_ref: expected_trait_ref,
870 terr,
871 }))
872 })
873 }
874
875 fn confirm_trait_upcasting_unsize_candidate(
876 &mut self,
877 obligation: &PolyTraitObligation<'tcx>,
878 idx: usize,
879 ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
880 let tcx = self.tcx();
881
882 // `assemble_candidates_for_unsizing` should ensure there are no late-bound
883 // regions here. See the comment there for more details.
884 let predicate = obligation.predicate.no_bound_vars().unwrap();
885 let a_ty = self.infcx.shallow_resolve(predicate.self_ty());
886 let b_ty = self.infcx.shallow_resolve(predicate.trait_ref.args.type_at(1));
887
888 let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { bug!() };
889 let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { bug!() };
890
891 let source_principal = a_data.principal().unwrap().with_self_ty(tcx, a_ty);
892 let unnormalized_upcast_principal =
893 util::supertraits(tcx, source_principal).nth(idx).unwrap();
894
895 let nested = self
896 .match_upcast_principal(
897 obligation,
898 unnormalized_upcast_principal,
899 a_data,
900 b_data,
901 a_region,
902 b_region,
903 )?
904 .expect("did not expect ambiguity during confirmation");
905
906 let vtable_segment_callback = {
907 let mut vptr_offset = 0;
908 move |segment| {
909 match segment {
910 VtblSegment::MetadataDSA => {
911 vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
912 }
913 VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
914 vptr_offset += count_own_vtable_entries(tcx, trait_ref);
915 if trait_ref == unnormalized_upcast_principal {
916 if emit_vptr {
917 return ControlFlow::Break(Some(vptr_offset));
918 } else {
919 return ControlFlow::Break(None);
920 }
921 }
922
923 if emit_vptr {
924 vptr_offset += 1;
925 }
926 }
927 }
928 ControlFlow::Continue(())
929 }
930 };
931
932 let vtable_vptr_slot =
933 prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap();
934
935 Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }, nested))
936 }
937
938 fn confirm_builtin_unsize_candidate(
939 &mut self,
940 obligation: &PolyTraitObligation<'tcx>,
941 ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
942 let tcx = self.tcx();
943
944 // `assemble_candidates_for_unsizing` should ensure there are no late-bound
945 // regions here. See the comment there for more details.
946 let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
947 let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
948 let target = self.infcx.shallow_resolve(target);
949 debug!(?source, ?target, "confirm_builtin_unsize_candidate");
950
951 Ok(match (source.kind(), target.kind()) {
952 // Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
953 (&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b))
954 if dyn_a == dyn_b =>
955 {
956 // See `assemble_candidates_for_unsizing` for more info.
957 // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
958 let iter = data_a
959 .principal()
960 .map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
961 .into_iter()
962 .chain(
963 data_a
964 .projection_bounds()
965 .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
966 )
967 .chain(
968 data_b
969 .auto_traits()
970 .map(ty::ExistentialPredicate::AutoTrait)
971 .map(ty::Binder::dummy),
972 );
973 let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
974 let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);
975
976 // Require that the traits involved in this upcast are **equal**;
977 // only the **lifetime bound** is changed.
978 let InferOk { mut obligations, .. } = self
979 .infcx
980 .at(&obligation.cause, obligation.param_env)
981 .sup(DefineOpaqueTypes::No, target, source_trait)
982 .map_err(|_| Unimplemented)?;
983
984 // Register one obligation for 'a: 'b.
985 let outlives = ty::OutlivesPredicate(r_a, r_b);
986 obligations.push(Obligation::with_depth(
987 tcx,
988 obligation.cause.clone(),
989 obligation.recursion_depth + 1,
990 obligation.param_env,
991 obligation.predicate.rebind(outlives),
992 ));
993
994 ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
995 }
996
997 // `T` -> `Trait`
998 (_, &ty::Dynamic(ref data, r, ty::Dyn)) => {
999 let mut object_dids = data.auto_traits().chain(data.principal_def_id());
1000 if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) {
1001 return Err(TraitNotObjectSafe(did));
1002 }
1003
1004 let predicate_to_obligation = |predicate| {
1005 Obligation::with_depth(
1006 tcx,
1007 obligation.cause.clone(),
1008 obligation.recursion_depth + 1,
1009 obligation.param_env,
1010 predicate,
1011 )
1012 };
1013
1014 // Create obligations:
1015 // - Casting `T` to `Trait`
1016 // - For all the various builtin bounds attached to the object cast. (In other
1017 // words, if the object type is `Foo + Send`, this would create an obligation for
1018 // the `Send` check.)
1019 // - Projection predicates
1020 let mut nested: Vec<_> = data
1021 .iter()
1022 .map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source)))
1023 .collect();
1024
1025 // We can only make objects from sized types.
1026 let tr = ty::TraitRef::from_lang_item(
1027 tcx,
1028 LangItem::Sized,
1029 obligation.cause.span,
1030 [source],
1031 );
1032 nested.push(predicate_to_obligation(tr.to_predicate(tcx)));
1033
1034 // If the type is `Foo + 'a`, ensure that the type
1035 // being cast to `Foo + 'a` outlives `'a`:
1036 let outlives = ty::OutlivesPredicate(source, r);
1037 nested.push(predicate_to_obligation(
1038 ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx),
1039 ));
1040
1041 ImplSource::Builtin(BuiltinImplSource::Misc, nested)
1042 }
1043
1044 // `[T; n]` -> `[T]`
1045 (&ty::Array(a, _), &ty::Slice(b)) => {
1046 let InferOk { obligations, .. } = self
1047 .infcx
1048 .at(&obligation.cause, obligation.param_env)
1049 .eq(DefineOpaqueTypes::No, b, a)
1050 .map_err(|_| Unimplemented)?;
1051
1052 ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
1053 }
1054
1055 // `Struct<T>` -> `Struct<U>`
1056 (&ty::Adt(def, args_a), &ty::Adt(_, args_b)) => {
1057 let unsizing_params = tcx.unsizing_params_for_adt(def.did());
1058 if unsizing_params.is_empty() {
1059 return Err(Unimplemented);
1060 }
1061
1062 let tail_field = def.non_enum_variant().tail();
1063 let tail_field_ty = tcx.type_of(tail_field.did);
1064
1065 let mut nested = vec![];
1066
1067 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
1068 // normalizing in the process, since `type_of` returns something directly from
1069 // astconv (which means it's un-normalized).
1070 let source_tail = normalize_with_depth_to(
1071 self,
1072 obligation.param_env,
1073 obligation.cause.clone(),
1074 obligation.recursion_depth + 1,
1075 tail_field_ty.instantiate(tcx, args_a),
1076 &mut nested,
1077 );
1078 let target_tail = normalize_with_depth_to(
1079 self,
1080 obligation.param_env,
1081 obligation.cause.clone(),
1082 obligation.recursion_depth + 1,
1083 tail_field_ty.instantiate(tcx, args_b),
1084 &mut nested,
1085 );
1086
1087 // Check that the source struct with the target's
1088 // unsizing parameters is equal to the target.
1089 let args =
1090 tcx.mk_args_from_iter(args_a.iter().enumerate().map(|(i, k)| {
1091 if unsizing_params.contains(i as u32) { args_b[i] } else { k }
1092 }));
1093 let new_struct = Ty::new_adt(tcx, def, args);
1094 let InferOk { obligations, .. } = self
1095 .infcx
1096 .at(&obligation.cause, obligation.param_env)
1097 .eq(DefineOpaqueTypes::No, target, new_struct)
1098 .map_err(|_| Unimplemented)?;
1099 nested.extend(obligations);
1100
1101 // Construct the nested `TailField<T>: Unsize<TailField<U>>` predicate.
1102 let tail_unsize_obligation = obligation.with(
1103 tcx,
1104 ty::TraitRef::new(
1105 tcx,
1106 obligation.predicate.def_id(),
1107 [source_tail, target_tail],
1108 ),
1109 );
1110 nested.push(tail_unsize_obligation);
1111
1112 ImplSource::Builtin(BuiltinImplSource::Misc, nested)
1113 }
1114
1115 // `(.., T)` -> `(.., U)`
1116 (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
1117 assert_eq!(tys_a.len(), tys_b.len());
1118
1119 // The last field of the tuple has to exist.
1120 let (&a_last, a_mid) = tys_a.split_last().ok_or(Unimplemented)?;
1121 let &b_last = tys_b.last().unwrap();
1122
1123 // Check that the source tuple with the target's
1124 // last element is equal to the target.
1125 let new_tuple =
1126 Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
1127 let InferOk { mut obligations, .. } = self
1128 .infcx
1129 .at(&obligation.cause, obligation.param_env)
1130 .eq(DefineOpaqueTypes::No, target, new_tuple)
1131 .map_err(|_| Unimplemented)?;
1132
1133 // Add a nested `T: Unsize<U>` predicate.
1134 let last_unsize_obligation = obligation.with(
1135 tcx,
1136 ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
1137 );
1138 obligations.push(last_unsize_obligation);
1139
1140 ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
1141 }
1142
1143 _ => bug!("source: {source}, target: {target}"),
1144 })
1145 }
1146
1147 fn confirm_const_destruct_candidate(
1148 &mut self,
1149 obligation: &PolyTraitObligation<'tcx>,
1150 impl_def_id: Option<DefId>,
1151 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
1152 // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
1153 // FIXME(effects)
1154 if true {
1155 return Ok(vec![]);
1156 }
1157
1158 let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
1159
1160 let tcx = self.tcx();
1161 let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
1162
1163 let mut nested = vec![];
1164 let cause = obligation.derived_cause(BuiltinDerivedObligation);
1165
1166 // If we have a custom `impl const Drop`, then
1167 // first check it like a regular impl candidate.
1168 // This is copied from confirm_impl_candidate but remaps the predicate to `~const Drop` beforehand.
1169 if let Some(impl_def_id) = impl_def_id {
1170 let mut new_obligation = obligation.clone();
1171 new_obligation.predicate = new_obligation.predicate.map_bound(|mut trait_pred| {
1172 trait_pred.trait_ref.def_id = drop_trait;
1173 trait_pred
1174 });
1175 let args = self.rematch_impl(impl_def_id, &new_obligation);
1176 debug!(?args, "impl args");
1177
1178 let cause = obligation.derived_cause(|derived| {
1179 ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
1180 derived,
1181 impl_or_alias_def_id: impl_def_id,
1182 impl_def_predicate_index: None,
1183 span: obligation.cause.span,
1184 }))
1185 });
1186 let obligations = ensure_sufficient_stack(|| {
1187 self.vtable_impl(
1188 impl_def_id,
1189 args,
1190 &cause,
1191 new_obligation.recursion_depth + 1,
1192 new_obligation.param_env,
1193 obligation.predicate,
1194 )
1195 });
1196 nested.extend(obligations.nested);
1197 }
1198
1199 // We want to confirm the ADT's fields if we have an ADT
1200 let mut stack = match *self_ty.skip_binder().kind() {
1201 ty::Adt(def, args) => def.all_fields().map(|f| f.ty(tcx, args)).collect(),
1202 _ => vec![self_ty.skip_binder()],
1203 };
1204
1205 while let Some(nested_ty) = stack.pop() {
1206 match *nested_ty.kind() {
1207 // We know these types are trivially drop
1208 ty::Bool
1209 | ty::Char
1210 | ty::Int(_)
1211 | ty::Uint(_)
1212 | ty::Float(_)
1213 | ty::Infer(ty::IntVar(_))
1214 | ty::Infer(ty::FloatVar(_))
1215 | ty::Str
1216 | ty::RawPtr(_)
1217 | ty::Ref(..)
1218 | ty::FnDef(..)
1219 | ty::FnPtr(_)
1220 | ty::Never
1221 | ty::Foreign(_) => {}
1222
1223 // `ManuallyDrop` is trivially drop
1224 ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {}
1225
1226 // These types are built-in, so we can fast-track by registering
1227 // nested predicates for their constituent type(s)
1228 ty::Array(ty, _) | ty::Slice(ty) => {
1229 stack.push(ty);
1230 }
1231 ty::Tuple(tys) => {
1232 stack.extend(tys.iter());
1233 }
1234 ty::Closure(_, args) => {
1235 stack.push(args.as_closure().tupled_upvars_ty());
1236 }
1237 ty::Generator(_, args, _) => {
1238 let generator = args.as_generator();
1239 stack.extend([generator.tupled_upvars_ty(), generator.witness()]);
1240 }
1241 ty::GeneratorWitness(def_id, args) => {
1242 let tcx = self.tcx();
1243 stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
1244 let ty = bty.instantiate(tcx, args);
1245 debug_assert!(!ty.has_late_bound_regions());
1246 ty
1247 }))
1248 }
1249
1250 // If we have a projection type, make sure to normalize it so we replace it
1251 // with a fresh infer variable
1252 ty::Alias(ty::Projection | ty::Inherent, ..) => {
1253 // FIXME(effects) this needs constness
1254 let predicate = normalize_with_depth_to(
1255 self,
1256 obligation.param_env,
1257 cause.clone(),
1258 obligation.recursion_depth + 1,
1259 self_ty.rebind(ty::TraitPredicate {
1260 trait_ref: ty::TraitRef::from_lang_item(
1261 self.tcx(),
1262 LangItem::Destruct,
1263 cause.span,
1264 [nested_ty],
1265 ),
1266 polarity: ty::ImplPolarity::Positive,
1267 }),
1268 &mut nested,
1269 );
1270
1271 nested.push(Obligation::with_depth(
1272 tcx,
1273 cause.clone(),
1274 obligation.recursion_depth + 1,
1275 obligation.param_env,
1276 predicate,
1277 ));
1278 }
1279
1280 // If we have any other type (e.g. an ADT), just register a nested obligation
1281 // since it's either not `const Drop` (and we raise an error during selection),
1282 // or it's an ADT (and we need to check for a custom impl during selection)
1283 _ => {
1284 // FIXME(effects) this needs constness
1285 let predicate = self_ty.rebind(ty::TraitPredicate {
1286 trait_ref: ty::TraitRef::from_lang_item(
1287 self.tcx(),
1288 LangItem::Destruct,
1289 cause.span,
1290 [nested_ty],
1291 ),
1292 polarity: ty::ImplPolarity::Positive,
1293 });
1294
1295 nested.push(Obligation::with_depth(
1296 tcx,
1297 cause.clone(),
1298 obligation.recursion_depth + 1,
1299 obligation.param_env,
1300 predicate,
1301 ));
1302 }
1303 }
1304 }
1305
1306 Ok(nested)
1307 }
1308 }