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 use hir
::def_id
::DefId
;
12 use ty
::subst
::{Subst, Substs}
;
13 use ty
::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}
;
14 use util
::common
::ErrorReported
;
15 use util
::nodemap
::FnvHashSet
;
17 use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized}
;
19 fn anonymize_predicate
<'a
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
20 pred
: &ty
::Predicate
<'tcx
>)
21 -> ty
::Predicate
<'tcx
> {
23 ty
::Predicate
::Trait(ref data
) =>
24 ty
::Predicate
::Trait(tcx
.anonymize_late_bound_regions(data
)),
26 ty
::Predicate
::Equate(ref data
) =>
27 ty
::Predicate
::Equate(tcx
.anonymize_late_bound_regions(data
)),
29 ty
::Predicate
::RegionOutlives(ref data
) =>
30 ty
::Predicate
::RegionOutlives(tcx
.anonymize_late_bound_regions(data
)),
32 ty
::Predicate
::TypeOutlives(ref data
) =>
33 ty
::Predicate
::TypeOutlives(tcx
.anonymize_late_bound_regions(data
)),
35 ty
::Predicate
::Projection(ref data
) =>
36 ty
::Predicate
::Projection(tcx
.anonymize_late_bound_regions(data
)),
38 ty
::Predicate
::WellFormed(data
) =>
39 ty
::Predicate
::WellFormed(data
),
41 ty
::Predicate
::ObjectSafe(data
) =>
42 ty
::Predicate
::ObjectSafe(data
),
44 ty
::Predicate
::ClosureKind(closure_def_id
, kind
) =>
45 ty
::Predicate
::ClosureKind(closure_def_id
, kind
)
50 struct PredicateSet
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
51 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
52 set
: FnvHashSet
<ty
::Predicate
<'tcx
>>,
55 impl<'a
, 'gcx
, 'tcx
> PredicateSet
<'a
, 'gcx
, 'tcx
> {
56 fn new(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>) -> PredicateSet
<'a
, 'gcx
, 'tcx
> {
57 PredicateSet { tcx: tcx, set: FnvHashSet() }
60 fn insert(&mut self, pred
: &ty
::Predicate
<'tcx
>) -> bool
{
61 // We have to be careful here because we want
63 // for<'a> Foo<&'a int>
67 // for<'b> Foo<&'b int>
69 // to be considered equivalent. So normalize all late-bound
70 // regions before we throw things into the underlying set.
71 self.set
.insert(anonymize_predicate(self.tcx
, pred
))
75 ///////////////////////////////////////////////////////////////////////////
76 // `Elaboration` iterator
77 ///////////////////////////////////////////////////////////////////////////
79 /// "Elaboration" is the process of identifying all the predicates that
80 /// are implied by a source predicate. Currently this basically means
81 /// walking the "supertraits" and other similar assumptions. For
82 /// example, if we know that `T : Ord`, the elaborator would deduce
83 /// that `T : PartialOrd` holds as well. Similarly, if we have `trait
84 /// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
86 pub struct Elaborator
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
87 stack
: Vec
<ty
::Predicate
<'tcx
>>,
88 visited
: PredicateSet
<'a
, 'gcx
, 'tcx
>,
91 pub fn elaborate_trait_ref
<'cx
, 'gcx
, 'tcx
>(
92 tcx
: TyCtxt
<'cx
, 'gcx
, 'tcx
>,
93 trait_ref
: ty
::PolyTraitRef
<'tcx
>)
94 -> Elaborator
<'cx
, 'gcx
, 'tcx
>
96 elaborate_predicates(tcx
, vec
![trait_ref
.to_predicate()])
99 pub fn elaborate_trait_refs
<'cx
, 'gcx
, 'tcx
>(
100 tcx
: TyCtxt
<'cx
, 'gcx
, 'tcx
>,
101 trait_refs
: &[ty
::PolyTraitRef
<'tcx
>])
102 -> Elaborator
<'cx
, 'gcx
, 'tcx
>
104 let predicates
= trait_refs
.iter()
105 .map(|trait_ref
| trait_ref
.to_predicate())
107 elaborate_predicates(tcx
, predicates
)
110 pub fn elaborate_predicates
<'cx
, 'gcx
, 'tcx
>(
111 tcx
: TyCtxt
<'cx
, 'gcx
, 'tcx
>,
112 mut predicates
: Vec
<ty
::Predicate
<'tcx
>>)
113 -> Elaborator
<'cx
, 'gcx
, 'tcx
>
115 let mut visited
= PredicateSet
::new(tcx
);
116 predicates
.retain(|pred
| visited
.insert(pred
));
117 Elaborator { stack: predicates, visited: visited }
120 impl<'cx
, 'gcx
, 'tcx
> Elaborator
<'cx
, 'gcx
, 'tcx
> {
121 pub fn filter_to_traits(self) -> FilterToTraits
<Self> {
122 FilterToTraits
::new(self)
125 fn push(&mut self, predicate
: &ty
::Predicate
<'tcx
>) {
126 let tcx
= self.visited
.tcx
;
128 ty
::Predicate
::Trait(ref data
) => {
129 // Predicates declared on the trait.
130 let predicates
= tcx
.lookup_super_predicates(data
.def_id());
132 let mut predicates
: Vec
<_
> =
133 predicates
.predicates
135 .map(|p
| p
.subst_supertrait(tcx
, &data
.to_poly_trait_ref()))
138 debug
!("super_predicates: data={:?} predicates={:?}",
141 // Only keep those bounds that we haven't already
142 // seen. This is necessary to prevent infinite
143 // recursion in some cases. One common case is when
144 // people define `trait Sized: Sized { }` rather than `trait
146 predicates
.retain(|r
| self.visited
.insert(r
));
148 self.stack
.extend(predicates
);
150 ty
::Predicate
::WellFormed(..) => {
151 // Currently, we do not elaborate WF predicates,
152 // although we easily could.
154 ty
::Predicate
::ObjectSafe(..) => {
155 // Currently, we do not elaborate object-safe
158 ty
::Predicate
::Equate(..) => {
159 // Currently, we do not "elaborate" predicates like
160 // `X == Y`, though conceivably we might. For example,
161 // `&X == &Y` implies that `X == Y`.
163 ty
::Predicate
::Projection(..) => {
164 // Nothing to elaborate in a projection predicate.
166 ty
::Predicate
::ClosureKind(..) => {
167 // Nothing to elaborate when waiting for a closure's kind to be inferred.
169 ty
::Predicate
::RegionOutlives(..) |
170 ty
::Predicate
::TypeOutlives(..) => {
171 // Currently, we do not "elaborate" predicates like
172 // `'a : 'b` or `T : 'a`. We could conceivably do
173 // more here. For example,
181 // and we could get even more if we took WF
182 // constraints into account. For example,
195 impl<'cx
, 'gcx
, 'tcx
> Iterator
for Elaborator
<'cx
, 'gcx
, 'tcx
> {
196 type Item
= ty
::Predicate
<'tcx
>;
198 fn next(&mut self) -> Option
<ty
::Predicate
<'tcx
>> {
199 // Extract next item from top-most stack frame, if any.
200 let next_predicate
= match self.stack
.pop() {
201 Some(predicate
) => predicate
,
203 // No more stack frames. Done.
207 self.push(&next_predicate
);
208 return Some(next_predicate
);
212 ///////////////////////////////////////////////////////////////////////////
213 // Supertrait iterator
214 ///////////////////////////////////////////////////////////////////////////
216 pub type Supertraits
<'cx
, 'gcx
, 'tcx
> = FilterToTraits
<Elaborator
<'cx
, 'gcx
, 'tcx
>>;
218 pub fn supertraits
<'cx
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'cx
, 'gcx
, 'tcx
>,
219 trait_ref
: ty
::PolyTraitRef
<'tcx
>)
220 -> Supertraits
<'cx
, 'gcx
, 'tcx
>
222 elaborate_trait_ref(tcx
, trait_ref
).filter_to_traits()
225 pub fn transitive_bounds
<'cx
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'cx
, 'gcx
, 'tcx
>,
226 bounds
: &[ty
::PolyTraitRef
<'tcx
>])
227 -> Supertraits
<'cx
, 'gcx
, 'tcx
>
229 elaborate_trait_refs(tcx
, bounds
).filter_to_traits()
232 ///////////////////////////////////////////////////////////////////////////
233 // Iterator over def-ids of supertraits
235 pub struct SupertraitDefIds
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
236 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
238 visited
: FnvHashSet
<DefId
>,
241 pub fn supertrait_def_ids
<'cx
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'cx
, 'gcx
, 'tcx
>,
243 -> SupertraitDefIds
<'cx
, 'gcx
, 'tcx
>
247 stack
: vec
![trait_def_id
],
248 visited
: Some(trait_def_id
).into_iter().collect(),
252 impl<'cx
, 'gcx
, 'tcx
> Iterator
for SupertraitDefIds
<'cx
, 'gcx
, 'tcx
> {
255 fn next(&mut self) -> Option
<DefId
> {
256 let def_id
= match self.stack
.pop() {
257 Some(def_id
) => def_id
,
258 None
=> { return None; }
261 let predicates
= self.tcx
.lookup_super_predicates(def_id
);
262 let visited
= &mut self.visited
;
264 predicates
.predicates
266 .filter_map(|p
| p
.to_opt_poly_trait_ref())
268 .filter(|&super_def_id
| visited
.insert(super_def_id
)));
273 ///////////////////////////////////////////////////////////////////////////
275 ///////////////////////////////////////////////////////////////////////////
277 /// A filter around an iterator of predicates that makes it yield up
278 /// just trait references.
279 pub struct FilterToTraits
<I
> {
283 impl<I
> FilterToTraits
<I
> {
284 fn new(base
: I
) -> FilterToTraits
<I
> {
285 FilterToTraits { base_iterator: base }
289 impl<'tcx
,I
:Iterator
<Item
=ty
::Predicate
<'tcx
>>> Iterator
for FilterToTraits
<I
> {
290 type Item
= ty
::PolyTraitRef
<'tcx
>;
292 fn next(&mut self) -> Option
<ty
::PolyTraitRef
<'tcx
>> {
294 match self.base_iterator
.next() {
298 Some(ty
::Predicate
::Trait(data
)) => {
299 return Some(data
.to_poly_trait_ref());
308 ///////////////////////////////////////////////////////////////////////////
310 ///////////////////////////////////////////////////////////////////////////
312 /// Instantiate all bound parameters of the impl with the given substs,
313 /// returning the resulting trait ref and all obligations that arise.
314 /// The obligations are closed under normalization.
315 pub fn impl_trait_ref_and_oblig
<'a
, 'gcx
, 'tcx
>(selcx
: &mut SelectionContext
<'a
, 'gcx
, 'tcx
>,
317 impl_substs
: &Substs
<'tcx
>)
318 -> (ty
::TraitRef
<'tcx
>,
319 Vec
<PredicateObligation
<'tcx
>>)
322 selcx
.tcx().impl_trait_ref(impl_def_id
).unwrap();
324 impl_trait_ref
.subst(selcx
.tcx(), impl_substs
);
325 let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 }
=
326 super::normalize(selcx
, ObligationCause
::dummy(), &impl_trait_ref
);
328 let predicates
= selcx
.tcx().lookup_predicates(impl_def_id
);
329 let predicates
= predicates
.instantiate(selcx
.tcx(), impl_substs
);
330 let Normalized { value: predicates, obligations: normalization_obligations2 }
=
331 super::normalize(selcx
, ObligationCause
::dummy(), &predicates
);
332 let impl_obligations
=
333 predicates_for_generics(ObligationCause
::dummy(), 0, &predicates
);
335 let impl_obligations
: Vec
<_
> =
336 impl_obligations
.into_iter()
337 .chain(normalization_obligations1
)
338 .chain(normalization_obligations2
)
341 (impl_trait_ref
, impl_obligations
)
344 /// See `super::obligations_for_generics`
345 pub fn predicates_for_generics
<'tcx
>(cause
: ObligationCause
<'tcx
>,
346 recursion_depth
: usize,
347 generic_bounds
: &ty
::InstantiatedPredicates
<'tcx
>)
348 -> Vec
<PredicateObligation
<'tcx
>>
350 debug
!("predicates_for_generics(generic_bounds={:?})",
353 generic_bounds
.predicates
.iter().map(|predicate
| {
354 Obligation
{ cause
: cause
.clone(),
355 recursion_depth
: recursion_depth
,
356 predicate
: predicate
.clone() }
360 pub fn predicate_for_trait_ref
<'tcx
>(
361 cause
: ObligationCause
<'tcx
>,
362 trait_ref
: ty
::TraitRef
<'tcx
>,
363 recursion_depth
: usize)
364 -> PredicateObligation
<'tcx
>
368 recursion_depth
: recursion_depth
,
369 predicate
: trait_ref
.to_predicate(),
373 impl<'a
, 'gcx
, 'tcx
> TyCtxt
<'a
, 'gcx
, 'tcx
> {
374 pub fn trait_ref_for_builtin_bound(self,
375 builtin_bound
: ty
::BuiltinBound
,
377 -> Result
<ty
::TraitRef
<'tcx
>, ErrorReported
>
379 match self.lang_items
.from_builtin_kind(builtin_bound
) {
383 substs
: Substs
::new_trait(self, param_ty
, &[])
393 pub fn predicate_for_trait_def(self,
394 cause
: ObligationCause
<'tcx
>,
396 recursion_depth
: usize,
398 ty_params
: &[Ty
<'tcx
>])
399 -> PredicateObligation
<'tcx
>
401 let trait_ref
= ty
::TraitRef
{
402 def_id
: trait_def_id
,
403 substs
: Substs
::new_trait(self, param_ty
, ty_params
)
405 predicate_for_trait_ref(cause
, trait_ref
, recursion_depth
)
408 pub fn predicate_for_builtin_bound(self,
409 cause
: ObligationCause
<'tcx
>,
410 builtin_bound
: ty
::BuiltinBound
,
411 recursion_depth
: usize,
413 -> Result
<PredicateObligation
<'tcx
>, ErrorReported
>
415 let trait_ref
= self.trait_ref_for_builtin_bound(builtin_bound
, param_ty
)?
;
416 Ok(predicate_for_trait_ref(cause
, trait_ref
, recursion_depth
))
419 /// Cast a trait reference into a reference to one of its super
420 /// traits; returns `None` if `target_trait_def_id` is not a
422 pub fn upcast_choices(self,
423 source_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
424 target_trait_def_id
: DefId
)
425 -> Vec
<ty
::PolyTraitRef
<'tcx
>>
427 if source_trait_ref
.def_id() == target_trait_def_id
{
428 return vec
![source_trait_ref
]; // shorcut the most common case
431 supertraits(self, source_trait_ref
)
432 .filter(|r
| r
.def_id() == target_trait_def_id
)
436 /// Given a trait `trait_ref`, returns the number of vtable entries
437 /// that come from `trait_ref`, excluding its supertraits. Used in
438 /// computing the vtable base for an upcast trait of a trait object.
439 pub fn count_own_vtable_entries(self, trait_ref
: ty
::PolyTraitRef
<'tcx
>) -> usize {
441 // Count number of methods and add them to the total offset.
442 // Skip over associated types and constants.
443 for trait_item
in &self.trait_items(trait_ref
.def_id())[..] {
444 if let ty
::MethodTraitItem(_
) = *trait_item
{
451 /// Given an upcast trait object described by `object`, returns the
452 /// index of the method `method_def_id` (which should be part of
453 /// `object.upcast_trait_ref`) within the vtable for `object`.
454 pub fn get_vtable_index_of_object_method
<N
>(self,
455 object
: &super::VtableObjectData
<'tcx
, N
>,
456 method_def_id
: DefId
) -> usize {
457 // Count number of methods preceding the one we are selecting and
458 // add them to the total offset.
459 // Skip over associated types and constants.
460 let mut entries
= object
.vtable_base
;
461 for trait_item
in &self.trait_items(object
.upcast_trait_ref
.def_id())[..] {
462 if trait_item
.def_id() == method_def_id
{
463 // The item with the ID we were given really ought to be a method.
464 assert
!(match *trait_item
{
465 ty
::MethodTraitItem(_
) => true,
471 if let ty
::MethodTraitItem(_
) = *trait_item
{
476 bug
!("get_vtable_index_of_object_method: {:?} was not found",
480 pub fn closure_trait_ref_and_return_type(self,
481 fn_trait_def_id
: DefId
,
483 sig
: &ty
::PolyFnSig
<'tcx
>,
484 tuple_arguments
: TupleArgumentsFlag
)
485 -> ty
::Binder
<(ty
::TraitRef
<'tcx
>, Ty
<'tcx
>)>
487 let arguments_tuple
= match tuple_arguments
{
488 TupleArgumentsFlag
::No
=> sig
.0.inputs
[0],
489 TupleArgumentsFlag
::Yes
=> self.mk_tup(sig
.0.inputs
.to_vec()),
491 let trait_ref
= ty
::TraitRef
{
492 def_id
: fn_trait_def_id
,
493 substs
: Substs
::new_trait(self, self_ty
, &[arguments_tuple
]),
495 ty
::Binder((trait_ref
, sig
.0.output
))
499 pub enum TupleArgumentsFlag { Yes, No }