]> git.lizzy.rs Git - rust.git/commitdiff
Add find_map_relevant_impl
authorDániel Buga <bugadani@gmail.com>
Fri, 9 Oct 2020 13:28:32 +0000 (15:28 +0200)
committerDániel Buga <bugadani@gmail.com>
Fri, 9 Oct 2020 14:22:49 +0000 (16:22 +0200)
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_middle/src/ty/trait_def.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir/src/transform/check_const_item_mutation.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_typeck/src/check/mod.rs
src/librustdoc/passes/collect_intra_doc_links.rs

index 60705f68681a1d6170a600ff5a05533695f3af7e..05b8dad3097e413f52c37020e56525c65c06ceec 100644 (file)
@@ -94,7 +94,7 @@ fn into_args(self) -> (DefId, DefId) {
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
     adt_destructor => {
         let _ = cdata;
-        tcx.calculate_dtor(def_id, &mut |_,_| Ok(()))
+        tcx.calculate_dtor(def_id, |_,_| Ok(()))
     }
     variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) }
     associated_item_def_ids => {
index 9d5b558234b3af16eb59ad54f74eea279b84c128..5599216c316dac62a5885c87ccb276db11035fca 100644 (file)
@@ -167,6 +167,41 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(
         }
     }
 
+    /// Applies function to every impl that could possibly match the self type `self_ty` and returns
+    /// the first non-none value.
+    pub fn find_map_relevant_impl<T, F: Fn(DefId) -> Option<T>>(
+        self,
+        def_id: DefId,
+        self_ty: Ty<'tcx>,
+        f: F,
+    ) -> Option<T> {
+        let impls = self.trait_impls_of(def_id);
+
+        for &impl_def_id in impls.blanket_impls.iter() {
+            if let result @ Some(_) = f(impl_def_id) {
+                return result;
+            }
+        }
+
+        if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
+            if let Some(impls) = impls.non_blanket_impls.get(&simp) {
+                for &impl_def_id in impls {
+                    if let result @ Some(_) = f(impl_def_id) {
+                        return result;
+                    }
+                }
+            }
+        } else {
+            for &impl_def_id in impls.non_blanket_impls.values().flatten() {
+                if let result @ Some(_) = f(impl_def_id) {
+                    return result;
+                }
+            }
+        }
+
+        None
+    }
+
     /// Returns an iterator containing all impls
     pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
         let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id);
index 4127b6535bca6c5a013d0bf624dd61660367757f..5ac12dfa993661dea69f2be093b6cc07f98f5961 100644 (file)
@@ -341,19 +341,19 @@ pub fn struct_lockstep_tails_with_normalize(
     pub fn calculate_dtor(
         self,
         adt_did: DefId,
-        validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>,
+        validate: impl Fn(Self, DefId) -> Result<(), ErrorReported>,
     ) -> Option<ty::Destructor> {
         let drop_trait = self.lang_items().drop_trait()?;
         self.ensure().coherent_trait(drop_trait);
 
-        let mut dtor_did = None;
         let ty = self.type_of(adt_did);
-        self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
+        let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
             if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
                 if validate(self, impl_did).is_ok() {
-                    dtor_did = Some(item.def_id);
+                    return Some(item.def_id);
                 }
             }
+            None
         });
 
         Some(ty::Destructor { did: dtor_did? })
index 4d4e9b989171a75001196db61d84daa422a283c0..fb89b36060a28ace819f2ffa1748cbc471a597a0 100644 (file)
@@ -34,7 +34,6 @@ fn is_const_item(&self, local: Local) -> Option<DefId> {
 
     fn is_const_item_without_destructor(&self, local: Local) -> Option<DefId> {
         let def_id = self.is_const_item(local)?;
-        let mut any_dtor = |_tcx, _def_id| Ok(());
 
         // We avoid linting mutation of a const item if the const's type has a
         // Drop impl. The Drop logic observes the mutation which was performed.
@@ -54,7 +53,7 @@ fn is_const_item_without_destructor(&self, local: Local) -> Option<DefId> {
         //
         //     #[const_mutation_allowed]
         //     pub const LOG: Log = Log { msg: "" };
-        match self.tcx.calculate_dtor(def_id, &mut any_dtor) {
+        match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) {
             Some(_) => None,
             None => Some(def_id),
         }
index cb3de57cfed079952f2489af638c58582b0b2206..05e3ed343511338af7fc5ef3b06ef4912a6379b3 100644 (file)
@@ -1384,17 +1384,11 @@ fn note_version_mismatch(
         trait_ref: &ty::PolyTraitRef<'tcx>,
     ) {
         let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(
+            self.tcx.find_map_relevant_impl(
                 trait_def_id,
                 trait_ref.skip_binder().self_ty(),
-                |impl_def_id| {
-                    if trait_impl.is_none() {
-                        trait_impl = Some(impl_def_id);
-                    }
-                },
-            );
-            trait_impl
+                |impl_def_id| Some(impl_def_id),
+            )
         };
         let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
         let all_traits = self.tcx.all_traits(LOCAL_CRATE);
index 97172d391ba659a71f4f84e3c2b6a311bd8c3468..1cb6ae21a47bbba05072f23fc61d156e1f409922 100644 (file)
@@ -264,7 +264,7 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
-    tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl)
+    tcx.calculate_dtor(def_id, dropck::check_drop_impl)
 }
 
 /// If this `DefId` is a "primary tables entry", returns
index b9be3e2f92b4696653d6a4d48f68750ff0330e89..ab39910766164eb9e0261a89adb720d3cc2544be 100644 (file)
@@ -650,14 +650,9 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
     let ty = cx.tcx.type_of(type_);
     let iter = in_scope_traits.iter().flat_map(|&trait_| {
         trace!("considering explicit impl for trait {:?}", trait_);
-        let mut saw_impl = false;
-        // Look at each trait implementation to see if it's an impl for `did`
-        cx.tcx.for_each_relevant_impl(trait_, ty, |impl_| {
-            // FIXME: this is inefficient, find a way to short-circuit for_each_* so this doesn't take as long
-            if saw_impl {
-                return;
-            }
 
+        // Look at each trait implementation to see if it's an impl for `did`
+        cx.tcx.find_map_relevant_impl(trait_, ty, |impl_| {
             let trait_ref = cx.tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
             // Check if these are the same type.
             let impl_type = trait_ref.self_ty();
@@ -668,7 +663,7 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
                 type_
             );
             // Fast path: if this is a primitive simple `==` will work
-            saw_impl = impl_type == ty
+            let saw_impl = impl_type == ty
                 || match impl_type.kind() {
                     // Check if these are the same def_id
                     ty::Adt(def, _) => {
@@ -678,8 +673,9 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
                     ty::Foreign(def_id) => *def_id == type_,
                     _ => false,
                 };
-        });
-        if saw_impl { Some(trait_) } else { None }
+
+            if saw_impl { Some(trait_) } else { None }
+        })
     });
     iter.collect()
 }