1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
4 use crate::check::FnCtxt;
5 use crate::middle::lang_items::FnOnceTraitLangItem;
6 use crate::namespace::Namespace;
7 use crate::util::nodemap::FxHashSet;
8 use errors::{Applicability, DiagnosticBuilder, pluralise};
9 use rustc::hir::{self, ExprKind, Node, QPath};
10 use rustc::hir::def::{Res, DefKind};
11 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
12 use rustc::hir::map as hir_map;
13 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
14 use rustc::traits::Obligation;
15 use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
16 use rustc::ty::print::with_crate_prefix;
17 use syntax_pos::{Span, FileName};
19 use syntax::util::lev_distance;
21 use std::cmp::Ordering;
23 use super::{MethodError, NoMatchData, CandidateSource};
24 use super::probe::Mode;
26 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27 fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
30 // Not all of these (e.g., unsafe fns) implement `FnOnce`,
31 // so we look for these beforehand.
35 // If it's not a simple function, look for things which implement `FnOnce`.
37 let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) {
38 Ok(fn_once) => fn_once,
39 Err(..) => return false,
42 self.autoderef(span, ty).any(|(ty, _)| {
44 let fn_once_substs = tcx.mk_substs_trait(ty, &[
45 self.next_ty_var(TypeVariableOrigin {
46 kind: TypeVariableOriginKind::MiscVariable,
50 let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
51 let poly_trait_ref = trait_ref.to_poly_trait_ref();
53 Obligation::misc(span,
56 poly_trait_ref.to_predicate());
57 self.predicate_may_hold(&obligation)
64 pub fn report_method_error<'b>(
68 item_name: ast::Ident,
69 source: SelfSource<'b>,
70 error: MethodError<'tcx>,
71 args: Option<&'tcx [hir::Expr]>,
72 ) -> Option<DiagnosticBuilder<'_>> {
75 // Avoid suggestions when we don't know what's going on.
76 if rcvr_ty.references_error() {
80 let print_disambiguation_help = |
81 err: &mut DiagnosticBuilder<'_>,
85 "to disambiguate the method call, write `{}::{}({}{})` instead",
88 if rcvr_ty.is_region_ptr() && args.is_some() {
89 if rcvr_ty.is_mutable_ptr() {
99 .map(|arg| self.tcx.sess.source_map().span_to_snippet(arg.span)
100 .unwrap_or_else(|_| "...".to_owned()))
103 ).unwrap_or_else(|| "...".to_owned())
107 let report_candidates = |
109 err: &mut DiagnosticBuilder<'_>,
110 mut sources: Vec<CandidateSource>,
114 // Dynamic limit to avoid hiding just one candidate, which is silly.
115 let limit = if sources.len() == 5 { 5 } else { 4 };
117 for (idx, source) in sources.iter().take(limit).enumerate() {
119 CandidateSource::ImplSource(impl_did) => {
120 // Provide the best span we can. Use the item, if local to crate, else
121 // the impl, if local to crate (item may be defaulted), else nothing.
122 let item = match self.associated_item(
127 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
128 self.associated_item(
129 impl_trait_ref.def_id,
137 let note_span = self.tcx.hir().span_if_local(item.def_id).or_else(|| {
138 self.tcx.hir().span_if_local(impl_did)
141 let impl_ty = self.impl_self_ty(span, impl_did).ty;
143 let insertion = match self.tcx.impl_trait_ref(impl_did) {
144 None => String::new(),
146 format!(" of the trait `{}`",
147 self.tcx.def_path_str(trait_ref.def_id))
151 let note_str = if sources.len() > 1 {
152 format!("candidate #{} is defined in an impl{} for the type `{}`",
157 format!("the candidate is defined in an impl{} for the type `{}`",
161 if let Some(note_span) = note_span {
162 // We have a span pointing to the method. Show note with snippet.
163 err.span_note(self.tcx.sess.source_map().def_span(note_span),
168 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
169 print_disambiguation_help(err, self.tcx.def_path_str(trait_ref.def_id));
172 CandidateSource::TraitSource(trait_did) => {
173 let item = match self.associated_item(
181 let item_span = self.tcx.sess.source_map()
182 .def_span(self.tcx.def_span(item.def_id));
183 if sources.len() > 1 {
186 "candidate #{} is defined in the trait `{}`",
188 self.tcx.def_path_str(trait_did));
192 "the candidate is defined in the trait `{}`",
193 self.tcx.def_path_str(trait_did));
195 print_disambiguation_help(err, self.tcx.def_path_str(trait_did));
199 if sources.len() > limit {
200 err.note(&format!("and {} others", sources.len() - limit));
205 MethodError::NoMatch(NoMatchData {
206 static_candidates: static_sources,
207 unsatisfied_predicates,
214 let actual = self.resolve_vars_if_possible(&rcvr_ty);
215 let ty_str = self.ty_to_string(actual);
216 let is_method = mode == Mode::MethodCall;
217 let item_kind = if is_method {
219 } else if actual.is_enum() {
220 "variant or associated item"
222 match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
223 (Some(name), false) if name.is_lowercase() => {
224 "function or associated item"
226 (Some(_), false) => "associated item",
227 (Some(_), true) | (None, false) => {
228 "variant or associated item"
230 (None, true) => "variant",
233 let mut err = if !actual.references_error() {
234 // Suggest clamping down the type if the method that is being attempted to
235 // be used exists at all, and the type is an ambiguous numeric type
236 // ({integer}/{float}).
237 let mut candidates = all_traits(self.tcx)
240 self.associated_item(info.def_id, item_name, Namespace::Value)
242 if let (true, false, SelfSource::MethodCall(expr), Some(_)) =
243 (actual.is_numeric(),
244 actual.has_concrete_skeleton(),
247 let mut err = struct_span_err!(
251 "can't call {} `{}` on ambiguous numeric type `{}`",
256 let concrete_type = if actual.is_integral() {
262 ExprKind::Lit(ref lit) => {
264 let snippet = tcx.sess.source_map().span_to_snippet(lit.span)
265 .unwrap_or_else(|_| "<numeric literal>".to_owned());
269 &format!("you must specify a concrete type for \
270 this numeric value, like `{}`", concrete_type),
271 format!("{}_{}", snippet, concrete_type),
272 Applicability::MaybeIncorrect,
275 ExprKind::Path(ref qpath) => {
277 if let &QPath::Resolved(_, ref path) = &qpath {
278 if let hir::def::Res::Local(hir_id) = path.res {
279 let span = tcx.hir().span(hir_id);
280 let snippet = tcx.sess.source_map().span_to_snippet(span);
281 let filename = tcx.sess.source_map().span_to_filename(span);
283 let parent_node = self.tcx.hir().get(
284 self.tcx.hir().get_parent_node(hir_id),
287 "you must specify a type for this binding, like `{}`",
291 match (filename, parent_node, snippet) {
292 (FileName::Real(_), Node::Local(hir::Local {
293 source: hir::LocalSource::Normal,
296 }), Ok(ref snippet)) => {
298 // account for `let x: _ = 42;`
300 span.to(ty.as_ref().map(|ty| ty.span)
303 format!("{}: {}", snippet, concrete_type),
304 Applicability::MaybeIncorrect,
308 err.span_label(span, msg);
319 span = item_name.span;
320 let mut err = struct_span_err!(
324 "no {} named `{}` found for type `{}` in the current scope",
329 if let Some(span) = tcx.sess.confused_type_with_std_module.borrow()
332 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
335 "you are looking for the module in `std`, \
336 not the primitive type",
337 format!("std::{}", snippet),
338 Applicability::MachineApplicable,
342 if let ty::RawPtr(_) = &actual.kind {
343 err.note("try using `<*const T>::as_ref()` to get a reference to the \
344 type behind the pointer: https://doc.rust-lang.org/std/\
345 primitive.pointer.html#method.as_ref");
346 err.note("using `<*const T>::as_ref()` on a pointer \
347 which is unaligned or points to invalid \
348 or uninitialized memory is undefined behavior");
353 tcx.sess.diagnostic().struct_dummy()
356 if let Some(def) = actual.ty_adt_def() {
357 if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
358 let def_sp = tcx.sess.source_map().def_span(full_sp);
359 err.span_label(def_sp, format!("{} `{}` not found {}",
362 if def.is_enum() && !is_method {
370 // If the method name is the name of a field with a function or closure type,
371 // give a helping note that it has to be called as `(x.f)(...)`.
372 if let SelfSource::MethodCall(expr) = source {
373 let field_receiver = self
374 .autoderef(span, rcvr_ty)
375 .find_map(|(ty, _)| match ty.kind {
376 ty::Adt(def, substs) if !def.is_enum() => {
377 let variant = &def.non_enum_variant();
378 self.tcx.find_field_index(item_name, variant).map(|index| {
379 let field = &variant.fields[index];
380 let field_ty = field.ty(tcx, substs);
387 if let Some((field, field_ty)) = field_receiver {
388 let scope = self.tcx.hir().get_module_parent(self.body_id);
389 let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
392 if self.is_fn_ty(&field_ty, span) {
393 let expr_span = expr.span.to(item_name.span);
394 err.multipart_suggestion(
396 "to call the function stored in `{}`, \
397 surround the field access with parentheses",
401 (expr_span.shrink_to_lo(), '('.to_string()),
402 (expr_span.shrink_to_hi(), ')'.to_string()),
404 Applicability::MachineApplicable,
407 let call_expr = self.tcx.hir().expect_expr(
408 self.tcx.hir().get_parent_node(expr.hir_id),
411 if let Some(span) = call_expr.span.trim_start(item_name.span) {
414 "remove the arguments",
416 Applicability::MaybeIncorrect,
422 let field_kind = if is_accessible {
427 err.span_label(item_name.span, format!("{}, not a method", field_kind));
428 } else if lev_candidate.is_none() && static_sources.is_empty() {
429 err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
430 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
433 err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
434 self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
437 if self.is_fn_ty(&rcvr_ty, span) {
438 macro_rules! report_function {
439 ($span:expr, $name:expr) => {
440 err.note(&format!("{} is a function, perhaps you wish to call it",
445 if let SelfSource::MethodCall(expr) = source {
446 if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
447 report_function!(expr.span, expr_string);
448 } else if let ExprKind::Path(QPath::Resolved(_, ref path)) =
451 if let Some(segment) = path.segments.last() {
452 report_function!(expr.span, segment.ident);
458 if !static_sources.is_empty() {
459 err.note("found the following associated functions; to be used as methods, \
460 functions must have a `self` parameter");
461 err.span_label(span, "this is an associated function, not a method");
463 if static_sources.len() == 1 {
464 if let SelfSource::MethodCall(expr) = source {
467 "use associated function syntax instead",
468 format!("{}::{}", self.ty_to_value_string(actual), item_name),
469 Applicability::MachineApplicable,
474 self.ty_to_value_string(actual),
479 report_candidates(span, &mut err, static_sources);
480 } else if static_sources.len() > 1 {
481 report_candidates(span, &mut err, static_sources);
484 if !unsatisfied_predicates.is_empty() {
485 let mut bound_list = unsatisfied_predicates.iter()
486 .map(|p| format!("`{} : {}`", p.self_ty(), p))
487 .collect::<Vec<_>>();
489 bound_list.dedup(); // #35677
490 let bound_list = bound_list.join("\n");
491 err.note(&format!("the method `{}` exists but the following trait bounds \
492 were not satisfied:\n{}",
497 if actual.is_numeric() && actual.is_fresh() {
500 self.suggest_traits_to_import(&mut err,
505 out_of_scope_traits);
508 if actual.is_enum() {
509 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
510 if let Some(suggestion) = lev_distance::find_best_match_for_name(
511 adt_def.variants.iter().map(|s| &s.ident.name),
517 "there is a variant with a similar name",
518 suggestion.to_string(),
519 Applicability::MaybeIncorrect,
524 if let Some(lev_candidate) = lev_candidate {
525 let def_kind = lev_candidate.def_kind();
529 "there is {} {} with a similar name",
531 def_kind.descr(lev_candidate.def_id),
533 lev_candidate.ident.to_string(),
534 Applicability::MaybeIncorrect,
541 MethodError::Ambiguity(sources) => {
542 let mut err = struct_span_err!(self.sess(),
545 "multiple applicable items in scope");
546 err.span_label(span, format!("multiple `{}` found", item_name));
548 report_candidates(span, &mut err, sources);
552 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
553 let mut err = struct_span_err!(self.tcx.sess, span, E0624,
554 "{} `{}` is private", kind.descr(def_id), item_name);
555 self.suggest_valid_traits(&mut err, out_of_scope_traits);
559 MethodError::IllegalSizedBound(candidates) => {
560 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
561 let mut err = self.sess().struct_span_err(span, &msg);
562 if !candidates.is_empty() {
563 let help = format!("{an}other candidate{s} {were} found in the following \
564 trait{s}, perhaps add a `use` for {one_of_them}:",
565 an = if candidates.len() == 1 {"an" } else { "" },
566 s = pluralise!(candidates.len()),
567 were = if candidates.len() == 1 { "was" } else { "were" },
568 one_of_them = if candidates.len() == 1 {
573 self.suggest_use_candidates(&mut err, help, candidates);
578 MethodError::BadReturnType => {
579 bug!("no return type expectations but got BadReturnType")
585 /// Print out the type for use in value namespace.
586 fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
588 ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
589 _ => self.ty_to_string(ty),
593 fn suggest_use_candidates(&self,
594 err: &mut DiagnosticBuilder<'_>,
596 candidates: Vec<DefId>) {
597 let module_did = self.tcx.hir().get_module_parent(self.body_id);
598 let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
599 let krate = self.tcx.hir().krate();
600 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
601 if let Some(span) = span {
602 let path_strings = candidates.iter().map(|did| {
603 // Produce an additional newline to separate the new use statement
604 // from the directly following item.
605 let additional_newline = if found_use {
612 with_crate_prefix(|| self.tcx.def_path_str(*did)),
617 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
619 let limit = if candidates.len() == 5 { 5 } else { 4 };
620 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
621 if candidates.len() > 1 {
624 "\ncandidate #{}: `use {};`",
626 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
633 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
638 if candidates.len() > limit {
639 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
645 fn suggest_valid_traits(
647 err: &mut DiagnosticBuilder<'_>,
648 valid_out_of_scope_traits: Vec<DefId>,
650 if !valid_out_of_scope_traits.is_empty() {
651 let mut candidates = valid_out_of_scope_traits;
654 err.help("items from traits can only be used if the trait is in scope");
656 "the following {traits_are} implemented but not in scope; \
657 perhaps add a `use` for {one_of_them}:",
658 traits_are = if candidates.len() == 1 {
663 one_of_them = if candidates.len() == 1 {
670 self.suggest_use_candidates(err, msg, candidates);
677 fn suggest_traits_to_import<'b>(
679 err: &mut DiagnosticBuilder<'_>,
682 item_name: ast::Ident,
683 source: SelfSource<'b>,
684 valid_out_of_scope_traits: Vec<DefId>,
686 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
690 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
692 // There are no traits implemented, so lets suggest some traits to
693 // implement, by finding ones that have the item name, and are
694 // legal to implement.
695 let mut candidates = all_traits(self.tcx)
698 // We approximate the coherence rules to only suggest
699 // traits that are legal to implement by requiring that
700 // either the type or trait is local. Multi-dispatch means
701 // this isn't perfect (that is, there are cases when
702 // implementing a trait would be legal but is rejected
704 (type_is_local || info.def_id.is_local()) &&
705 self.associated_item(info.def_id, item_name, Namespace::Value)
707 // We only want to suggest public or local traits (#45781).
708 item.vis == ty::Visibility::Public || info.def_id.is_local()
712 .collect::<Vec<_>>();
714 if !candidates.is_empty() {
715 // Sort from most relevant to least relevant.
716 candidates.sort_by(|a, b| a.cmp(b).reverse());
719 let param_type = match rcvr_ty.kind {
720 ty::Param(param) => Some(param),
721 ty::Ref(_, ty, _) => match ty.kind {
722 ty::Param(param) => Some(param),
727 err.help(if param_type.is_some() {
728 "items from traits can only be used if the type parameter is bounded by the trait"
730 "items from traits can only be used if the trait is implemented and in scope"
732 let mut msg = format!(
733 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
735 traits_define = if candidates.len() == 1 {
740 action = if let Some(param) = param_type {
741 format!("restrict type parameter `{}` with", param)
743 "implement".to_string()
745 one_of_them = if candidates.len() == 1 {
752 // Obtain the span for `param` and use it for a structured suggestion.
753 let mut suggested = false;
754 if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) {
755 let table = table.borrow();
756 if let Some(did) = table.local_id_root {
757 let generics = self.tcx.generics_of(did);
758 let type_param = generics.type_param(param, self.tcx);
759 let hir = &self.tcx.hir();
760 if let Some(id) = hir.as_local_hir_id(type_param.def_id) {
761 // Get the `hir::Param` to verify whether it already has any bounds.
762 // We do this to avoid suggesting code that ends up as `T: FooBar`,
763 // instead we suggest `T: Foo + Bar` in that case.
764 let mut has_bounds = false;
765 let mut impl_trait = false;
766 if let Node::GenericParam(ref param) = hir.get(id) {
768 hir::GenericParamKind::Type { synthetic: Some(_), .. } => {
769 // We've found `fn foo(x: impl Trait)` instead of
770 // `fn foo<T>(x: T)`. We want to suggest the correct
771 // `fn foo(x: impl Trait + TraitBound)` instead of
772 // `fn foo<T: TraitBound>(x: T)`. (#63706)
774 has_bounds = param.bounds.len() > 1;
777 has_bounds = !param.bounds.is_empty();
781 let sp = hir.span(id);
782 // `sp` only covers `T`, change it so that it covers
783 // `T:` when appropriate
784 let sp = if has_bounds {
788 .next_point(self.tcx.sess.source_map().next_point(sp)))
793 // FIXME: contrast `t.def_id` against `param.bounds` to not suggest traits
794 // already there. That can happen when the cause is that we're in a const
795 // scope or associated function used as a method.
796 err.span_suggestions(
799 candidates.iter().map(|t| format!(
802 if impl_trait { " +" } else { ":" },
803 self.tcx.def_path_str(t.def_id),
804 if has_bounds { " +"} else { "" },
806 Applicability::MaybeIncorrect,
814 for (i, trait_info) in candidates.iter().enumerate() {
815 msg.push_str(&format!(
816 "\ncandidate #{}: `{}`",
818 self.tcx.def_path_str(trait_info.def_id),
826 /// Checks whether there is a local type somewhere in the chain of
827 /// autoderefs of `rcvr_ty`.
828 fn type_derefs_to_local(&self,
831 source: SelfSource<'_>) -> bool {
832 fn is_local(ty: Ty<'_>) -> bool {
834 ty::Adt(def, _) => def.did.is_local(),
835 ty::Foreign(did) => did.is_local(),
837 ty::Dynamic(ref tr, ..) =>
838 tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false),
840 ty::Param(_) => true,
842 // Everything else (primitive types, etc.) is effectively
843 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
844 // the noise from these sort of types is usually just really
845 // annoying, rather than any sort of help).
850 // This occurs for UFCS desugaring of `T::method`, where there is no
851 // receiver expression for the method call, and thus no autoderef.
852 if let SelfSource::QPath(_) = source {
853 return is_local(self.resolve_type_vars_with_obligations(rcvr_ty));
856 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
860 #[derive(Copy, Clone)]
861 pub enum SelfSource<'a> {
863 MethodCall(&'a hir::Expr /* rcvr */),
866 #[derive(Copy, Clone)]
867 pub struct TraitInfo {
871 impl PartialEq for TraitInfo {
872 fn eq(&self, other: &TraitInfo) -> bool {
873 self.cmp(other) == Ordering::Equal
876 impl Eq for TraitInfo {}
877 impl PartialOrd for TraitInfo {
878 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
879 Some(self.cmp(other))
882 impl Ord for TraitInfo {
883 fn cmp(&self, other: &TraitInfo) -> Ordering {
884 // Local crates are more important than remote ones (local:
885 // `cnum == 0`), and otherwise we throw in the defid for totality.
887 let lhs = (other.def_id.krate, other.def_id);
888 let rhs = (self.def_id.krate, self.def_id);
893 /// Retrieves all traits in this crate and any dependent crates.
894 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
895 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
898 /// Computes all traits in this crate and any dependent crates.
899 fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
900 use hir::itemlikevisit;
902 let mut traits = vec![];
906 struct Visitor<'a, 'tcx> {
907 map: &'a hir_map::Map<'tcx>,
908 traits: &'a mut Vec<DefId>,
911 impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
912 fn visit_item(&mut self, i: &'v hir::Item) {
914 hir::ItemKind::Trait(..) |
915 hir::ItemKind::TraitAlias(..) => {
916 let def_id = self.map.local_def_id(i.hir_id);
917 self.traits.push(def_id);
923 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
925 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {}
928 tcx.hir().krate().visit_all_item_likes(&mut Visitor {
935 let mut external_mods = FxHashSet::default();
936 fn handle_external_res(
938 traits: &mut Vec<DefId>,
939 external_mods: &mut FxHashSet<DefId>,
943 Res::Def(DefKind::Trait, def_id) |
944 Res::Def(DefKind::TraitAlias, def_id) => {
947 Res::Def(DefKind::Mod, def_id) => {
948 if !external_mods.insert(def_id) {
951 for child in tcx.item_children(def_id).iter() {
952 handle_external_res(tcx, traits, external_mods, child.res)
958 for &cnum in tcx.crates().iter() {
961 index: CRATE_DEF_INDEX,
963 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
969 pub fn provide(providers: &mut ty::query::Providers<'_>) {
970 providers.all_traits = |tcx, cnum| {
971 assert_eq!(cnum, LOCAL_CRATE);
972 &tcx.arena.alloc(compute_all_traits(tcx))[..]
976 struct UsePlacementFinder<'tcx> {
977 target_module: hir::HirId,
983 impl UsePlacementFinder<'tcx> {
986 krate: &'tcx hir::Crate,
987 target_module: hir::HirId,
988 ) -> (Option<Span>, bool) {
989 let mut finder = UsePlacementFinder {
995 hir::intravisit::walk_crate(&mut finder, krate);
996 (finder.span, finder.found_use)
1000 impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1003 module: &'tcx hir::Mod,
1007 if self.span.is_some() {
1010 if hir_id != self.target_module {
1011 hir::intravisit::walk_mod(self, module, hir_id);
1014 // Find a `use` statement.
1015 for item_id in &module.item_ids {
1016 let item = self.tcx.hir().expect_item(item_id.id);
1018 hir::ItemKind::Use(..) => {
1019 // Don't suggest placing a `use` before the prelude
1020 // import or other generated ones.
1021 if !item.span.from_expansion() {
1022 self.span = Some(item.span.shrink_to_lo());
1023 self.found_use = true;
1027 // Don't place `use` before `extern crate`...
1028 hir::ItemKind::ExternCrate(_) => {}
1029 // ...but do place them before the first other item.
1030 _ => if self.span.map_or(true, |span| item.span < span ) {
1031 if !item.span.from_expansion() {
1032 // Don't insert between attributes and an item.
1033 if item.attrs.is_empty() {
1034 self.span = Some(item.span.shrink_to_lo());
1036 // Find the first attribute on the item.
1037 for attr in &item.attrs {
1038 if self.span.map_or(true, |span| attr.span < span) {
1039 self.span = Some(attr.span.shrink_to_lo());
1049 fn nested_visit_map<'this>(
1051 ) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> {
1052 hir::intravisit::NestedVisitorMap::None