]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_typeck/src/check/method/suggest.rs
Use () for all_traits.
[rust.git] / compiler / rustc_typeck / src / check / method / suggest.rs
index 02fe8312c4c1fed6a777d771762a01c7af3450a6..2320a29e6d823a8c362fcd82638c0b4ae3a5c482 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
@@ -579,6 +579,7 @@ fn report_function<T: std::fmt::Display>(
                 }
 
                 let mut restrict_type_params = false;
+                let mut unsatisfied_bounds = false;
                 if !unsatisfied_predicates.is_empty() {
                     let def_span = |def_id| {
                         self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
@@ -739,6 +740,7 @@ trait bound{s}",
                         err.note(&format!(
                             "the following trait bounds were not satisfied:\n{bound_list}"
                         ));
+                        unsatisfied_bounds = true;
                     }
                 }
 
@@ -752,6 +754,7 @@ trait bound{s}",
                         source,
                         out_of_scope_traits,
                         &unsatisfied_predicates,
+                        unsatisfied_bounds,
                     );
                 }
 
@@ -984,10 +987,17 @@ fn suggest_traits_to_import(
         source: SelfSource<'tcx>,
         valid_out_of_scope_traits: Vec<DefId>,
         unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
+        unsatisfied_bounds: bool,
     ) {
         let mut alt_rcvr_sugg = false;
-        if let SelfSource::MethodCall(rcvr) = source {
+        if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
             debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
+            let skippable = [
+                self.tcx.lang_items().clone_trait(),
+                self.tcx.lang_items().deref_trait(),
+                self.tcx.lang_items().deref_mut_trait(),
+                self.tcx.lang_items().drop_trait(),
+            ];
             // Try alternative arbitrary self types that could fulfill this call.
             // FIXME: probe for all types that *could* be arbitrary self-types, not
             // just this list.
@@ -996,6 +1006,27 @@ fn suggest_traits_to_import(
                 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
                 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
             ] {
+                if let Ok(pick) = self.lookup_probe(
+                    span,
+                    item_name,
+                    rcvr_ty,
+                    rcvr,
+                    crate::check::method::probe::ProbeScope::AllTraits,
+                ) {
+                    // If the method is defined for the receiver we have, it likely wasn't `use`d.
+                    // We point at the method, but we just skip the rest of the check for arbitrary
+                    // self types and rely on the suggestion to `use` the trait from
+                    // `suggest_valid_traits`.
+                    let did = Some(pick.item.container.id());
+                    let skip = skippable.contains(&did);
+                    if pick.autoderefs == 0 && !skip {
+                        err.span_label(
+                            pick.item.ident.span,
+                            &format!("the method is available for `{}` here", rcvr_ty),
+                        );
+                    }
+                    break;
+                }
                 for (rcvr_ty, pre) in &[
                     (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
                     (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
@@ -1015,13 +1046,7 @@ fn suggest_traits_to_import(
                             // We don't want to suggest a container type when the missing
                             // method is `.clone()` or `.deref()` otherwise we'd suggest
                             // `Arc::new(foo).clone()`, which is far from what the user wants.
-                            let skip = [
-                                self.tcx.lang_items().clone_trait(),
-                                self.tcx.lang_items().deref_trait(),
-                                self.tcx.lang_items().deref_mut_trait(),
-                                self.tcx.lang_items().drop_trait(),
-                            ]
-                            .contains(&did);
+                            let skip = skippable.contains(&did);
                             // Make sure the method is defined for the *actual* receiver: we don't
                             // want to treat `Box<Self>` as a receiver if it only works because of
                             // an autoderef to `&self`
@@ -1047,7 +1072,7 @@ fn suggest_traits_to_import(
                 }
             }
         }
-        if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) {
+        if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
             return;
         }
 
@@ -1415,11 +1440,11 @@ fn cmp(&self, other: &TraitInfo) -> Ordering {
 
 /// Retrieves all traits in this crate and any dependent crates.
 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
-    tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
+    tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
 }
 
 /// Computes all traits in this crate and any dependent crates.
-fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
+fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
     use hir::itemlikevisit;
 
     let mut traits = vec![];
@@ -1478,14 +1503,11 @@ fn handle_external_res(
         handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
     }
 
-    traits
+    tcx.arena.alloc_from_iter(traits)
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    providers.all_traits = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        &tcx.arena.alloc(compute_all_traits(tcx))[..]
-    }
+    providers.all_traits = compute_all_traits;
 }
 
 struct UsePlacementFinder<'tcx> {