|  | 
|  | 1 | +// Copyright 2018 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 | + | 
|  | 11 | +use rustc::hir; | 
|  | 12 | +use rustc::traits; | 
|  | 13 | +use rustc::ty::ToPredicate; | 
|  | 14 | +use rustc::ty::subst::Subst; | 
|  | 15 | +use rustc::infer::InferOk; | 
|  | 16 | +use syntax_pos::DUMMY_SP; | 
|  | 17 | + | 
|  | 18 | +use core::DocAccessLevels; | 
|  | 19 | + | 
|  | 20 | +use super::*; | 
|  | 21 | + | 
|  | 22 | +use self::def_ctor::{get_def_from_def_id, get_def_from_node_id}; | 
|  | 23 | + | 
|  | 24 | +pub struct BlanketImplFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { | 
|  | 25 | +    pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, | 
|  | 26 | +} | 
|  | 27 | + | 
|  | 28 | +impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { | 
|  | 29 | +    pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { | 
|  | 30 | +        BlanketImplFinder { cx } | 
|  | 31 | +    } | 
|  | 32 | + | 
|  | 33 | +    pub fn get_with_def_id(&self, def_id: DefId) -> Vec<Item> { | 
|  | 34 | +        get_def_from_def_id(&self.cx, def_id, &|def_ctor| { | 
|  | 35 | +            self.get_blanket_impls(def_id, &def_ctor, None) | 
|  | 36 | +        }) | 
|  | 37 | +    } | 
|  | 38 | + | 
|  | 39 | +    pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec<Item> { | 
|  | 40 | +        get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| { | 
|  | 41 | +            let did = self.cx.tcx.hir.local_def_id(id); | 
|  | 42 | +            self.get_blanket_impls(did, &def_ctor, Some(name)) | 
|  | 43 | +        }) | 
|  | 44 | +    } | 
|  | 45 | + | 
|  | 46 | +    pub fn get_blanket_impls<F>( | 
|  | 47 | +        &self, | 
|  | 48 | +        def_id: DefId, | 
|  | 49 | +        def_ctor: &F, | 
|  | 50 | +        name: Option<String>, | 
|  | 51 | +    ) -> Vec<Item> | 
|  | 52 | +    where F: Fn(DefId) -> Def { | 
|  | 53 | +        let mut impls = Vec::new(); | 
|  | 54 | +        if self.cx | 
|  | 55 | +            .tcx | 
|  | 56 | +            .get_attrs(def_id) | 
|  | 57 | +            .lists("doc") | 
|  | 58 | +            .has_word("hidden") | 
|  | 59 | +        { | 
|  | 60 | +            debug!( | 
|  | 61 | +                "get_blanket_impls(def_id={:?}, def_ctor=...): item has doc('hidden'), \ | 
|  | 62 | +                 aborting", | 
|  | 63 | +                def_id | 
|  | 64 | +            ); | 
|  | 65 | +            return impls; | 
|  | 66 | +        } | 
|  | 67 | +        let ty = self.cx.tcx.type_of(def_id); | 
|  | 68 | +        if self.cx.access_levels.borrow().is_doc_reachable(def_id) || ty.is_primitive() { | 
|  | 69 | +            let generics = self.cx.tcx.generics_of(def_id); | 
|  | 70 | +            let real_name = name.clone().map(|name| Ident::from_str(&name)); | 
|  | 71 | +            let param_env = self.cx.tcx.param_env(def_id); | 
|  | 72 | +            for &trait_def_id in self.cx.all_traits.iter() { | 
|  | 73 | +                if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) || | 
|  | 74 | +                   self.cx.generated_synthetics | 
|  | 75 | +                          .borrow_mut() | 
|  | 76 | +                          .get(&(def_id, trait_def_id)) | 
|  | 77 | +                          .is_some() { | 
|  | 78 | +                    continue | 
|  | 79 | +                } | 
|  | 80 | +                self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { | 
|  | 81 | +                    self.cx.tcx.infer_ctxt().enter(|infcx| { | 
|  | 82 | +                        let t_generics = infcx.tcx.generics_of(impl_def_id); | 
|  | 83 | +                        let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) | 
|  | 84 | +                                                 .expect("Cannot get impl trait"); | 
|  | 85 | + | 
|  | 86 | +                        match trait_ref.self_ty().sty { | 
|  | 87 | +                            ty::TypeVariants::TyParam(_) => {}, | 
|  | 88 | +                            _ => return, | 
|  | 89 | +                        } | 
|  | 90 | + | 
|  | 91 | +                        let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id); | 
|  | 92 | +                        let ty = ty.subst(infcx.tcx, substs); | 
|  | 93 | +                        let param_env = param_env.subst(infcx.tcx, substs); | 
|  | 94 | + | 
|  | 95 | +                        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); | 
|  | 96 | +                        let trait_ref = trait_ref.subst(infcx.tcx, impl_substs); | 
|  | 97 | + | 
|  | 98 | +                        // Require the type the impl is implemented on to match | 
|  | 99 | +                        // our type, and ignore the impl if there was a mismatch. | 
|  | 100 | +                        let cause = traits::ObligationCause::dummy(); | 
|  | 101 | +                        let eq_result = infcx.at(&cause, param_env) | 
|  | 102 | +                                             .eq(trait_ref.self_ty(), ty); | 
|  | 103 | +                        if let Ok(InferOk { value: (), obligations }) = eq_result { | 
|  | 104 | +                            // FIXME(eddyb) ignoring `obligations` might cause false positives. | 
|  | 105 | +                            drop(obligations); | 
|  | 106 | + | 
|  | 107 | +                            let may_apply = infcx.predicate_may_hold(&traits::Obligation::new( | 
|  | 108 | +                                cause.clone(), | 
|  | 109 | +                                param_env, | 
|  | 110 | +                                trait_ref.to_predicate(), | 
|  | 111 | +                            )); | 
|  | 112 | +                            if !may_apply { | 
|  | 113 | +                                return | 
|  | 114 | +                            } | 
|  | 115 | +                            self.cx.generated_synthetics.borrow_mut() | 
|  | 116 | +                                                        .insert((def_id, trait_def_id)); | 
|  | 117 | +                            let trait_ = hir::TraitRef { | 
|  | 118 | +                                path: get_path_for_type(infcx.tcx, | 
|  | 119 | +                                                        trait_def_id, | 
|  | 120 | +                                                        hir::def::Def::Trait), | 
|  | 121 | +                                ref_id: ast::DUMMY_NODE_ID, | 
|  | 122 | +                            }; | 
|  | 123 | +                            let provided_trait_methods = | 
|  | 124 | +                                infcx.tcx.provided_trait_methods(trait_def_id) | 
|  | 125 | +                                         .into_iter() | 
|  | 126 | +                                         .map(|meth| meth.ident.to_string()) | 
|  | 127 | +                                         .collect(); | 
|  | 128 | + | 
|  | 129 | +                            let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics); | 
|  | 130 | +                            let predicates = infcx.tcx.predicates_of(impl_def_id); | 
|  | 131 | + | 
|  | 132 | +                            impls.push(Item { | 
|  | 133 | +                                source: infcx.tcx.def_span(impl_def_id).clean(self.cx), | 
|  | 134 | +                                name: None, | 
|  | 135 | +                                attrs: Default::default(), | 
|  | 136 | +                                visibility: None, | 
|  | 137 | +                                def_id: self.cx.next_def_id(impl_def_id.krate), | 
|  | 138 | +                                stability: None, | 
|  | 139 | +                                deprecation: None, | 
|  | 140 | +                                inner: ImplItem(Impl { | 
|  | 141 | +                                    unsafety: hir::Unsafety::Normal, | 
|  | 142 | +                                    generics: (t_generics, &predicates).clean(self.cx), | 
|  | 143 | +                                    provided_trait_methods, | 
|  | 144 | +                                    trait_: Some(trait_.clean(self.cx)), | 
|  | 145 | +                                    for_: ty.clean(self.cx), | 
|  | 146 | +                                    items: infcx.tcx.associated_items(impl_def_id) | 
|  | 147 | +                                                    .collect::<Vec<_>>() | 
|  | 148 | +                                                    .clean(self.cx), | 
|  | 149 | +                                    polarity: None, | 
|  | 150 | +                                    synthetic: false, | 
|  | 151 | +                                    blanket_impl: Some(infcx.tcx.type_of(impl_def_id) | 
|  | 152 | +                                                                .clean(self.cx)), | 
|  | 153 | +                                }), | 
|  | 154 | +                            }); | 
|  | 155 | +                        } | 
|  | 156 | +                    }); | 
|  | 157 | +                }); | 
|  | 158 | +            } | 
|  | 159 | +        } | 
|  | 160 | +        impls | 
|  | 161 | +    } | 
|  | 162 | +} | 
0 commit comments