1 //! Code for projecting associated types out of trait references.
2
3 use super::check_substs_compatible;
4 use super::specialization_graph;
5 use super::translate_substs;
6 use super::util;
7 use super::ImplSourceUserDefinedData;
8 use super::MismatchedProjectionTypes;
9 use super::Obligation;
10 use super::ObligationCause;
11 use super::PredicateObligation;
12 use super::Selection;
13 use super::SelectionContext;
14 use super::SelectionError;
15 use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
16
17 use crate::errors::InherentProjectionNormalizationOverflow;
18 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
19 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
20 use crate::traits::error_reporting::TypeErrCtxtExt as _;
21 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
22 use crate::traits::select::ProjectionMatchesProjection;
23 use rustc_data_structures::sso::SsoHashSet;
24 use rustc_data_structures::stack::ensure_sufficient_stack;
25 use rustc_errors::ErrorGuaranteed;
26 use rustc_hir::def::DefKind;
27 use rustc_hir::lang_items::LangItem;
28 use rustc_infer::infer::at::At;
29 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
30 use rustc_infer::infer::DefineOpaqueTypes;
31 use rustc_infer::traits::FulfillmentError;
32 use rustc_infer::traits::ObligationCauseCode;
33 use rustc_infer::traits::TraitEngine;
34 use rustc_middle::traits::select::OverflowError;
35 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
36 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
37 use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
38 use rustc_span::symbol::sym;
39
40 use std::collections::BTreeMap;
41
42 pub use rustc_middle::traits::Reveal;
43
44 pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
45
46 pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
47
48 pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
49
50 pub(super) struct InProgress;
51
52 pub trait NormalizeExt<'tcx> {
53 /// Normalize a value using the `AssocTypeNormalizer`.
54 ///
55 /// This normalization should be used when the type contains inference variables or the
56 /// projection may be fallible.
normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>57 fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>;
58
59 /// Deeply normalizes `value`, replacing all aliases which can by normalized in
60 /// the current environment. In the new solver this errors in case normalization
61 /// fails or is ambiguous. This only normalizes opaque types with `Reveal::All`.
62 ///
63 /// In the old solver this simply uses `normalizes` and adds the nested obligations
64 /// to the `fulfill_cx`. This is necessary as we otherwise end up recomputing the
65 /// same goals in both a temporary and the shared context which negatively impacts
66 /// performance as these don't share caching.
67 ///
68 /// FIXME(-Ztrait-solver=next): This has the same behavior as `traits::fully_normalize`
69 /// in the new solver, but because of performance reasons, we currently reuse an
70 /// existing fulfillment context in the old solver. Once we also eagerly prove goals with
71 /// the old solver or have removed the old solver, remove `traits::fully_normalize` and
72 /// rename this function to `At::fully_normalize`.
deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>( self, value: T, fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result<T, Vec<FulfillmentError<'tcx>>>73 fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
74 self,
75 value: T,
76 fulfill_cx: &mut dyn TraitEngine<'tcx>,
77 ) -> Result<T, Vec<FulfillmentError<'tcx>>>;
78 }
79
80 impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> {
normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T>81 fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> {
82 if self.infcx.next_trait_solver() {
83 InferOk { value, obligations: Vec::new() }
84 } else {
85 let mut selcx = SelectionContext::new(self.infcx);
86 let Normalized { value, obligations } =
87 normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
88 InferOk { value, obligations }
89 }
90 }
91
deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>( self, value: T, fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result<T, Vec<FulfillmentError<'tcx>>>92 fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
93 self,
94 value: T,
95 fulfill_cx: &mut dyn TraitEngine<'tcx>,
96 ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
97 if self.infcx.next_trait_solver() {
98 crate::solve::deeply_normalize(self, value)
99 } else {
100 let value = self
101 .normalize(value)
102 .into_value_registering_obligations(self.infcx, &mut *fulfill_cx);
103 let errors = fulfill_cx.select_where_possible(self.infcx);
104 let value = self.infcx.resolve_vars_if_possible(value);
105 if errors.is_empty() { Ok(value) } else { Err(errors) }
106 }
107 }
108 }
109
110 /// When attempting to resolve `<T as TraitRef>::Name` ...
111 #[derive(Debug)]
112 pub enum ProjectionError<'tcx> {
113 /// ...we found multiple sources of information and couldn't resolve the ambiguity.
114 TooManyCandidates,
115
116 /// ...an error occurred matching `T : TraitRef`
117 TraitSelectionError(SelectionError<'tcx>),
118 }
119
120 #[derive(PartialEq, Eq, Debug)]
121 enum ProjectionCandidate<'tcx> {
122 /// From a where-clause in the env or object type
123 ParamEnv(ty::PolyProjectionPredicate<'tcx>),
124
125 /// From the definition of `Trait` when you have something like
126 /// `<<A as Trait>::B as Trait2>::C`.
127 TraitDef(ty::PolyProjectionPredicate<'tcx>),
128
129 /// Bounds specified on an object type
130 Object(ty::PolyProjectionPredicate<'tcx>),
131
132 /// From an "impl" (or a "pseudo-impl" returned by select)
133 Select(Selection<'tcx>),
134
135 ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
136 }
137
138 enum ProjectionCandidateSet<'tcx> {
139 None,
140 Single(ProjectionCandidate<'tcx>),
141 Ambiguous,
142 Error(SelectionError<'tcx>),
143 }
144
145 impl<'tcx> ProjectionCandidateSet<'tcx> {
mark_ambiguous(&mut self)146 fn mark_ambiguous(&mut self) {
147 *self = ProjectionCandidateSet::Ambiguous;
148 }
149
mark_error(&mut self, err: SelectionError<'tcx>)150 fn mark_error(&mut self, err: SelectionError<'tcx>) {
151 *self = ProjectionCandidateSet::Error(err);
152 }
153
154 // Returns true if the push was successful, or false if the candidate
155 // was discarded -- this could be because of ambiguity, or because
156 // a higher-priority candidate is already there.
push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool157 fn push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool {
158 use self::ProjectionCandidate::*;
159 use self::ProjectionCandidateSet::*;
160
161 // This wacky variable is just used to try and
162 // make code readable and avoid confusing paths.
163 // It is assigned a "value" of `()` only on those
164 // paths in which we wish to convert `*self` to
165 // ambiguous (and return false, because the candidate
166 // was not used). On other paths, it is not assigned,
167 // and hence if those paths *could* reach the code that
168 // comes after the match, this fn would not compile.
169 let convert_to_ambiguous;
170
171 match self {
172 None => {
173 *self = Single(candidate);
174 return true;
175 }
176
177 Single(current) => {
178 // Duplicates can happen inside ParamEnv. In the case, we
179 // perform a lazy deduplication.
180 if current == &candidate {
181 return false;
182 }
183
184 // Prefer where-clauses. As in select, if there are multiple
185 // candidates, we prefer where-clause candidates over impls. This
186 // may seem a bit surprising, since impls are the source of
187 // "truth" in some sense, but in fact some of the impls that SEEM
188 // applicable are not, because of nested obligations. Where
189 // clauses are the safer choice. See the comment on
190 // `select::SelectionCandidate` and #21974 for more details.
191 match (current, candidate) {
192 (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
193 (ParamEnv(..), _) => return false,
194 (_, ParamEnv(..)) => unreachable!(),
195 (_, _) => convert_to_ambiguous = (),
196 }
197 }
198
199 Ambiguous | Error(..) => {
200 return false;
201 }
202 }
203
204 // We only ever get here when we moved from a single candidate
205 // to ambiguous.
206 let () = convert_to_ambiguous;
207 *self = Ambiguous;
208 false
209 }
210 }
211
212 /// States returned from `poly_project_and_unify_type`. Takes the place
213 /// of the old return type, which was:
214 /// ```ignore (not-rust)
215 /// Result<
216 /// Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
217 /// MismatchedProjectionTypes<'tcx>,
218 /// >
219 /// ```
220 pub(super) enum ProjectAndUnifyResult<'tcx> {
221 /// The projection bound holds subject to the given obligations. If the
222 /// projection cannot be normalized because the required trait bound does
223 /// not hold, this is returned, with `obligations` being a predicate that
224 /// cannot be proven.
225 Holds(Vec<PredicateObligation<'tcx>>),
226 /// The projection cannot be normalized due to ambiguity. Resolving some
227 /// inference variables in the projection may fix this.
228 FailedNormalization,
229 /// The project cannot be normalized because `poly_project_and_unify_type`
230 /// is called recursively while normalizing the same projection.
231 Recursive,
232 // the projection can be normalized, but is not equal to the expected type.
233 // Returns the type error that arose from the mismatch.
234 MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>),
235 }
236
237 /// Evaluates constraints of the form:
238 /// ```ignore (not-rust)
239 /// for<...> <T as Trait>::U == V
240 /// ```
241 /// If successful, this may result in additional obligations. Also returns
242 /// the projection cache key used to track these additional obligations.
243 #[instrument(level = "debug", skip(selcx))]
poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx>244 pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
245 selcx: &mut SelectionContext<'cx, 'tcx>,
246 obligation: &PolyProjectionObligation<'tcx>,
247 ) -> ProjectAndUnifyResult<'tcx> {
248 let infcx = selcx.infcx;
249 let r = infcx.commit_if_ok(|_snapshot| {
250 let old_universe = infcx.universe();
251 let placeholder_predicate =
252 infcx.instantiate_binder_with_placeholders(obligation.predicate);
253 let new_universe = infcx.universe();
254
255 let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
256 match project_and_unify_type(selcx, &placeholder_obligation) {
257 ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
258 ProjectAndUnifyResult::Holds(obligations)
259 if old_universe != new_universe
260 && selcx.tcx().features().generic_associated_types_extended =>
261 {
262 // If the `generic_associated_types_extended` feature is active, then we ignore any
263 // obligations references lifetimes from any universe greater than or equal to the
264 // universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`,
265 // which isn't quite what we want. Ideally, we want either an implied
266 // `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we
267 // substitute concrete regions. There is design work to be done here; until then,
268 // however, this allows experimenting potential GAT features without running into
269 // well-formedness issues.
270 let new_obligations = obligations
271 .into_iter()
272 .filter(|obligation| {
273 let mut visitor = MaxUniverse::new();
274 obligation.predicate.visit_with(&mut visitor);
275 visitor.max_universe() < new_universe
276 })
277 .collect();
278 Ok(ProjectAndUnifyResult::Holds(new_obligations))
279 }
280 other => Ok(other),
281 }
282 });
283
284 match r {
285 Ok(inner) => inner,
286 Err(err) => ProjectAndUnifyResult::MismatchedProjectionTypes(err),
287 }
288 }
289
290 /// Evaluates constraints of the form:
291 /// ```ignore (not-rust)
292 /// <T as Trait>::U == V
293 /// ```
294 /// If successful, this may result in additional obligations.
295 ///
296 /// See [poly_project_and_unify_type] for an explanation of the return value.
297 #[instrument(level = "debug", skip(selcx))]
project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx>298 fn project_and_unify_type<'cx, 'tcx>(
299 selcx: &mut SelectionContext<'cx, 'tcx>,
300 obligation: &ProjectionObligation<'tcx>,
301 ) -> ProjectAndUnifyResult<'tcx> {
302 let mut obligations = vec![];
303
304 let infcx = selcx.infcx;
305 let normalized = match opt_normalize_projection_type(
306 selcx,
307 obligation.param_env,
308 obligation.predicate.projection_ty,
309 obligation.cause.clone(),
310 obligation.recursion_depth,
311 &mut obligations,
312 ) {
313 Ok(Some(n)) => n,
314 Ok(None) => return ProjectAndUnifyResult::FailedNormalization,
315 Err(InProgress) => return ProjectAndUnifyResult::Recursive,
316 };
317 debug!(?normalized, ?obligations, "project_and_unify_type result");
318 let actual = obligation.predicate.term;
319 // For an example where this is necessary see tests/ui/impl-trait/nested-return-type2.rs
320 // This allows users to omit re-mentioning all bounds on an associated type and just use an
321 // `impl Trait` for the assoc type to add more bounds.
322 let InferOk { value: actual, obligations: new } =
323 selcx.infcx.replace_opaque_types_with_inference_vars(
324 actual,
325 obligation.cause.body_id,
326 obligation.cause.span,
327 obligation.param_env,
328 );
329 obligations.extend(new);
330
331 // Need to define opaque types to support nested opaque types like `impl Fn() -> impl Trait`
332 match infcx.at(&obligation.cause, obligation.param_env).eq(
333 DefineOpaqueTypes::Yes,
334 normalized,
335 actual,
336 ) {
337 Ok(InferOk { obligations: inferred_obligations, value: () }) => {
338 obligations.extend(inferred_obligations);
339 ProjectAndUnifyResult::Holds(obligations)
340 }
341 Err(err) => {
342 debug!("equating types encountered error {:?}", err);
343 ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err })
344 }
345 }
346 }
347
348 /// As `normalize`, but with a custom depth.
normalize_with_depth<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, value: T, ) -> Normalized<'tcx, T> where T: TypeFoldable<TyCtxt<'tcx>>,349 pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>(
350 selcx: &'a mut SelectionContext<'b, 'tcx>,
351 param_env: ty::ParamEnv<'tcx>,
352 cause: ObligationCause<'tcx>,
353 depth: usize,
354 value: T,
355 ) -> Normalized<'tcx, T>
356 where
357 T: TypeFoldable<TyCtxt<'tcx>>,
358 {
359 let mut obligations = Vec::new();
360 let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
361 Normalized { value, obligations }
362 }
363
364 #[instrument(level = "info", skip(selcx, param_env, cause, obligations))]
normalize_with_depth_to<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, value: T, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> T where T: TypeFoldable<TyCtxt<'tcx>>,365 pub(crate) fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
366 selcx: &'a mut SelectionContext<'b, 'tcx>,
367 param_env: ty::ParamEnv<'tcx>,
368 cause: ObligationCause<'tcx>,
369 depth: usize,
370 value: T,
371 obligations: &mut Vec<PredicateObligation<'tcx>>,
372 ) -> T
373 where
374 T: TypeFoldable<TyCtxt<'tcx>>,
375 {
376 debug!(obligations.len = obligations.len());
377 let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
378 let result = ensure_sufficient_stack(|| normalizer.fold(value));
379 debug!(?result, obligations.len = normalizer.obligations.len());
380 debug!(?normalizer.obligations,);
381 result
382 }
383
384 #[instrument(level = "info", skip(selcx, param_env, cause, obligations))]
try_normalize_with_depth_to<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, value: T, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> T where T: TypeFoldable<TyCtxt<'tcx>>,385 pub(crate) fn try_normalize_with_depth_to<'a, 'b, 'tcx, T>(
386 selcx: &'a mut SelectionContext<'b, 'tcx>,
387 param_env: ty::ParamEnv<'tcx>,
388 cause: ObligationCause<'tcx>,
389 depth: usize,
390 value: T,
391 obligations: &mut Vec<PredicateObligation<'tcx>>,
392 ) -> T
393 where
394 T: TypeFoldable<TyCtxt<'tcx>>,
395 {
396 debug!(obligations.len = obligations.len());
397 let mut normalizer = AssocTypeNormalizer::new_without_eager_inference_replacement(
398 selcx,
399 param_env,
400 cause,
401 depth,
402 obligations,
403 );
404 let result = ensure_sufficient_stack(|| normalizer.fold(value));
405 debug!(?result, obligations.len = normalizer.obligations.len());
406 debug!(?normalizer.obligations,);
407 result
408 }
409
needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>( value: &T, reveal: Reveal, ) -> bool410 pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
411 value: &T,
412 reveal: Reveal,
413 ) -> bool {
414 match reveal {
415 Reveal::UserFacing => value.has_type_flags(
416 ty::TypeFlags::HAS_TY_PROJECTION
417 | ty::TypeFlags::HAS_TY_INHERENT
418 | ty::TypeFlags::HAS_CT_PROJECTION,
419 ),
420 Reveal::All => value.has_type_flags(
421 ty::TypeFlags::HAS_TY_PROJECTION
422 | ty::TypeFlags::HAS_TY_INHERENT
423 | ty::TypeFlags::HAS_TY_OPAQUE
424 | ty::TypeFlags::HAS_CT_PROJECTION,
425 ),
426 }
427 }
428
429 struct AssocTypeNormalizer<'a, 'b, 'tcx> {
430 selcx: &'a mut SelectionContext<'b, 'tcx>,
431 param_env: ty::ParamEnv<'tcx>,
432 cause: ObligationCause<'tcx>,
433 obligations: &'a mut Vec<PredicateObligation<'tcx>>,
434 depth: usize,
435 universes: Vec<Option<ty::UniverseIndex>>,
436 /// If true, when a projection is unable to be completed, an inference
437 /// variable will be created and an obligation registered to project to that
438 /// inference variable. Also, constants will be eagerly evaluated.
439 eager_inference_replacement: bool,
440 }
441
442 impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
new( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &'a mut Vec<PredicateObligation<'tcx>>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx>443 fn new(
444 selcx: &'a mut SelectionContext<'b, 'tcx>,
445 param_env: ty::ParamEnv<'tcx>,
446 cause: ObligationCause<'tcx>,
447 depth: usize,
448 obligations: &'a mut Vec<PredicateObligation<'tcx>>,
449 ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
450 debug_assert!(!selcx.infcx.next_trait_solver());
451 AssocTypeNormalizer {
452 selcx,
453 param_env,
454 cause,
455 obligations,
456 depth,
457 universes: vec![],
458 eager_inference_replacement: true,
459 }
460 }
461
new_without_eager_inference_replacement( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &'a mut Vec<PredicateObligation<'tcx>>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx>462 fn new_without_eager_inference_replacement(
463 selcx: &'a mut SelectionContext<'b, 'tcx>,
464 param_env: ty::ParamEnv<'tcx>,
465 cause: ObligationCause<'tcx>,
466 depth: usize,
467 obligations: &'a mut Vec<PredicateObligation<'tcx>>,
468 ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
469 AssocTypeNormalizer {
470 selcx,
471 param_env,
472 cause,
473 obligations,
474 depth,
475 universes: vec![],
476 eager_inference_replacement: false,
477 }
478 }
479
fold<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T480 fn fold<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
481 let value = self.selcx.infcx.resolve_vars_if_possible(value);
482 debug!(?value);
483
484 assert!(
485 !value.has_escaping_bound_vars(),
486 "Normalizing {:?} without wrapping in a `Binder`",
487 value
488 );
489
490 if !needs_normalization(&value, self.param_env.reveal()) {
491 value
492 } else {
493 value.fold_with(self)
494 }
495 }
496 }
497
498 impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx> {
interner(&self) -> TyCtxt<'tcx>499 fn interner(&self) -> TyCtxt<'tcx> {
500 self.selcx.tcx()
501 }
502
fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>( &mut self, t: ty::Binder<'tcx, T>, ) -> ty::Binder<'tcx, T>503 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
504 &mut self,
505 t: ty::Binder<'tcx, T>,
506 ) -> ty::Binder<'tcx, T> {
507 self.universes.push(None);
508 let t = t.super_fold_with(self);
509 self.universes.pop();
510 t
511 }
512
fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx>513 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
514 if !needs_normalization(&ty, self.param_env.reveal()) {
515 return ty;
516 }
517
518 let (kind, data) = match *ty.kind() {
519 ty::Alias(kind, alias_ty) => (kind, alias_ty),
520 _ => return ty.super_fold_with(self),
521 };
522
523 // We try to be a little clever here as a performance optimization in
524 // cases where there are nested projections under binders.
525 // For example:
526 // ```
527 // for<'a> fn(<T as Foo>::One<'a, Box<dyn Bar<'a, Item=<T as Foo>::Two<'a>>>>)
528 // ```
529 // We normalize the substs on the projection before the projecting, but
530 // if we're naive, we'll
531 // replace bound vars on inner, project inner, replace placeholders on inner,
532 // replace bound vars on outer, project outer, replace placeholders on outer
533 //
534 // However, if we're a bit more clever, we can replace the bound vars
535 // on the entire type before normalizing nested projections, meaning we
536 // replace bound vars on outer, project inner,
537 // project outer, replace placeholders on outer
538 //
539 // This is possible because the inner `'a` will already be a placeholder
540 // when we need to normalize the inner projection
541 //
542 // On the other hand, this does add a bit of complexity, since we only
543 // replace bound vars if the current type is a `Projection` and we need
544 // to make sure we don't forget to fold the substs regardless.
545
546 match kind {
547 ty::Opaque => {
548 // Only normalize `impl Trait` outside of type inference, usually in codegen.
549 match self.param_env.reveal() {
550 Reveal::UserFacing => ty.super_fold_with(self),
551
552 Reveal::All => {
553 let recursion_limit = self.interner().recursion_limit();
554 if !recursion_limit.value_within_limit(self.depth) {
555 self.selcx.infcx.err_ctxt().report_overflow_error(
556 &ty,
557 self.cause.span,
558 true,
559 |_| {},
560 );
561 }
562
563 let substs = data.substs.fold_with(self);
564 let generic_ty = self.interner().type_of(data.def_id);
565 let concrete_ty = generic_ty.subst(self.interner(), substs);
566 self.depth += 1;
567 let folded_ty = self.fold_ty(concrete_ty);
568 self.depth -= 1;
569 folded_ty
570 }
571 }
572 }
573
574 ty::Projection if !data.has_escaping_bound_vars() => {
575 // This branch is *mostly* just an optimization: when we don't
576 // have escaping bound vars, we don't need to replace them with
577 // placeholders (see branch below). *Also*, we know that we can
578 // register an obligation to *later* project, since we know
579 // there won't be bound vars there.
580 let data = data.fold_with(self);
581 let normalized_ty = if self.eager_inference_replacement {
582 normalize_projection_type(
583 self.selcx,
584 self.param_env,
585 data,
586 self.cause.clone(),
587 self.depth,
588 &mut self.obligations,
589 )
590 } else {
591 opt_normalize_projection_type(
592 self.selcx,
593 self.param_env,
594 data,
595 self.cause.clone(),
596 self.depth,
597 &mut self.obligations,
598 )
599 .ok()
600 .flatten()
601 .unwrap_or_else(|| ty.super_fold_with(self).into())
602 };
603 debug!(
604 ?self.depth,
605 ?ty,
606 ?normalized_ty,
607 obligations.len = ?self.obligations.len(),
608 "AssocTypeNormalizer: normalized type"
609 );
610 normalized_ty.ty().unwrap()
611 }
612
613 ty::Projection => {
614 // If there are escaping bound vars, we temporarily replace the
615 // bound vars with placeholders. Note though, that in the case
616 // that we still can't project for whatever reason (e.g. self
617 // type isn't known enough), we *can't* register an obligation
618 // and return an inference variable (since then that obligation
619 // would have bound vars and that's a can of worms). Instead,
620 // we just give up and fall back to pretending like we never tried!
621 //
622 // Note: this isn't necessarily the final approach here; we may
623 // want to figure out how to register obligations with escaping vars
624 // or handle this some other way.
625
626 let infcx = self.selcx.infcx;
627 let (data, mapped_regions, mapped_types, mapped_consts) =
628 BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
629 let data = data.fold_with(self);
630 let normalized_ty = opt_normalize_projection_type(
631 self.selcx,
632 self.param_env,
633 data,
634 self.cause.clone(),
635 self.depth,
636 &mut self.obligations,
637 )
638 .ok()
639 .flatten()
640 .map(|term| term.ty().unwrap())
641 .map(|normalized_ty| {
642 PlaceholderReplacer::replace_placeholders(
643 infcx,
644 mapped_regions,
645 mapped_types,
646 mapped_consts,
647 &self.universes,
648 normalized_ty,
649 )
650 })
651 .unwrap_or_else(|| ty.super_fold_with(self));
652
653 debug!(
654 ?self.depth,
655 ?ty,
656 ?normalized_ty,
657 obligations.len = ?self.obligations.len(),
658 "AssocTypeNormalizer: normalized type"
659 );
660 normalized_ty
661 }
662 ty::Weak => {
663 let infcx = self.selcx.infcx;
664 self.obligations.extend(
665 infcx
666 .tcx
667 .predicates_of(data.def_id)
668 .instantiate_own(infcx.tcx, data.substs)
669 .map(|(mut predicate, span)| {
670 if data.has_escaping_bound_vars() {
671 (predicate, ..) = BoundVarReplacer::replace_bound_vars(
672 infcx,
673 &mut self.universes,
674 predicate,
675 );
676 }
677 let mut cause = self.cause.clone();
678 cause.map_code(|code| {
679 ObligationCauseCode::TypeAlias(code, span, data.def_id)
680 });
681 Obligation::new(infcx.tcx, cause, self.param_env, predicate)
682 }),
683 );
684 infcx.tcx.type_of(data.def_id).subst(infcx.tcx, data.substs).fold_with(self)
685 }
686
687 ty::Inherent if !data.has_escaping_bound_vars() => {
688 // This branch is *mostly* just an optimization: when we don't
689 // have escaping bound vars, we don't need to replace them with
690 // placeholders (see branch below). *Also*, we know that we can
691 // register an obligation to *later* project, since we know
692 // there won't be bound vars there.
693
694 let data = data.fold_with(self);
695
696 // FIXME(inherent_associated_types): Do we need to honor `self.eager_inference_replacement`
697 // here like `ty::Projection`?
698 normalize_inherent_projection(
699 self.selcx,
700 self.param_env,
701 data,
702 self.cause.clone(),
703 self.depth,
704 &mut self.obligations,
705 )
706 }
707
708 ty::Inherent => {
709 let infcx = self.selcx.infcx;
710 let (data, mapped_regions, mapped_types, mapped_consts) =
711 BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
712 let data = data.fold_with(self);
713 let ty = normalize_inherent_projection(
714 self.selcx,
715 self.param_env,
716 data,
717 self.cause.clone(),
718 self.depth,
719 &mut self.obligations,
720 );
721
722 PlaceholderReplacer::replace_placeholders(
723 infcx,
724 mapped_regions,
725 mapped_types,
726 mapped_consts,
727 &self.universes,
728 ty,
729 )
730 }
731 }
732 }
733
734 #[instrument(skip(self), level = "debug")]
fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx>735 fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
736 let tcx = self.selcx.tcx();
737 if tcx.features().generic_const_exprs
738 || !needs_normalization(&constant, self.param_env.reveal())
739 {
740 constant
741 } else {
742 let constant = constant.super_fold_with(self);
743 debug!(?constant, ?self.param_env);
744 with_replaced_escaping_bound_vars(
745 self.selcx.infcx,
746 &mut self.universes,
747 constant,
748 |constant| constant.eval(tcx, self.param_env),
749 )
750 }
751 }
752
753 #[inline]
fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx>754 fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
755 if p.allow_normalization() && needs_normalization(&p, self.param_env.reveal()) {
756 p.super_fold_with(self)
757 } else {
758 p
759 }
760 }
761 }
762
763 pub struct BoundVarReplacer<'me, 'tcx> {
764 infcx: &'me InferCtxt<'tcx>,
765 // These three maps track the bound variable that were replaced by placeholders. It might be
766 // nice to remove these since we already have the `kind` in the placeholder; we really just need
767 // the `var` (but we *could* bring that into scope if we were to track them as we pass them).
768 mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
769 mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
770 mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
771 // The current depth relative to *this* folding, *not* the entire normalization. In other words,
772 // the depth of binders we've passed here.
773 current_index: ty::DebruijnIndex,
774 // The `UniverseIndex` of the binding levels above us. These are optional, since we are lazy:
775 // we don't actually create a universe until we see a bound var we have to replace.
776 universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
777 }
778
779 /// Executes `f` on `value` after replacing all escaping bound variables with placeholders
780 /// and then replaces these placeholders with the original bound variables in the result.
781 ///
782 /// In most places, bound variables should be replaced right when entering a binder, making
783 /// this function unnecessary. However, normalization currently does not do that, so we have
784 /// to do this lazily.
785 ///
786 /// You should not add any additional uses of this function, at least not without first
787 /// discussing it with t-types.
788 ///
789 /// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
790 /// normalization as well, at which point this function will be unnecessary and can be removed.
with_replaced_escaping_bound_vars< 'a, 'tcx, T: TypeFoldable<TyCtxt<'tcx>>, R: TypeFoldable<TyCtxt<'tcx>>, >( infcx: &'a InferCtxt<'tcx>, universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>, value: T, f: impl FnOnce(T) -> R, ) -> R791 pub fn with_replaced_escaping_bound_vars<
792 'a,
793 'tcx,
794 T: TypeFoldable<TyCtxt<'tcx>>,
795 R: TypeFoldable<TyCtxt<'tcx>>,
796 >(
797 infcx: &'a InferCtxt<'tcx>,
798 universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
799 value: T,
800 f: impl FnOnce(T) -> R,
801 ) -> R {
802 if value.has_escaping_bound_vars() {
803 let (value, mapped_regions, mapped_types, mapped_consts) =
804 BoundVarReplacer::replace_bound_vars(infcx, universe_indices, value);
805 let result = f(value);
806 PlaceholderReplacer::replace_placeholders(
807 infcx,
808 mapped_regions,
809 mapped_types,
810 mapped_consts,
811 universe_indices,
812 result,
813 )
814 } else {
815 f(value)
816 }
817 }
818
819 impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
820 /// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
821 /// use a binding level above `universe_indices.len()`, we fail.
replace_bound_vars<T: TypeFoldable<TyCtxt<'tcx>>>( infcx: &'me InferCtxt<'tcx>, universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>, value: T, ) -> ( T, BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>, BTreeMap<ty::PlaceholderType, ty::BoundTy>, BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>, )822 pub fn replace_bound_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
823 infcx: &'me InferCtxt<'tcx>,
824 universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
825 value: T,
826 ) -> (
827 T,
828 BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
829 BTreeMap<ty::PlaceholderType, ty::BoundTy>,
830 BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
831 ) {
832 let mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion> = BTreeMap::new();
833 let mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy> = BTreeMap::new();
834 let mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar> = BTreeMap::new();
835
836 let mut replacer = BoundVarReplacer {
837 infcx,
838 mapped_regions,
839 mapped_types,
840 mapped_consts,
841 current_index: ty::INNERMOST,
842 universe_indices,
843 };
844
845 let value = value.fold_with(&mut replacer);
846
847 (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
848 }
849
universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex850 fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
851 let infcx = self.infcx;
852 let index =
853 self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
854 let universe = self.universe_indices[index].unwrap_or_else(|| {
855 for i in self.universe_indices.iter_mut().take(index + 1) {
856 *i = i.or_else(|| Some(infcx.create_next_universe()))
857 }
858 self.universe_indices[index].unwrap()
859 });
860 universe
861 }
862 }
863
864 impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
interner(&self) -> TyCtxt<'tcx>865 fn interner(&self) -> TyCtxt<'tcx> {
866 self.infcx.tcx
867 }
868
fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>( &mut self, t: ty::Binder<'tcx, T>, ) -> ty::Binder<'tcx, T>869 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
870 &mut self,
871 t: ty::Binder<'tcx, T>,
872 ) -> ty::Binder<'tcx, T> {
873 self.current_index.shift_in(1);
874 let t = t.super_fold_with(self);
875 self.current_index.shift_out(1);
876 t
877 }
878
fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx>879 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
880 match *r {
881 ty::ReLateBound(debruijn, _)
882 if debruijn.as_usize() + 1
883 > self.current_index.as_usize() + self.universe_indices.len() =>
884 {
885 bug!("Bound vars outside of `self.universe_indices`");
886 }
887 ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
888 let universe = self.universe_for(debruijn);
889 let p = ty::PlaceholderRegion { universe, bound: br };
890 self.mapped_regions.insert(p, br);
891 ty::Region::new_placeholder(self.infcx.tcx, p)
892 }
893 _ => r,
894 }
895 }
896
fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx>897 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
898 match *t.kind() {
899 ty::Bound(debruijn, _)
900 if debruijn.as_usize() + 1
901 > self.current_index.as_usize() + self.universe_indices.len() =>
902 {
903 bug!("Bound vars outside of `self.universe_indices`");
904 }
905 ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
906 let universe = self.universe_for(debruijn);
907 let p = ty::PlaceholderType { universe, bound: bound_ty };
908 self.mapped_types.insert(p, bound_ty);
909 Ty::new_placeholder(self.infcx.tcx, p)
910 }
911 _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
912 _ => t,
913 }
914 }
915
fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx>916 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
917 match ct.kind() {
918 ty::ConstKind::Bound(debruijn, _)
919 if debruijn.as_usize() + 1
920 > self.current_index.as_usize() + self.universe_indices.len() =>
921 {
922 bug!("Bound vars outside of `self.universe_indices`");
923 }
924 ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
925 let universe = self.universe_for(debruijn);
926 let p = ty::PlaceholderConst { universe, bound: bound_const };
927 self.mapped_consts.insert(p, bound_const);
928 ty::Const::new_placeholder(self.infcx.tcx, p, ct.ty())
929 }
930 _ => ct.super_fold_with(self),
931 }
932 }
933
fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx>934 fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
935 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
936 }
937 }
938
939 /// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
940 pub struct PlaceholderReplacer<'me, 'tcx> {
941 infcx: &'me InferCtxt<'tcx>,
942 mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
943 mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
944 mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
945 universe_indices: &'me [Option<ty::UniverseIndex>],
946 current_index: ty::DebruijnIndex,
947 }
948
949 impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>( infcx: &'me InferCtxt<'tcx>, mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>, mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>, mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>, universe_indices: &'me [Option<ty::UniverseIndex>], value: T, ) -> T950 pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
951 infcx: &'me InferCtxt<'tcx>,
952 mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
953 mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
954 mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
955 universe_indices: &'me [Option<ty::UniverseIndex>],
956 value: T,
957 ) -> T {
958 let mut replacer = PlaceholderReplacer {
959 infcx,
960 mapped_regions,
961 mapped_types,
962 mapped_consts,
963 universe_indices,
964 current_index: ty::INNERMOST,
965 };
966 value.fold_with(&mut replacer)
967 }
968 }
969
970 impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
interner(&self) -> TyCtxt<'tcx>971 fn interner(&self) -> TyCtxt<'tcx> {
972 self.infcx.tcx
973 }
974
fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>( &mut self, t: ty::Binder<'tcx, T>, ) -> ty::Binder<'tcx, T>975 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
976 &mut self,
977 t: ty::Binder<'tcx, T>,
978 ) -> ty::Binder<'tcx, T> {
979 if !t.has_placeholders() && !t.has_infer_regions() {
980 return t;
981 }
982 self.current_index.shift_in(1);
983 let t = t.super_fold_with(self);
984 self.current_index.shift_out(1);
985 t
986 }
987
fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx>988 fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
989 let r1 = match *r0 {
990 ty::ReVar(vid) => self
991 .infcx
992 .inner
993 .borrow_mut()
994 .unwrap_region_constraints()
995 .opportunistic_resolve_var(self.infcx.tcx, vid),
996 _ => r0,
997 };
998
999 let r2 = match *r1 {
1000 ty::RePlaceholder(p) => {
1001 let replace_var = self.mapped_regions.get(&p);
1002 match replace_var {
1003 Some(replace_var) => {
1004 let index = self
1005 .universe_indices
1006 .iter()
1007 .position(|u| matches!(u, Some(pu) if *pu == p.universe))
1008 .unwrap_or_else(|| bug!("Unexpected placeholder universe."));
1009 let db = ty::DebruijnIndex::from_usize(
1010 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
1011 );
1012 ty::Region::new_late_bound(self.interner(), db, *replace_var)
1013 }
1014 None => r1,
1015 }
1016 }
1017 _ => r1,
1018 };
1019
1020 debug!(?r0, ?r1, ?r2, "fold_region");
1021
1022 r2
1023 }
1024
fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx>1025 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1026 match *ty.kind() {
1027 ty::Placeholder(p) => {
1028 let replace_var = self.mapped_types.get(&p);
1029 match replace_var {
1030 Some(replace_var) => {
1031 let index = self
1032 .universe_indices
1033 .iter()
1034 .position(|u| matches!(u, Some(pu) if *pu == p.universe))
1035 .unwrap_or_else(|| bug!("Unexpected placeholder universe."));
1036 let db = ty::DebruijnIndex::from_usize(
1037 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
1038 );
1039 Ty::new_bound(self.infcx.tcx, db, *replace_var)
1040 }
1041 None => ty,
1042 }
1043 }
1044
1045 _ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self),
1046 _ => ty,
1047 }
1048 }
1049
fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx>1050 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1051 if let ty::ConstKind::Placeholder(p) = ct.kind() {
1052 let replace_var = self.mapped_consts.get(&p);
1053 match replace_var {
1054 Some(replace_var) => {
1055 let index = self
1056 .universe_indices
1057 .iter()
1058 .position(|u| matches!(u, Some(pu) if *pu == p.universe))
1059 .unwrap_or_else(|| bug!("Unexpected placeholder universe."));
1060 let db = ty::DebruijnIndex::from_usize(
1061 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
1062 );
1063 ty::Const::new_bound(self.infcx.tcx, db, *replace_var, ct.ty())
1064 }
1065 None => ct,
1066 }
1067 } else {
1068 ct.super_fold_with(self)
1069 }
1070 }
1071 }
1072
1073 /// The guts of `normalize`: normalize a specific projection like `<T
1074 /// as Trait>::Item`. The result is always a type (and possibly
1075 /// additional obligations). If ambiguity arises, which implies that
1076 /// there are unresolved type variables in the projection, we will
1077 /// substitute a fresh type variable `$X` and generate a new
1078 /// obligation `<T as Trait>::Item == $X` for later.
normalize_projection_type<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> Term<'tcx>1079 pub fn normalize_projection_type<'a, 'b, 'tcx>(
1080 selcx: &'a mut SelectionContext<'b, 'tcx>,
1081 param_env: ty::ParamEnv<'tcx>,
1082 projection_ty: ty::AliasTy<'tcx>,
1083 cause: ObligationCause<'tcx>,
1084 depth: usize,
1085 obligations: &mut Vec<PredicateObligation<'tcx>>,
1086 ) -> Term<'tcx> {
1087 opt_normalize_projection_type(
1088 selcx,
1089 param_env,
1090 projection_ty,
1091 cause.clone(),
1092 depth,
1093 obligations,
1094 )
1095 .ok()
1096 .flatten()
1097 .unwrap_or_else(move || {
1098 // if we bottom out in ambiguity, create a type variable
1099 // and a deferred predicate to resolve this when more type
1100 // information is available.
1101
1102 selcx.infcx.infer_projection(param_env, projection_ty, cause, depth + 1, obligations).into()
1103 })
1104 }
1105
1106 /// The guts of `normalize`: normalize a specific projection like `<T
1107 /// as Trait>::Item`. The result is always a type (and possibly
1108 /// additional obligations). Returns `None` in the case of ambiguity,
1109 /// which indicates that there are unbound type variables.
1110 ///
1111 /// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
1112 /// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
1113 /// often immediately appended to another obligations vector. So now this
1114 /// function takes an obligations vector and appends to it directly, which is
1115 /// slightly uglier but avoids the need for an extra short-lived allocation.
1116 #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
opt_normalize_projection_type<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> Result<Option<Term<'tcx>>, InProgress>1117 fn opt_normalize_projection_type<'a, 'b, 'tcx>(
1118 selcx: &'a mut SelectionContext<'b, 'tcx>,
1119 param_env: ty::ParamEnv<'tcx>,
1120 projection_ty: ty::AliasTy<'tcx>,
1121 cause: ObligationCause<'tcx>,
1122 depth: usize,
1123 obligations: &mut Vec<PredicateObligation<'tcx>>,
1124 ) -> Result<Option<Term<'tcx>>, InProgress> {
1125 let infcx = selcx.infcx;
1126 debug_assert!(!selcx.infcx.next_trait_solver());
1127 // Don't use the projection cache in intercrate mode -
1128 // the `infcx` may be re-used between intercrate in non-intercrate
1129 // mode, which could lead to using incorrect cache results.
1130 let use_cache = !selcx.is_intercrate();
1131
1132 let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
1133 let cache_key = ProjectionCacheKey::new(projection_ty);
1134
1135 // FIXME(#20304) For now, I am caching here, which is good, but it
1136 // means we don't capture the type variables that are created in
1137 // the case of ambiguity. Which means we may create a large stream
1138 // of such variables. OTOH, if we move the caching up a level, we
1139 // would not benefit from caching when proving `T: Trait<U=Foo>`
1140 // bounds. It might be the case that we want two distinct caches,
1141 // or else another kind of cache entry.
1142
1143 let cache_result = if use_cache {
1144 infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
1145 } else {
1146 Ok(())
1147 };
1148 match cache_result {
1149 Ok(()) => debug!("no cache"),
1150 Err(ProjectionCacheEntry::Ambiguous) => {
1151 // If we found ambiguity the last time, that means we will continue
1152 // to do so until some type in the key changes (and we know it
1153 // hasn't, because we just fully resolved it).
1154 debug!("found cache entry: ambiguous");
1155 return Ok(None);
1156 }
1157 Err(ProjectionCacheEntry::InProgress) => {
1158 // Under lazy normalization, this can arise when
1159 // bootstrapping. That is, imagine an environment with a
1160 // where-clause like `A::B == u32`. Now, if we are asked
1161 // to normalize `A::B`, we will want to check the
1162 // where-clauses in scope. So we will try to unify `A::B`
1163 // with `A::B`, which can trigger a recursive
1164 // normalization.
1165
1166 debug!("found cache entry: in-progress");
1167
1168 // Cache that normalizing this projection resulted in a cycle. This
1169 // should ensure that, unless this happens within a snapshot that's
1170 // rolled back, fulfillment or evaluation will notice the cycle.
1171
1172 if use_cache {
1173 infcx.inner.borrow_mut().projection_cache().recur(cache_key);
1174 }
1175 return Err(InProgress);
1176 }
1177 Err(ProjectionCacheEntry::Recur) => {
1178 debug!("recur cache");
1179 return Err(InProgress);
1180 }
1181 Err(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => {
1182 // This is the hottest path in this function.
1183 //
1184 // If we find the value in the cache, then return it along
1185 // with the obligations that went along with it. Note
1186 // that, when using a fulfillment context, these
1187 // obligations could in principle be ignored: they have
1188 // already been registered when the cache entry was
1189 // created (and hence the new ones will quickly be
1190 // discarded as duplicated). But when doing trait
1191 // evaluation this is not the case, and dropping the trait
1192 // evaluations can causes ICEs (e.g., #43132).
1193 debug!(?ty, "found normalized ty");
1194 obligations.extend(ty.obligations);
1195 return Ok(Some(ty.value));
1196 }
1197 Err(ProjectionCacheEntry::Error) => {
1198 debug!("opt_normalize_projection_type: found error");
1199 let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
1200 obligations.extend(result.obligations);
1201 return Ok(Some(result.value.into()));
1202 }
1203 }
1204
1205 let obligation =
1206 Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_ty);
1207
1208 match project(selcx, &obligation) {
1209 Ok(Projected::Progress(Progress {
1210 term: projected_term,
1211 obligations: mut projected_obligations,
1212 })) => {
1213 // if projection succeeded, then what we get out of this
1214 // is also non-normalized (consider: it was derived from
1215 // an impl, where-clause etc) and hence we must
1216 // re-normalize it
1217
1218 let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term);
1219
1220 let mut result = if projected_term.has_projections() {
1221 let mut normalizer = AssocTypeNormalizer::new(
1222 selcx,
1223 param_env,
1224 cause,
1225 depth + 1,
1226 &mut projected_obligations,
1227 );
1228 let normalized_ty = normalizer.fold(projected_term);
1229
1230 Normalized { value: normalized_ty, obligations: projected_obligations }
1231 } else {
1232 Normalized { value: projected_term, obligations: projected_obligations }
1233 };
1234
1235 let mut deduped: SsoHashSet<_> = Default::default();
1236 result.obligations.retain(|projected_obligation| {
1237 if !deduped.insert(projected_obligation.clone()) {
1238 return false;
1239 }
1240 true
1241 });
1242
1243 if use_cache {
1244 infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
1245 }
1246 obligations.extend(result.obligations);
1247 Ok(Some(result.value))
1248 }
1249 Ok(Projected::NoProgress(projected_ty)) => {
1250 let result = Normalized { value: projected_ty, obligations: vec![] };
1251 if use_cache {
1252 infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
1253 }
1254 // No need to extend `obligations`.
1255 Ok(Some(result.value))
1256 }
1257 Err(ProjectionError::TooManyCandidates) => {
1258 debug!("opt_normalize_projection_type: too many candidates");
1259 if use_cache {
1260 infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
1261 }
1262 Ok(None)
1263 }
1264 Err(ProjectionError::TraitSelectionError(_)) => {
1265 debug!("opt_normalize_projection_type: ERROR");
1266 // if we got an error processing the `T as Trait` part,
1267 // just return `ty::err` but add the obligation `T :
1268 // Trait`, which when processed will cause the error to be
1269 // reported later
1270
1271 if use_cache {
1272 infcx.inner.borrow_mut().projection_cache().error(cache_key);
1273 }
1274 let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
1275 obligations.extend(result.obligations);
1276 Ok(Some(result.value.into()))
1277 }
1278 }
1279 }
1280
1281 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
1282 /// hold. In various error cases, we cannot generate a valid
1283 /// normalized projection. Therefore, we create an inference variable
1284 /// return an associated obligation that, when fulfilled, will lead to
1285 /// an error.
1286 ///
1287 /// Note that we used to return `Error` here, but that was quite
1288 /// dubious -- the premise was that an error would *eventually* be
1289 /// reported, when the obligation was processed. But in general once
1290 /// you see an `Error` you are supposed to be able to assume that an
1291 /// error *has been* reported, so that you can take whatever heuristic
1292 /// paths you want to take. To make things worse, it was possible for
1293 /// cycles to arise, where you basically had a setup like `<MyType<$0>
1294 /// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
1295 /// Trait>::Foo>` to `[type error]` would lead to an obligation of
1296 /// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
1297 /// an error for this obligation, but we legitimately should not,
1298 /// because it contains `[type error]`. Yuck! (See issue #29857 for
1299 /// one case where this arose.)
normalize_to_error<'a, 'tcx>( selcx: &mut SelectionContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, ) -> NormalizedTy<'tcx>1300 fn normalize_to_error<'a, 'tcx>(
1301 selcx: &mut SelectionContext<'a, 'tcx>,
1302 param_env: ty::ParamEnv<'tcx>,
1303 projection_ty: ty::AliasTy<'tcx>,
1304 cause: ObligationCause<'tcx>,
1305 depth: usize,
1306 ) -> NormalizedTy<'tcx> {
1307 let trait_ref = ty::Binder::dummy(projection_ty.trait_ref(selcx.tcx()));
1308 let trait_obligation = Obligation {
1309 cause,
1310 recursion_depth: depth,
1311 param_env,
1312 predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
1313 };
1314 let tcx = selcx.infcx.tcx;
1315 let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
1316 kind: TypeVariableOriginKind::NormalizeProjectionType,
1317 span: tcx.def_span(projection_ty.def_id),
1318 });
1319 Normalized { value: new_value, obligations: vec![trait_obligation] }
1320 }
1321
1322 /// Confirm and normalize the given inherent projection.
1323 #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
normalize_inherent_projection<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, alias_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> Ty<'tcx>1324 pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
1325 selcx: &'a mut SelectionContext<'b, 'tcx>,
1326 param_env: ty::ParamEnv<'tcx>,
1327 alias_ty: ty::AliasTy<'tcx>,
1328 cause: ObligationCause<'tcx>,
1329 depth: usize,
1330 obligations: &mut Vec<PredicateObligation<'tcx>>,
1331 ) -> Ty<'tcx> {
1332 let tcx = selcx.tcx();
1333
1334 if !tcx.recursion_limit().value_within_limit(depth) {
1335 // Halt compilation because it is important that overflows never be masked.
1336 tcx.sess.emit_fatal(InherentProjectionNormalizationOverflow {
1337 span: cause.span,
1338 ty: alias_ty.to_string(),
1339 });
1340 }
1341
1342 let substs = compute_inherent_assoc_ty_substs(
1343 selcx,
1344 param_env,
1345 alias_ty,
1346 cause.clone(),
1347 depth,
1348 obligations,
1349 );
1350
1351 // Register the obligations arising from the impl and from the associated type itself.
1352 let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, substs);
1353 for (predicate, span) in predicates {
1354 let predicate = normalize_with_depth_to(
1355 selcx,
1356 param_env,
1357 cause.clone(),
1358 depth + 1,
1359 predicate,
1360 obligations,
1361 );
1362
1363 let nested_cause = ObligationCause::new(
1364 cause.span,
1365 cause.body_id,
1366 // FIXME(inherent_associated_types): Since we can't pass along the self type to the
1367 // cause code, inherent projections will be printed with identity substitutions in
1368 // diagnostics which is not ideal.
1369 // Consider creating separate cause codes for this specific situation.
1370 if span.is_dummy() {
1371 super::ItemObligation(alias_ty.def_id)
1372 } else {
1373 super::BindingObligation(alias_ty.def_id, span)
1374 },
1375 );
1376
1377 obligations.push(Obligation::with_depth(
1378 tcx,
1379 nested_cause,
1380 depth + 1,
1381 param_env,
1382 predicate,
1383 ));
1384 }
1385
1386 let ty = tcx.type_of(alias_ty.def_id).subst(tcx, substs);
1387
1388 let mut ty = selcx.infcx.resolve_vars_if_possible(ty);
1389 if ty.has_projections() {
1390 ty = normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, ty, obligations);
1391 }
1392
1393 ty
1394 }
1395
compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, alias_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec<PredicateObligation<'tcx>>, ) -> ty::SubstsRef<'tcx>1396 pub fn compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>(
1397 selcx: &'a mut SelectionContext<'b, 'tcx>,
1398 param_env: ty::ParamEnv<'tcx>,
1399 alias_ty: ty::AliasTy<'tcx>,
1400 cause: ObligationCause<'tcx>,
1401 depth: usize,
1402 obligations: &mut Vec<PredicateObligation<'tcx>>,
1403 ) -> ty::SubstsRef<'tcx> {
1404 let tcx = selcx.tcx();
1405
1406 let impl_def_id = tcx.parent(alias_ty.def_id);
1407 let impl_substs = selcx.infcx.fresh_substs_for_item(cause.span, impl_def_id);
1408
1409 let impl_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs);
1410 let impl_ty =
1411 normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
1412
1413 // Infer the generic parameters of the impl by unifying the
1414 // impl type with the self type of the projection.
1415 let self_ty = alias_ty.self_ty();
1416 match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, impl_ty, self_ty) {
1417 Ok(mut ok) => obligations.append(&mut ok.obligations),
1418 Err(_) => {
1419 tcx.sess.delay_span_bug(
1420 cause.span,
1421 format!(
1422 "{self_ty:?} was a subtype of {impl_ty:?} during selection but now it is not"
1423 ),
1424 );
1425 }
1426 }
1427
1428 alias_ty.rebase_substs_onto_impl(impl_substs, tcx)
1429 }
1430
1431 enum Projected<'tcx> {
1432 Progress(Progress<'tcx>),
1433 NoProgress(ty::Term<'tcx>),
1434 }
1435
1436 struct Progress<'tcx> {
1437 term: ty::Term<'tcx>,
1438 obligations: Vec<PredicateObligation<'tcx>>,
1439 }
1440
1441 impl<'tcx> Progress<'tcx> {
error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self1442 fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
1443 Progress { term: Ty::new_error(tcx, guar).into(), obligations: vec![] }
1444 }
1445
with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self1446 fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
1447 self.obligations.append(&mut obligations);
1448 self
1449 }
1450 }
1451
1452 /// Computes the result of a projection type (if we can).
1453 ///
1454 /// IMPORTANT:
1455 /// - `obligation` must be fully normalized
1456 #[instrument(level = "info", skip(selcx))]
project<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, ) -> Result<Projected<'tcx>, ProjectionError<'tcx>>1457 fn project<'cx, 'tcx>(
1458 selcx: &mut SelectionContext<'cx, 'tcx>,
1459 obligation: &ProjectionTyObligation<'tcx>,
1460 ) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
1461 if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
1462 // This should really be an immediate error, but some existing code
1463 // relies on being able to recover from this.
1464 return Err(ProjectionError::TraitSelectionError(SelectionError::Overflow(
1465 OverflowError::Canonical,
1466 )));
1467 }
1468
1469 if let Err(guar) = obligation.predicate.error_reported() {
1470 return Ok(Projected::Progress(Progress::error(selcx.tcx(), guar)));
1471 }
1472
1473 let mut candidates = ProjectionCandidateSet::None;
1474
1475 assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
1476
1477 // Make sure that the following procedures are kept in order. ParamEnv
1478 // needs to be first because it has highest priority, and Select checks
1479 // the return value of push_candidate which assumes it's ran at last.
1480 assemble_candidates_from_param_env(selcx, obligation, &mut candidates);
1481
1482 assemble_candidates_from_trait_def(selcx, obligation, &mut candidates);
1483
1484 assemble_candidates_from_object_ty(selcx, obligation, &mut candidates);
1485
1486 if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates {
1487 // Avoid normalization cycle from selection (see
1488 // `assemble_candidates_from_object_ty`).
1489 // FIXME(lazy_normalization): Lazy normalization should save us from
1490 // having to special case this.
1491 } else {
1492 assemble_candidates_from_impls(selcx, obligation, &mut candidates);
1493 };
1494
1495 match candidates {
1496 ProjectionCandidateSet::Single(candidate) => {
1497 Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate)))
1498 }
1499 ProjectionCandidateSet::None => {
1500 let tcx = selcx.tcx();
1501 let term = match tcx.def_kind(obligation.predicate.def_id) {
1502 DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection(
1503 tcx,
1504 obligation.predicate.def_id,
1505 obligation.predicate.substs,
1506 )
1507 .into(),
1508 DefKind::AssocConst => ty::Const::new_unevaluated(
1509 tcx,
1510 ty::UnevaluatedConst::new(
1511 obligation.predicate.def_id,
1512 obligation.predicate.substs,
1513 ),
1514 tcx.type_of(obligation.predicate.def_id)
1515 .subst(tcx, obligation.predicate.substs),
1516 )
1517 .into(),
1518 kind => {
1519 bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id))
1520 }
1521 };
1522
1523 Ok(Projected::NoProgress(term))
1524 }
1525 // Error occurred while trying to processing impls.
1526 ProjectionCandidateSet::Error(e) => Err(ProjectionError::TraitSelectionError(e)),
1527 // Inherent ambiguity that prevents us from even enumerating the
1528 // candidates.
1529 ProjectionCandidateSet::Ambiguous => Err(ProjectionError::TooManyCandidates),
1530 }
1531 }
1532
1533 /// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the
1534 /// corresponding trait ref. If this yields an `impl`, then we're able to project
1535 /// to a concrete type, since we have an `impl`'s method to provide the RPITIT.
assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, )1536 fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
1537 selcx: &mut SelectionContext<'cx, 'tcx>,
1538 obligation: &ProjectionTyObligation<'tcx>,
1539 candidate_set: &mut ProjectionCandidateSet<'tcx>,
1540 ) {
1541 let tcx = selcx.tcx();
1542 if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
1543 let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
1544
1545 let trait_def_id = tcx.parent(trait_fn_def_id);
1546 let trait_substs =
1547 obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
1548 let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);
1549
1550 let _ = selcx.infcx.commit_if_ok(|_| {
1551 match selcx.select(&obligation.with(tcx, trait_predicate)) {
1552 Ok(Some(super::ImplSource::UserDefined(data))) => {
1553 candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
1554 Ok(())
1555 }
1556 Ok(None) => {
1557 candidate_set.mark_ambiguous();
1558 Err(())
1559 }
1560 Ok(Some(_)) => {
1561 // Don't know enough about the impl to provide a useful signature
1562 Err(())
1563 }
1564 Err(e) => {
1565 debug!(error = ?e, "selection error");
1566 candidate_set.mark_error(e);
1567 Err(())
1568 }
1569 }
1570 });
1571 }
1572 }
1573
1574 /// The first thing we have to do is scan through the parameter
1575 /// environment to see whether there are any projection predicates
1576 /// there that can answer this question.
assemble_candidates_from_param_env<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, )1577 fn assemble_candidates_from_param_env<'cx, 'tcx>(
1578 selcx: &mut SelectionContext<'cx, 'tcx>,
1579 obligation: &ProjectionTyObligation<'tcx>,
1580 candidate_set: &mut ProjectionCandidateSet<'tcx>,
1581 ) {
1582 assemble_candidates_from_predicates(
1583 selcx,
1584 obligation,
1585 candidate_set,
1586 ProjectionCandidate::ParamEnv,
1587 obligation.param_env.caller_bounds().iter(),
1588 false,
1589 );
1590 }
1591
1592 /// In the case of a nested projection like `<<A as Foo>::FooT as Bar>::BarT`, we may find
1593 /// that the definition of `Foo` has some clues:
1594 ///
1595 /// ```ignore (illustrative)
1596 /// trait Foo {
1597 /// type FooT : Bar<BarT=i32>
1598 /// }
1599 /// ```
1600 ///
1601 /// Here, for example, we could conclude that the result is `i32`.
assemble_candidates_from_trait_def<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, )1602 fn assemble_candidates_from_trait_def<'cx, 'tcx>(
1603 selcx: &mut SelectionContext<'cx, 'tcx>,
1604 obligation: &ProjectionTyObligation<'tcx>,
1605 candidate_set: &mut ProjectionCandidateSet<'tcx>,
1606 ) {
1607 debug!("assemble_candidates_from_trait_def(..)");
1608
1609 let tcx = selcx.tcx();
1610 // Check whether the self-type is itself a projection.
1611 // If so, extract what we know from the trait and try to come up with a good answer.
1612 let bounds = match *obligation.predicate.self_ty().kind() {
1613 // Excluding IATs and type aliases here as they don't have meaningful item bounds.
1614 ty::Alias(ty::Projection | ty::Opaque, ref data) => {
1615 tcx.item_bounds(data.def_id).subst(tcx, data.substs)
1616 }
1617 ty::Infer(ty::TyVar(_)) => {
1618 // If the self-type is an inference variable, then it MAY wind up
1619 // being a projected type, so induce an ambiguity.
1620 candidate_set.mark_ambiguous();
1621 return;
1622 }
1623 _ => return,
1624 };
1625
1626 assemble_candidates_from_predicates(
1627 selcx,
1628 obligation,
1629 candidate_set,
1630 ProjectionCandidate::TraitDef,
1631 bounds.iter(),
1632 true,
1633 );
1634 }
1635
1636 /// In the case of a trait object like
1637 /// `<dyn Iterator<Item = ()> as Iterator>::Item` we can use the existential
1638 /// predicate in the trait object.
1639 ///
1640 /// We don't go through the select candidate for these bounds to avoid cycles:
1641 /// In the above case, `dyn Iterator<Item = ()>: Iterator` would create a
1642 /// nested obligation of `<dyn Iterator<Item = ()> as Iterator>::Item: Sized`,
1643 /// this then has to be normalized without having to prove
1644 /// `dyn Iterator<Item = ()>: Iterator` again.
assemble_candidates_from_object_ty<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, )1645 fn assemble_candidates_from_object_ty<'cx, 'tcx>(
1646 selcx: &mut SelectionContext<'cx, 'tcx>,
1647 obligation: &ProjectionTyObligation<'tcx>,
1648 candidate_set: &mut ProjectionCandidateSet<'tcx>,
1649 ) {
1650 debug!("assemble_candidates_from_object_ty(..)");
1651
1652 let tcx = selcx.tcx();
1653
1654 if !tcx.trait_def(obligation.predicate.trait_def_id(tcx)).implement_via_object {
1655 return;
1656 }
1657
1658 let self_ty = obligation.predicate.self_ty();
1659 let object_ty = selcx.infcx.shallow_resolve(self_ty);
1660 let data = match object_ty.kind() {
1661 ty::Dynamic(data, ..) => data,
1662 ty::Infer(ty::TyVar(_)) => {
1663 // If the self-type is an inference variable, then it MAY wind up
1664 // being an object type, so induce an ambiguity.
1665 candidate_set.mark_ambiguous();
1666 return;
1667 }
1668 _ => return,
1669 };
1670 let env_predicates = data
1671 .projection_bounds()
1672 .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
1673 .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
1674
1675 assemble_candidates_from_predicates(
1676 selcx,
1677 obligation,
1678 candidate_set,
1679 ProjectionCandidate::Object,
1680 env_predicates,
1681 false,
1682 );
1683 }
1684
1685 #[instrument(
1686 level = "debug",
1687 skip(selcx, candidate_set, ctor, env_predicates, potentially_unnormalized_candidates)
1688 )]
assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>, env_predicates: impl Iterator<Item = ty::Clause<'tcx>>, potentially_unnormalized_candidates: bool, )1689 fn assemble_candidates_from_predicates<'cx, 'tcx>(
1690 selcx: &mut SelectionContext<'cx, 'tcx>,
1691 obligation: &ProjectionTyObligation<'tcx>,
1692 candidate_set: &mut ProjectionCandidateSet<'tcx>,
1693 ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>,
1694 env_predicates: impl Iterator<Item = ty::Clause<'tcx>>,
1695 potentially_unnormalized_candidates: bool,
1696 ) {
1697 let infcx = selcx.infcx;
1698 for predicate in env_predicates {
1699 let bound_predicate = predicate.kind();
1700 if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {
1701 let data = bound_predicate.rebind(data);
1702 if data.projection_def_id() != obligation.predicate.def_id {
1703 continue;
1704 }
1705
1706 let is_match = infcx.probe(|_| {
1707 selcx.match_projection_projections(
1708 obligation,
1709 data,
1710 potentially_unnormalized_candidates,
1711 )
1712 });
1713
1714 match is_match {
1715 ProjectionMatchesProjection::Yes => {
1716 candidate_set.push_candidate(ctor(data));
1717
1718 if potentially_unnormalized_candidates
1719 && !obligation.predicate.has_non_region_infer()
1720 {
1721 // HACK: Pick the first trait def candidate for a fully
1722 // inferred predicate. This is to allow duplicates that
1723 // differ only in normalization.
1724 return;
1725 }
1726 }
1727 ProjectionMatchesProjection::Ambiguous => {
1728 candidate_set.mark_ambiguous();
1729 }
1730 ProjectionMatchesProjection::No => {}
1731 }
1732 }
1733 }
1734 }
1735
1736 #[instrument(level = "debug", skip(selcx, obligation, candidate_set))]
assemble_candidates_from_impls<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, )1737 fn assemble_candidates_from_impls<'cx, 'tcx>(
1738 selcx: &mut SelectionContext<'cx, 'tcx>,
1739 obligation: &ProjectionTyObligation<'tcx>,
1740 candidate_set: &mut ProjectionCandidateSet<'tcx>,
1741 ) {
1742 // Can't assemble candidate from impl for RPITIT
1743 if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
1744 return;
1745 }
1746
1747 // If we are resolving `<T as TraitRef<...>>::Item == Type`,
1748 // start out by selecting the predicate `T as TraitRef<...>`:
1749 let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
1750 let trait_obligation = obligation.with(selcx.tcx(), trait_ref);
1751 let _ = selcx.infcx.commit_if_ok(|_| {
1752 let impl_source = match selcx.select(&trait_obligation) {
1753 Ok(Some(impl_source)) => impl_source,
1754 Ok(None) => {
1755 candidate_set.mark_ambiguous();
1756 return Err(());
1757 }
1758 Err(e) => {
1759 debug!(error = ?e, "selection error");
1760 candidate_set.mark_error(e);
1761 return Err(());
1762 }
1763 };
1764
1765 let eligible = match &impl_source {
1766 super::ImplSource::UserDefined(impl_data) => {
1767 // We have to be careful when projecting out of an
1768 // impl because of specialization. If we are not in
1769 // codegen (i.e., projection mode is not "any"), and the
1770 // impl's type is declared as default, then we disable
1771 // projection (even if the trait ref is fully
1772 // monomorphic). In the case where trait ref is not
1773 // fully monomorphic (i.e., includes type parameters),
1774 // this is because those type parameters may
1775 // ultimately be bound to types from other crates that
1776 // may have specialized impls we can't see. In the
1777 // case where the trait ref IS fully monomorphic, this
1778 // is a policy decision that we made in the RFC in
1779 // order to preserve flexibility for the crate that
1780 // defined the specializable impl to specialize later
1781 // for existing types.
1782 //
1783 // In either case, we handle this by not adding a
1784 // candidate for an impl if it contains a `default`
1785 // type.
1786 //
1787 // NOTE: This should be kept in sync with the similar code in
1788 // `rustc_ty_utils::instance::resolve_associated_item()`.
1789 let node_item =
1790 specialization_graph::assoc_def(selcx.tcx(), impl_data.impl_def_id, obligation.predicate.def_id)
1791 .map_err(|ErrorGuaranteed { .. }| ())?;
1792
1793 if node_item.is_final() {
1794 // Non-specializable items are always projectable.
1795 true
1796 } else {
1797 // Only reveal a specializable default if we're past type-checking
1798 // and the obligation is monomorphic, otherwise passes such as
1799 // transmute checking and polymorphic MIR optimizations could
1800 // get a result which isn't correct for all monomorphizations.
1801 if obligation.param_env.reveal() == Reveal::All {
1802 // NOTE(eddyb) inference variables can resolve to parameters, so
1803 // assume `poly_trait_ref` isn't monomorphic, if it contains any.
1804 let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(trait_ref);
1805 !poly_trait_ref.still_further_specializable()
1806 } else {
1807 debug!(
1808 assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
1809 ?obligation.predicate,
1810 "assemble_candidates_from_impls: not eligible due to default",
1811 );
1812 false
1813 }
1814 }
1815 }
1816 super::ImplSource::Builtin(..) => {
1817 // While a builtin impl may be known to exist, the associated type may not yet
1818 // be known. Any type with multiple potential associated types is therefore
1819 // not eligible.
1820 let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
1821
1822 let lang_items = selcx.tcx().lang_items();
1823 if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(trait_ref.def_id))
1824 || selcx.tcx().fn_trait_kind_from_def_id(trait_ref.def_id).is_some()
1825 {
1826 true
1827 } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
1828 match self_ty.kind() {
1829 ty::Bool
1830 | ty::Char
1831 | ty::Int(_)
1832 | ty::Uint(_)
1833 | ty::Float(_)
1834 | ty::Adt(..)
1835 | ty::Foreign(_)
1836 | ty::Str
1837 | ty::Array(..)
1838 | ty::Slice(_)
1839 | ty::RawPtr(..)
1840 | ty::Ref(..)
1841 | ty::FnDef(..)
1842 | ty::FnPtr(..)
1843 | ty::Dynamic(..)
1844 | ty::Closure(..)
1845 | ty::Generator(..)
1846 | ty::GeneratorWitness(..)
1847 | ty::GeneratorWitnessMIR(..)
1848 | ty::Never
1849 | ty::Tuple(..)
1850 // Integers and floats always have `u8` as their discriminant.
1851 | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
1852
1853 // type parameters, opaques, and unnormalized projections have pointer
1854 // metadata if they're known (e.g. by the param_env) to be sized
1855 ty::Param(_)
1856 | ty::Alias(..)
1857 | ty::Bound(..)
1858 | ty::Placeholder(..)
1859 | ty::Infer(..)
1860 | ty::Error(_) => false,
1861 }
1862 } else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
1863 let tail = selcx.tcx().struct_tail_with_normalize(
1864 self_ty,
1865 |ty| {
1866 // We throw away any obligations we get from this, since we normalize
1867 // and confirm these obligations once again during confirmation
1868 normalize_with_depth(
1869 selcx,
1870 obligation.param_env,
1871 obligation.cause.clone(),
1872 obligation.recursion_depth + 1,
1873 ty,
1874 )
1875 .value
1876 },
1877 || {},
1878 );
1879
1880 match tail.kind() {
1881 ty::Bool
1882 | ty::Char
1883 | ty::Int(_)
1884 | ty::Uint(_)
1885 | ty::Float(_)
1886 | ty::Str
1887 | ty::Array(..)
1888 | ty::Slice(_)
1889 | ty::RawPtr(..)
1890 | ty::Ref(..)
1891 | ty::FnDef(..)
1892 | ty::FnPtr(..)
1893 | ty::Dynamic(..)
1894 | ty::Closure(..)
1895 | ty::Generator(..)
1896 | ty::GeneratorWitness(..)
1897 | ty::GeneratorWitnessMIR(..)
1898 | ty::Never
1899 // Extern types have unit metadata, according to RFC 2850
1900 | ty::Foreign(_)
1901 // If returned by `struct_tail_without_normalization` this is a unit struct
1902 // without any fields, or not a struct, and therefore is Sized.
1903 | ty::Adt(..)
1904 // If returned by `struct_tail_without_normalization` this is the empty tuple.
1905 | ty::Tuple(..)
1906 // Integers and floats are always Sized, and so have unit type metadata.
1907 | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
1908
1909 // type parameters, opaques, and unnormalized projections have pointer
1910 // metadata if they're known (e.g. by the param_env) to be sized
1911 ty::Param(_) | ty::Alias(..)
1912 if selcx.infcx.predicate_must_hold_modulo_regions(
1913 &obligation.with(
1914 selcx.tcx(),
1915 ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty])
1916 .without_const(),
1917 ),
1918 ) =>
1919 {
1920 true
1921 }
1922
1923 // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
1924 ty::Param(_)
1925 | ty::Alias(..)
1926 | ty::Bound(..)
1927 | ty::Placeholder(..)
1928 | ty::Infer(..)
1929 | ty::Error(_) => {
1930 if tail.has_infer_types() {
1931 candidate_set.mark_ambiguous();
1932 }
1933 false
1934 }
1935 }
1936 } else {
1937 bug!("unexpected builtin trait with associated type: {trait_ref:?}")
1938 }
1939 }
1940 super::ImplSource::Param(..) => {
1941 // This case tell us nothing about the value of an
1942 // associated type. Consider:
1943 //
1944 // ```
1945 // trait SomeTrait { type Foo; }
1946 // fn foo<T:SomeTrait>(...) { }
1947 // ```
1948 //
1949 // If the user writes `<T as SomeTrait>::Foo`, then the `T
1950 // : SomeTrait` binding does not help us decide what the
1951 // type `Foo` is (at least, not more specifically than
1952 // what we already knew).
1953 //
1954 // But wait, you say! What about an example like this:
1955 //
1956 // ```
1957 // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
1958 // ```
1959 //
1960 // Doesn't the `T : SomeTrait<Foo=usize>` predicate help
1961 // resolve `T::Foo`? And of course it does, but in fact
1962 // that single predicate is desugared into two predicates
1963 // in the compiler: a trait predicate (`T : SomeTrait`) and a
1964 // projection. And the projection where clause is handled
1965 // in `assemble_candidates_from_param_env`.
1966 false
1967 }
1968 super::ImplSource::Object(_) => {
1969 // Handled by the `Object` projection candidate. See
1970 // `assemble_candidates_from_object_ty` for an explanation of
1971 // why we special case object types.
1972 false
1973 }
1974 | super::ImplSource::TraitUpcasting(_) => {
1975 // These traits have no associated types.
1976 selcx.tcx().sess.delay_span_bug(
1977 obligation.cause.span,
1978 format!("Cannot project an associated type from `{:?}`", impl_source),
1979 );
1980 return Err(());
1981 }
1982 };
1983
1984 if eligible {
1985 if candidate_set.push_candidate(ProjectionCandidate::Select(impl_source)) {
1986 Ok(())
1987 } else {
1988 Err(())
1989 }
1990 } else {
1991 Err(())
1992 }
1993 });
1994 }
1995
confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, candidate: ProjectionCandidate<'tcx>, ) -> Progress<'tcx>1996 fn confirm_candidate<'cx, 'tcx>(
1997 selcx: &mut SelectionContext<'cx, 'tcx>,
1998 obligation: &ProjectionTyObligation<'tcx>,
1999 candidate: ProjectionCandidate<'tcx>,
2000 ) -> Progress<'tcx> {
2001 debug!(?obligation, ?candidate, "confirm_candidate");
2002 let mut progress = match candidate {
2003 ProjectionCandidate::ParamEnv(poly_projection)
2004 | ProjectionCandidate::Object(poly_projection) => {
2005 confirm_param_env_candidate(selcx, obligation, poly_projection, false)
2006 }
2007
2008 ProjectionCandidate::TraitDef(poly_projection) => {
2009 confirm_param_env_candidate(selcx, obligation, poly_projection, true)
2010 }
2011
2012 ProjectionCandidate::Select(impl_source) => {
2013 confirm_select_candidate(selcx, obligation, impl_source)
2014 }
2015 ProjectionCandidate::ImplTraitInTrait(data) => {
2016 confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
2017 }
2018 };
2019
2020 // When checking for cycle during evaluation, we compare predicates with
2021 // "syntactic" equality. Since normalization generally introduces a type
2022 // with new region variables, we need to resolve them to existing variables
2023 // when possible for this to work. See `auto-trait-projection-recursion.rs`
2024 // for a case where this matters.
2025 if progress.term.has_infer_regions() {
2026 progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx));
2027 }
2028 progress
2029 }
2030
confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_source: Selection<'tcx>, ) -> Progress<'tcx>2031 fn confirm_select_candidate<'cx, 'tcx>(
2032 selcx: &mut SelectionContext<'cx, 'tcx>,
2033 obligation: &ProjectionTyObligation<'tcx>,
2034 impl_source: Selection<'tcx>,
2035 ) -> Progress<'tcx> {
2036 match impl_source {
2037 super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
2038 super::ImplSource::Builtin(data) => {
2039 let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
2040 let lang_items = selcx.tcx().lang_items();
2041 if lang_items.gen_trait() == Some(trait_def_id) {
2042 confirm_generator_candidate(selcx, obligation, data)
2043 } else if lang_items.future_trait() == Some(trait_def_id) {
2044 confirm_future_candidate(selcx, obligation, data)
2045 } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() {
2046 if obligation.predicate.self_ty().is_closure() {
2047 confirm_closure_candidate(selcx, obligation, data)
2048 } else {
2049 confirm_fn_pointer_candidate(selcx, obligation, data)
2050 }
2051 } else {
2052 confirm_builtin_candidate(selcx, obligation, data)
2053 }
2054 }
2055 super::ImplSource::Object(_)
2056 | super::ImplSource::Param(..)
2057 | super::ImplSource::TraitUpcasting(_) => {
2058 // we don't create Select candidates with this kind of resolution
2059 span_bug!(
2060 obligation.cause.span,
2061 "Cannot project an associated type from `{:?}`",
2062 impl_source
2063 )
2064 }
2065 }
2066 }
2067
confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx>2068 fn confirm_generator_candidate<'cx, 'tcx>(
2069 selcx: &mut SelectionContext<'cx, 'tcx>,
2070 obligation: &ProjectionTyObligation<'tcx>,
2071 nested: Vec<PredicateObligation<'tcx>>,
2072 ) -> Progress<'tcx> {
2073 let ty::Generator(_, substs, _) =
2074 selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
2075 else {
2076 unreachable!()
2077 };
2078 let gen_sig = substs.as_generator().poly_sig();
2079 let Normalized { value: gen_sig, obligations } = normalize_with_depth(
2080 selcx,
2081 obligation.param_env,
2082 obligation.cause.clone(),
2083 obligation.recursion_depth + 1,
2084 gen_sig,
2085 );
2086
2087 debug!(?obligation, ?gen_sig, ?obligations, "confirm_generator_candidate");
2088
2089 let tcx = selcx.tcx();
2090
2091 let gen_def_id = tcx.require_lang_item(LangItem::Generator, None);
2092
2093 let predicate = super::util::generator_trait_ref_and_outputs(
2094 tcx,
2095 gen_def_id,
2096 obligation.predicate.self_ty(),
2097 gen_sig,
2098 )
2099 .map_bound(|(trait_ref, yield_ty, return_ty)| {
2100 let name = tcx.associated_item(obligation.predicate.def_id).name;
2101 let ty = if name == sym::Return {
2102 return_ty
2103 } else if name == sym::Yield {
2104 yield_ty
2105 } else {
2106 bug!()
2107 };
2108
2109 ty::ProjectionPredicate {
2110 projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
2111 term: ty.into(),
2112 }
2113 });
2114
2115 confirm_param_env_candidate(selcx, obligation, predicate, false)
2116 .with_addl_obligations(nested)
2117 .with_addl_obligations(obligations)
2118 }
2119
confirm_future_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx>2120 fn confirm_future_candidate<'cx, 'tcx>(
2121 selcx: &mut SelectionContext<'cx, 'tcx>,
2122 obligation: &ProjectionTyObligation<'tcx>,
2123 nested: Vec<PredicateObligation<'tcx>>,
2124 ) -> Progress<'tcx> {
2125 let ty::Generator(_, substs, _) =
2126 selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
2127 else {
2128 unreachable!()
2129 };
2130 let gen_sig = substs.as_generator().poly_sig();
2131 let Normalized { value: gen_sig, obligations } = normalize_with_depth(
2132 selcx,
2133 obligation.param_env,
2134 obligation.cause.clone(),
2135 obligation.recursion_depth + 1,
2136 gen_sig,
2137 );
2138
2139 debug!(?obligation, ?gen_sig, ?obligations, "confirm_future_candidate");
2140
2141 let tcx = selcx.tcx();
2142 let fut_def_id = tcx.require_lang_item(LangItem::Future, None);
2143
2144 let predicate = super::util::future_trait_ref_and_outputs(
2145 tcx,
2146 fut_def_id,
2147 obligation.predicate.self_ty(),
2148 gen_sig,
2149 )
2150 .map_bound(|(trait_ref, return_ty)| {
2151 debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
2152
2153 ty::ProjectionPredicate {
2154 projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
2155 term: return_ty.into(),
2156 }
2157 });
2158
2159 confirm_param_env_candidate(selcx, obligation, predicate, false)
2160 .with_addl_obligations(nested)
2161 .with_addl_obligations(obligations)
2162 }
2163
confirm_builtin_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, data: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx>2164 fn confirm_builtin_candidate<'cx, 'tcx>(
2165 selcx: &mut SelectionContext<'cx, 'tcx>,
2166 obligation: &ProjectionTyObligation<'tcx>,
2167 data: Vec<PredicateObligation<'tcx>>,
2168 ) -> Progress<'tcx> {
2169 let tcx = selcx.tcx();
2170 let self_ty = obligation.predicate.self_ty();
2171 let substs = tcx.mk_substs(&[self_ty.into()]);
2172 let lang_items = tcx.lang_items();
2173 let item_def_id = obligation.predicate.def_id;
2174 let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
2175 let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
2176 let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
2177 assert_eq!(discriminant_def_id, item_def_id);
2178
2179 (self_ty.discriminant_ty(tcx).into(), Vec::new())
2180 } else if lang_items.pointee_trait() == Some(trait_def_id) {
2181 let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
2182 assert_eq!(metadata_def_id, item_def_id);
2183
2184 let mut obligations = Vec::new();
2185 let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| {
2186 normalize_with_depth_to(
2187 selcx,
2188 obligation.param_env,
2189 obligation.cause.clone(),
2190 obligation.recursion_depth + 1,
2191 ty,
2192 &mut obligations,
2193 )
2194 });
2195 if check_is_sized {
2196 let sized_predicate = ty::TraitRef::from_lang_item(
2197 tcx,
2198 LangItem::Sized,
2199 obligation.cause.span(),
2200 [self_ty],
2201 )
2202 .without_const();
2203 obligations.push(obligation.with(tcx, sized_predicate));
2204 }
2205 (metadata_ty.into(), obligations)
2206 } else {
2207 bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate);
2208 };
2209
2210 let predicate =
2211 ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
2212
2213 confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
2214 .with_addl_obligations(obligations)
2215 .with_addl_obligations(data)
2216 }
2217
confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx>2218 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
2219 selcx: &mut SelectionContext<'cx, 'tcx>,
2220 obligation: &ProjectionTyObligation<'tcx>,
2221 nested: Vec<PredicateObligation<'tcx>>,
2222 ) -> Progress<'tcx> {
2223 let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
2224 let sig = fn_type.fn_sig(selcx.tcx());
2225 let Normalized { value: sig, obligations } = normalize_with_depth(
2226 selcx,
2227 obligation.param_env,
2228 obligation.cause.clone(),
2229 obligation.recursion_depth + 1,
2230 sig,
2231 );
2232
2233 confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
2234 .with_addl_obligations(nested)
2235 .with_addl_obligations(obligations)
2236 }
2237
confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, nested: Vec<PredicateObligation<'tcx>>, ) -> Progress<'tcx>2238 fn confirm_closure_candidate<'cx, 'tcx>(
2239 selcx: &mut SelectionContext<'cx, 'tcx>,
2240 obligation: &ProjectionTyObligation<'tcx>,
2241 nested: Vec<PredicateObligation<'tcx>>,
2242 ) -> Progress<'tcx> {
2243 let ty::Closure(_, substs) =
2244 selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
2245 else {
2246 unreachable!()
2247 };
2248 let closure_sig = substs.as_closure().sig();
2249 let Normalized { value: closure_sig, obligations } = normalize_with_depth(
2250 selcx,
2251 obligation.param_env,
2252 obligation.cause.clone(),
2253 obligation.recursion_depth + 1,
2254 closure_sig,
2255 );
2256
2257 debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate");
2258
2259 confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
2260 .with_addl_obligations(nested)
2261 .with_addl_obligations(obligations)
2262 }
2263
confirm_callable_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, flag: util::TupleArgumentsFlag, ) -> Progress<'tcx>2264 fn confirm_callable_candidate<'cx, 'tcx>(
2265 selcx: &mut SelectionContext<'cx, 'tcx>,
2266 obligation: &ProjectionTyObligation<'tcx>,
2267 fn_sig: ty::PolyFnSig<'tcx>,
2268 flag: util::TupleArgumentsFlag,
2269 ) -> Progress<'tcx> {
2270 let tcx = selcx.tcx();
2271
2272 debug!(?obligation, ?fn_sig, "confirm_callable_candidate");
2273
2274 let fn_once_def_id = tcx.require_lang_item(LangItem::FnOnce, None);
2275 let fn_once_output_def_id = tcx.require_lang_item(LangItem::FnOnceOutput, None);
2276
2277 let predicate = super::util::closure_trait_ref_and_return_type(
2278 tcx,
2279 fn_once_def_id,
2280 obligation.predicate.self_ty(),
2281 fn_sig,
2282 flag,
2283 )
2284 .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
2285 projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
2286 term: ret_type.into(),
2287 });
2288
2289 confirm_param_env_candidate(selcx, obligation, predicate, true)
2290 }
2291
confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidate: bool, ) -> Progress<'tcx>2292 fn confirm_param_env_candidate<'cx, 'tcx>(
2293 selcx: &mut SelectionContext<'cx, 'tcx>,
2294 obligation: &ProjectionTyObligation<'tcx>,
2295 poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
2296 potentially_unnormalized_candidate: bool,
2297 ) -> Progress<'tcx> {
2298 let infcx = selcx.infcx;
2299 let cause = &obligation.cause;
2300 let param_env = obligation.param_env;
2301
2302 let cache_entry = infcx.instantiate_binder_with_fresh_vars(
2303 cause.span,
2304 LateBoundRegionConversionTime::HigherRankedType,
2305 poly_cache_entry,
2306 );
2307
2308 let cache_projection = cache_entry.projection_ty;
2309 let mut nested_obligations = Vec::new();
2310 let obligation_projection = obligation.predicate;
2311 let obligation_projection = ensure_sufficient_stack(|| {
2312 normalize_with_depth_to(
2313 selcx,
2314 obligation.param_env,
2315 obligation.cause.clone(),
2316 obligation.recursion_depth + 1,
2317 obligation_projection,
2318 &mut nested_obligations,
2319 )
2320 });
2321 let cache_projection = if potentially_unnormalized_candidate {
2322 ensure_sufficient_stack(|| {
2323 normalize_with_depth_to(
2324 selcx,
2325 obligation.param_env,
2326 obligation.cause.clone(),
2327 obligation.recursion_depth + 1,
2328 cache_projection,
2329 &mut nested_obligations,
2330 )
2331 })
2332 } else {
2333 cache_projection
2334 };
2335
2336 debug!(?cache_projection, ?obligation_projection);
2337
2338 match infcx.at(cause, param_env).eq(
2339 DefineOpaqueTypes::No,
2340 cache_projection,
2341 obligation_projection,
2342 ) {
2343 Ok(InferOk { value: _, obligations }) => {
2344 nested_obligations.extend(obligations);
2345 assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
2346 // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take
2347 // a term instead.
2348 Progress { term: cache_entry.term, obligations: nested_obligations }
2349 }
2350 Err(e) => {
2351 let msg = format!(
2352 "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
2353 obligation, poly_cache_entry, e,
2354 );
2355 debug!("confirm_param_env_candidate: {}", msg);
2356 let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg);
2357 Progress { term: err.into(), obligations: vec![] }
2358 }
2359 }
2360 }
2361
confirm_impl_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx>2362 fn confirm_impl_candidate<'cx, 'tcx>(
2363 selcx: &mut SelectionContext<'cx, 'tcx>,
2364 obligation: &ProjectionTyObligation<'tcx>,
2365 impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
2366 ) -> Progress<'tcx> {
2367 let tcx = selcx.tcx();
2368
2369 let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
2370 let assoc_item_id = obligation.predicate.def_id;
2371 let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
2372
2373 let param_env = obligation.param_env;
2374 let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
2375 Ok(assoc_ty) => assoc_ty,
2376 Err(guar) => return Progress::error(tcx, guar),
2377 };
2378
2379 if !assoc_ty.item.defaultness(tcx).has_value() {
2380 // This means that the impl is missing a definition for the
2381 // associated type. This error will be reported by the type
2382 // checker method `check_impl_items_against_trait`, so here we
2383 // just return Error.
2384 debug!(
2385 "confirm_impl_candidate: no associated type {:?} for {:?}",
2386 assoc_ty.item.name, obligation.predicate
2387 );
2388 return Progress { term: Ty::new_misc_error(tcx).into(), obligations: nested };
2389 }
2390 // If we're trying to normalize `<Vec<u32> as X>::A<S>` using
2391 //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
2392 //
2393 // * `obligation.predicate.substs` is `[Vec<u32>, S]`
2394 // * `substs` is `[u32]`
2395 // * `substs` ends up as `[u32, S]`
2396 let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
2397 let substs =
2398 translate_substs(selcx.infcx, param_env, impl_def_id, substs, assoc_ty.defining_node);
2399 let ty = tcx.type_of(assoc_ty.item.def_id);
2400 let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
2401 let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
2402 let did = assoc_ty.item.def_id;
2403 let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, did);
2404 let uv = ty::UnevaluatedConst::new(did, identity_substs);
2405 ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into())
2406 } else {
2407 ty.map_bound(|ty| ty.into())
2408 };
2409 if !check_substs_compatible(tcx, assoc_ty.item, substs) {
2410 let err = Ty::new_error_with_message(
2411 tcx,
2412 obligation.cause.span,
2413 "impl item and trait item have different parameters",
2414 );
2415 Progress { term: err.into(), obligations: nested }
2416 } else {
2417 assoc_ty_own_obligations(selcx, obligation, &mut nested);
2418 Progress { term: term.subst(tcx, substs), obligations: nested }
2419 }
2420 }
2421
confirm_impl_trait_in_trait_candidate<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx>2422 fn confirm_impl_trait_in_trait_candidate<'tcx>(
2423 selcx: &mut SelectionContext<'_, 'tcx>,
2424 obligation: &ProjectionTyObligation<'tcx>,
2425 data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
2426 ) -> Progress<'tcx> {
2427 let tcx = selcx.tcx();
2428 let mut obligations = data.nested;
2429
2430 let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
2431 let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
2432 Ok(assoc_ty) => assoc_ty,
2433 Err(guar) => return Progress::error(tcx, guar),
2434 };
2435 // We don't support specialization for RPITITs anyways... yet.
2436 // Also don't try to project to an RPITIT that has no value
2437 if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() {
2438 return Progress { term: Ty::new_misc_error(tcx).into(), obligations };
2439 }
2440
2441 // Use the default `impl Trait` for the trait, e.g., for a default trait body
2442 if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
2443 return Progress {
2444 term: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs)
2445 .into(),
2446 obligations,
2447 };
2448 }
2449
2450 // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
2451 // since `data.substs` are the impl substs.
2452 let impl_fn_substs =
2453 obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
2454 let impl_fn_substs = translate_substs(
2455 selcx.infcx,
2456 obligation.param_env,
2457 data.impl_def_id,
2458 impl_fn_substs,
2459 leaf_def.defining_node,
2460 );
2461
2462 if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
2463 let err = Ty::new_error_with_message(
2464 tcx,
2465 obligation.cause.span,
2466 "impl method and trait method have different parameters",
2467 );
2468 return Progress { term: err.into(), obligations };
2469 }
2470
2471 let impl_fn_def_id = leaf_def.item.def_id;
2472
2473 let cause = ObligationCause::new(
2474 obligation.cause.span,
2475 obligation.cause.body_id,
2476 super::ItemObligation(impl_fn_def_id),
2477 );
2478 let predicates = normalize_with_depth_to(
2479 selcx,
2480 obligation.param_env,
2481 cause.clone(),
2482 obligation.recursion_depth + 1,
2483 tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
2484 &mut obligations,
2485 );
2486 obligations.extend(predicates.into_iter().map(|(pred, span)| {
2487 Obligation::with_depth(
2488 tcx,
2489 ObligationCause::new(
2490 obligation.cause.span,
2491 obligation.cause.body_id,
2492 if span.is_dummy() {
2493 super::ItemObligation(impl_fn_def_id)
2494 } else {
2495 super::BindingObligation(impl_fn_def_id, span)
2496 },
2497 ),
2498 obligation.recursion_depth + 1,
2499 obligation.param_env,
2500 pred,
2501 )
2502 }));
2503
2504 let ty = normalize_with_depth_to(
2505 selcx,
2506 obligation.param_env,
2507 cause.clone(),
2508 obligation.recursion_depth + 1,
2509 tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
2510 |guar| Ty::new_error(tcx, guar),
2511 |tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
2512 ),
2513 &mut obligations,
2514 );
2515
2516 Progress { term: ty.into(), obligations }
2517 }
2518
2519 // Get obligations corresponding to the predicates from the where-clause of the
2520 // associated type itself.
assoc_ty_own_obligations<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, nested: &mut Vec<PredicateObligation<'tcx>>, )2521 fn assoc_ty_own_obligations<'cx, 'tcx>(
2522 selcx: &mut SelectionContext<'cx, 'tcx>,
2523 obligation: &ProjectionTyObligation<'tcx>,
2524 nested: &mut Vec<PredicateObligation<'tcx>>,
2525 ) {
2526 let tcx = selcx.tcx();
2527 let predicates = tcx
2528 .predicates_of(obligation.predicate.def_id)
2529 .instantiate_own(tcx, obligation.predicate.substs);
2530 for (predicate, span) in predicates {
2531 let normalized = normalize_with_depth_to(
2532 selcx,
2533 obligation.param_env,
2534 obligation.cause.clone(),
2535 obligation.recursion_depth + 1,
2536 predicate,
2537 nested,
2538 );
2539
2540 let nested_cause = if matches!(
2541 obligation.cause.code(),
2542 super::CompareImplItemObligation { .. }
2543 | super::CheckAssociatedTypeBounds { .. }
2544 | super::AscribeUserTypeProvePredicate(..)
2545 ) {
2546 obligation.cause.clone()
2547 } else if span.is_dummy() {
2548 ObligationCause::new(
2549 obligation.cause.span,
2550 obligation.cause.body_id,
2551 super::ItemObligation(obligation.predicate.def_id),
2552 )
2553 } else {
2554 ObligationCause::new(
2555 obligation.cause.span,
2556 obligation.cause.body_id,
2557 super::BindingObligation(obligation.predicate.def_id, span),
2558 )
2559 };
2560 nested.push(Obligation::with_depth(
2561 tcx,
2562 nested_cause,
2563 obligation.recursion_depth + 1,
2564 obligation.param_env,
2565 normalized,
2566 ));
2567 }
2568 }
2569
2570 pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized {
from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, ) -> Option<Self>2571 fn from_poly_projection_predicate(
2572 selcx: &mut SelectionContext<'cx, 'tcx>,
2573 predicate: ty::PolyProjectionPredicate<'tcx>,
2574 ) -> Option<Self>;
2575 }
2576
2577 impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, ) -> Option<Self>2578 fn from_poly_projection_predicate(
2579 selcx: &mut SelectionContext<'cx, 'tcx>,
2580 predicate: ty::PolyProjectionPredicate<'tcx>,
2581 ) -> Option<Self> {
2582 let infcx = selcx.infcx;
2583 // We don't do cross-snapshot caching of obligations with escaping regions,
2584 // so there's no cache key to use
2585 predicate.no_bound_vars().map(|predicate| {
2586 ProjectionCacheKey::new(
2587 // We don't attempt to match up with a specific type-variable state
2588 // from a specific call to `opt_normalize_projection_type` - if
2589 // there's no precise match, the original cache entry is "stranded"
2590 // anyway.
2591 infcx.resolve_vars_if_possible(predicate.projection_ty),
2592 )
2593 })
2594 }
2595 }
2596