1 // Copyright 2012-2015 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 traits::specialization_graph;
14 use ty::fold::TypeFoldable;
19 /// A trait's definition with type information.
23 pub unsafety: hir::Unsafety,
25 /// If `true`, then this trait had the `#[rustc_paren_sugar]`
26 /// attribute, indicating that it should be used with `Foo()`
27 /// sugar. This is a temporary thing -- eventually any trait will
28 /// be usable with the sugar (or without it).
29 pub paren_sugar: bool,
31 pub has_default_impl: bool,
33 /// The ICH of this trait's DefPath, cached here so it doesn't have to be
34 /// recomputed all the time.
35 pub def_path_hash: u64,
38 // We don't store the list of impls in a flat list because each cached list of
39 // `relevant_impls_for` we would then duplicate all blanket impls. By keeping
40 // blanket and non-blanket impls separate, we can share the list of blanket
43 pub struct TraitImpls {
44 blanket_impls: Rc<Vec<DefId>>,
45 non_blanket_impls: Rc<Vec<DefId>>,
49 pub fn iter(&self) -> TraitImplsIter {
51 blanket_impls: self.blanket_impls.clone(),
52 non_blanket_impls: self.non_blanket_impls.clone(),
59 pub struct TraitImplsIter {
60 blanket_impls: Rc<Vec<DefId>>,
61 non_blanket_impls: Rc<Vec<DefId>>,
65 impl Iterator for TraitImplsIter {
68 fn next(&mut self) -> Option<DefId> {
69 if self.index < self.blanket_impls.len() {
70 let bi_index = self.index;
72 Some(self.blanket_impls[bi_index])
74 let nbi_index = self.index - self.blanket_impls.len();
75 if nbi_index < self.non_blanket_impls.len() {
77 Some(self.non_blanket_impls[nbi_index])
84 fn size_hint(&self) -> (usize, Option<usize>) {
85 let items_left = (self.blanket_impls.len() + self.non_blanket_impls.len()) - self.index;
86 (items_left, Some(items_left))
90 impl ExactSizeIterator for TraitImplsIter {}
92 impl<'a, 'gcx, 'tcx> TraitDef {
93 pub fn new(def_id: DefId,
94 unsafety: hir::Unsafety,
96 has_default_impl: bool,
108 pub fn ancestors(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
110 -> specialization_graph::Ancestors {
111 specialization_graph::ancestors(tcx, self.def_id, of_impl)
114 pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) {
115 for impl_def_id in tcx.trait_impls_of(self.def_id).iter() {
120 /// Iterate over every impl that could possibly match the
121 /// self-type `self_ty`.
122 pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
123 tcx: TyCtxt<'a, 'gcx, 'tcx>,
127 // simplify_type(.., false) basically replaces type parameters and
128 // projections with infer-variables. This is, of course, done on
129 // the impl trait-ref when it is instantiated, but not on the
130 // predicate trait-ref which is passed here.
132 // for example, if we match `S: Copy` against an impl like
133 // `impl<T:Copy> Copy for Option<T>`, we replace the type variable
134 // in `Option<T>` with an infer variable, to `Option<_>` (this
135 // doesn't actually change fast_reject output), but we don't
136 // replace `S` with anything - this impl of course can't be
137 // selected, and as there are hundreds of similar impls,
138 // considering them would significantly harm performance.
139 let relevant_impls = if let Some(simplified_self_ty) =
140 fast_reject::simplify_type(tcx, self_ty, true) {
141 tcx.relevant_trait_impls_for((self.def_id, simplified_self_ty))
143 tcx.trait_impls_of(self.def_id)
146 for impl_def_id in relevant_impls.iter() {
152 // Query provider for `trait_impls_of`.
153 pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
156 let remote_impls = if trait_id.is_local() {
157 // Traits defined in the current crate can't have impls in upstream
158 // crates, so we don't bother querying the cstore.
161 tcx.sess.cstore.implementations_of_trait(Some(trait_id))
164 let mut blanket_impls = Vec::new();
165 let mut non_blanket_impls = Vec::new();
167 let local_impls = tcx.hir
168 .trait_impls(trait_id)
170 .map(|&node_id| tcx.hir.local_def_id(node_id));
172 for impl_def_id in local_impls.chain(remote_impls.into_iter()) {
173 let impl_self_ty = tcx.type_of(impl_def_id);
174 if impl_def_id.is_local() && impl_self_ty.references_error() {
178 if fast_reject::simplify_type(tcx, impl_self_ty, false).is_some() {
179 non_blanket_impls.push(impl_def_id);
181 blanket_impls.push(impl_def_id);
186 blanket_impls: Rc::new(blanket_impls),
187 non_blanket_impls: Rc::new(non_blanket_impls),
191 // Query provider for `relevant_trait_impls_for`.
192 pub(super) fn relevant_trait_impls_provider<'a, 'tcx>(
193 tcx: TyCtxt<'a, 'tcx, 'tcx>,
194 (trait_id, self_ty): (DefId, fast_reject::SimplifiedType))
197 let all_trait_impls = tcx.trait_impls_of(trait_id);
199 let relevant: Vec<DefId> = all_trait_impls
203 .filter(|&impl_def_id| {
204 let impl_self_ty = tcx.type_of(impl_def_id);
205 let impl_simple_self_ty = fast_reject::simplify_type(tcx,
208 impl_simple_self_ty == self_ty
212 if all_trait_impls.non_blanket_impls.len() == relevant.len() {
213 // If we didn't filter anything out, re-use the existing vec.
217 blanket_impls: all_trait_impls.blanket_impls.clone(),
218 non_blanket_impls: Rc::new(relevant),