]> git.proxmox.com Git - rustc.git/blame - 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
CommitLineData
f035d41b
XL
1//! Confirmation.
2//!
3//! Confirmation unifies the output type parameters of the trait
4//! with the values found in the obligation, possibly yielding a
9c376795 5//! type error. See the [rustc dev guide] for more details.
f035d41b
XL
6//!
7//! [rustc dev guide]:
8//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
fe692bf9 9use rustc_ast::Mutability;
f035d41b 10use rustc_data_structures::stack::ensure_sufficient_stack;
3dfed10e 11use rustc_hir::lang_items::LangItem;
29967ef6 12use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
353b0b11 13use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
add651ee 14use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
2b03887a 15use rustc_middle::ty::{
add651ee
FG
16 self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
17 TraitPredicate, Ty, TyCtxt, TypeVisitableExt,
2b03887a 18};
f035d41b
XL
19use rustc_span::def_id::DefId;
20
29967ef6 21use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
353b0b11 22use crate::traits::util::{self, closure_trait_ref_and_return_type};
487cf647
FG
23use crate::traits::vtable::{
24 count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
25 VtblSegment,
26};
f035d41b 27use crate::traits::{
923072b8 28 BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
add651ee
FG
29 ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
30 OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection,
31 SelectionError, TraitNotObjectSafe, Unimplemented,
f035d41b 32};
f035d41b
XL
33
34use super::BuiltinImplConditions;
35use super::SelectionCandidate::{self, *};
36use super::SelectionContext;
37
38use std::iter;
94222f64 39use std::ops::ControlFlow;
f035d41b
XL
40
41impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29967ef6 42 #[instrument(level = "debug", skip(self))]
f035d41b
XL
43 pub(super) fn confirm_candidate(
44 &mut self,
fe692bf9 45 obligation: &PolyTraitObligation<'tcx>,
f035d41b
XL
46 candidate: SelectionCandidate<'tcx>,
47 ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
064997fb 48 let mut impl_src = match candidate {
f035d41b
XL
49 BuiltinCandidate { has_nested } => {
50 let data = self.confirm_builtin_candidate(obligation, has_nested);
add651ee 51 ImplSource::Builtin(BuiltinImplSource::Misc, data)
064997fb
FG
52 }
53
54 TransmutabilityCandidate => {
55 let data = self.confirm_transmutability_candidate(obligation)?;
add651ee 56 ImplSource::Builtin(BuiltinImplSource::Misc, data)
f035d41b
XL
57 }
58
59 ParamCandidate(param) => {
a2a8927a
XL
60 let obligations =
61 self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
add651ee 62 ImplSource::Param(obligations)
f035d41b
XL
63 }
64
65 ImplCandidate(impl_def_id) => {
064997fb 66 ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
f035d41b
XL
67 }
68
2b03887a 69 AutoImplCandidate => {
fe692bf9 70 let data = self.confirm_auto_impl_candidate(obligation)?;
add651ee 71 ImplSource::Builtin(BuiltinImplSource::Misc, data)
f035d41b
XL
72 }
73
add651ee 74 ProjectionCandidate(idx, _) => {
29967ef6 75 let obligations = self.confirm_projection_candidate(obligation, idx)?;
add651ee 76 ImplSource::Param(obligations)
29967ef6
XL
77 }
78
add651ee 79 ObjectCandidate(idx) => self.confirm_object_candidate(obligation, idx)?,
f035d41b 80
9c376795 81 ClosureCandidate { .. } => {
f035d41b 82 let vtable_closure = self.confirm_closure_candidate(obligation)?;
add651ee 83 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure)
f035d41b
XL
84 }
85
86 GeneratorCandidate => {
87 let vtable_generator = self.confirm_generator_candidate(obligation)?;
add651ee 88 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_generator)
f035d41b
XL
89 }
90
487cf647
FG
91 FutureCandidate => {
92 let vtable_future = self.confirm_future_candidate(obligation)?;
add651ee 93 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_future)
487cf647
FG
94 }
95
9c376795
FG
96 FnPointerCandidate { is_const } => {
97 let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
add651ee 98 ImplSource::Builtin(BuiltinImplSource::Misc, data)
f035d41b
XL
99 }
100
2b03887a
FG
101 TraitAliasCandidate => {
102 let data = self.confirm_trait_alias_candidate(obligation);
add651ee 103 ImplSource::Builtin(BuiltinImplSource::Misc, data)
f035d41b
XL
104 }
105
f035d41b
XL
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.
add651ee 110 ImplSource::Builtin(BuiltinImplSource::Misc, Vec::new())
f035d41b
XL
111 }
112
add651ee 113 BuiltinUnsizeCandidate => self.confirm_builtin_unsize_candidate(obligation)?,
94222f64
XL
114
115 TraitUpcastingUnsizeCandidate(idx) => {
add651ee 116 self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
94222f64 117 }
c295e0f8 118
5e7ed085
FG
119 ConstDestructCandidate(def_id) => {
120 let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
add651ee 121 ImplSource::Builtin(BuiltinImplSource::Misc, data)
5099ac24 122 }
064997fb
FG
123 };
124
353b0b11
FG
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
064997fb 131 Ok(impl_src)
f035d41b
XL
132 }
133
29967ef6
XL
134 fn confirm_projection_candidate(
135 &mut self,
fe692bf9 136 obligation: &PolyTraitObligation<'tcx>,
29967ef6
XL
137 idx: usize,
138 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
064997fb 139 let tcx = self.tcx();
29967ef6 140
064997fb
FG
141 let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
142 let placeholder_trait_predicate =
9ffffee4 143 self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
064997fb
FG
144 let placeholder_self_ty = placeholder_trait_predicate.self_ty();
145 let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
add651ee 146 let (def_id, args) = match *placeholder_self_ty.kind() {
fe692bf9 147 // Excluding IATs and type aliases here as they don't have meaningful item bounds.
add651ee
FG
148 ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
149 (def_id, args)
49aad941 150 }
064997fb
FG
151 _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
152 };
29967ef6 153
add651ee
FG
154 let candidate_predicate =
155 tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args);
064997fb 156 let candidate = candidate_predicate
fe692bf9 157 .as_trait_clause()
064997fb
FG
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)
353b0b11 173 .sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
064997fb
FG
174 .map(|InferOk { obligations, .. }| obligations)
175 .map_err(|_| Unimplemented)
176 })?);
177
9c376795 178 if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
add651ee 179 let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
9c376795 180 for (predicate, _) in predicates {
064997fb
FG
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(
487cf647 190 self.tcx(),
064997fb
FG
191 obligation.cause.clone(),
192 obligation.recursion_depth + 1,
193 obligation.param_env,
194 normalized,
195 ));
29967ef6 196 }
064997fb 197 }
29967ef6 198
064997fb 199 Ok(obligations)
f035d41b
XL
200 }
201
202 fn confirm_param_candidate(
203 &mut self,
fe692bf9 204 obligation: &PolyTraitObligation<'tcx>,
f035d41b
XL
205 param: ty::PolyTraitRef<'tcx>,
206 ) -> Vec<PredicateObligation<'tcx>> {
29967ef6 207 debug!(?obligation, ?param, "confirm_param_candidate");
f035d41b
XL
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,
fe692bf9 227 obligation: &PolyTraitObligation<'tcx>,
f035d41b 228 has_nested: bool,
fe692bf9 229 ) -> Vec<PredicateObligation<'tcx>> {
29967ef6 230 debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
f035d41b
XL
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 };
5e7ed085
FG
244 let BuiltinImplConditions::Where(nested) = conditions else {
245 bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
f035d41b
XL
246 };
247
248 let cause = obligation.derived_cause(BuiltinDerivedObligation);
353b0b11
FG
249 self.collect_predicates_for_types(
250 obligation.param_env,
251 cause,
252 obligation.recursion_depth + 1,
253 trait_def,
254 nested,
255 )
f035d41b
XL
256 } else {
257 vec![]
258 };
259
29967ef6 260 debug!(?obligations);
f035d41b 261
fe692bf9 262 obligations
f035d41b
XL
263 }
264
fe692bf9 265 #[instrument(level = "debug", skip(self))]
064997fb
FG
266 fn confirm_transmutability_candidate(
267 &mut self,
fe692bf9
FG
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();
add651ee
FG
287 let scope = predicate.trait_ref.args.type_at(2);
288 let assume_const = predicate.trait_ref.args.const_at(3);
fe692bf9
FG
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 }
064997fb 319
49aad941
FG
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));
064997fb 327
49aad941
FG
328 let Some(assume) = rustc_transmute::Assume::from_const(
329 self.infcx.tcx,
330 obligation.param_env,
add651ee 331 predicate.trait_ref.args.const_at(3),
49aad941
FG
332 ) else {
333 return Err(Unimplemented);
334 };
064997fb 335
add651ee
FG
336 let dst = predicate.trait_ref.args.type_at(0);
337 let src = predicate.trait_ref.args.type_at(1);
fe692bf9 338 debug!(?src, ?dst);
064997fb 339 let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
49aad941
FG
340 let maybe_transmutable = transmute_env.is_transmutable(
341 obligation.cause.clone(),
fe692bf9 342 rustc_transmute::Types { dst, src },
add651ee 343 predicate.trait_ref.args.type_at(2),
49aad941
FG
344 assume,
345 );
064997fb 346
fe692bf9
FG
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)
064997fb
FG
355 }
356
94222f64 357 /// This handles the case where an `auto trait Foo` impl is being used.
f035d41b
XL
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,
fe692bf9
FG
364 obligation: &PolyTraitObligation<'tcx>,
365 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
2b03887a 366 debug!(?obligation, "confirm_auto_impl_candidate");
f035d41b 367
fc512014 368 let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
fe692bf9
FG
369 let types = self.constituent_types_for_ty(self_ty)?;
370 Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
f035d41b
XL
371 }
372
373 /// See `confirm_auto_impl_candidate`.
374 fn vtable_auto_impl(
375 &mut self,
fe692bf9 376 obligation: &PolyTraitObligation<'tcx>,
f035d41b 377 trait_def_id: DefId,
cdc7bbd5 378 nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
fe692bf9 379 ) -> Vec<PredicateObligation<'tcx>> {
29967ef6 380 debug!(?nested, "vtable_auto_impl");
f035d41b
XL
381 ensure_sufficient_stack(|| {
382 let cause = obligation.derived_cause(BuiltinDerivedObligation);
f035d41b 383
064997fb 384 let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
9ffffee4 385 let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref);
064997fb
FG
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,
add651ee 391 &trait_ref.args,
064997fb
FG
392 obligation.predicate,
393 );
f035d41b 394
5e7ed085
FG
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
9c376795
FG
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.
f035d41b
XL
405 obligations.extend(trait_obligations);
406
29967ef6 407 debug!(?obligations, "vtable_auto_impl");
f035d41b 408
fe692bf9 409 obligations
f035d41b
XL
410 })
411 }
412
413 fn confirm_impl_candidate(
414 &mut self,
fe692bf9 415 obligation: &PolyTraitObligation<'tcx>,
f035d41b
XL
416 impl_def_id: DefId,
417 ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
29967ef6 418 debug!(?obligation, ?impl_def_id, "confirm_impl_candidate");
f035d41b
XL
419
420 // First, create the substitutions by matching the impl again,
421 // this time not in a probe.
add651ee
FG
422 let args = self.rematch_impl(impl_def_id, obligation);
423 debug!(?args, "impl args");
064997fb
FG
424 ensure_sufficient_stack(|| {
425 self.vtable_impl(
426 impl_def_id,
add651ee 427 args,
064997fb
FG
428 &obligation.cause,
429 obligation.recursion_depth + 1,
430 obligation.param_env,
431 obligation.predicate,
432 )
f035d41b
XL
433 })
434 }
435
436 fn vtable_impl(
437 &mut self,
438 impl_def_id: DefId,
add651ee 439 args: Normalized<'tcx, GenericArgsRef<'tcx>>,
5e7ed085 440 cause: &ObligationCause<'tcx>,
f035d41b
XL
441 recursion_depth: usize,
442 param_env: ty::ParamEnv<'tcx>,
5e7ed085 443 parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
f035d41b 444 ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
add651ee 445 debug!(?impl_def_id, ?args, ?recursion_depth, "vtable_impl");
f035d41b
XL
446
447 let mut impl_obligations = self.impl_or_trait_obligations(
448 cause,
449 recursion_depth,
450 param_env,
451 impl_def_id,
add651ee 452 &args.value,
5e7ed085 453 parent_trait_pred,
f035d41b
XL
454 );
455
29967ef6 456 debug!(?impl_obligations, "vtable_impl");
f035d41b
XL
457
458 // Because of RFC447, the impl-trait-ref and obligations
add651ee 459 // are sufficient to determine the impl args, without
f035d41b
XL
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`
add651ee 463 impl_obligations.extend(args.obligations);
f035d41b 464
add651ee 465 ImplSourceUserDefinedData { impl_def_id, args: args.value, nested: impl_obligations }
f035d41b
XL
466 }
467
468 fn confirm_object_candidate(
469 &mut self,
fe692bf9 470 obligation: &PolyTraitObligation<'tcx>,
29967ef6 471 index: usize,
add651ee 472 ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
29967ef6
XL
473 let tcx = self.tcx();
474 debug!(?obligation, ?index, "confirm_object_candidate");
475
9ffffee4 476 let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
29967ef6
XL
477 let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
478 let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
5e7ed085
FG
479 let ty::Dynamic(data, ..) = *self_ty.kind() else {
480 span_bug!(obligation.cause.span, "object candidate with non-object");
f035d41b
XL
481 };
482
fc512014
XL
483 let object_trait_ref = data.principal().unwrap_or_else(|| {
484 span_bug!(obligation.cause.span, "object candidate with no principal")
485 });
9ffffee4 486 let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
923072b8
FG
487 obligation.cause.span,
488 HigherRankedType,
489 object_trait_ref,
490 );
fc512014 491 let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty);
29967ef6 492
f035d41b 493 let mut nested = vec![];
f035d41b 494
29967ef6 495 let mut supertraits = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref));
29967ef6 496 let unnormalized_upcast_trait_ref =
136023e0 497 supertraits.nth(index).expect("supertraits iterator no longer has as many elements");
29967ef6
XL
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,
fc512014 504 unnormalized_upcast_trait_ref,
29967ef6
XL
505 &mut nested,
506 );
507
508 nested.extend(self.infcx.commit_if_ok(|_| {
509 self.infcx
510 .at(&obligation.cause, obligation.param_env)
353b0b11 511 .sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref)
29967ef6
XL
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())
add651ee 520 .instantiate(tcx, trait_predicate.trait_ref.args)
29967ef6
XL
521 .predicates
522 .into_iter()
523 {
5e7ed085
FG
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 );
487cf647 532 nested.push(obligation.with(tcx, normalized_super_trait));
f035d41b
XL
533 }
534
29967ef6
XL
535 let assoc_types: Vec<_> = tcx
536 .associated_items(trait_predicate.def_id())
537 .in_definition_order()
781aab86
FG
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))
29967ef6
XL
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 {
5e7ed085
FG
547 let defs: &ty::Generics = tcx.generics_of(assoc_type);
548
549 if !defs.params.is_empty() && !tcx.features().generic_associated_types_extended {
cdc7bbd5 550 tcx.sess.delay_span_bug(
29967ef6 551 obligation.cause.span,
cdc7bbd5 552 "GATs in trait object shouldn't have been considered",
29967ef6 553 );
781aab86 554 return Err(SelectionError::TraitNotObjectSafe(trait_predicate.trait_ref.def_id));
29967ef6 555 }
5e7ed085 556
29967ef6
XL
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>`.
9c376795 560 for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
add651ee
FG
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 };
29967ef6
XL
620 let normalized_bound = normalize_with_depth_to(
621 self,
622 obligation.param_env,
623 obligation.cause.clone(),
624 obligation.recursion_depth + 1,
fc512014 625 subst_bound,
29967ef6
XL
626 &mut nested,
627 );
487cf647 628 nested.push(obligation.with(tcx, normalized_bound));
29967ef6
XL
629 }
630 }
631
632 debug!(?nested, "object nested obligations");
136023e0 633
487cf647 634 let vtable_base = vtable_trait_first_method_offset(
136023e0
XL
635 tcx,
636 (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
637 );
638
add651ee 639 Ok(ImplSource::Builtin(BuiltinImplSource::Object { vtable_base: vtable_base }, nested))
f035d41b
XL
640 }
641
642 fn confirm_fn_pointer_candidate(
643 &mut self,
fe692bf9 644 obligation: &PolyTraitObligation<'tcx>,
add651ee
FG
645 // FIXME(effects)
646 _is_const: bool,
fe692bf9 647 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
29967ef6 648 debug!(?obligation, "confirm_fn_pointer_candidate");
f035d41b 649
9c376795 650 let tcx = self.tcx();
353b0b11 651
add651ee 652 let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else {
353b0b11
FG
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
9c376795 660 let sig = self_ty.fn_sig(tcx);
f035d41b 661 let trait_ref = closure_trait_ref_and_return_type(
9c376795 662 tcx,
f035d41b
XL
663 obligation.predicate.def_id(),
664 self_ty,
665 sig,
666 util::TupleArgumentsFlag::Yes,
667 )
668 .map_bound(|(trait_ref, _)| trait_ref);
669
2b03887a 670 let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
9c376795
FG
671 let cause = obligation.derived_cause(BuiltinDerivedObligation);
672
2b03887a 673 // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
9ffffee4 674 let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
2b03887a
FG
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 );
49aad941 683 let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]);
487cf647 684 nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
2b03887a 685
fe692bf9 686 Ok(nested)
f035d41b
XL
687 }
688
689 fn confirm_trait_alias_candidate(
690 &mut self,
fe692bf9
FG
691 obligation: &PolyTraitObligation<'tcx>,
692 ) -> Vec<PredicateObligation<'tcx>> {
2b03887a 693 debug!(?obligation, "confirm_trait_alias_candidate");
f035d41b 694
9ffffee4 695 let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
064997fb
FG
696 let trait_ref = predicate.trait_ref;
697 let trait_def_id = trait_ref.def_id;
add651ee 698 let args = trait_ref.args;
f035d41b 699
064997fb
FG
700 let trait_obligations = self.impl_or_trait_obligations(
701 &obligation.cause,
702 obligation.recursion_depth,
703 obligation.param_env,
704 trait_def_id,
add651ee 705 &args,
064997fb
FG
706 obligation.predicate,
707 );
f035d41b 708
064997fb 709 debug!(?trait_def_id, ?trait_obligations, "trait alias obligations");
f035d41b 710
fe692bf9 711 trait_obligations
f035d41b
XL
712 }
713
714 fn confirm_generator_candidate(
715 &mut self,
fe692bf9
FG
716 obligation: &PolyTraitObligation<'tcx>,
717 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
add651ee 718 // Okay to skip binder because the args on generator types never
f035d41b
XL
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());
add651ee 722 let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
5e7ed085 723 bug!("closure candidate for non-closure {:?}", obligation);
f035d41b
XL
724 };
725
add651ee 726 debug!(?obligation, ?generator_def_id, ?args, "confirm_generator_candidate");
f035d41b 727
add651ee 728 let gen_sig = args.as_generator().poly_sig();
487cf647
FG
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);
f035d41b 746
5e7ed085
FG
747 let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
748 debug!(?trait_ref, ?nested, "generator candidate obligations");
f035d41b 749
fe692bf9 750 Ok(nested)
f035d41b
XL
751 }
752
487cf647
FG
753 fn confirm_future_candidate(
754 &mut self,
fe692bf9
FG
755 obligation: &PolyTraitObligation<'tcx>,
756 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
add651ee 757 // Okay to skip binder because the args on generator types never
487cf647
FG
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());
add651ee 761 let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
487cf647
FG
762 bug!("closure candidate for non-closure {:?}", obligation);
763 };
764
add651ee 765 debug!(?obligation, ?generator_def_id, ?args, "confirm_future_candidate");
487cf647 766
add651ee 767 let gen_sig = args.as_generator().poly_sig();
487cf647
FG
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
fe692bf9 780 Ok(nested)
487cf647
FG
781 }
782
c295e0f8 783 #[instrument(skip(self), level = "debug")]
f035d41b
XL
784 fn confirm_closure_candidate(
785 &mut self,
fe692bf9
FG
786 obligation: &PolyTraitObligation<'tcx>,
787 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
f035d41b
XL
788 let kind = self
789 .tcx()
487cf647 790 .fn_trait_kind_from_def_id(obligation.predicate.def_id())
f035d41b
XL
791 .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
792
add651ee 793 // Okay to skip binder because the args on closure types never
f035d41b
XL
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());
add651ee 797 let ty::Closure(closure_def_id, args) = *self_ty.kind() else {
5e7ed085 798 bug!("closure candidate for non-closure {:?}", obligation);
f035d41b
XL
799 };
800
add651ee 801 let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
5e7ed085 802 let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
f035d41b 803
5e7ed085 804 debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
f035d41b 805
fe692bf9
FG
806 nested.push(obligation.with(
807 self.tcx(),
add651ee 808 ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)),
fe692bf9 809 ));
f035d41b 810
fe692bf9 811 Ok(nested)
f035d41b
XL
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:
04454e1e
FG
828 /// ```ignore (illustrative)
829 /// impl Fn(i32) for Closure { ... }
830 /// ```
f035d41b
XL
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.
c295e0f8 839 #[instrument(skip(self), level = "trace")]
f035d41b
XL
840 fn confirm_poly_trait_refs(
841 &mut self,
fe692bf9 842 obligation: &PolyTraitObligation<'tcx>,
49aad941 843 self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
f035d41b 844 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
5e7ed085
FG
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(|| {
064997fb
FG
849 normalize_with_depth(
850 self,
851 obligation.param_env,
852 obligation.cause.clone(),
853 obligation.recursion_depth + 1,
49aad941 854 (obligation_trait_ref, self_ty_trait_ref),
064997fb 855 )
5e7ed085
FG
856 });
857
353b0b11 858 // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
f035d41b 859 self.infcx
5e7ed085 860 .at(&obligation.cause, obligation.param_env)
353b0b11 861 .sup(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref)
5e7ed085
FG
862 .map(|InferOk { mut obligations, .. }| {
863 obligations.extend(nested);
864 obligations
865 })
49aad941
FG
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 })
f035d41b
XL
873 }
874
94222f64
XL
875 fn confirm_trait_upcasting_unsize_candidate(
876 &mut self,
fe692bf9 877 obligation: &PolyTraitObligation<'tcx>,
94222f64 878 idx: usize,
add651ee 879 ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
94222f64
XL
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.
add651ee
FG
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");
94222f64
XL
905
906 let vtable_segment_callback = {
907 let mut vptr_offset = 0;
908 move |segment| {
909 match segment {
910 VtblSegment::MetadataDSA => {
923072b8 911 vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
94222f64
XL
912 }
913 VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
487cf647 914 vptr_offset += count_own_vtable_entries(tcx, trait_ref);
add651ee 915 if trait_ref == unnormalized_upcast_principal {
94222f64
XL
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 =
add651ee 933 prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap();
94222f64 934
add651ee 935 Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }, nested))
94222f64
XL
936 }
937
f035d41b
XL
938 fn confirm_builtin_unsize_candidate(
939 &mut self,
fe692bf9 940 obligation: &PolyTraitObligation<'tcx>,
add651ee 941 ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
f035d41b
XL
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());
add651ee 947 let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
f035d41b 948 let target = self.infcx.shallow_resolve(target);
29967ef6 949 debug!(?source, ?target, "confirm_builtin_unsize_candidate");
f035d41b 950
add651ee 951 Ok(match (source.kind(), target.kind()) {
94222f64 952 // Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
487cf647
FG
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 {
f035d41b 956 // See `assemble_candidates_for_unsizing` for more info.
5e7ed085 957 // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
fc512014
XL
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 );
9ffffee4 973 let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
fe692bf9 974 let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);
f035d41b
XL
975
976 // Require that the traits involved in this upcast are **equal**;
977 // only the **lifetime bound** is changed.
add651ee 978 let InferOk { mut obligations, .. } = self
f035d41b
XL
979 .infcx
980 .at(&obligation.cause, obligation.param_env)
353b0b11 981 .sup(DefineOpaqueTypes::No, target, source_trait)
f035d41b 982 .map_err(|_| Unimplemented)?;
f035d41b
XL
983
984 // Register one obligation for 'a: 'b.
f035d41b 985 let outlives = ty::OutlivesPredicate(r_a, r_b);
add651ee 986 obligations.push(Obligation::with_depth(
487cf647 987 tcx,
49aad941 988 obligation.cause.clone(),
f035d41b
XL
989 obligation.recursion_depth + 1,
990 obligation.param_env,
487cf647 991 obligation.predicate.rebind(outlives),
f035d41b 992 ));
add651ee
FG
993
994 ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
f035d41b
XL
995 }
996
997 // `T` -> `Trait`
f2b60f7d 998 (_, &ty::Dynamic(ref data, r, ty::Dyn)) => {
f035d41b 999 let mut object_dids = data.auto_traits().chain(data.principal_def_id());
9ffffee4 1000 if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) {
f035d41b
XL
1001 return Err(TraitNotObjectSafe(did));
1002 }
1003
f035d41b
XL
1004 let predicate_to_obligation = |predicate| {
1005 Obligation::with_depth(
487cf647 1006 tcx,
49aad941 1007 obligation.cause.clone(),
f035d41b
XL
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
add651ee
FG
1020 let mut nested: Vec<_> = data
1021 .iter()
1022 .map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source)))
1023 .collect();
f035d41b
XL
1024
1025 // We can only make objects from sized types.
49aad941
FG
1026 let tr = ty::TraitRef::from_lang_item(
1027 tcx,
1028 LangItem::Sized,
1029 obligation.cause.span,
1030 [source],
1031 );
fe692bf9 1032 nested.push(predicate_to_obligation(tr.to_predicate(tcx)));
f035d41b
XL
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);
fe692bf9
FG
1037 nested.push(predicate_to_obligation(
1038 ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx),
1039 ));
add651ee
FG
1040
1041 ImplSource::Builtin(BuiltinImplSource::Misc, nested)
f035d41b
XL
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)
353b0b11 1049 .eq(DefineOpaqueTypes::No, b, a)
f035d41b 1050 .map_err(|_| Unimplemented)?;
add651ee
FG
1051
1052 ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
f035d41b
XL
1053 }
1054
1055 // `Struct<T>` -> `Struct<U>`
add651ee 1056 (&ty::Adt(def, args_a), &ty::Adt(_, args_b)) => {
9ffffee4 1057 let unsizing_params = tcx.unsizing_params_for_adt(def.did());
3c0e092e
XL
1058 if unsizing_params.is_empty() {
1059 return Err(Unimplemented);
f035d41b
XL
1060 }
1061
fe692bf9 1062 let tail_field = def.non_enum_variant().tail();
9ffffee4
FG
1063 let tail_field_ty = tcx.type_of(tail_field.did);
1064
add651ee
FG
1065 let mut nested = vec![];
1066
f2b60f7d
FG
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,
add651ee 1075 tail_field_ty.instantiate(tcx, args_a),
f2b60f7d
FG
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,
add651ee 1083 tail_field_ty.instantiate(tcx, args_b),
f2b60f7d
FG
1084 &mut nested,
1085 );
f035d41b
XL
1086
1087 // Check that the source struct with the target's
1088 // unsizing parameters is equal to the target.
add651ee
FG
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);
f035d41b
XL
1094 let InferOk { obligations, .. } = self
1095 .infcx
1096 .at(&obligation.cause, obligation.param_env)
353b0b11 1097 .eq(DefineOpaqueTypes::No, target, new_struct)
f035d41b
XL
1098 .map_err(|_| Unimplemented)?;
1099 nested.extend(obligations);
1100
1101 // Construct the nested `TailField<T>: Unsize<TailField<U>>` predicate.
353b0b11 1102 let tail_unsize_obligation = obligation.with(
f035d41b 1103 tcx,
49aad941
FG
1104 ty::TraitRef::new(
1105 tcx,
1106 obligation.predicate.def_id(),
1107 [source_tail, target_tail],
1108 ),
353b0b11
FG
1109 );
1110 nested.push(tail_unsize_obligation);
add651ee
FG
1111
1112 ImplSource::Builtin(BuiltinImplSource::Misc, nested)
f035d41b
XL
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.
9ffffee4 1125 let new_tuple =
fe692bf9 1126 Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
add651ee 1127 let InferOk { mut obligations, .. } = self
f035d41b
XL
1128 .infcx
1129 .at(&obligation.cause, obligation.param_env)
353b0b11 1130 .eq(DefineOpaqueTypes::No, target, new_tuple)
f035d41b 1131 .map_err(|_| Unimplemented)?;
f035d41b 1132
353b0b11 1133 // Add a nested `T: Unsize<U>` predicate.
49aad941
FG
1134 let last_unsize_obligation = obligation.with(
1135 tcx,
1136 ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
1137 );
add651ee
FG
1138 obligations.push(last_unsize_obligation);
1139
1140 ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
f035d41b
XL
1141 }
1142
487cf647 1143 _ => bug!("source: {source}, target: {target}"),
add651ee 1144 })
f035d41b 1145 }
5099ac24 1146
5e7ed085 1147 fn confirm_const_destruct_candidate(
5099ac24 1148 &mut self,
fe692bf9 1149 obligation: &PolyTraitObligation<'tcx>,
5099ac24 1150 impl_def_id: Option<DefId>,
fe692bf9 1151 ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
5e7ed085 1152 // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
add651ee
FG
1153 // FIXME(effects)
1154 if true {
fe692bf9 1155 return Ok(vec![]);
5e7ed085
FG
1156 }
1157
1158 let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
5099ac24
FG
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
5e7ed085
FG
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.
5099ac24 1169 if let Some(impl_def_id) = impl_def_id {
064997fb
FG
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 });
add651ee
FG
1175 let args = self.rematch_impl(impl_def_id, &new_obligation);
1176 debug!(?args, "impl args");
064997fb
FG
1177
1178 let cause = obligation.derived_cause(|derived| {
1179 ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
1180 derived,
9ffffee4
FG
1181 impl_or_alias_def_id: impl_def_id,
1182 impl_def_predicate_index: None,
064997fb
FG
1183 span: obligation.cause.span,
1184 }))
1185 });
1186 let obligations = ensure_sufficient_stack(|| {
1187 self.vtable_impl(
1188 impl_def_id,
add651ee 1189 args,
064997fb
FG
1190 &cause,
1191 new_obligation.recursion_depth + 1,
1192 new_obligation.param_env,
1193 obligation.predicate,
1194 )
5e7ed085
FG
1195 });
1196 nested.extend(obligations.nested);
5099ac24
FG
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() {
add651ee 1201 ty::Adt(def, args) => def.all_fields().map(|f| f.ty(tcx, args)).collect(),
5099ac24
FG
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
2b03887a
FG
1223 // `ManuallyDrop` is trivially drop
1224 ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {}
1225
5099ac24 1226 // These types are built-in, so we can fast-track by registering
5e7ed085 1227 // nested predicates for their constituent type(s)
5099ac24
FG
1228 ty::Array(ty, _) | ty::Slice(ty) => {
1229 stack.push(ty);
1230 }
1231 ty::Tuple(tys) => {
5e7ed085 1232 stack.extend(tys.iter());
5099ac24 1233 }
add651ee
FG
1234 ty::Closure(_, args) => {
1235 stack.push(args.as_closure().tupled_upvars_ty());
5099ac24 1236 }
add651ee
FG
1237 ty::Generator(_, args, _) => {
1238 let generator = args.as_generator();
5099ac24
FG
1239 stack.extend([generator.tupled_upvars_ty(), generator.witness()]);
1240 }
781aab86 1241 ty::GeneratorWitness(def_id, args) => {
9ffffee4
FG
1242 let tcx = self.tcx();
1243 stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
add651ee 1244 let ty = bty.instantiate(tcx, args);
9ffffee4
FG
1245 debug_assert!(!ty.has_late_bound_regions());
1246 ty
1247 }))
1248 }
5099ac24
FG
1249
1250 // If we have a projection type, make sure to normalize it so we replace it
1251 // with a fresh infer variable
49aad941 1252 ty::Alias(ty::Projection | ty::Inherent, ..) => {
add651ee 1253 // FIXME(effects) this needs constness
064997fb
FG
1254 let predicate = normalize_with_depth_to(
1255 self,
1256 obligation.param_env,
1257 cause.clone(),
1258 obligation.recursion_depth + 1,
487cf647 1259 self_ty.rebind(ty::TraitPredicate {
49aad941
FG
1260 trait_ref: ty::TraitRef::from_lang_item(
1261 self.tcx(),
1262 LangItem::Destruct,
1263 cause.span,
1264 [nested_ty],
1265 ),
487cf647
FG
1266 polarity: ty::ImplPolarity::Positive,
1267 }),
064997fb
FG
1268 &mut nested,
1269 );
1270
1271 nested.push(Obligation::with_depth(
487cf647 1272 tcx,
064997fb
FG
1273 cause.clone(),
1274 obligation.recursion_depth + 1,
1275 obligation.param_env,
1276 predicate,
1277 ));
5099ac24
FG
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 _ => {
add651ee 1284 // FIXME(effects) this needs constness
487cf647 1285 let predicate = self_ty.rebind(ty::TraitPredicate {
49aad941
FG
1286 trait_ref: ty::TraitRef::from_lang_item(
1287 self.tcx(),
1288 LangItem::Destruct,
1289 cause.span,
1290 [nested_ty],
1291 ),
487cf647
FG
1292 polarity: ty::ImplPolarity::Positive,
1293 });
5099ac24
FG
1294
1295 nested.push(Obligation::with_depth(
487cf647 1296 tcx,
5099ac24
FG
1297 cause.clone(),
1298 obligation.recursion_depth + 1,
1299 obligation.param_env,
1300 predicate,
1301 ));
1302 }
1303 }
1304 }
1305
fe692bf9 1306 Ok(nested)
5099ac24 1307 }
f035d41b 1308}