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::report_overflow_error
;
15 use super::Obligation
;
16 use super::ObligationCause
;
17 use super::PredicateObligation
;
18 use super::SelectionContext
;
19 use super::SelectionError
;
20 use super::VtableClosureData
;
21 use super::VtableImplData
;
25 use middle
::subst
::Subst
;
26 use middle
::ty
::{self, AsPredicate
, ReferencesError
, RegionEscape
,
27 HasProjectionTypes
, ToPolyTraitRef
, Ty
};
28 use middle
::ty_fold
::{self, TypeFoldable, TypeFolder}
;
29 use syntax
::parse
::token
;
30 use util
::common
::FN_OUTPUT_NAME
;
34 pub type PolyProjectionObligation
<'tcx
> =
35 Obligation
<'tcx
, ty
::PolyProjectionPredicate
<'tcx
>>;
37 pub type ProjectionObligation
<'tcx
> =
38 Obligation
<'tcx
, ty
::ProjectionPredicate
<'tcx
>>;
40 pub type ProjectionTyObligation
<'tcx
> =
41 Obligation
<'tcx
, ty
::ProjectionTy
<'tcx
>>;
43 /// When attempting to resolve `<T as TraitRef>::Name` ...
45 pub enum ProjectionTyError
<'tcx
> {
46 /// ...we found multiple sources of information and couldn't resolve the ambiguity.
49 /// ...an error occurred matching `T : TraitRef`
50 TraitSelectionError(SelectionError
<'tcx
>),
54 pub struct MismatchedProjectionTypes
<'tcx
> {
55 pub err
: ty
::type_err
<'tcx
>
58 #[derive(PartialEq, Eq, Debug)]
59 enum ProjectionTyCandidate
<'tcx
> {
60 ParamEnv(ty
::PolyProjectionPredicate
<'tcx
>),
61 Impl(VtableImplData
<'tcx
, PredicateObligation
<'tcx
>>),
62 Closure(VtableClosureData
<'tcx
, PredicateObligation
<'tcx
>>),
66 struct ProjectionTyCandidateSet
<'tcx
> {
67 vec
: Vec
<ProjectionTyCandidate
<'tcx
>>,
71 /// Evaluates constraints of the form:
73 /// for<...> <T as Trait>::U == V
75 /// If successful, this may result in additional obligations.
76 pub fn poly_project_and_unify_type
<'cx
,'tcx
>(
77 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
78 obligation
: &PolyProjectionObligation
<'tcx
>)
79 -> Result
<Option
<Vec
<PredicateObligation
<'tcx
>>>, MismatchedProjectionTypes
<'tcx
>>
81 debug
!("poly_project_and_unify_type(obligation={:?})",
84 let infcx
= selcx
.infcx();
85 infcx
.commit_if_ok(|snapshot
| {
86 let (skol_predicate
, skol_map
) =
87 infcx
.skolemize_late_bound_regions(&obligation
.predicate
, snapshot
);
89 let skol_obligation
= obligation
.with(skol_predicate
);
90 match project_and_unify_type(selcx
, &skol_obligation
) {
92 match infcx
.leak_check(&skol_map
, snapshot
) {
93 Ok(()) => Ok(infcx
.plug_leaks(skol_map
, snapshot
, &result
)),
94 Err(e
) => Err(MismatchedProjectionTypes { err: e }
),
104 /// Evaluates constraints of the form:
106 /// <T as Trait>::U == V
108 /// If successful, this may result in additional obligations.
109 fn project_and_unify_type
<'cx
,'tcx
>(
110 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
111 obligation
: &ProjectionObligation
<'tcx
>)
112 -> Result
<Option
<Vec
<PredicateObligation
<'tcx
>>>, MismatchedProjectionTypes
<'tcx
>>
114 debug
!("project_and_unify_type(obligation={:?})",
117 let Normalized { value: normalized_ty, obligations }
=
118 match opt_normalize_projection_type(selcx
,
119 obligation
.predicate
.projection_ty
.clone(),
120 obligation
.cause
.clone(),
121 obligation
.recursion_depth
) {
124 consider_unification_despite_ambiguity(selcx
, obligation
);
129 debug
!("project_and_unify_type: normalized_ty={:?} obligations={:?}",
133 let infcx
= selcx
.infcx();
134 let origin
= infer
::RelateOutputImplTypes(obligation
.cause
.span
);
135 match infer
::mk_eqty(infcx
, true, origin
, normalized_ty
, obligation
.predicate
.ty
) {
136 Ok(()) => Ok(Some(obligations
)),
137 Err(err
) => Err(MismatchedProjectionTypes { err: err }
),
141 fn consider_unification_despite_ambiguity
<'cx
,'tcx
>(selcx
: &mut SelectionContext
<'cx
,'tcx
>,
142 obligation
: &ProjectionObligation
<'tcx
>) {
143 debug
!("consider_unification_despite_ambiguity(obligation={:?})",
146 let def_id
= obligation
.predicate
.projection_ty
.trait_ref
.def_id
;
147 match selcx
.tcx().lang_items
.fn_trait_kind(def_id
) {
152 let infcx
= selcx
.infcx();
153 let self_ty
= obligation
.predicate
.projection_ty
.trait_ref
.self_ty();
154 let self_ty
= infcx
.shallow_resolve(self_ty
);
155 debug
!("consider_unification_despite_ambiguity: self_ty.sty={:?}",
158 ty
::TyClosure(closure_def_id
, substs
) => {
159 let closure_typer
= selcx
.closure_typer();
160 let closure_type
= closure_typer
.closure_type(closure_def_id
, substs
);
161 let ty
::Binder((_
, ret_type
)) =
162 util
::closure_trait_ref_and_return_type(infcx
.tcx
,
166 util
::TupleArgumentsFlag
::No
);
167 // We don't have to normalize the return type here - this is only
168 // reached for TyClosure: Fn inputs where the closure kind is
169 // still unknown, which should only occur in typeck where the
170 // closure type is already normalized.
172 infcx
.replace_late_bound_regions_with_fresh_var(
173 obligation
.cause
.span
,
174 infer
::AssocTypeProjection(obligation
.predicate
.projection_ty
.item_name
),
175 &ty
::Binder(ret_type
));
177 debug
!("consider_unification_despite_ambiguity: ret_type={:?}",
179 let origin
= infer
::RelateOutputImplTypes(obligation
.cause
.span
);
180 let obligation_ty
= obligation
.predicate
.ty
;
181 match infer
::mk_eqty(infcx
, true, origin
, obligation_ty
, ret_type
) {
183 Err(_
) => { /* ignore errors */ }
190 /// Normalizes any associated type projections in `value`, replacing
191 /// them with a fully resolved type where possible. The return value
192 /// combines the normalized result and any additional obligations that
193 /// were incurred as result.
194 pub fn normalize
<'a
,'b
,'tcx
,T
>(selcx
: &'a
mut SelectionContext
<'b
,'tcx
>,
195 cause
: ObligationCause
<'tcx
>,
197 -> Normalized
<'tcx
, T
>
198 where T
: TypeFoldable
<'tcx
> + HasProjectionTypes
200 normalize_with_depth(selcx
, cause
, 0, value
)
203 /// As `normalize`, but with a custom depth.
204 pub fn normalize_with_depth
<'a
,'b
,'tcx
,T
>(selcx
: &'a
mut SelectionContext
<'b
,'tcx
>,
205 cause
: ObligationCause
<'tcx
>,
208 -> Normalized
<'tcx
, T
>
209 where T
: TypeFoldable
<'tcx
> + HasProjectionTypes
211 let mut normalizer
= AssociatedTypeNormalizer
::new(selcx
, cause
, depth
);
212 let result
= normalizer
.fold(value
);
216 obligations
: normalizer
.obligations
,
220 struct AssociatedTypeNormalizer
<'a
,'b
:'a
,'tcx
:'b
> {
221 selcx
: &'a
mut SelectionContext
<'b
,'tcx
>,
222 cause
: ObligationCause
<'tcx
>,
223 obligations
: Vec
<PredicateObligation
<'tcx
>>,
227 impl<'a
,'b
,'tcx
> AssociatedTypeNormalizer
<'a
,'b
,'tcx
> {
228 fn new(selcx
: &'a
mut SelectionContext
<'b
,'tcx
>,
229 cause
: ObligationCause
<'tcx
>,
231 -> AssociatedTypeNormalizer
<'a
,'b
,'tcx
>
233 AssociatedTypeNormalizer
{
241 fn fold
<T
:TypeFoldable
<'tcx
> + HasProjectionTypes
>(&mut self, value
: &T
) -> T
{
242 let value
= self.selcx
.infcx().resolve_type_vars_if_possible(value
);
244 if !value
.has_projection_types() {
247 value
.fold_with(self)
252 impl<'a
,'b
,'tcx
> TypeFolder
<'tcx
> for AssociatedTypeNormalizer
<'a
,'b
,'tcx
> {
253 fn tcx(&self) -> &ty
::ctxt
<'tcx
> {
257 fn fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
258 // We don't want to normalize associated types that occur inside of region
259 // binders, because they may contain bound regions, and we can't cope with that.
263 // for<'a> fn(<T as Foo<&'a>>::A)
265 // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
266 // normalize it when we instantiate those bound regions (which
267 // should occur eventually).
269 let ty
= ty_fold
::super_fold_ty(self, ty
);
271 ty
::TyProjection(ref data
) if !data
.has_escaping_regions() => { // (*)
273 // (*) This is kind of hacky -- we need to be able to
274 // handle normalization within binders because
275 // otherwise we wind up a need to normalize when doing
276 // trait matching (since you can have a trait
277 // obligation like `for<'a> T::B : Fn(&'a int)`), but
278 // we can't normalize with bound regions in scope. So
279 // far now we just ignore binders but only normalize
280 // if all bound regions are gone (and then we still
281 // have to renormalize whenever we instantiate a
282 // binder). It would be better to normalize in a
283 // binding-aware fashion.
285 let Normalized { value: ty, obligations }
=
286 normalize_projection_type(self.selcx
,
290 self.obligations
.extend(obligations
);
302 pub struct Normalized
<'tcx
,T
> {
304 pub obligations
: Vec
<PredicateObligation
<'tcx
>>,
307 pub type NormalizedTy
<'tcx
> = Normalized
<'tcx
, Ty
<'tcx
>>;
309 impl<'tcx
,T
> Normalized
<'tcx
,T
> {
310 pub fn with
<U
>(self, value
: U
) -> Normalized
<'tcx
,U
> {
311 Normalized { value: value, obligations: self.obligations }
315 /// The guts of `normalize`: normalize a specific projection like `<T
316 /// as Trait>::Item`. The result is always a type (and possibly
317 /// additional obligations). If ambiguity arises, which implies that
318 /// there are unresolved type variables in the projection, we will
319 /// substitute a fresh type variable `$X` and generate a new
320 /// obligation `<T as Trait>::Item == $X` for later.
321 pub fn normalize_projection_type
<'a
,'b
,'tcx
>(
322 selcx
: &'a
mut SelectionContext
<'b
,'tcx
>,
323 projection_ty
: ty
::ProjectionTy
<'tcx
>,
324 cause
: ObligationCause
<'tcx
>,
326 -> NormalizedTy
<'tcx
>
328 opt_normalize_projection_type(selcx
, projection_ty
.clone(), cause
.clone(), depth
)
329 .unwrap_or_else(move || {
330 // if we bottom out in ambiguity, create a type variable
331 // and a deferred predicate to resolve this when more type
332 // information is available.
334 let ty_var
= selcx
.infcx().next_ty_var();
335 let projection
= ty
::Binder(ty
::ProjectionPredicate
{
336 projection_ty
: projection_ty
,
339 let obligation
= Obligation
::with_depth(cause
, depth
+1, projection
.as_predicate());
342 obligations
: vec
!(obligation
)
347 /// The guts of `normalize`: normalize a specific projection like `<T
348 /// as Trait>::Item`. The result is always a type (and possibly
349 /// additional obligations). Returns `None` in the case of ambiguity,
350 /// which indicates that there are unbound type variables.
351 fn opt_normalize_projection_type
<'a
,'b
,'tcx
>(
352 selcx
: &'a
mut SelectionContext
<'b
,'tcx
>,
353 projection_ty
: ty
::ProjectionTy
<'tcx
>,
354 cause
: ObligationCause
<'tcx
>,
356 -> Option
<NormalizedTy
<'tcx
>>
358 debug
!("normalize_projection_type(\
359 projection_ty={:?}, \
364 let obligation
= Obligation
::with_depth(cause
.clone(), depth
, projection_ty
.clone());
365 match project_type(selcx
, &obligation
) {
366 Ok(ProjectedTy
::Progress(projected_ty
, mut obligations
)) => {
367 // if projection succeeded, then what we get out of this
368 // is also non-normalized (consider: it was derived from
369 // an impl, where-clause etc) and hence we must
372 debug
!("normalize_projection_type: projected_ty={:?} depth={} obligations={:?}",
377 if ty
::type_has_projection(projected_ty
) {
378 let mut normalizer
= AssociatedTypeNormalizer
::new(selcx
, cause
, depth
);
379 let normalized_ty
= normalizer
.fold(&projected_ty
);
381 debug
!("normalize_projection_type: normalized_ty={:?} depth={}",
385 obligations
.extend(normalizer
.obligations
);
387 value
: normalized_ty
,
388 obligations
: obligations
,
393 obligations
: obligations
,
397 Ok(ProjectedTy
::NoProgress(projected_ty
)) => {
398 debug
!("normalize_projection_type: projected_ty={:?} no progress",
405 Err(ProjectionTyError
::TooManyCandidates
) => {
406 debug
!("normalize_projection_type: too many candidates");
409 Err(ProjectionTyError
::TraitSelectionError(_
)) => {
410 debug
!("normalize_projection_type: ERROR");
411 // if we got an error processing the `T as Trait` part,
412 // just return `ty::err` but add the obligation `T :
413 // Trait`, which when processed will cause the error to be
416 Some(normalize_to_error(selcx
, projection_ty
, cause
, depth
))
421 /// in various error cases, we just set TyError and return an obligation
422 /// that, when fulfilled, will lead to an error.
424 /// FIXME: the TyError created here can enter the obligation we create,
425 /// leading to error messages involving TyError.
426 fn normalize_to_error
<'a
,'tcx
>(selcx
: &mut SelectionContext
<'a
,'tcx
>,
427 projection_ty
: ty
::ProjectionTy
<'tcx
>,
428 cause
: ObligationCause
<'tcx
>,
430 -> NormalizedTy
<'tcx
>
432 let trait_ref
= projection_ty
.trait_ref
.to_poly_trait_ref();
433 let trait_obligation
= Obligation
{ cause
: cause
,
434 recursion_depth
: depth
,
435 predicate
: trait_ref
.as_predicate() };
437 value
: selcx
.tcx().types
.err
,
438 obligations
: vec
!(trait_obligation
)
442 enum ProjectedTy
<'tcx
> {
443 Progress(Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>),
444 NoProgress(Ty
<'tcx
>),
447 /// Compute the result of a projection type (if we can).
448 fn project_type
<'cx
,'tcx
>(
449 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
450 obligation
: &ProjectionTyObligation
<'tcx
>)
451 -> Result
<ProjectedTy
<'tcx
>, ProjectionTyError
<'tcx
>>
453 debug
!("project(obligation={:?})",
456 let recursion_limit
= selcx
.tcx().sess
.recursion_limit
.get();
457 if obligation
.recursion_depth
>= recursion_limit
{
458 debug
!("project: overflow!");
459 report_overflow_error(selcx
.infcx(), &obligation
);
462 let obligation_trait_ref
=
463 selcx
.infcx().resolve_type_vars_if_possible(&obligation
.predicate
.trait_ref
);
465 debug
!("project: obligation_trait_ref={:?}", obligation_trait_ref
);
467 if obligation_trait_ref
.references_error() {
468 return Ok(ProjectedTy
::Progress(selcx
.tcx().types
.err
, vec
!()));
471 let mut candidates
= ProjectionTyCandidateSet
{
476 assemble_candidates_from_param_env(selcx
,
478 &obligation_trait_ref
,
481 assemble_candidates_from_trait_def(selcx
,
483 &obligation_trait_ref
,
486 if let Err(e
) = assemble_candidates_from_impls(selcx
,
488 &obligation_trait_ref
,
490 return Err(ProjectionTyError
::TraitSelectionError(e
));
493 debug
!("{} candidates, ambiguous={}",
494 candidates
.vec
.len(),
495 candidates
.ambiguous
);
497 // We probably need some winnowing logic similar to select here.
501 // Note: `candidates.vec` seems to be on the critical path of the
502 // compiler. Replacing it with an hash set was also tried, which would
503 // render the following dedup unnecessary. It led to cleaner code but
504 // prolonged compiling time of `librustc` from 5m30s to 6m in one test, or
505 // ~9% performance lost.
506 if candidates
.vec
.len() > 1 {
508 while i
< candidates
.vec
.len() {
509 let has_dup
= (0..i
).any(|j
| candidates
.vec
[i
] == candidates
.vec
[j
]);
511 candidates
.vec
.swap_remove(i
);
518 if candidates
.ambiguous
|| candidates
.vec
.len() > 1 {
519 return Err(ProjectionTyError
::TooManyCandidates
);
522 match candidates
.vec
.pop() {
524 let (ty
, obligations
) = confirm_candidate(selcx
, obligation
, candidate
);
525 Ok(ProjectedTy
::Progress(ty
, obligations
))
528 Ok(ProjectedTy
::NoProgress(ty
::mk_projection(selcx
.tcx(),
529 obligation
.predicate
.trait_ref
.clone(),
530 obligation
.predicate
.item_name
)))
535 /// The first thing we have to do is scan through the parameter
536 /// environment to see whether there are any projection predicates
537 /// there that can answer this question.
538 fn assemble_candidates_from_param_env
<'cx
,'tcx
>(
539 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
540 obligation
: &ProjectionTyObligation
<'tcx
>,
541 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
542 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>)
544 let env_predicates
= selcx
.param_env().caller_bounds
.iter().cloned();
545 assemble_candidates_from_predicates(selcx
, obligation
, obligation_trait_ref
,
546 candidate_set
, env_predicates
);
549 /// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
550 /// that the definition of `Foo` has some clues:
554 /// type FooT : Bar<BarT=i32>
558 /// Here, for example, we could conclude that the result is `i32`.
559 fn assemble_candidates_from_trait_def
<'cx
,'tcx
>(
560 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
561 obligation
: &ProjectionTyObligation
<'tcx
>,
562 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
563 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>)
565 // Check whether the self-type is itself a projection.
566 let trait_ref
= match obligation_trait_ref
.self_ty().sty
{
567 ty
::TyProjection(ref data
) => data
.trait_ref
.clone(),
568 ty
::TyInfer(ty
::TyVar(_
)) => {
569 // If the self-type is an inference variable, then it MAY wind up
570 // being a projected type, so induce an ambiguity.
571 candidate_set
.ambiguous
= true;
577 // If so, extract what we know from the trait and try to come up with a good answer.
578 let trait_predicates
= ty
::lookup_predicates(selcx
.tcx(), trait_ref
.def_id
);
579 let bounds
= trait_predicates
.instantiate(selcx
.tcx(), trait_ref
.substs
);
580 let bounds
= elaborate_predicates(selcx
.tcx(), bounds
.predicates
.into_vec());
581 assemble_candidates_from_predicates(selcx
, obligation
, obligation_trait_ref
,
582 candidate_set
, bounds
)
585 fn assemble_candidates_from_predicates
<'cx
,'tcx
,I
>(
586 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
587 obligation
: &ProjectionTyObligation
<'tcx
>,
588 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
589 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>,
591 where I
: Iterator
<Item
=ty
::Predicate
<'tcx
>>
593 debug
!("assemble_candidates_from_predicates(obligation={:?})",
595 let infcx
= selcx
.infcx();
596 for predicate
in env_predicates
{
597 debug
!("assemble_candidates_from_predicates: predicate={:?}",
600 ty
::Predicate
::Projection(ref data
) => {
601 let same_name
= data
.item_name() == obligation
.predicate
.item_name
;
603 let is_match
= same_name
&& infcx
.probe(|_
| {
604 let origin
= infer
::Misc(obligation
.cause
.span
);
605 let data_poly_trait_ref
=
606 data
.to_poly_trait_ref();
607 let obligation_poly_trait_ref
=
608 obligation_trait_ref
.to_poly_trait_ref();
609 infcx
.sub_poly_trait_refs(false,
612 obligation_poly_trait_ref
).is_ok()
615 debug
!("assemble_candidates_from_predicates: candidate={:?} \
616 is_match={} same_name={}",
617 data
, is_match
, same_name
);
620 candidate_set
.vec
.push(
621 ProjectionTyCandidate
::ParamEnv(data
.clone()));
629 fn assemble_candidates_from_object_type
<'cx
,'tcx
>(
630 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
631 obligation
: &ProjectionTyObligation
<'tcx
>,
632 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
633 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>,
636 debug
!("assemble_candidates_from_object_type(object_ty={:?})",
638 let data
= match object_ty
.sty
{
639 ty
::TyTrait(ref data
) => data
,
641 selcx
.tcx().sess
.span_bug(
642 obligation
.cause
.span
,
643 &format
!("assemble_candidates_from_object_type called with non-object: {:?}",
647 let projection_bounds
= data
.projection_bounds_with_self_ty(selcx
.tcx(), object_ty
);
648 let env_predicates
= projection_bounds
.iter()
649 .map(|p
| p
.as_predicate())
651 let env_predicates
= elaborate_predicates(selcx
.tcx(), env_predicates
);
652 assemble_candidates_from_predicates(selcx
, obligation
, obligation_trait_ref
,
653 candidate_set
, env_predicates
)
656 fn assemble_candidates_from_impls
<'cx
,'tcx
>(
657 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
658 obligation
: &ProjectionTyObligation
<'tcx
>,
659 obligation_trait_ref
: &ty
::TraitRef
<'tcx
>,
660 candidate_set
: &mut ProjectionTyCandidateSet
<'tcx
>)
661 -> Result
<(), SelectionError
<'tcx
>>
663 // If we are resolving `<T as TraitRef<...>>::Item == Type`,
664 // start out by selecting the predicate `T as TraitRef<...>`:
665 let poly_trait_ref
= obligation_trait_ref
.to_poly_trait_ref();
666 let trait_obligation
= obligation
.with(poly_trait_ref
.to_poly_trait_predicate());
667 let vtable
= match selcx
.select(&trait_obligation
) {
668 Ok(Some(vtable
)) => vtable
,
670 candidate_set
.ambiguous
= true;
674 debug
!("assemble_candidates_from_impls: selection error {:?}",
681 super::VtableImpl(data
) => {
682 debug
!("assemble_candidates_from_impls: impl candidate {:?}",
685 candidate_set
.vec
.push(
686 ProjectionTyCandidate
::Impl(data
));
688 super::VtableObject(data
) => {
689 assemble_candidates_from_object_type(
690 selcx
, obligation
, obligation_trait_ref
, candidate_set
,
693 super::VtableClosure(data
) => {
694 candidate_set
.vec
.push(
695 ProjectionTyCandidate
::Closure(data
));
697 super::VtableFnPointer(fn_type
) => {
698 candidate_set
.vec
.push(
699 ProjectionTyCandidate
::FnPointer(fn_type
));
701 super::VtableParam(..) => {
702 // This case tell us nothing about the value of an
703 // associated type. Consider:
706 // trait SomeTrait { type Foo; }
707 // fn foo<T:SomeTrait>(...) { }
710 // If the user writes `<T as SomeTrait>::Foo`, then the `T
711 // : SomeTrait` binding does not help us decide what the
712 // type `Foo` is (at least, not more specifically than
713 // what we already knew).
715 // But wait, you say! What about an example like this:
718 // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
721 // Doesn't the `T : Sometrait<Foo=usize>` predicate help
722 // resolve `T::Foo`? And of course it does, but in fact
723 // that single predicate is desugared into two predicates
724 // in the compiler: a trait predicate (`T : SomeTrait`) and a
725 // projection. And the projection where clause is handled
726 // in `assemble_candidates_from_param_env`.
728 super::VtableDefaultImpl(..) |
729 super::VtableBuiltin(..) => {
730 // These traits have no associated types.
731 selcx
.tcx().sess
.span_bug(
732 obligation
.cause
.span
,
733 &format
!("Cannot project an associated type from `{:?}`",
741 fn confirm_candidate
<'cx
,'tcx
>(
742 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
743 obligation
: &ProjectionTyObligation
<'tcx
>,
744 candidate
: ProjectionTyCandidate
<'tcx
>)
745 -> (Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>)
747 debug
!("confirm_candidate(candidate={:?}, obligation={:?})",
752 ProjectionTyCandidate
::ParamEnv(poly_projection
) => {
753 confirm_param_env_candidate(selcx
, obligation
, poly_projection
)
756 ProjectionTyCandidate
::Impl(impl_vtable
) => {
757 confirm_impl_candidate(selcx
, obligation
, impl_vtable
)
760 ProjectionTyCandidate
::Closure(closure_vtable
) => {
761 confirm_closure_candidate(selcx
, obligation
, closure_vtable
)
764 ProjectionTyCandidate
::FnPointer(fn_type
) => {
765 confirm_fn_pointer_candidate(selcx
, obligation
, fn_type
)
770 fn confirm_fn_pointer_candidate
<'cx
,'tcx
>(
771 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
772 obligation
: &ProjectionTyObligation
<'tcx
>,
774 -> (Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>)
776 let fn_type
= selcx
.infcx().shallow_resolve(fn_type
);
777 let sig
= ty
::ty_fn_sig(fn_type
);
778 confirm_callable_candidate(selcx
, obligation
, sig
, util
::TupleArgumentsFlag
::Yes
)
781 fn confirm_closure_candidate
<'cx
,'tcx
>(
782 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
783 obligation
: &ProjectionTyObligation
<'tcx
>,
784 vtable
: VtableClosureData
<'tcx
, PredicateObligation
<'tcx
>>)
785 -> (Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>)
787 let closure_typer
= selcx
.closure_typer();
788 let closure_type
= closure_typer
.closure_type(vtable
.closure_def_id
, &vtable
.substs
);
792 } = normalize_with_depth(selcx
,
793 obligation
.cause
.clone(),
794 obligation
.recursion_depth
+1,
796 let (ty
, mut cc_obligations
) = confirm_callable_candidate(selcx
,
799 util
::TupleArgumentsFlag
::No
);
800 obligations
.append(&mut cc_obligations
);
804 fn confirm_callable_candidate
<'cx
,'tcx
>(
805 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
806 obligation
: &ProjectionTyObligation
<'tcx
>,
807 fn_sig
: &ty
::PolyFnSig
<'tcx
>,
808 flag
: util
::TupleArgumentsFlag
)
809 -> (Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>)
811 let tcx
= selcx
.tcx();
813 debug
!("confirm_callable_candidate({:?},{:?})",
817 // the `Output` associated type is declared on `FnOnce`
818 let fn_once_def_id
= tcx
.lang_items
.fn_once_trait().unwrap();
820 // Note: we unwrap the binder here but re-create it below (1)
821 let ty
::Binder((trait_ref
, ret_type
)) =
822 util
::closure_trait_ref_and_return_type(tcx
,
824 obligation
.predicate
.trait_ref
.self_ty(),
828 let predicate
= ty
::Binder(ty
::ProjectionPredicate
{ // (1) recreate binder here
829 projection_ty
: ty
::ProjectionTy
{
830 trait_ref
: trait_ref
,
831 item_name
: token
::intern(FN_OUTPUT_NAME
),
836 confirm_param_env_candidate(selcx
, obligation
, predicate
)
839 fn confirm_param_env_candidate
<'cx
,'tcx
>(
840 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
841 obligation
: &ProjectionTyObligation
<'tcx
>,
842 poly_projection
: ty
::PolyProjectionPredicate
<'tcx
>)
843 -> (Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>)
845 let infcx
= selcx
.infcx();
848 infcx
.replace_late_bound_regions_with_fresh_var(
849 obligation
.cause
.span
,
850 infer
::LateBoundRegionConversionTime
::HigherRankedType
,
853 assert_eq
!(projection
.projection_ty
.item_name
,
854 obligation
.predicate
.item_name
);
856 let origin
= infer
::RelateOutputImplTypes(obligation
.cause
.span
);
857 match infcx
.sub_trait_refs(false,
859 obligation
.predicate
.trait_ref
.clone(),
860 projection
.projection_ty
.trait_ref
.clone()) {
863 selcx
.tcx().sess
.span_bug(
864 obligation
.cause
.span
,
865 &format
!("Failed to unify `{:?}` and `{:?}` in projection: {}",
872 (projection
.ty
, vec
!())
875 fn confirm_impl_candidate
<'cx
,'tcx
>(
876 selcx
: &mut SelectionContext
<'cx
,'tcx
>,
877 obligation
: &ProjectionTyObligation
<'tcx
>,
878 impl_vtable
: VtableImplData
<'tcx
, PredicateObligation
<'tcx
>>)
879 -> (Ty
<'tcx
>, Vec
<PredicateObligation
<'tcx
>>)
881 // there don't seem to be nicer accessors to these:
882 let impl_or_trait_items_map
= selcx
.tcx().impl_or_trait_items
.borrow();
884 // Look for the associated type in the impl
885 for impl_item
in &selcx
.tcx().impl_items
.borrow()[&impl_vtable
.impl_def_id
] {
886 if let ty
::TypeTraitItem(ref assoc_ty
) = impl_or_trait_items_map
[&impl_item
.def_id()] {
887 if assoc_ty
.name
== obligation
.predicate
.item_name
{
888 return (assoc_ty
.ty
.unwrap().subst(selcx
.tcx(), &impl_vtable
.substs
),
894 // It is not in the impl - get the default from the trait.
895 let trait_ref
= obligation
.predicate
.trait_ref
;
896 for trait_item
in ty
::trait_items(selcx
.tcx(), trait_ref
.def_id
).iter() {
897 if let &ty
::TypeTraitItem(ref assoc_ty
) = trait_item
{
898 if assoc_ty
.name
== obligation
.predicate
.item_name
{
899 if let Some(ty
) = assoc_ty
.ty
{
900 return (ty
.subst(selcx
.tcx(), trait_ref
.substs
),
903 // This means that the impl is missing a
904 // definition for the associated type. This error
905 // ought to be reported by the type checker method
906 // `check_impl_items_against_trait`, so here we
907 // just return TyError.
908 return (selcx
.tcx().types
.err
, vec
!());
914 selcx
.tcx().sess
.span_bug(obligation
.cause
.span
,
915 &format
!("No associated type for {:?}",
919 impl<'tcx
, T
: TypeFoldable
<'tcx
>> TypeFoldable
<'tcx
> for Normalized
<'tcx
, T
> {
920 fn fold_with
<F
: TypeFolder
<'tcx
>>(&self, folder
: &mut F
) -> Normalized
<'tcx
, T
> {
922 value
: self.value
.fold_with(folder
),
923 obligations
: self.obligations
.fold_with(folder
),
928 impl<'tcx
, T
:fmt
::Debug
> fmt
::Debug
for Normalized
<'tcx
, T
> {
929 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
930 write
!(f
, "Normalized({:?},{:?})",