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