]>
Commit | Line | Data |
---|---|---|
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 | 9 | use rustc_ast::Mutability; |
f035d41b | 10 | use rustc_data_structures::stack::ensure_sufficient_stack; |
3dfed10e | 11 | use rustc_hir::lang_items::LangItem; |
29967ef6 | 12 | use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; |
353b0b11 | 13 | use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; |
add651ee | 14 | use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch}; |
2b03887a | 15 | use rustc_middle::ty::{ |
add651ee FG |
16 | self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate, |
17 | TraitPredicate, Ty, TyCtxt, TypeVisitableExt, | |
2b03887a | 18 | }; |
f035d41b XL |
19 | use rustc_span::def_id::DefId; |
20 | ||
29967ef6 | 21 | use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; |
353b0b11 | 22 | use crate::traits::util::{self, closure_trait_ref_and_return_type}; |
487cf647 FG |
23 | use crate::traits::vtable::{ |
24 | count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset, | |
25 | VtblSegment, | |
26 | }; | |
f035d41b | 27 | use 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 | |
34 | use super::BuiltinImplConditions; | |
35 | use super::SelectionCandidate::{self, *}; | |
36 | use super::SelectionContext; | |
37 | ||
38 | use std::iter; | |
94222f64 | 39 | use std::ops::ControlFlow; |
f035d41b XL |
40 | |
41 | impl<'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 | } |