1 // Copyright 2012-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 // This file contains various trait resolution methods used by trans.
12 // They all assume regions can be erased and monomorphic types. It
13 // seems likely that they should eventually be merged into more
16 use dep_graph
::{DepKind, DepTrackingMapConfig}
;
17 use infer
::TransNormalize
;
18 use std
::marker
::PhantomData
;
19 use syntax_pos
::DUMMY_SP
;
20 use traits
::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable}
;
21 use ty
::{self, Ty, TyCtxt}
;
22 use ty
::subst
::{Subst, Substs}
;
23 use ty
::fold
::{TypeFoldable, TypeFolder}
;
25 /// Attempts to resolve an obligation to a vtable.. The result is
26 /// a shallow vtable resolution -- meaning that we do not
27 /// (necessarily) resolve all nested obligations on the impl. Note
28 /// that type check should guarantee to us that all nested
29 /// obligations *could be* resolved if we wanted to.
30 /// Assumes that this is run after the entire crate has been successfully type-checked.
31 pub fn trans_fulfill_obligation
<'a
, 'tcx
>(ty
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
32 (param_env
, trait_ref
):
33 (ty
::ParamEnv
<'tcx
>, ty
::PolyTraitRef
<'tcx
>))
36 // Remove any references to regions; this helps improve caching.
37 let trait_ref
= ty
.erase_regions(&trait_ref
);
39 debug
!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
40 (param_env
, trait_ref
), trait_ref
.def_id());
42 // Do the initial selection for the obligation. This yields the
43 // shallow result we are looking for -- that is, what specific impl.
44 ty
.infer_ctxt().enter(|infcx
| {
45 let mut selcx
= SelectionContext
::new(&infcx
);
47 let obligation_cause
= ObligationCause
::dummy();
48 let obligation
= Obligation
::new(obligation_cause
,
50 trait_ref
.to_poly_trait_predicate());
52 let selection
= match selcx
.select(&obligation
) {
53 Ok(Some(selection
)) => selection
,
55 // Ambiguity can happen when monomorphizing during trans
56 // expands to some humongo type that never occurred
57 // statically -- this humongo type can then overflow,
58 // leading to an ambiguous result. So report this as an
59 // overflow bug, since I believe this is the only case
60 // where ambiguity can result.
61 bug
!("Encountered ambiguity selecting `{:?}` during trans, \
62 presuming due to overflow",
66 bug
!("Encountered error `{:?}` selecting `{:?}` during trans",
71 debug
!("fulfill_obligation: selection={:?}", selection
);
73 // Currently, we use a fulfillment context to completely resolve
74 // all nested obligations. This is because they can inform the
75 // inference of the impl's type parameters.
76 let mut fulfill_cx
= FulfillmentContext
::new();
77 let vtable
= selection
.map(|predicate
| {
78 debug
!("fulfill_obligation: register_predicate_obligation {:?}", predicate
);
79 fulfill_cx
.register_predicate_obligation(&infcx
, predicate
);
81 let vtable
= infcx
.drain_fulfillment_cx_or_panic(DUMMY_SP
, &mut fulfill_cx
, &vtable
);
83 info
!("Cache miss: {:?} => {:?}", trait_ref
, vtable
);
88 impl<'a
, 'tcx
> TyCtxt
<'a
, 'tcx
, 'tcx
> {
89 /// Monomorphizes a type from the AST by first applying the in-scope
90 /// substitutions and then normalizing any associated types.
91 pub fn trans_apply_param_substs
<T
>(self,
92 param_substs
: &Substs
<'tcx
>,
95 where T
: TransNormalize
<'tcx
>
97 debug
!("apply_param_substs(param_substs={:?}, value={:?})", param_substs
, value
);
98 let substituted
= value
.subst(self, param_substs
);
99 let substituted
= self.erase_regions(&substituted
);
100 AssociatedTypeNormalizer
::new(self).fold(&substituted
)
103 pub fn trans_apply_param_substs_env
<T
>(
105 param_substs
: &Substs
<'tcx
>,
106 param_env
: ty
::ParamEnv
<'tcx
>,
110 T
: TransNormalize
<'tcx
>,
113 "apply_param_substs_env(param_substs={:?}, value={:?}, param_env={:?})",
118 let substituted
= value
.subst(self, param_substs
);
119 let substituted
= self.erase_regions(&substituted
);
120 AssociatedTypeNormalizerEnv
::new(self, param_env
).fold(&substituted
)
124 struct AssociatedTypeNormalizer
<'a
, 'gcx
: 'a
> {
125 tcx
: TyCtxt
<'a
, 'gcx
, 'gcx
>,
128 impl<'a
, 'gcx
> AssociatedTypeNormalizer
<'a
, 'gcx
> {
129 fn new(tcx
: TyCtxt
<'a
, 'gcx
, 'gcx
>) -> Self {
130 AssociatedTypeNormalizer { tcx }
133 fn fold
<T
:TypeFoldable
<'gcx
>>(&mut self, value
: &T
) -> T
{
134 if !value
.has_projections() {
137 value
.fold_with(self)
142 impl<'a
, 'gcx
> TypeFolder
<'gcx
, 'gcx
> for AssociatedTypeNormalizer
<'a
, 'gcx
> {
143 fn tcx
<'c
>(&'c
self) -> TyCtxt
<'c
, 'gcx
, 'gcx
> {
147 fn fold_ty(&mut self, ty
: Ty
<'gcx
>) -> Ty
<'gcx
> {
148 if !ty
.has_projections() {
151 debug
!("AssociatedTypeNormalizer: ty={:?}", ty
);
152 self.tcx
.fully_normalize_monormophic_ty(ty
)
157 struct AssociatedTypeNormalizerEnv
<'a
, 'gcx
: 'a
> {
158 tcx
: TyCtxt
<'a
, 'gcx
, 'gcx
>,
159 param_env
: ty
::ParamEnv
<'gcx
>,
162 impl<'a
, 'gcx
> AssociatedTypeNormalizerEnv
<'a
, 'gcx
> {
163 fn new(tcx
: TyCtxt
<'a
, 'gcx
, 'gcx
>, param_env
: ty
::ParamEnv
<'gcx
>) -> Self {
164 Self { tcx, param_env }
167 fn fold
<T
: TypeFoldable
<'gcx
>>(&mut self, value
: &T
) -> T
{
168 if !value
.has_projections() {
171 value
.fold_with(self)
176 impl<'a
, 'gcx
> TypeFolder
<'gcx
, 'gcx
> for AssociatedTypeNormalizerEnv
<'a
, 'gcx
> {
177 fn tcx
<'c
>(&'c
self) -> TyCtxt
<'c
, 'gcx
, 'gcx
> {
181 fn fold_ty(&mut self, ty
: Ty
<'gcx
>) -> Ty
<'gcx
> {
182 if !ty
.has_projections() {
185 debug
!("AssociatedTypeNormalizerEnv: ty={:?}", ty
);
186 self.tcx
.normalize_associated_type_in_env(&ty
, self.param_env
)
191 // Implement DepTrackingMapConfig for `trait_cache`
192 pub struct TraitSelectionCache
<'tcx
> {
193 data
: PhantomData
<&'
tcx ()>
196 impl<'tcx
> DepTrackingMapConfig
for TraitSelectionCache
<'tcx
> {
197 type Key
= (ty
::ParamEnv
<'tcx
>, ty
::PolyTraitRef
<'tcx
>);
198 type Value
= Vtable
<'tcx
, ()>;
199 fn to_dep_kind() -> DepKind
{
206 pub struct ProjectionCache
<'gcx
> {
207 data
: PhantomData
<&'
gcx ()>
210 impl<'gcx
> DepTrackingMapConfig
for ProjectionCache
<'gcx
> {
212 type Value
= Ty
<'gcx
>;
213 fn to_dep_kind() -> DepKind
{