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 middle::subst::{Substs, VecPerParamSpace};
12 use middle::infer::InferCtxt;
13 use middle::ty::{self, Ty, AsPredicate, ToPolyTraitRef};
17 use syntax::codemap::Span;
18 use util::common::ErrorReported;
19 use util::nodemap::FnvHashSet;
20 use util::ppaux::Repr;
22 use super::{Obligation, ObligationCause, PredicateObligation,
23 VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData};
25 struct PredicateSet<'a,'tcx:'a> {
26 tcx: &'a ty::ctxt<'tcx>,
27 set: FnvHashSet<ty::Predicate<'tcx>>,
30 impl<'a,'tcx> PredicateSet<'a,'tcx> {
31 fn new(tcx: &'a ty::ctxt<'tcx>) -> PredicateSet<'a,'tcx> {
32 PredicateSet { tcx: tcx, set: FnvHashSet() }
35 fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
36 // We have to be careful here because we want
38 // for<'a> Foo<&'a int>
42 // for<'b> Foo<&'b int>
44 // to be considered equivalent. So normalize all late-bound
45 // regions before we throw things into the underlying set.
46 let normalized_pred = match *pred {
47 ty::Predicate::Trait(ref data) =>
48 ty::Predicate::Trait(ty::anonymize_late_bound_regions(self.tcx, data)),
50 ty::Predicate::Equate(ref data) =>
51 ty::Predicate::Equate(ty::anonymize_late_bound_regions(self.tcx, data)),
53 ty::Predicate::RegionOutlives(ref data) =>
54 ty::Predicate::RegionOutlives(ty::anonymize_late_bound_regions(self.tcx, data)),
56 ty::Predicate::TypeOutlives(ref data) =>
57 ty::Predicate::TypeOutlives(ty::anonymize_late_bound_regions(self.tcx, data)),
59 ty::Predicate::Projection(ref data) =>
60 ty::Predicate::Projection(ty::anonymize_late_bound_regions(self.tcx, data)),
62 self.set.insert(normalized_pred)
66 ///////////////////////////////////////////////////////////////////////////
67 // `Elaboration` iterator
68 ///////////////////////////////////////////////////////////////////////////
70 /// "Elaboration" is the process of identifying all the predicates that
71 /// are implied by a source predicate. Currently this basically means
72 /// walking the "supertraits" and other similar assumptions. For
73 /// example, if we know that `T : Ord`, the elaborator would deduce
74 /// that `T : PartialOrd` holds as well. Similarly, if we have `trait
75 /// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
77 pub struct Elaborator<'cx, 'tcx:'cx> {
78 tcx: &'cx ty::ctxt<'tcx>,
79 stack: Vec<ty::Predicate<'tcx>>,
80 visited: PredicateSet<'cx,'tcx>,
83 pub fn elaborate_trait_ref<'cx, 'tcx>(
84 tcx: &'cx ty::ctxt<'tcx>,
85 trait_ref: ty::PolyTraitRef<'tcx>)
86 -> Elaborator<'cx, 'tcx>
88 elaborate_predicates(tcx, vec![trait_ref.as_predicate()])
91 pub fn elaborate_trait_refs<'cx, 'tcx>(
92 tcx: &'cx ty::ctxt<'tcx>,
93 trait_refs: &[ty::PolyTraitRef<'tcx>])
94 -> Elaborator<'cx, 'tcx>
96 let predicates = trait_refs.iter()
97 .map(|trait_ref| trait_ref.as_predicate())
99 elaborate_predicates(tcx, predicates)
102 pub fn elaborate_predicates<'cx, 'tcx>(
103 tcx: &'cx ty::ctxt<'tcx>,
104 mut predicates: Vec<ty::Predicate<'tcx>>)
105 -> Elaborator<'cx, 'tcx>
107 let mut visited = PredicateSet::new(tcx);
108 predicates.retain(|pred| visited.insert(pred));
109 Elaborator { tcx: tcx, stack: predicates, visited: visited }
112 impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
113 pub fn filter_to_traits(self) -> FilterToTraits<Elaborator<'cx, 'tcx>> {
114 FilterToTraits::new(self)
117 fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
119 ty::Predicate::Trait(ref data) => {
120 // Predicates declared on the trait.
121 let predicates = ty::lookup_super_predicates(self.tcx, data.def_id());
123 let mut predicates: Vec<_> =
124 predicates.predicates
126 .map(|p| p.subst_supertrait(self.tcx, &data.to_poly_trait_ref()))
129 debug!("super_predicates: data={} predicates={}",
130 data.repr(self.tcx), predicates.repr(self.tcx));
132 // Only keep those bounds that we haven't already
133 // seen. This is necessary to prevent infinite
134 // recursion in some cases. One common case is when
135 // people define `trait Sized: Sized { }` rather than `trait
137 predicates.retain(|r| self.visited.insert(r));
139 self.stack.extend(predicates.into_iter());
141 ty::Predicate::Equate(..) => {
142 // Currently, we do not "elaborate" predicates like
143 // `X == Y`, though conceivably we might. For example,
144 // `&X == &Y` implies that `X == Y`.
146 ty::Predicate::Projection(..) => {
147 // Nothing to elaborate in a projection predicate.
149 ty::Predicate::RegionOutlives(..) |
150 ty::Predicate::TypeOutlives(..) => {
151 // Currently, we do not "elaborate" predicates like
152 // `'a : 'b` or `T : 'a`. We could conceivably do
153 // more here. For example,
161 // and we could get even more if we took WF
162 // constraints into account. For example,
175 impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> {
176 type Item = ty::Predicate<'tcx>;
178 fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
179 // Extract next item from top-most stack frame, if any.
180 let next_predicate = match self.stack.pop() {
181 Some(predicate) => predicate,
183 // No more stack frames. Done.
187 self.push(&next_predicate);
188 return Some(next_predicate);
192 ///////////////////////////////////////////////////////////////////////////
193 // Supertrait iterator
194 ///////////////////////////////////////////////////////////////////////////
196 pub type Supertraits<'cx, 'tcx> = FilterToTraits<Elaborator<'cx, 'tcx>>;
198 pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
199 trait_ref: ty::PolyTraitRef<'tcx>)
200 -> Supertraits<'cx, 'tcx>
202 elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
205 pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
206 bounds: &[ty::PolyTraitRef<'tcx>])
207 -> Supertraits<'cx, 'tcx>
209 elaborate_trait_refs(tcx, bounds).filter_to_traits()
212 ///////////////////////////////////////////////////////////////////////////
213 // Iterator over def-ids of supertraits
215 pub struct SupertraitDefIds<'cx, 'tcx:'cx> {
216 tcx: &'cx ty::ctxt<'tcx>,
217 stack: Vec<ast::DefId>,
218 visited: FnvHashSet<ast::DefId>,
221 pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
222 trait_def_id: ast::DefId)
223 -> SupertraitDefIds<'cx, 'tcx>
227 stack: vec![trait_def_id],
228 visited: Some(trait_def_id).into_iter().collect(),
232 impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> {
233 type Item = ast::DefId;
235 fn next(&mut self) -> Option<ast::DefId> {
236 let def_id = match self.stack.pop() {
237 Some(def_id) => def_id,
238 None => { return None; }
241 let predicates = ty::lookup_super_predicates(self.tcx, def_id);
242 let visited = &mut self.visited;
244 predicates.predicates
246 .filter_map(|p| p.to_opt_poly_trait_ref())
248 .filter(|&super_def_id| visited.insert(super_def_id)));
253 ///////////////////////////////////////////////////////////////////////////
255 ///////////////////////////////////////////////////////////////////////////
257 /// A filter around an iterator of predicates that makes it yield up
258 /// just trait references.
259 pub struct FilterToTraits<I> {
263 impl<I> FilterToTraits<I> {
264 fn new(base: I) -> FilterToTraits<I> {
265 FilterToTraits { base_iterator: base }
269 impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
270 type Item = ty::PolyTraitRef<'tcx>;
272 fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
274 match self.base_iterator.next() {
278 Some(ty::Predicate::Trait(data)) => {
279 return Some(data.to_poly_trait_ref());
288 ///////////////////////////////////////////////////////////////////////////
290 ///////////////////////////////////////////////////////////////////////////
292 // determine the `self` type, using fresh variables for all variables
293 // declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
294 // would return ($0, $1) where $0 and $1 are freshly instantiated type
296 pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
298 impl_def_id: ast::DefId)
302 let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
303 infcx.fresh_substs_for_generics(span, &impl_generics)
306 impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> {
307 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308 write!(f, "VtableImpl({:?})", self.impl_def_id)
312 impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> {
313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314 write!(f, "VtableObject(...)")
318 /// See `super::obligations_for_generics`
319 pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
320 cause: ObligationCause<'tcx>,
321 recursion_depth: usize,
322 generic_bounds: &ty::InstantiatedPredicates<'tcx>)
323 -> VecPerParamSpace<PredicateObligation<'tcx>>
325 debug!("predicates_for_generics(generic_bounds={})",
326 generic_bounds.repr(tcx));
328 generic_bounds.predicates.map(|predicate| {
329 Obligation { cause: cause.clone(),
330 recursion_depth: recursion_depth,
331 predicate: predicate.clone() }
335 pub fn trait_ref_for_builtin_bound<'tcx>(
336 tcx: &ty::ctxt<'tcx>,
337 builtin_bound: ty::BuiltinBound,
339 -> Result<Rc<ty::TraitRef<'tcx>>, ErrorReported>
341 match tcx.lang_items.from_builtin_kind(builtin_bound) {
343 Ok(Rc::new(ty::TraitRef {
345 substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
356 pub fn predicate_for_trait_ref<'tcx>(
357 cause: ObligationCause<'tcx>,
358 trait_ref: Rc<ty::TraitRef<'tcx>>,
359 recursion_depth: usize)
360 -> Result<PredicateObligation<'tcx>, ErrorReported>
364 recursion_depth: recursion_depth,
365 predicate: trait_ref.as_predicate(),
369 pub fn predicate_for_trait_def<'tcx>(
370 tcx: &ty::ctxt<'tcx>,
371 cause: ObligationCause<'tcx>,
372 trait_def_id: ast::DefId,
373 recursion_depth: usize,
375 -> Result<PredicateObligation<'tcx>, ErrorReported>
377 let trait_ref = Rc::new(ty::TraitRef {
378 def_id: trait_def_id,
379 substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
381 predicate_for_trait_ref(cause, trait_ref, recursion_depth)
384 pub fn predicate_for_builtin_bound<'tcx>(
385 tcx: &ty::ctxt<'tcx>,
386 cause: ObligationCause<'tcx>,
387 builtin_bound: ty::BuiltinBound,
388 recursion_depth: usize,
390 -> Result<PredicateObligation<'tcx>, ErrorReported>
392 let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
393 predicate_for_trait_ref(cause, trait_ref, recursion_depth)
396 /// Cast a trait reference into a reference to one of its super
397 /// traits; returns `None` if `target_trait_def_id` is not a
399 pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
400 source_trait_ref: ty::PolyTraitRef<'tcx>,
401 target_trait_def_id: ast::DefId)
402 -> Vec<ty::PolyTraitRef<'tcx>>
404 if source_trait_ref.def_id() == target_trait_def_id {
405 return vec![source_trait_ref]; // shorcut the most common case
408 supertraits(tcx, source_trait_ref)
409 .filter(|r| r.def_id() == target_trait_def_id)
413 /// Given an object of type `object_trait_ref`, returns the index of
414 /// the method `n_method` found in the trait `trait_def_id` (which
415 /// should be a supertrait of `object_trait_ref`) within the vtable
416 /// for `object_trait_ref`.
417 pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
418 object_trait_ref: ty::PolyTraitRef<'tcx>,
419 trait_def_id: ast::DefId,
420 method_offset_in_trait: usize) -> usize {
421 // We need to figure the "real index" of the method in a
422 // listing of all the methods of an object. We do this by
423 // iterating down the supertraits of the object's trait until
424 // we find the trait the method came from, counting up the
425 // methods from them.
426 let mut method_count = 0;
428 for bound_ref in transitive_bounds(tcx, &[object_trait_ref]) {
429 if bound_ref.def_id() == trait_def_id {
433 let trait_items = ty::trait_items(tcx, bound_ref.def_id());
434 for trait_item in &**trait_items {
436 ty::MethodTraitItem(_) => method_count += 1,
437 ty::TypeTraitItem(_) => {}
442 // count number of methods preceding the one we are selecting and
443 // add them to the total offset; skip over associated types.
444 let trait_items = ty::trait_items(tcx, trait_def_id);
445 for trait_item in trait_items.iter().take(method_offset_in_trait) {
447 ty::MethodTraitItem(_) => method_count += 1,
448 ty::TypeTraitItem(_) => {}
452 // the item at the offset we were given really ought to be a method
453 assert!(match trait_items[method_offset_in_trait] {
454 ty::MethodTraitItem(_) => true,
455 ty::TypeTraitItem(_) => false
461 pub enum TupleArgumentsFlag { Yes, No }
463 pub fn closure_trait_ref_and_return_type<'tcx>(
464 tcx: &ty::ctxt<'tcx>,
465 fn_trait_def_id: ast::DefId,
467 sig: &ty::PolyFnSig<'tcx>,
468 tuple_arguments: TupleArgumentsFlag)
469 -> ty::Binder<(Rc<ty::TraitRef<'tcx>>, Ty<'tcx>)>
471 let arguments_tuple = match tuple_arguments {
472 TupleArgumentsFlag::No => sig.0.inputs[0],
473 TupleArgumentsFlag::Yes => ty::mk_tup(tcx, sig.0.inputs.to_vec()),
475 let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
476 let trait_ref = Rc::new(ty::TraitRef {
477 def_id: fn_trait_def_id,
478 substs: tcx.mk_substs(trait_substs),
480 ty::Binder((trait_ref, sig.0.output.unwrap_or(ty::mk_nil(tcx))))
483 impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
484 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
485 format!("Obligation(predicate={},depth={})",
486 self.predicate.repr(tcx),
487 self.recursion_depth)
491 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
492 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
494 super::VtableImpl(ref v) =>
497 super::VtableDefaultImpl(ref t) =>
500 super::VtableClosure(ref d, ref s) =>
501 format!("VtableClosure({},{})",
505 super::VtableFnPointer(ref d) =>
506 format!("VtableFnPointer({})",
509 super::VtableObject(ref d) =>
510 format!("VtableObject({})",
513 super::VtableParam(ref n) =>
514 format!("VtableParam({})",
517 super::VtableBuiltin(ref d) =>
523 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableImplData<'tcx, N> {
524 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
525 format!("VtableImpl(impl_def_id={}, substs={}, nested={})",
526 self.impl_def_id.repr(tcx),
527 self.substs.repr(tcx),
528 self.nested.repr(tcx))
532 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
533 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
534 format!("VtableBuiltin(nested={})",
535 self.nested.repr(tcx))
539 impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData<N> {
540 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
541 format!("VtableDefaultImplData(trait_def_id={}, nested={})",
542 self.trait_def_id.repr(tcx),
543 self.nested.repr(tcx))
547 impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
548 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
549 format!("VtableObject(object_ty={})",
550 self.object_ty.repr(tcx))
554 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
555 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
557 super::Unimplemented =>
558 format!("Unimplemented"),
560 super::OutputTypeParameterMismatch(ref a, ref b, ref c) =>
561 format!("OutputTypeParameterMismatch({},{},{})",
569 impl<'tcx> Repr<'tcx> for super::FulfillmentError<'tcx> {
570 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
571 format!("FulfillmentError({},{})",
572 self.obligation.repr(tcx),
577 impl<'tcx> Repr<'tcx> for super::FulfillmentErrorCode<'tcx> {
578 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
580 super::CodeSelectionError(ref o) => o.repr(tcx),
581 super::CodeProjectionError(ref o) => o.repr(tcx),
582 super::CodeAmbiguity => format!("Ambiguity")
587 impl<'tcx> fmt::Debug for super::FulfillmentErrorCode<'tcx> {
588 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
590 super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
591 super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
592 super::CodeAmbiguity => write!(f, "Ambiguity")
597 impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> {
598 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
603 impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> {
604 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605 write!(f, "MismatchedProjectionTypes(..)")