]> git.proxmox.com Git - rustc.git/blame - src/librustc/traits/util.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc / 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
54a0048b
SL
11use hir::def_id::DefId;
12use infer::InferCtxt;
13use ty::subst::{Subst, Substs};
14use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
1a4d82fc
JJ
15use syntax::codemap::Span;
16use util::common::ErrorReported;
85aaf69f 17use util::nodemap::FnvHashSet;
1a4d82fc 18
54a0048b 19use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
1a4d82fc 20
85aaf69f 21struct PredicateSet<'a,'tcx:'a> {
54a0048b 22 tcx: &'a TyCtxt<'tcx>,
85aaf69f
SL
23 set: FnvHashSet<ty::Predicate<'tcx>>,
24}
25
26impl<'a,'tcx> PredicateSet<'a,'tcx> {
54a0048b 27 fn new(tcx: &'a TyCtxt<'tcx>) -> PredicateSet<'a,'tcx> {
85aaf69f
SL
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> {
54a0048b 80 tcx: &'cx TyCtxt<'tcx>,
c34b1796 81 stack: Vec<ty::Predicate<'tcx>>,
85aaf69f 82 visited: PredicateSet<'cx,'tcx>,
1a4d82fc
JJ
83}
84
1a4d82fc 85pub fn elaborate_trait_ref<'cx, 'tcx>(
54a0048b 86 tcx: &'cx TyCtxt<'tcx>,
1a4d82fc
JJ
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>(
54a0048b 94 tcx: &'cx TyCtxt<'tcx>,
1a4d82fc
JJ
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>(
54a0048b 105 tcx: &'cx TyCtxt<'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 207
54a0048b 208pub fn supertraits<'cx, 'tcx>(tcx: &'cx TyCtxt<'tcx>,
1a4d82fc
JJ
209 trait_ref: ty::PolyTraitRef<'tcx>)
210 -> Supertraits<'cx, 'tcx>
211{
212 elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
213}
214
54a0048b 215pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx TyCtxt<'tcx>,
1a4d82fc
JJ
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> {
54a0048b 226 tcx: &'cx TyCtxt<'tcx>,
e9174d1e
SL
227 stack: Vec<DefId>,
228 visited: FnvHashSet<DefId>,
c34b1796
AL
229}
230
54a0048b 231pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx TyCtxt<'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
54a0048b
SL
302/// Instantiate all bound parameters of the impl with the given substs,
303/// returning the resulting trait ref and all obligations that arise.
304/// The obligations are closed under normalization.
305pub fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
306 impl_def_id: DefId,
307 impl_substs: &Substs<'tcx>)
308 -> (ty::TraitRef<'tcx>,
309 Vec<PredicateObligation<'tcx>>)
310{
311 let impl_trait_ref =
312 selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
313 let impl_trait_ref =
314 impl_trait_ref.subst(selcx.tcx(), impl_substs);
315 let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
316 super::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref);
317
318 let predicates = selcx.tcx().lookup_predicates(impl_def_id);
319 let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
320 let Normalized { value: predicates, obligations: normalization_obligations2 } =
321 super::normalize(selcx, ObligationCause::dummy(), &predicates);
322 let impl_obligations =
323 predicates_for_generics(ObligationCause::dummy(), 0, &predicates);
324
325 let impl_obligations: Vec<_> =
326 impl_obligations.into_iter()
327 .chain(normalization_obligations1)
328 .chain(normalization_obligations2)
329 .collect();
330
331 (impl_trait_ref, impl_obligations)
332}
333
1a4d82fc
JJ
334// determine the `self` type, using fresh variables for all variables
335// declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
336// would return ($0, $1) where $0 and $1 are freshly instantiated type
337// variables.
c34b1796
AL
338pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
339 span: Span,
e9174d1e 340 impl_def_id: DefId)
c34b1796 341 -> Substs<'tcx>
1a4d82fc
JJ
342{
343 let tcx = infcx.tcx;
c1a9b12d 344 let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
1a4d82fc
JJ
345 infcx.fresh_substs_for_generics(span, &impl_generics)
346}
347
1a4d82fc 348/// See `super::obligations_for_generics`
62682a34 349pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
c34b1796 350 recursion_depth: usize,
85aaf69f 351 generic_bounds: &ty::InstantiatedPredicates<'tcx>)
62682a34 352 -> Vec<PredicateObligation<'tcx>>
1a4d82fc 353{
62682a34
SL
354 debug!("predicates_for_generics(generic_bounds={:?})",
355 generic_bounds);
1a4d82fc 356
62682a34 357 generic_bounds.predicates.iter().map(|predicate| {
1a4d82fc
JJ
358 Obligation { cause: cause.clone(),
359 recursion_depth: recursion_depth,
360 predicate: predicate.clone() }
62682a34 361 }).collect()
1a4d82fc
JJ
362}
363
364pub fn trait_ref_for_builtin_bound<'tcx>(
54a0048b 365 tcx: &TyCtxt<'tcx>,
1a4d82fc
JJ
366 builtin_bound: ty::BuiltinBound,
367 param_ty: Ty<'tcx>)
d9579d0f 368 -> Result<ty::TraitRef<'tcx>, ErrorReported>
1a4d82fc
JJ
369{
370 match tcx.lang_items.from_builtin_kind(builtin_bound) {
371 Ok(def_id) => {
d9579d0f 372 Ok(ty::TraitRef {
1a4d82fc
JJ
373 def_id: def_id,
374 substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
d9579d0f 375 })
1a4d82fc
JJ
376 }
377 Err(e) => {
85aaf69f 378 tcx.sess.err(&e);
1a4d82fc
JJ
379 Err(ErrorReported)
380 }
381 }
382}
383
c34b1796 384pub fn predicate_for_trait_ref<'tcx>(
1a4d82fc 385 cause: ObligationCause<'tcx>,
d9579d0f 386 trait_ref: ty::TraitRef<'tcx>,
c34b1796 387 recursion_depth: usize)
d9579d0f 388 -> PredicateObligation<'tcx>
1a4d82fc 389{
d9579d0f 390 Obligation {
1a4d82fc
JJ
391 cause: cause,
392 recursion_depth: recursion_depth,
c1a9b12d 393 predicate: trait_ref.to_predicate(),
d9579d0f 394 }
1a4d82fc
JJ
395}
396
c34b1796 397pub fn predicate_for_trait_def<'tcx>(
54a0048b 398 tcx: &TyCtxt<'tcx>,
c34b1796 399 cause: ObligationCause<'tcx>,
e9174d1e 400 trait_def_id: DefId,
c34b1796 401 recursion_depth: usize,
d9579d0f
AL
402 param_ty: Ty<'tcx>,
403 ty_params: Vec<Ty<'tcx>>)
404 -> PredicateObligation<'tcx>
c34b1796 405{
d9579d0f 406 let trait_ref = ty::TraitRef {
c34b1796 407 def_id: trait_def_id,
d9579d0f
AL
408 substs: tcx.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
409 };
c34b1796
AL
410 predicate_for_trait_ref(cause, trait_ref, recursion_depth)
411}
412
413pub fn predicate_for_builtin_bound<'tcx>(
54a0048b 414 tcx: &TyCtxt<'tcx>,
c34b1796
AL
415 cause: ObligationCause<'tcx>,
416 builtin_bound: ty::BuiltinBound,
417 recursion_depth: usize,
418 param_ty: Ty<'tcx>)
419 -> Result<PredicateObligation<'tcx>, ErrorReported>
420{
54a0048b 421 let trait_ref = trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)?;
d9579d0f 422 Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth))
c34b1796
AL
423}
424
1a4d82fc
JJ
425/// Cast a trait reference into a reference to one of its super
426/// traits; returns `None` if `target_trait_def_id` is not a
427/// supertrait.
54a0048b 428pub fn upcast<'tcx>(tcx: &TyCtxt<'tcx>,
1a4d82fc 429 source_trait_ref: ty::PolyTraitRef<'tcx>,
e9174d1e 430 target_trait_def_id: DefId)
c34b1796 431 -> Vec<ty::PolyTraitRef<'tcx>>
1a4d82fc
JJ
432{
433 if source_trait_ref.def_id() == target_trait_def_id {
c34b1796 434 return vec![source_trait_ref]; // shorcut the most common case
1a4d82fc
JJ
435 }
436
c34b1796
AL
437 supertraits(tcx, source_trait_ref)
438 .filter(|r| r.def_id() == target_trait_def_id)
439 .collect()
1a4d82fc
JJ
440}
441
b039eaaf 442/// Given a trait `trait_ref`, returns the number of vtable entries
c1a9b12d
SL
443/// that come from `trait_ref`, excluding its supertraits. Used in
444/// computing the vtable base for an upcast trait of a trait object.
54a0048b 445pub fn count_own_vtable_entries<'tcx>(tcx: &TyCtxt<'tcx>,
c1a9b12d
SL
446 trait_ref: ty::PolyTraitRef<'tcx>)
447 -> usize {
448 let mut entries = 0;
449 // Count number of methods and add them to the total offset.
450 // Skip over associated types and constants.
451 for trait_item in &tcx.trait_items(trait_ref.def_id())[..] {
452 if let ty::MethodTraitItem(_) = *trait_item {
453 entries += 1;
1a4d82fc 454 }
85aaf69f 455 }
c1a9b12d
SL
456 entries
457}
85aaf69f 458
c1a9b12d
SL
459/// Given an upcast trait object described by `object`, returns the
460/// index of the method `method_def_id` (which should be part of
461/// `object.upcast_trait_ref`) within the vtable for `object`.
54a0048b 462pub fn get_vtable_index_of_object_method<'tcx>(tcx: &TyCtxt<'tcx>,
c1a9b12d 463 object: &super::VtableObjectData<'tcx>,
e9174d1e 464 method_def_id: DefId) -> usize {
c1a9b12d
SL
465 // Count number of methods preceding the one we are selecting and
466 // add them to the total offset.
467 // Skip over associated types and constants.
468 let mut entries = object.vtable_base;
469 for trait_item in &tcx.trait_items(object.upcast_trait_ref.def_id())[..] {
470 if trait_item.def_id() == method_def_id {
471 // The item with the ID we were given really ought to be a method.
472 assert!(match *trait_item {
473 ty::MethodTraitItem(_) => true,
474 _ => false
475 });
476
477 return entries;
478 }
479 if let ty::MethodTraitItem(_) = *trait_item {
480 entries += 1;
85aaf69f
SL
481 }
482 }
483
54a0048b
SL
484 bug!("get_vtable_index_of_object_method: {:?} was not found",
485 method_def_id);
85aaf69f
SL
486}
487
488pub enum TupleArgumentsFlag { Yes, No }
489
490pub fn closure_trait_ref_and_return_type<'tcx>(
54a0048b 491 tcx: &TyCtxt<'tcx>,
e9174d1e 492 fn_trait_def_id: DefId,
85aaf69f
SL
493 self_ty: Ty<'tcx>,
494 sig: &ty::PolyFnSig<'tcx>,
495 tuple_arguments: TupleArgumentsFlag)
d9579d0f 496 -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)>
85aaf69f
SL
497{
498 let arguments_tuple = match tuple_arguments {
499 TupleArgumentsFlag::No => sig.0.inputs[0],
c1a9b12d 500 TupleArgumentsFlag::Yes => tcx.mk_tup(sig.0.inputs.to_vec()),
85aaf69f
SL
501 };
502 let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
d9579d0f 503 let trait_ref = ty::TraitRef {
85aaf69f
SL
504 def_id: fn_trait_def_id,
505 substs: tcx.mk_substs(trait_substs),
d9579d0f 506 };
c1a9b12d 507 ty::Binder((trait_ref, sig.0.output.unwrap_or(tcx.mk_nil())))
1a4d82fc 508}