]> git.proxmox.com Git - rustc.git/blame - src/librustc/middle/traits/util.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc / middle / traits / util.rs
CommitLineData
1a4d82fc
JJ
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.
4//
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.
10
e9174d1e 11use middle::def_id::DefId;
1a4d82fc 12use middle::infer::InferCtxt;
e9174d1e 13use middle::subst::Substs;
c1a9b12d 14use middle::ty::{self, Ty, ToPredicate, ToPolyTraitRef};
1a4d82fc
JJ
15use syntax::codemap::Span;
16use util::common::ErrorReported;
85aaf69f 17use util::nodemap::FnvHashSet;
1a4d82fc 18
e9174d1e 19use super::{Obligation, ObligationCause, PredicateObligation};
1a4d82fc 20
85aaf69f
SL
21struct PredicateSet<'a,'tcx:'a> {
22 tcx: &'a ty::ctxt<'tcx>,
23 set: FnvHashSet<ty::Predicate<'tcx>>,
24}
25
26impl<'a,'tcx> PredicateSet<'a,'tcx> {
27 fn new(tcx: &'a ty::ctxt<'tcx>) -> PredicateSet<'a,'tcx> {
28 PredicateSet { tcx: tcx, set: FnvHashSet() }
29 }
30
31 fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
32 // We have to be careful here because we want
33 //
34 // for<'a> Foo<&'a int>
35 //
36 // and
37 //
38 // for<'b> Foo<&'b int>
39 //
40 // to be considered equivalent. So normalize all late-bound
41 // regions before we throw things into the underlying set.
42 let normalized_pred = match *pred {
43 ty::Predicate::Trait(ref data) =>
c1a9b12d 44 ty::Predicate::Trait(self.tcx.anonymize_late_bound_regions(data)),
85aaf69f
SL
45
46 ty::Predicate::Equate(ref data) =>
c1a9b12d 47 ty::Predicate::Equate(self.tcx.anonymize_late_bound_regions(data)),
85aaf69f
SL
48
49 ty::Predicate::RegionOutlives(ref data) =>
c1a9b12d 50 ty::Predicate::RegionOutlives(self.tcx.anonymize_late_bound_regions(data)),
85aaf69f
SL
51
52 ty::Predicate::TypeOutlives(ref data) =>
c1a9b12d 53 ty::Predicate::TypeOutlives(self.tcx.anonymize_late_bound_regions(data)),
85aaf69f
SL
54
55 ty::Predicate::Projection(ref data) =>
c1a9b12d 56 ty::Predicate::Projection(self.tcx.anonymize_late_bound_regions(data)),
e9174d1e
SL
57
58 ty::Predicate::WellFormed(data) =>
59 ty::Predicate::WellFormed(data),
60
61 ty::Predicate::ObjectSafe(data) =>
62 ty::Predicate::ObjectSafe(data),
85aaf69f
SL
63 };
64 self.set.insert(normalized_pred)
65 }
66}
67
1a4d82fc
JJ
68///////////////////////////////////////////////////////////////////////////
69// `Elaboration` iterator
70///////////////////////////////////////////////////////////////////////////
71
72/// "Elaboration" is the process of identifying all the predicates that
73/// are implied by a source predicate. Currently this basically means
74/// walking the "supertraits" and other similar assumptions. For
75/// example, if we know that `T : Ord`, the elaborator would deduce
76/// that `T : PartialOrd` holds as well. Similarly, if we have `trait
77/// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
78/// 'static`.
79pub struct Elaborator<'cx, 'tcx:'cx> {
80 tcx: &'cx ty::ctxt<'tcx>,
c34b1796 81 stack: Vec<ty::Predicate<'tcx>>,
85aaf69f 82 visited: PredicateSet<'cx,'tcx>,
1a4d82fc
JJ
83}
84
1a4d82fc
JJ
85pub fn elaborate_trait_ref<'cx, 'tcx>(
86 tcx: &'cx ty::ctxt<'tcx>,
87 trait_ref: ty::PolyTraitRef<'tcx>)
88 -> Elaborator<'cx, 'tcx>
89{
c1a9b12d 90 elaborate_predicates(tcx, vec![trait_ref.to_predicate()])
1a4d82fc
JJ
91}
92
93pub fn elaborate_trait_refs<'cx, 'tcx>(
94 tcx: &'cx ty::ctxt<'tcx>,
95 trait_refs: &[ty::PolyTraitRef<'tcx>])
96 -> Elaborator<'cx, 'tcx>
97{
98 let predicates = trait_refs.iter()
c1a9b12d 99 .map(|trait_ref| trait_ref.to_predicate())
1a4d82fc
JJ
100 .collect();
101 elaborate_predicates(tcx, predicates)
102}
103
104pub fn elaborate_predicates<'cx, 'tcx>(
105 tcx: &'cx ty::ctxt<'tcx>,
85aaf69f 106 mut predicates: Vec<ty::Predicate<'tcx>>)
1a4d82fc
JJ
107 -> Elaborator<'cx, 'tcx>
108{
85aaf69f
SL
109 let mut visited = PredicateSet::new(tcx);
110 predicates.retain(|pred| visited.insert(pred));
c34b1796 111 Elaborator { tcx: tcx, stack: predicates, visited: visited }
1a4d82fc
JJ
112}
113
114impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
c34b1796
AL
115 pub fn filter_to_traits(self) -> FilterToTraits<Elaborator<'cx, 'tcx>> {
116 FilterToTraits::new(self)
1a4d82fc
JJ
117 }
118
119 fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
120 match *predicate {
121 ty::Predicate::Trait(ref data) => {
c34b1796 122 // Predicates declared on the trait.
c1a9b12d 123 let predicates = self.tcx.lookup_super_predicates(data.def_id());
c34b1796
AL
124
125 let mut predicates: Vec<_> =
126 predicates.predicates
127 .iter()
128 .map(|p| p.subst_supertrait(self.tcx, &data.to_poly_trait_ref()))
129 .collect();
130
62682a34
SL
131 debug!("super_predicates: data={:?} predicates={:?}",
132 data, predicates);
1a4d82fc
JJ
133
134 // Only keep those bounds that we haven't already
135 // seen. This is necessary to prevent infinite
136 // recursion in some cases. One common case is when
137 // people define `trait Sized: Sized { }` rather than `trait
138 // Sized { }`.
85aaf69f 139 predicates.retain(|r| self.visited.insert(r));
1a4d82fc 140
62682a34 141 self.stack.extend(predicates);
1a4d82fc 142 }
e9174d1e
SL
143 ty::Predicate::WellFormed(..) => {
144 // Currently, we do not elaborate WF predicates,
145 // although we easily could.
146 }
147 ty::Predicate::ObjectSafe(..) => {
148 // Currently, we do not elaborate object-safe
149 // predicates.
150 }
1a4d82fc
JJ
151 ty::Predicate::Equate(..) => {
152 // Currently, we do not "elaborate" predicates like
153 // `X == Y`, though conceivably we might. For example,
154 // `&X == &Y` implies that `X == Y`.
155 }
156 ty::Predicate::Projection(..) => {
157 // Nothing to elaborate in a projection predicate.
158 }
159 ty::Predicate::RegionOutlives(..) |
160 ty::Predicate::TypeOutlives(..) => {
161 // Currently, we do not "elaborate" predicates like
162 // `'a : 'b` or `T : 'a`. We could conceivably do
163 // more here. For example,
164 //
165 // &'a int : 'b
166 //
167 // implies that
168 //
169 // 'a : 'b
170 //
171 // and we could get even more if we took WF
172 // constraints into account. For example,
173 //
174 // &'a &'b int : 'c
175 //
176 // implies that
177 //
178 // 'b : 'a
179 // 'a : 'c
180 }
181 }
182 }
183}
184
185impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> {
186 type Item = ty::Predicate<'tcx>;
187
188 fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
c34b1796
AL
189 // Extract next item from top-most stack frame, if any.
190 let next_predicate = match self.stack.pop() {
191 Some(predicate) => predicate,
192 None => {
193 // No more stack frames. Done.
194 return None;
1a4d82fc 195 }
c34b1796
AL
196 };
197 self.push(&next_predicate);
198 return Some(next_predicate);
1a4d82fc
JJ
199 }
200}
201
202///////////////////////////////////////////////////////////////////////////
203// Supertrait iterator
204///////////////////////////////////////////////////////////////////////////
205
c34b1796 206pub type Supertraits<'cx, 'tcx> = FilterToTraits<Elaborator<'cx, 'tcx>>;
1a4d82fc
JJ
207
208pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
209 trait_ref: ty::PolyTraitRef<'tcx>)
210 -> Supertraits<'cx, 'tcx>
211{
212 elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
213}
214
215pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
216 bounds: &[ty::PolyTraitRef<'tcx>])
217 -> Supertraits<'cx, 'tcx>
218{
219 elaborate_trait_refs(tcx, bounds).filter_to_traits()
220}
221
c34b1796
AL
222///////////////////////////////////////////////////////////////////////////
223// Iterator over def-ids of supertraits
224
225pub struct SupertraitDefIds<'cx, 'tcx:'cx> {
226 tcx: &'cx ty::ctxt<'tcx>,
e9174d1e
SL
227 stack: Vec<DefId>,
228 visited: FnvHashSet<DefId>,
c34b1796
AL
229}
230
231pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
e9174d1e 232 trait_def_id: DefId)
c34b1796
AL
233 -> SupertraitDefIds<'cx, 'tcx>
234{
235 SupertraitDefIds {
236 tcx: tcx,
237 stack: vec![trait_def_id],
238 visited: Some(trait_def_id).into_iter().collect(),
239 }
240}
241
242impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> {
e9174d1e 243 type Item = DefId;
c34b1796 244
e9174d1e 245 fn next(&mut self) -> Option<DefId> {
c34b1796
AL
246 let def_id = match self.stack.pop() {
247 Some(def_id) => def_id,
248 None => { return None; }
249 };
250
c1a9b12d 251 let predicates = self.tcx.lookup_super_predicates(def_id);
c34b1796
AL
252 let visited = &mut self.visited;
253 self.stack.extend(
254 predicates.predicates
255 .iter()
256 .filter_map(|p| p.to_opt_poly_trait_ref())
257 .map(|t| t.def_id())
258 .filter(|&super_def_id| visited.insert(super_def_id)));
259 Some(def_id)
260 }
261}
262
263///////////////////////////////////////////////////////////////////////////
264// Other
265///////////////////////////////////////////////////////////////////////////
266
267/// A filter around an iterator of predicates that makes it yield up
268/// just trait references.
269pub struct FilterToTraits<I> {
270 base_iterator: I
271}
272
273impl<I> FilterToTraits<I> {
274 fn new(base: I) -> FilterToTraits<I> {
275 FilterToTraits { base_iterator: base }
276 }
277}
278
279impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
1a4d82fc
JJ
280 type Item = ty::PolyTraitRef<'tcx>;
281
282 fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
283 loop {
c34b1796 284 match self.base_iterator.next() {
1a4d82fc
JJ
285 None => {
286 return None;
287 }
288 Some(ty::Predicate::Trait(data)) => {
289 return Some(data.to_poly_trait_ref());
290 }
291 Some(_) => {
292 }
293 }
294 }
295 }
296}
297
298///////////////////////////////////////////////////////////////////////////
299// Other
300///////////////////////////////////////////////////////////////////////////
301
302// determine the `self` type, using fresh variables for all variables
303// declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
304// would return ($0, $1) where $0 and $1 are freshly instantiated type
305// variables.
c34b1796
AL
306pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
307 span: Span,
e9174d1e 308 impl_def_id: DefId)
c34b1796 309 -> Substs<'tcx>
1a4d82fc
JJ
310{
311 let tcx = infcx.tcx;
c1a9b12d 312 let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
1a4d82fc
JJ
313 infcx.fresh_substs_for_generics(span, &impl_generics)
314}
315
1a4d82fc 316/// See `super::obligations_for_generics`
62682a34 317pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
c34b1796 318 recursion_depth: usize,
85aaf69f 319 generic_bounds: &ty::InstantiatedPredicates<'tcx>)
62682a34 320 -> Vec<PredicateObligation<'tcx>>
1a4d82fc 321{
62682a34
SL
322 debug!("predicates_for_generics(generic_bounds={:?})",
323 generic_bounds);
1a4d82fc 324
62682a34 325 generic_bounds.predicates.iter().map(|predicate| {
1a4d82fc
JJ
326 Obligation { cause: cause.clone(),
327 recursion_depth: recursion_depth,
328 predicate: predicate.clone() }
62682a34 329 }).collect()
1a4d82fc
JJ
330}
331
332pub fn trait_ref_for_builtin_bound<'tcx>(
333 tcx: &ty::ctxt<'tcx>,
334 builtin_bound: ty::BuiltinBound,
335 param_ty: Ty<'tcx>)
d9579d0f 336 -> Result<ty::TraitRef<'tcx>, ErrorReported>
1a4d82fc
JJ
337{
338 match tcx.lang_items.from_builtin_kind(builtin_bound) {
339 Ok(def_id) => {
d9579d0f 340 Ok(ty::TraitRef {
1a4d82fc
JJ
341 def_id: def_id,
342 substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
d9579d0f 343 })
1a4d82fc
JJ
344 }
345 Err(e) => {
85aaf69f 346 tcx.sess.err(&e);
1a4d82fc
JJ
347 Err(ErrorReported)
348 }
349 }
350}
351
c34b1796
AL
352
353pub fn predicate_for_trait_ref<'tcx>(
1a4d82fc 354 cause: ObligationCause<'tcx>,
d9579d0f 355 trait_ref: ty::TraitRef<'tcx>,
c34b1796 356 recursion_depth: usize)
d9579d0f 357 -> PredicateObligation<'tcx>
1a4d82fc 358{
d9579d0f 359 Obligation {
1a4d82fc
JJ
360 cause: cause,
361 recursion_depth: recursion_depth,
c1a9b12d 362 predicate: trait_ref.to_predicate(),
d9579d0f 363 }
1a4d82fc
JJ
364}
365
c34b1796
AL
366pub fn predicate_for_trait_def<'tcx>(
367 tcx: &ty::ctxt<'tcx>,
368 cause: ObligationCause<'tcx>,
e9174d1e 369 trait_def_id: DefId,
c34b1796 370 recursion_depth: usize,
d9579d0f
AL
371 param_ty: Ty<'tcx>,
372 ty_params: Vec<Ty<'tcx>>)
373 -> PredicateObligation<'tcx>
c34b1796 374{
d9579d0f 375 let trait_ref = ty::TraitRef {
c34b1796 376 def_id: trait_def_id,
d9579d0f
AL
377 substs: tcx.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
378 };
c34b1796
AL
379 predicate_for_trait_ref(cause, trait_ref, recursion_depth)
380}
381
382pub fn predicate_for_builtin_bound<'tcx>(
383 tcx: &ty::ctxt<'tcx>,
384 cause: ObligationCause<'tcx>,
385 builtin_bound: ty::BuiltinBound,
386 recursion_depth: usize,
387 param_ty: Ty<'tcx>)
388 -> Result<PredicateObligation<'tcx>, ErrorReported>
389{
390 let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
d9579d0f 391 Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth))
c34b1796
AL
392}
393
1a4d82fc
JJ
394/// Cast a trait reference into a reference to one of its super
395/// traits; returns `None` if `target_trait_def_id` is not a
396/// supertrait.
397pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
398 source_trait_ref: ty::PolyTraitRef<'tcx>,
e9174d1e 399 target_trait_def_id: DefId)
c34b1796 400 -> Vec<ty::PolyTraitRef<'tcx>>
1a4d82fc
JJ
401{
402 if source_trait_ref.def_id() == target_trait_def_id {
c34b1796 403 return vec![source_trait_ref]; // shorcut the most common case
1a4d82fc
JJ
404 }
405
c34b1796
AL
406 supertraits(tcx, source_trait_ref)
407 .filter(|r| r.def_id() == target_trait_def_id)
408 .collect()
1a4d82fc
JJ
409}
410
b039eaaf 411/// Given a trait `trait_ref`, returns the number of vtable entries
c1a9b12d
SL
412/// that come from `trait_ref`, excluding its supertraits. Used in
413/// computing the vtable base for an upcast trait of a trait object.
414pub fn count_own_vtable_entries<'tcx>(tcx: &ty::ctxt<'tcx>,
415 trait_ref: ty::PolyTraitRef<'tcx>)
416 -> usize {
417 let mut entries = 0;
418 // Count number of methods and add them to the total offset.
419 // Skip over associated types and constants.
420 for trait_item in &tcx.trait_items(trait_ref.def_id())[..] {
421 if let ty::MethodTraitItem(_) = *trait_item {
422 entries += 1;
1a4d82fc 423 }
85aaf69f 424 }
c1a9b12d
SL
425 entries
426}
85aaf69f 427
c1a9b12d
SL
428/// Given an upcast trait object described by `object`, returns the
429/// index of the method `method_def_id` (which should be part of
430/// `object.upcast_trait_ref`) within the vtable for `object`.
431pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
432 object: &super::VtableObjectData<'tcx>,
e9174d1e 433 method_def_id: DefId) -> usize {
c1a9b12d
SL
434 // Count number of methods preceding the one we are selecting and
435 // add them to the total offset.
436 // Skip over associated types and constants.
437 let mut entries = object.vtable_base;
438 for trait_item in &tcx.trait_items(object.upcast_trait_ref.def_id())[..] {
439 if trait_item.def_id() == method_def_id {
440 // The item with the ID we were given really ought to be a method.
441 assert!(match *trait_item {
442 ty::MethodTraitItem(_) => true,
443 _ => false
444 });
445
446 return entries;
447 }
448 if let ty::MethodTraitItem(_) = *trait_item {
449 entries += 1;
85aaf69f
SL
450 }
451 }
452
c1a9b12d
SL
453 tcx.sess.bug(&format!("get_vtable_index_of_object_method: {:?} was not found",
454 method_def_id));
85aaf69f
SL
455}
456
457pub enum TupleArgumentsFlag { Yes, No }
458
459pub fn closure_trait_ref_and_return_type<'tcx>(
460 tcx: &ty::ctxt<'tcx>,
e9174d1e 461 fn_trait_def_id: DefId,
85aaf69f
SL
462 self_ty: Ty<'tcx>,
463 sig: &ty::PolyFnSig<'tcx>,
464 tuple_arguments: TupleArgumentsFlag)
d9579d0f 465 -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)>
85aaf69f
SL
466{
467 let arguments_tuple = match tuple_arguments {
468 TupleArgumentsFlag::No => sig.0.inputs[0],
c1a9b12d 469 TupleArgumentsFlag::Yes => tcx.mk_tup(sig.0.inputs.to_vec()),
85aaf69f
SL
470 };
471 let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
d9579d0f 472 let trait_ref = ty::TraitRef {
85aaf69f
SL
473 def_id: fn_trait_def_id,
474 substs: tcx.mk_substs(trait_substs),
d9579d0f 475 };
c1a9b12d 476 ty::Binder((trait_ref, sig.0.output.unwrap_or(tcx.mk_nil())))
1a4d82fc 477}