1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Code for projecting associated types out of trait references.
13 use super::elaborate_predicates
;
14 use super::specialization_graph
;
15 use super::translate_substs
;
16 use super::Obligation
;
17 use super::ObligationCause
;
18 use super::PredicateObligation
;
19 use super::SelectionContext
;
20 use super::SelectionError
;
21 use super::VtableClosureData
;
22 use super::VtableFnPointerData
;
23 use super::VtableImplData
;
26 use hir
::def_id
::DefId
;
27 use infer
::{InferOk, TypeOrigin}
;
28 use rustc_data_structures
::snapshot_map
::{Snapshot, SnapshotMap}
;
29 use syntax
::parse
::token
;
32 use ty
::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt}
;
33 use ty
::fold
::{TypeFoldable, TypeFolder}
;
34 use util
::common
::FN_OUTPUT_NAME
;
38 /// Depending on the stage of compilation, we want projection to be
39 /// more or less conservative.
40 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
41 pub enum ProjectionMode
{
43 /// At coherence-checking time, we're still constructing the
44 /// specialization graph, and thus we only project
45 /// non-`default` associated types that are defined directly in
46 /// the applicable impl. (This behavior should be improved over
47 /// time, to allow for successful projections modulo cycles
48 /// between different impls).
50 /// Here's an example that will fail due to the restriction:
57 /// impl<T> Assoc for T {
58 /// type Output = bool;
61 /// impl Assoc for u8 {} // <- inherits the non-default type from above
64 /// impl Foo for u32 {}
65 /// impl Foo for <u8 as Assoc>::Output {} // <- this projection will fail
68 /// The projection would succeed if `Output` had been defined
69 /// directly in the impl for `u8`.
72 /// At type-checking time, we refuse to project any associated
73 /// type that is marked `default`. Non-`default` ("final") types
74 /// are always projected. This is necessary in general for
75 /// soundness of specialization. However, we *could* allow
76 /// projections in fully-monomorphic cases. We choose not to,
77 /// because we prefer for `default type` to force the type
78 /// definition to be treated abstractly by any consumers of the
79 /// impl. Concretely, that means that the following example will
87 /// impl<T> Assoc for T {
88 /// default type Output = bool;
92 /// let <() as Assoc>::Output = true;
96 /// At trans time, all projections will succeed.
100 impl ProjectionMode
{
101 pub fn is_topmost(&self) -> bool
{
103 ProjectionMode
::Topmost
=> true,
108 pub fn is_any_final(&self) -> bool
{
110 ProjectionMode
::AnyFinal
=> true,
115 pub fn is_any(&self) -> bool
{
117 ProjectionMode
::Any
=> true,
124 pub type PolyProjectionObligation
<'tcx
> =
125 Obligation
<'tcx
, ty
::PolyProjectionPredicate
<'tcx
>>;
127 pub type ProjectionObligation
<'tcx
> =
128 Obligation
<'tcx
, ty
::ProjectionPredicate
<'tcx
>>;
130 pub type ProjectionTyObligation
<'tcx
> =
131 Obligation
<'tcx
, ty
::ProjectionTy
<'tcx
>>;
133 /// When attempting to resolve `<T as TraitRef>::Name` ...
135 pub enum ProjectionTyError
<'tcx
> {
136 /// ...we found multiple sources of information and couldn't resolve the ambiguity.
139 /// ...an error occurred matching `T : TraitRef`
140 TraitSelectionError(SelectionError
<'tcx
>),
144 pub struct MismatchedProjectionTypes
<'tcx
> {
145 pub err
: ty
::error
::TypeError
<'tcx
>
148 #[derive(PartialEq, Eq, Debug)]
149 enum ProjectionTyCandidate
<'tcx
> {
150 // from a where-clause in the env or object type
151 ParamEnv(ty
::PolyProjectionPredicate
<'tcx
>),
153 // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
154 TraitDef(ty
::PolyProjectionPredicate
<'tcx
>),
156 // from a "impl" (or a "pseudo-impl" returned by select)
160 struct ProjectionTyCandidateSet
<'tcx
> {
161 vec
: Vec
<ProjectionTyCandidate
<'tcx
>>,
165 /// Evaluates constraints of the form:
167 /// for<...> <T as Trait>::U == V
169 /// If successful, this may result in additional obligations.
170 pub fn poly_project_and_unify_type
<'cx
, 'gcx
, 'tcx
>(
171 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
172 obligation
: &PolyProjectionObligation
<'tcx
>)
173 -> Result
<Option
<Vec
<PredicateObligation
<'tcx
>>>, MismatchedProjectionTypes
<'tcx
>>
175 debug
!("poly_project_and_unify_type(obligation={:?})",
178 let infcx
= selcx
.infcx();
179 infcx
.commit_if_ok(|snapshot
| {
180 let (skol_predicate
, skol_map
) =
181 infcx
.skolemize_late_bound_regions(&obligation
.predicate
, snapshot
);
183 let skol_obligation
= obligation
.with(skol_predicate
);
184 match project_and_unify_type(selcx
, &skol_obligation
) {
186 let span
= obligation
.cause
.span
;
187 match infcx
.leak_check(false, span
, &skol_map
, snapshot
) {
188 Ok(()) => Ok(infcx
.plug_leaks(skol_map
, snapshot
, &result
)),
189 Err(e
) => Err(MismatchedProjectionTypes { err: e }
),
199 /// Evaluates constraints of the form:
201 /// <T as Trait>::U == V
203 /// If successful, this may result in additional obligations.
204 fn project_and_unify_type
<'cx
, 'gcx
, 'tcx
>(
205 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
206 obligation
: &ProjectionObligation
<'tcx
>)
207 -> Result
<Option
<Vec
<PredicateObligation
<'tcx
>>>, MismatchedProjectionTypes
<'tcx
>>
209 debug
!("project_and_unify_type(obligation={:?})",
212 let Normalized { value: normalized_ty, mut obligations }
=
213 match opt_normalize_projection_type(selcx
,
214 obligation
.predicate
.projection_ty
.clone(),
215 obligation
.cause
.clone(),
216 obligation
.recursion_depth
) {
218 None
=> return Ok(None
),
221 debug
!("project_and_unify_type: normalized_ty={:?} obligations={:?}",
225 let infcx
= selcx
.infcx();
226 let origin
= TypeOrigin
::RelateOutputImplTypes(obligation
.cause
.span
);
227 match infcx
.eq_types(true, origin
, normalized_ty
, obligation
.predicate
.ty
) {
228 Ok(InferOk { obligations: inferred_obligations, .. }
) => {
229 // FIXME(#32730) once obligations are generated in inference, drop this assertion
230 assert
!(inferred_obligations
.is_empty());
231 obligations
.extend(inferred_obligations
);
232 Ok(Some(obligations
))
234 Err(err
) => Err(MismatchedProjectionTypes { err: err }
),
238 /// Normalizes any associated type projections in `value`, replacing
239 /// them with a fully resolved type where possible. The return value
240 /// combines the normalized result and any additional obligations that
241 /// were incurred as result.
242 pub fn normalize
<'a
, 'b
, 'gcx
, 'tcx
, T
>(selcx
: &'a
mut SelectionContext
<'b
, 'gcx
, 'tcx
>,
243 cause
: ObligationCause
<'tcx
>,
245 -> Normalized
<'tcx
, T
>
246 where T
: TypeFoldable
<'tcx
>
248 normalize_with_depth(selcx
, cause
, 0, value
)
251 /// As `normalize`, but with a custom depth.
252 pub fn normalize_with_depth
<'a
, 'b
, 'gcx
, 'tcx
, T
>(
253 selcx
: &'a
mut SelectionContext
<'b
, 'gcx
, 'tcx
>,
254 cause
: ObligationCause
<'tcx
>,
257 -> Normalized
<'tcx
, T
>
259 where T
: TypeFoldable
<'tcx
>
261 debug
!("normalize_with_depth(depth={}, value={:?})", depth
, value
);
262 let mut normalizer
= AssociatedTypeNormalizer
::new(selcx
, cause
, depth
);
263 let result
= normalizer
.fold(value
);
264 debug
!("normalize_with_depth: depth={} result={:?} with {} obligations",
265 depth
, result
, normalizer
.obligations
.len());
266 debug
!("normalize_with_depth: depth={} obligations={:?}",
267 depth
, normalizer
.obligations
);
270 obligations
: normalizer
.obligations
,
274 struct AssociatedTypeNormalizer
<'a
, 'b
: 'a
, 'gcx
: 'b
+'tcx
, 'tcx
: 'b
> {
275 selcx
: &'a
mut SelectionContext
<'b
, 'gcx
, 'tcx
>,
276 cause
: ObligationCause
<'tcx
>,
277 obligations
: Vec
<PredicateObligation
<'tcx
>>,
281 impl<'a
, 'b
, 'gcx
, 'tcx
> AssociatedTypeNormalizer
<'a
, 'b
, 'gcx
, 'tcx
> {
282 fn new(selcx
: &'a
mut SelectionContext
<'b
, 'gcx
, 'tcx
>,
283 cause
: ObligationCause
<'tcx
>,
285 -> AssociatedTypeNormalizer
<'a
, 'b
, 'gcx
, 'tcx
>
287 AssociatedTypeNormalizer
{
295 fn fold
<T
:TypeFoldable
<'tcx
>>(&mut self, value
: &T
) -> T
{
296 let value
= self.selcx
.infcx().resolve_type_vars_if_possible(value
);
298 if !value
.has_projection_types() {
301 value
.fold_with(self)
306 impl<'a
, 'b
, 'gcx
, 'tcx
> TypeFolder
<'gcx
, 'tcx
> for AssociatedTypeNormalizer
<'a
, 'b
, 'gcx
, 'tcx
> {
307 fn tcx
<'c
>(&'c
self) -> TyCtxt
<'c
, 'gcx
, 'tcx
> {
311 fn fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
312 // We don't want to normalize associated types that occur inside of region
313 // binders, because they may contain bound regions, and we can't cope with that.
317 // for<'a> fn(<T as Foo<&'a>>::A)
319 // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
320 // normalize it when we instantiate those bound regions (which
321 // should occur eventually).
323 let ty
= ty
.super_fold_with(self);
325 ty
::TyProjection(ref data
) if !data
.has_escaping_regions() => { // (*)
327 // (*) This is kind of hacky -- we need to be able to
328 // handle normalization within binders because
329 // otherwise we wind up a need to normalize when doing
330 // trait matching (since you can have a trait
331 // obligation like `for<'a> T::B : Fn(&'a int)`), but
332 // we can't normalize with bound regions in scope. So
333 // far now we just ignore binders but only normalize
334 // if all bound regions are gone (and then we still
335 // have to renormalize whenever we instantiate a
336 // binder). It would be better to normalize in a
337 // binding-aware fashion.
339 let Normalized { value: normalized_ty, obligations }
=
340 normalize_projection_type(self.selcx
,
344 debug
!("AssociatedTypeNormalizer: depth={} normalized {:?} to {:?} \
345 with {} add'l obligations",
346 self.depth
, ty
, normalized_ty
, obligations
.len());
347 self.obligations
.extend(obligations
);
359 pub struct Normalized
<'tcx
,T
> {
361 pub obligations
: Vec
<PredicateObligation
<'tcx
>>,
364 pub type NormalizedTy
<'tcx
> = Normalized
<'tcx
, Ty
<'tcx
>>;
366 impl<'tcx
,T
> Normalized
<'tcx
,T
> {
367 pub fn with
<U
>(self, value
: U
) -> Normalized
<'tcx
,U
> {
368 Normalized { value: value, obligations: self.obligations }
372 /// The guts of `normalize`: normalize a specific projection like `<T
373 /// as Trait>::Item`. The result is always a type (and possibly
374 /// additional obligations). If ambiguity arises, which implies that
375 /// there are unresolved type variables in the projection, we will
376 /// substitute a fresh type variable `$X` and generate a new
377 /// obligation `<T as Trait>::Item == $X` for later.
378 pub fn normalize_projection_type
<'a
, 'b
, 'gcx
, 'tcx
>(
379 selcx
: &'a
mut SelectionContext
<'b
, 'gcx
, 'tcx
>,
380 projection_ty
: ty
::ProjectionTy
<'tcx
>,
381 cause
: ObligationCause
<'tcx
>,
383 -> NormalizedTy
<'tcx
>
385 opt_normalize_projection_type(selcx
, projection_ty
.clone(), cause
.clone(), depth
)
386 .unwrap_or_else(move || {
387 // if we bottom out in ambiguity, create a type variable
388 // and a deferred predicate to resolve this when more type
389 // information is available.
391 let ty_var
= selcx
.infcx().next_ty_var();
392 let projection
= ty
::Binder(ty
::ProjectionPredicate
{
393 projection_ty
: projection_ty
,
396 let obligation
= Obligation
::with_depth(
397 cause
, depth
+ 1, projection
.to_predicate());
400 obligations
: vec
!(obligation
)
405 /// The guts of `normalize`: normalize a specific projection like `<T
406 /// as Trait>::Item`. The result is always a type (and possibly
407 /// additional obligations). Returns `None` in the case of ambiguity,
408 /// which indicates that there are unbound type variables.
409 fn opt_normalize_projection_type
<'a
, 'b
, 'gcx
, 'tcx
>(
410 selcx
: &'a
mut SelectionContext
<'b
, 'gcx
, 'tcx
>,
411 projection_ty
: ty
::ProjectionTy
<'tcx
>,
412 cause
: ObligationCause
<'tcx
>,
414 -> Option
<NormalizedTy
<'tcx
>>
416 let infcx
= selcx
.infcx();
418 let projection_ty
= infcx
.resolve_type_vars_if_possible(&projection_ty
);
420 debug
!("opt_normalize_projection_type(\
421 projection_ty={:?}, \
426 // FIXME(#20304) For now, I am caching here, which is good, but it
427 // means we don't capture the type variables that are created in
428 // the case of ambiguity. Which means we may create a large stream
429 // of such variables. OTOH, if we move the caching up a level, we
430 // would not benefit from caching when proving `T: Trait<U=Foo>`
431 // bounds. It might be the case that we want two distinct caches,
432 // or else another kind of cache entry.
434 match infcx
.projection_cache
.borrow_mut().try_start(projection_ty
) {
436 Err(ProjectionCacheEntry
::Ambiguous
) => {
437 // If we found ambiguity the last time, that generally
438 // means we will continue to do so until some type in the
439 // key changes (and we know it hasn't, because we just
440 // fully resolved it). One exception though is closure
441 // types, which can transition from having a fixed kind to
442 // no kind with no visible change in the key.
444 // FIXME(#32286) refactor this so that closure type
446 debug
!("opt_normalize_projection_type: \
447 found cache entry: ambiguous");
448 if !projection_ty
.has_closure_types() {
452 Err(ProjectionCacheEntry
::InProgress
) => {
453 // If while normalized A::B, we are asked to normalize
454 // A::B, just return A::B itself. This is a conservative
455 // answer, in the sense that A::B *is* clearly equivalent
456 // to A::B, though there may be a better value we can
459 // Under lazy normalization, this can arise when
460 // bootstrapping. That is, imagine an environment with a
461 // where-clause like `A::B == u32`. Now, if we are asked
462 // to normalize `A::B`, we will want to check the
463 // where-clauses in scope. So we will try to unify `A::B`
464 // with `A::B`, which can trigger a recursive
465 // normalization. In that case, I think we will want this code:
468 // let ty = selcx.tcx().mk_projection(projection_ty.trait_ref,
469 // projection_ty.item_name);
470 // return Some(NormalizedTy { value: v, obligations: vec![] });
473 debug
!("opt_normalize_projection_type: \
474 found cache entry: in-progress");
476 // But for now, let's classify this as an overflow:
477 let recursion_limit
= selcx
.tcx().sess
.recursion_limit
.get();
478 let obligation
= Obligation
::with_depth(cause
.clone(),
481 selcx
.infcx().report_overflow_error(&obligation
, false);
483 Err(ProjectionCacheEntry
::NormalizedTy(ty
)) => {
484 // If we find the value in the cache, then the obligations
485 // have already been returned from the previous entry (and
486 // should therefore have been honored).
487 debug
!("opt_normalize_projection_type: \
488 found normalized ty `{:?}`",
490 return Some(NormalizedTy { value: ty, obligations: vec![] }
);
492 Err(ProjectionCacheEntry
::Error
) => {
493 debug
!("opt_normalize_projection_type: \
495 return Some(normalize_to_error(selcx
, projection_ty
, cause
, depth
));
499 let obligation
= Obligation
::with_depth(cause
.clone(), depth
, projection_ty
.clone());
500 match project_type(selcx
, &obligation
) {
501 Ok(ProjectedTy
::Progress(Progress
{ ty
: projected_ty
,
504 // if projection succeeded, then what we get out of this
505 // is also non-normalized (consider: it was derived from
506 // an impl, where-clause etc) and hence we must
509 debug
!("opt_normalize_projection_type: \
519 let result
= if projected_ty
.has_projection_types() {
520 let mut normalizer
= AssociatedTypeNormalizer
::new(selcx
, cause
, depth
+1);
521 let normalized_ty
= normalizer
.fold(&projected_ty
);
523 debug
!("opt_normalize_projection_type: \
524 normalized_ty={:?} depth={}",
528 obligations
.extend(normalizer
.obligations
);
530 value
: normalized_ty
,
531 obligations
: obligations
,
536 obligations
: obligations
,
539 infcx
.projection_cache
.borrow_mut()
540 .complete(projection_ty
, &result
, cacheable
);
543 Ok(ProjectedTy
::NoProgress(projected_ty
)) => {
544 debug
!("opt_normalize_projection_type: \
545 projected_ty={:?} no progress",
547 let result
= Normalized
{
551 infcx
.projection_cache
.borrow_mut()
552 .complete(projection_ty
, &result
, true);
555 Err(ProjectionTyError
::TooManyCandidates
) => {
556 debug
!("opt_normalize_projection_type: \
557 too many candidates");
558 infcx
.projection_cache
.borrow_mut()
559 .ambiguous(projection_ty
);
562 Err(ProjectionTyError
::TraitSelectionError(_
)) => {
563 debug
!("opt_normalize_projection_type: ERROR");
564 // if we got an error processing the `T as Trait` part,
565 // just return `ty::err` but add the obligation `T :
566 // Trait`, which when processed will cause the error to be
569 infcx
.projection_cache
.borrow_mut()
570 .error(projection_ty
);
571 Some(normalize_to_error(selcx
, projection_ty
, cause
, depth
))
576 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
577 /// hold. In various error cases, we cannot generate a valid
578 /// normalized projection. Therefore, we create an inference variable
579 /// return an associated obligation that, when fulfilled, will lead to
582 /// Note that we used to return `TyError` here, but that was quite
583 /// dubious -- the premise was that an error would *eventually* be
584 /// reported, when the obligation was processed. But in general once
585 /// you see a `TyError` you are supposed to be able to assume that an
586 /// error *has been* reported, so that you can take whatever heuristic
587 /// paths you want to take. To make things worse, it was possible for
588 /// cycles to arise, where you basically had a setup like `<MyType<$0>
589 /// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
590 /// Trait>::Foo> to `[type error]` would lead to an obligation of
591 /// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
592 /// an error for this obligation, but we legitimately should not,
593 /// because it contains `[type error]`. Yuck! (See issue #29857 for
594 /// one case where this arose.)
595 fn normalize_to_error
<'a
, 'gcx
, 'tcx
>(selcx
: &mut SelectionContext
<'a
, 'gcx
, 'tcx
>,
596 projection_ty
: ty
::ProjectionTy
<'tcx
>,
597 cause
: ObligationCause
<'tcx
>,
599 -> NormalizedTy
<'tcx
>
601 let trait_ref
= projection_ty
.trait_ref
.to_poly_trait_ref();
602 let trait_obligation
= Obligation
{ cause
: cause
,
603 recursion_depth
: depth
,
604 predicate
: trait_ref
.to_predicate() };
605 let new_value
= selcx
.infcx().next_ty_var();
608 obligations
: vec
!(trait_obligation
)
612 enum ProjectedTy
<'tcx
> {
613 Progress(Progress
<'tcx
>),
614 NoProgress(Ty
<'tcx
>),
617 struct Progress
<'tcx
> {
619 obligations
: Vec
<PredicateObligation
<'tcx
>>,
623 impl<'tcx
> Progress
<'tcx
> {
624 fn error
<'a
,'gcx
>(tcx
: TyCtxt
<'a
,'gcx
,'tcx
>) -> Self {
632 fn with_addl_obligations(mut self,
633 mut obligations
: Vec
<PredicateObligation
<'tcx
>>)
635 debug
!("with_addl_obligations: self.obligations.len={} obligations.len={}",
636 self.obligations
.len(), obligations
.len());
638 debug
!("with_addl_obligations: self.obligations={:?} obligations={:?}",
639 self.obligations
, obligations
);
641 self.obligations
.append(&mut obligations
);
646 /// Compute the result of a projection type (if we can).
649 /// - `obligation` must be fully normalized
650 fn project_type
<'cx
, 'gcx
, 'tcx
>(
651 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
652 obligation
: &ProjectionTyObligation
<'tcx
>)
653 -> Result
<ProjectedTy
<'tcx
>, ProjectionTyError
<'tcx
>>
655 debug
!("project(obligation={:?})",
658 let recursion_limit
= selcx
.tcx().sess
.recursion_limit
.get();
659 if obligation
.recursion_depth
>= recursion_limit
{
660 debug
!("project: overflow!");
661 selcx
.infcx().report_overflow_error(&obligation
, true);
664 let obligation_trait_ref
= &obligation
.predicate
.trait_ref
;
666 debug
!("project: obligation_trait_ref={:?}", obligation_trait_ref
);
668 if obligation_trait_ref
.references_error() {
669 return Ok(ProjectedTy
::Progress(Progress
::error(selcx
.tcx())));
672 let mut candidates
= ProjectionTyCandidateSet
{
677 assemble_candidates_from_param_env(selcx
,
679 &obligation_trait_ref
,
682 assemble_candidates_from_trait_def(selcx
,
684 &obligation_trait_ref
,
687 if let Err(e
) = assemble_candidates_from_impls(selcx
,
689 &obligation_trait_ref
,
691 return Err(ProjectionTyError
::TraitSelectionError(e
));
694 debug
!("{} candidates, ambiguous={}",
695 candidates
.vec
.len(),
696 candidates
.ambiguous
);
698 // Inherent ambiguity that prevents us from even enumerating the
700 if candidates
.ambiguous
{
701 return Err(ProjectionTyError
::TooManyCandidates
);
706 // Note: `candidates.vec` seems to be on the critical path of the
707 // compiler. Replacing it with an hash set was also tried, which would
708 // render the following dedup unnecessary. It led to cleaner code but
709 // prolonged compiling time of `librustc` from 5m30s to 6m in one test, or
710 // ~9% performance lost.
711 if candidates
.vec
.len() > 1 {
713 while i
< candidates
.vec
.len() {
714 let has_dup
= (0..i
).any(|j
| candidates
.vec
[i
] == candidates
.vec
[j
]);
716 candidates
.vec
.swap_remove(i
);
723 // Prefer where-clauses. As in select, if there are multiple
724 // candidates, we prefer where-clause candidates over impls. This
725 // may seem a bit surprising, since impls are the source of
726 // "truth" in some sense, but in fact some of the impls that SEEM
727 // applicable are not, because of nested obligations. Where
728 // clauses are the safer choice. See the comment on
729 // `select::SelectionCandidate` and #21974 for more details.
730 if candidates
.vec
.len() > 1 {
731 debug
!("retaining param-env candidates only from {:?}", candidates
.vec
);
732 candidates
.vec
.retain(|c
| match *c
{
733 ProjectionTyCandidate
::ParamEnv(..) => true,
734 ProjectionTyCandidate
::TraitDef(..) |
735 ProjectionTyCandidate
::Select
=> false,
737 debug
!("resulting candidate set: {:?}", candidates
.vec
);
738 if candidates
.vec
.len() != 1 {
739 return Err(ProjectionTyError
::TooManyCandidates
);
743 assert
!(candidates
.vec
.len() <= 1);
745 match candidates
.vec
.pop() {
747 Ok(ProjectedTy
::Progress(
748 confirm_candidate(selcx
,
750 &obligation_trait_ref
,
754 Ok(ProjectedTy
::NoProgress(
755 selcx
.tcx().mk_projection(
756 obligation
.predicate
.trait_ref
.clone(),
757 obligation
.predicate
.item_name
)))
762 /// The first thing we have to do is scan through the parameter
763 /// environment to see whether there are any projection predicates
764 /// there that can answer this question.
765 fn assemble_candidates_from_param_env
<'cx
, 'gcx
, 'tcx
>(
766 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
767 obligation
: &ProjectionTyObligation
<'tcx
>,
768 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
769 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>)
771 debug
!("assemble_candidates_from_param_env(..)");
772 let env_predicates
= selcx
.param_env().caller_bounds
.iter().cloned();
773 assemble_candidates_from_predicates(selcx
,
775 obligation_trait_ref
,
777 ProjectionTyCandidate
::ParamEnv
,
781 /// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
782 /// that the definition of `Foo` has some clues:
786 /// type FooT : Bar<BarT=i32>
790 /// Here, for example, we could conclude that the result is `i32`.
791 fn assemble_candidates_from_trait_def
<'cx
, 'gcx
, 'tcx
>(
792 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
793 obligation
: &ProjectionTyObligation
<'tcx
>,
794 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
795 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>)
797 debug
!("assemble_candidates_from_trait_def(..)");
799 // Check whether the self-type is itself a projection.
800 let trait_ref
= match obligation_trait_ref
.self_ty().sty
{
801 ty
::TyProjection(ref data
) => data
.trait_ref
.clone(),
802 ty
::TyInfer(ty
::TyVar(_
)) => {
803 // If the self-type is an inference variable, then it MAY wind up
804 // being a projected type, so induce an ambiguity.
805 candidate_set
.ambiguous
= true;
811 // If so, extract what we know from the trait and try to come up with a good answer.
812 let trait_predicates
= selcx
.tcx().lookup_predicates(trait_ref
.def_id
);
813 let bounds
= trait_predicates
.instantiate(selcx
.tcx(), trait_ref
.substs
);
814 let bounds
= elaborate_predicates(selcx
.tcx(), bounds
.predicates
.into_vec());
815 assemble_candidates_from_predicates(selcx
,
817 obligation_trait_ref
,
819 ProjectionTyCandidate
::TraitDef
,
823 fn assemble_candidates_from_predicates
<'cx
, 'gcx
, 'tcx
, I
>(
824 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
825 obligation
: &ProjectionTyObligation
<'tcx
>,
826 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
827 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>,
828 ctor
: fn(ty
::PolyProjectionPredicate
<'tcx
>) -> ProjectionTyCandidate
<'tcx
>,
830 where I
: Iterator
<Item
=ty
::Predicate
<'tcx
>>
832 debug
!("assemble_candidates_from_predicates(obligation={:?})",
834 let infcx
= selcx
.infcx();
835 for predicate
in env_predicates
{
836 debug
!("assemble_candidates_from_predicates: predicate={:?}",
839 ty
::Predicate
::Projection(ref data
) => {
840 let same_name
= data
.item_name() == obligation
.predicate
.item_name
;
842 let is_match
= same_name
&& infcx
.probe(|_
| {
843 let origin
= TypeOrigin
::Misc(obligation
.cause
.span
);
844 let data_poly_trait_ref
=
845 data
.to_poly_trait_ref();
846 let obligation_poly_trait_ref
=
847 obligation_trait_ref
.to_poly_trait_ref();
848 infcx
.sub_poly_trait_refs(false,
851 obligation_poly_trait_ref
)
852 // FIXME(#32730) once obligations are propagated from unification in
853 // inference, drop this assertion
854 .map(|InferOk { obligations, .. }
| assert
!(obligations
.is_empty()))
858 debug
!("assemble_candidates_from_predicates: candidate={:?} \
859 is_match={} same_name={}",
860 data
, is_match
, same_name
);
863 candidate_set
.vec
.push(ctor(data
.clone()));
871 fn assemble_candidates_from_impls
<'cx
, 'gcx
, 'tcx
>(
872 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
873 obligation
: &ProjectionTyObligation
<'tcx
>,
874 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
875 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>)
876 -> Result
<(), SelectionError
<'tcx
>>
878 // If we are resolving `<T as TraitRef<...>>::Item == Type`,
879 // start out by selecting the predicate `T as TraitRef<...>`:
880 let poly_trait_ref
= obligation_trait_ref
.to_poly_trait_ref();
881 let trait_obligation
= obligation
.with(poly_trait_ref
.to_poly_trait_predicate());
882 selcx
.infcx().probe(|_
| {
883 let vtable
= match selcx
.select(&trait_obligation
) {
884 Ok(Some(vtable
)) => vtable
,
886 candidate_set
.ambiguous
= true;
890 debug
!("assemble_candidates_from_impls: selection error {:?}",
897 super::VtableClosure(_
) |
898 super::VtableFnPointer(_
) |
899 super::VtableObject(_
) => {
900 debug
!("assemble_candidates_from_impls: vtable={:?}",
903 candidate_set
.vec
.push(ProjectionTyCandidate
::Select
);
905 super::VtableImpl(ref impl_data
) if !selcx
.projection_mode().is_any() => {
906 // We have to be careful when projecting out of an
907 // impl because of specialization. If we are not in
908 // trans (i.e., projection mode is not "any"), and the
909 // impl's type is declared as default, then we disable
910 // projection (even if the trait ref is fully
911 // monomorphic). In the case where trait ref is not
912 // fully monomorphic (i.e., includes type parameters),
913 // this is because those type parameters may
914 // ultimately be bound to types from other crates that
915 // may have specialized impls we can't see. In the
916 // case where the trait ref IS fully monomorphic, this
917 // is a policy decision that we made in the RFC in
918 // order to preserve flexibility for the crate that
919 // defined the specializable impl to specialize later
920 // for existing types.
922 // In either case, we handle this by not adding a
923 // candidate for an impl if it contains a `default`
925 let opt_node_item
= assoc_ty_def(selcx
,
926 impl_data
.impl_def_id
,
927 obligation
.predicate
.item_name
);
928 let new_candidate
= if let Some(node_item
) = opt_node_item
{
929 if node_item
.node
.is_from_trait() {
930 if node_item
.item
.ty
.is_some() {
931 // The impl inherited a `type Foo =
932 // Bar` given in the trait, which is
933 // implicitly default. No candidate.
936 // The impl did not specify `type` and neither
940 // trait Foo { type T; }
941 // impl Foo for Bar { }
944 // This is an error, but it will be
945 // reported in `check_impl_items_against_trait`.
946 // We accept it here but will flag it as
947 // an error when we confirm the candidate
948 // (which will ultimately lead to `normalize_to_error`
950 Some(ProjectionTyCandidate
::Select
)
952 } else if node_item
.item
.defaultness
.is_default() {
953 // The impl specified `default type Foo =
954 // Bar`. No candidate.
957 // The impl specified `type Foo = Bar`
958 // with no default. Add a candidate.
959 Some(ProjectionTyCandidate
::Select
)
962 // This is saying that neither the trait nor
963 // the impl contain a definition for this
964 // associated type. Normally this situation
965 // could only arise through a compiler bug --
966 // if the user wrote a bad item name, it
967 // should have failed in astconv. **However**,
968 // at coherence-checking time, we only look at
969 // the topmost impl (we don't even consider
970 // the trait itself) for the definition -- and
971 // so in that case it may be that the trait
972 // *DOES* have a declaration, but we don't see
973 // it, and we end up in this branch.
975 // This is kind of tricky to handle actually.
976 // For now, we just unconditionally ICE,
977 // because otherwise, examples like the
978 // following will succeed:
985 // impl<T> Assoc for T {
986 // default type Output = bool;
989 // impl Assoc for u8 {}
990 // impl Assoc for u16 {}
993 // impl Foo for <u8 as Assoc>::Output {}
994 // impl Foo for <u16 as Assoc>::Output {}
999 // The essential problem here is that the
1000 // projection fails, leaving two unnormalized
1001 // types, which appear not to unify -- so the
1002 // overlap check succeeds, when it should
1004 bug
!("Tried to project an inherited associated type during \
1005 coherence checking, which is currently not supported.");
1007 candidate_set
.vec
.extend(new_candidate
);
1009 super::VtableImpl(_
) => {
1010 // In trans mode, we can just project out of impls, no prob.
1011 assert
!(selcx
.projection_mode().is_any());
1012 candidate_set
.vec
.push(ProjectionTyCandidate
::Select
);
1014 super::VtableParam(..) => {
1015 // This case tell us nothing about the value of an
1016 // associated type. Consider:
1019 // trait SomeTrait { type Foo; }
1020 // fn foo<T:SomeTrait>(...) { }
1023 // If the user writes `<T as SomeTrait>::Foo`, then the `T
1024 // : SomeTrait` binding does not help us decide what the
1025 // type `Foo` is (at least, not more specifically than
1026 // what we already knew).
1028 // But wait, you say! What about an example like this:
1031 // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
1034 // Doesn't the `T : Sometrait<Foo=usize>` predicate help
1035 // resolve `T::Foo`? And of course it does, but in fact
1036 // that single predicate is desugared into two predicates
1037 // in the compiler: a trait predicate (`T : SomeTrait`) and a
1038 // projection. And the projection where clause is handled
1039 // in `assemble_candidates_from_param_env`.
1041 super::VtableDefaultImpl(..) |
1042 super::VtableBuiltin(..) => {
1043 // These traits have no associated types.
1045 obligation
.cause
.span
,
1046 "Cannot project an associated type from `{:?}`",
1055 fn confirm_candidate
<'cx
, 'gcx
, 'tcx
>(
1056 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1057 obligation
: &ProjectionTyObligation
<'tcx
>,
1058 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
1059 candidate
: ProjectionTyCandidate
<'tcx
>)
1062 debug
!("confirm_candidate(candidate={:?}, obligation={:?})",
1067 ProjectionTyCandidate
::ParamEnv(poly_projection
) |
1068 ProjectionTyCandidate
::TraitDef(poly_projection
) => {
1069 confirm_param_env_candidate(selcx
, obligation
, poly_projection
)
1072 ProjectionTyCandidate
::Select
=> {
1073 confirm_select_candidate(selcx
, obligation
, obligation_trait_ref
)
1078 fn confirm_select_candidate
<'cx
, 'gcx
, 'tcx
>(
1079 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1080 obligation
: &ProjectionTyObligation
<'tcx
>,
1081 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>)
1084 let poly_trait_ref
= obligation_trait_ref
.to_poly_trait_ref();
1085 let trait_obligation
= obligation
.with(poly_trait_ref
.to_poly_trait_predicate());
1086 let vtable
= match selcx
.select(&trait_obligation
) {
1087 Ok(Some(vtable
)) => vtable
,
1090 obligation
.cause
.span
,
1091 "Failed to select `{:?}`",
1097 super::VtableImpl(data
) =>
1098 confirm_impl_candidate(selcx
, obligation
, data
),
1099 super::VtableClosure(data
) =>
1100 confirm_closure_candidate(selcx
, obligation
, data
),
1101 super::VtableFnPointer(data
) =>
1102 confirm_fn_pointer_candidate(selcx
, obligation
, data
),
1103 super::VtableObject(_
) =>
1104 confirm_object_candidate(selcx
, obligation
, obligation_trait_ref
),
1105 super::VtableDefaultImpl(..) |
1106 super::VtableParam(..) |
1107 super::VtableBuiltin(..) =>
1108 // we don't create Select candidates with this kind of resolution
1110 obligation
.cause
.span
,
1111 "Cannot project an associated type from `{:?}`",
1116 fn confirm_object_candidate
<'cx
, 'gcx
, 'tcx
>(
1117 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1118 obligation
: &ProjectionTyObligation
<'tcx
>,
1119 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>)
1122 let self_ty
= obligation_trait_ref
.self_ty();
1123 let object_ty
= selcx
.infcx().shallow_resolve(self_ty
);
1124 debug
!("confirm_object_candidate(object_ty={:?})",
1126 let data
= match object_ty
.sty
{
1127 ty
::TyTrait(ref data
) => data
,
1130 obligation
.cause
.span
,
1131 "confirm_object_candidate called with non-object: {:?}",
1135 let projection_bounds
= data
.projection_bounds_with_self_ty(selcx
.tcx(), object_ty
);
1136 let env_predicates
= projection_bounds
.iter()
1137 .map(|p
| p
.to_predicate())
1139 let env_predicate
= {
1140 let env_predicates
= elaborate_predicates(selcx
.tcx(), env_predicates
);
1142 // select only those projections that are actually projecting an
1143 // item with the correct name
1144 let env_predicates
= env_predicates
.filter_map(|p
| match p
{
1145 ty
::Predicate
::Projection(data
) =>
1146 if data
.item_name() == obligation
.predicate
.item_name
{
1154 // select those with a relevant trait-ref
1155 let mut env_predicates
= env_predicates
.filter(|data
| {
1156 let origin
= TypeOrigin
::RelateOutputImplTypes(obligation
.cause
.span
);
1157 let data_poly_trait_ref
= data
.to_poly_trait_ref();
1158 let obligation_poly_trait_ref
= obligation_trait_ref
.to_poly_trait_ref();
1159 selcx
.infcx().probe(|_
| {
1160 selcx
.infcx().sub_poly_trait_refs(false,
1162 data_poly_trait_ref
,
1163 obligation_poly_trait_ref
).is_ok()
1167 // select the first matching one; there really ought to be one or
1168 // else the object type is not WF, since an object type should
1169 // include all of its projections explicitly
1170 match env_predicates
.next() {
1171 Some(env_predicate
) => env_predicate
,
1173 debug
!("confirm_object_candidate: no env-predicate \
1174 found in object type `{:?}`; ill-formed",
1176 return Progress
::error(selcx
.tcx());
1181 confirm_param_env_candidate(selcx
, obligation
, env_predicate
)
1184 fn confirm_fn_pointer_candidate
<'cx
, 'gcx
, 'tcx
>(
1185 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1186 obligation
: &ProjectionTyObligation
<'tcx
>,
1187 fn_pointer_vtable
: VtableFnPointerData
<'tcx
, PredicateObligation
<'tcx
>>)
1190 // FIXME(#32730) drop this assertion once obligations are propagated from inference (fn pointer
1191 // vtable nested obligations ONLY come from unification in inference)
1192 assert
!(fn_pointer_vtable
.nested
.is_empty());
1193 let fn_type
= selcx
.infcx().shallow_resolve(fn_pointer_vtable
.fn_ty
);
1194 let sig
= fn_type
.fn_sig();
1195 confirm_callable_candidate(selcx
, obligation
, sig
, util
::TupleArgumentsFlag
::Yes
)
1198 fn confirm_closure_candidate
<'cx
, 'gcx
, 'tcx
>(
1199 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1200 obligation
: &ProjectionTyObligation
<'tcx
>,
1201 vtable
: VtableClosureData
<'tcx
, PredicateObligation
<'tcx
>>)
1204 let closure_typer
= selcx
.closure_typer();
1205 let closure_type
= closure_typer
.closure_type(vtable
.closure_def_id
, vtable
.substs
);
1207 value
: closure_type
,
1209 } = normalize_with_depth(selcx
,
1210 obligation
.cause
.clone(),
1211 obligation
.recursion_depth
+1,
1214 debug
!("confirm_closure_candidate: obligation={:?},closure_type={:?},obligations={:?}",
1219 confirm_callable_candidate(selcx
,
1222 util
::TupleArgumentsFlag
::No
)
1223 .with_addl_obligations(obligations
)
1224 .with_addl_obligations(vtable
.nested
)
1227 fn confirm_callable_candidate
<'cx
, 'gcx
, 'tcx
>(
1228 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1229 obligation
: &ProjectionTyObligation
<'tcx
>,
1230 fn_sig
: &ty
::PolyFnSig
<'tcx
>,
1231 flag
: util
::TupleArgumentsFlag
)
1234 let tcx
= selcx
.tcx();
1236 debug
!("confirm_callable_candidate({:?},{:?})",
1240 // the `Output` associated type is declared on `FnOnce`
1241 let fn_once_def_id
= tcx
.lang_items
.fn_once_trait().unwrap();
1243 // Note: we unwrap the binder here but re-create it below (1)
1244 let ty
::Binder((trait_ref
, ret_type
)) =
1245 tcx
.closure_trait_ref_and_return_type(fn_once_def_id
,
1246 obligation
.predicate
.trait_ref
.self_ty(),
1250 let predicate
= ty
::Binder(ty
::ProjectionPredicate
{ // (1) recreate binder here
1251 projection_ty
: ty
::ProjectionTy
{
1252 trait_ref
: trait_ref
,
1253 item_name
: token
::intern(FN_OUTPUT_NAME
),
1258 confirm_param_env_candidate(selcx
, obligation
, predicate
)
1261 fn confirm_param_env_candidate
<'cx
, 'gcx
, 'tcx
>(
1262 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1263 obligation
: &ProjectionTyObligation
<'tcx
>,
1264 poly_projection
: ty
::PolyProjectionPredicate
<'tcx
>)
1267 let infcx
= selcx
.infcx();
1268 let origin
= TypeOrigin
::RelateOutputImplTypes(obligation
.cause
.span
);
1269 let trait_ref
= obligation
.predicate
.trait_ref
;
1270 match infcx
.match_poly_projection_predicate(origin
, poly_projection
, trait_ref
) {
1271 Ok(InferOk { value: ty_match, obligations }
) => {
1272 // FIXME(#32730) once obligations are generated in inference, drop this assertion
1273 assert
!(obligations
.is_empty());
1276 obligations
: obligations
,
1277 cacheable
: ty_match
.unconstrained_regions
.is_empty(),
1282 obligation
.cause
.span
,
1283 "Failed to unify obligation `{:?}` \
1284 with poly_projection `{:?}`: {:?}",
1292 fn confirm_impl_candidate
<'cx
, 'gcx
, 'tcx
>(
1293 selcx
: &mut SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1294 obligation
: &ProjectionTyObligation
<'tcx
>,
1295 impl_vtable
: VtableImplData
<'tcx
, PredicateObligation
<'tcx
>>)
1298 let VtableImplData { substs, nested, impl_def_id }
= impl_vtable
;
1300 let tcx
= selcx
.tcx();
1301 let trait_ref
= obligation
.predicate
.trait_ref
;
1302 let assoc_ty
= assoc_ty_def(selcx
, impl_def_id
, obligation
.predicate
.item_name
);
1305 Some(node_item
) => {
1306 let ty
= node_item
.item
.ty
.unwrap_or_else(|| {
1307 // This means that the impl is missing a definition for the
1308 // associated type. This error will be reported by the type
1309 // checker method `check_impl_items_against_trait`, so here we
1310 // just return TyError.
1311 debug
!("confirm_impl_candidate: no associated type {:?} for {:?}",
1312 node_item
.item
.name
,
1313 obligation
.predicate
.trait_ref
);
1316 let substs
= translate_substs(selcx
.infcx(), impl_def_id
, substs
, node_item
.node
);
1318 ty
: ty
.subst(tcx
, substs
),
1319 obligations
: nested
,
1324 span_bug
!(obligation
.cause
.span
,
1325 "No associated type for {:?}",
1331 /// Locate the definition of an associated type in the specialization hierarchy,
1332 /// starting from the given impl.
1334 /// Based on the "projection mode", this lookup may in fact only examine the
1335 /// topmost impl. See the comments for `ProjectionMode` for more details.
1336 fn assoc_ty_def
<'cx
, 'gcx
, 'tcx
>(
1337 selcx
: &SelectionContext
<'cx
, 'gcx
, 'tcx
>,
1339 assoc_ty_name
: ast
::Name
)
1340 -> Option
<specialization_graph
::NodeItem
<Rc
<ty
::AssociatedType
<'tcx
>>>>
1342 let trait_def_id
= selcx
.tcx().impl_trait_ref(impl_def_id
).unwrap().def_id
;
1344 if selcx
.projection_mode().is_topmost() {
1345 let impl_node
= specialization_graph
::Node
::Impl(impl_def_id
);
1346 for item
in impl_node
.items(selcx
.tcx()) {
1347 if let ty
::TypeTraitItem(assoc_ty
) = item
{
1348 if assoc_ty
.name
== assoc_ty_name
{
1349 return Some(specialization_graph
::NodeItem
{
1350 node
: specialization_graph
::Node
::Impl(impl_def_id
),
1358 selcx
.tcx().lookup_trait_def(trait_def_id
)
1359 .ancestors(impl_def_id
)
1360 .type_defs(selcx
.tcx(), assoc_ty_name
)
1367 pub struct ProjectionCache
<'tcx
> {
1368 map
: SnapshotMap
<ty
::ProjectionTy
<'tcx
>, ProjectionCacheEntry
<'tcx
>>,
1371 #[derive(Clone, Debug)]
1372 enum ProjectionCacheEntry
<'tcx
> {
1376 NormalizedTy(Ty
<'tcx
>),
1379 // NB: intentionally not Clone
1380 pub struct ProjectionCacheSnapshot
{
1384 impl<'tcx
> ProjectionCache
<'tcx
> {
1385 pub fn new() -> Self {
1387 map
: SnapshotMap
::new()
1391 pub fn snapshot(&mut self) -> ProjectionCacheSnapshot
{
1392 ProjectionCacheSnapshot { snapshot: self.map.snapshot() }
1395 pub fn rollback_to(&mut self, snapshot
: ProjectionCacheSnapshot
) {
1396 self.map
.rollback_to(snapshot
.snapshot
);
1399 pub fn commit(&mut self, snapshot
: ProjectionCacheSnapshot
) {
1400 self.map
.commit(snapshot
.snapshot
);
1403 /// Try to start normalize `key`; returns an error if
1404 /// normalization already occured (this error corresponds to a
1405 /// cache hit, so it's actually a good thing).
1406 fn try_start(&mut self, key
: ty
::ProjectionTy
<'tcx
>)
1407 -> Result
<(), ProjectionCacheEntry
<'tcx
>> {
1408 match self.map
.get(&key
) {
1409 Some(entry
) => return Err(entry
.clone()),
1413 self.map
.insert(key
, ProjectionCacheEntry
::InProgress
);
1417 /// Indicates that `key` was normalized to `value`. If `cacheable` is false,
1418 /// then this result is sadly not cacheable.
1419 fn complete(&mut self,
1420 key
: ty
::ProjectionTy
<'tcx
>,
1421 value
: &NormalizedTy
<'tcx
>,
1423 let fresh_key
= if cacheable
{
1424 debug
!("ProjectionCacheEntry::complete: adding cache entry: key={:?}, value={:?}",
1426 self.map
.insert(key
, ProjectionCacheEntry
::NormalizedTy(value
.value
))
1428 debug
!("ProjectionCacheEntry::complete: cannot cache: key={:?}, value={:?}",
1430 !self.map
.remove(key
)
1433 assert
!(!fresh_key
, "never started projecting `{:?}`", key
);
1436 /// Indicates that trying to normalize `key` resulted in
1437 /// ambiguity. No point in trying it again then until we gain more
1438 /// type information (in which case, the "fully resolved" key will
1440 fn ambiguous(&mut self, key
: ty
::ProjectionTy
<'tcx
>) {
1441 let fresh
= self.map
.insert(key
, ProjectionCacheEntry
::Ambiguous
);
1442 assert
!(!fresh
, "never started projecting `{:?}`", key
);
1445 /// Indicates that trying to normalize `key` resulted in
1447 fn error(&mut self, key
: ty
::ProjectionTy
<'tcx
>) {
1448 let fresh
= self.map
.insert(key
, ProjectionCacheEntry
::Error
);
1449 assert
!(!fresh
, "never started projecting `{:?}`", key
);