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};
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 ambiuous 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.sty {
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.sty {
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 {
465 err.span_suggestion(expr.span.to(span),
466 "use associated function syntax instead",
468 self.ty_to_string(actual),
470 Applicability::MachineApplicable);
472 err.help(&format!("try with `{}::{}`",
473 self.ty_to_string(actual), item_name));
476 report_candidates(span, &mut err, static_sources);
477 } else if static_sources.len() > 1 {
478 report_candidates(span, &mut err, static_sources);
481 if !unsatisfied_predicates.is_empty() {
482 let mut bound_list = unsatisfied_predicates.iter()
483 .map(|p| format!("`{} : {}`", p.self_ty(), p))
484 .collect::<Vec<_>>();
486 bound_list.dedup(); // #35677
487 let bound_list = bound_list.join("\n");
488 err.note(&format!("the method `{}` exists but the following trait bounds \
489 were not satisfied:\n{}",
494 if actual.is_numeric() && actual.is_fresh() {
497 self.suggest_traits_to_import(&mut err,
502 out_of_scope_traits);
505 if actual.is_enum() {
506 let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
507 if let Some(suggestion) = lev_distance::find_best_match_for_name(
508 adt_def.variants.iter().map(|s| &s.ident.name),
514 "there is a variant with a similar name",
515 suggestion.to_string(),
516 Applicability::MaybeIncorrect,
521 if let Some(lev_candidate) = lev_candidate {
522 let def_kind = lev_candidate.def_kind();
526 "there is {} {} with a similar name",
528 def_kind.descr(lev_candidate.def_id),
530 lev_candidate.ident.to_string(),
531 Applicability::MaybeIncorrect,
538 MethodError::Ambiguity(sources) => {
539 let mut err = struct_span_err!(self.sess(),
542 "multiple applicable items in scope");
543 err.span_label(span, format!("multiple `{}` found", item_name));
545 report_candidates(span, &mut err, sources);
549 MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
550 let mut err = struct_span_err!(self.tcx.sess, span, E0624,
551 "{} `{}` is private", kind.descr(def_id), item_name);
552 self.suggest_valid_traits(&mut err, out_of_scope_traits);
556 MethodError::IllegalSizedBound(candidates) => {
557 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
558 let mut err = self.sess().struct_span_err(span, &msg);
559 if !candidates.is_empty() {
560 let help = format!("{an}other candidate{s} {were} found in the following \
561 trait{s}, perhaps add a `use` for {one_of_them}:",
562 an = if candidates.len() == 1 {"an" } else { "" },
563 s = if candidates.len() == 1 { "" } else { "s" },
564 were = if candidates.len() == 1 { "was" } else { "were" },
565 one_of_them = if candidates.len() == 1 {
570 self.suggest_use_candidates(&mut err, help, candidates);
575 MethodError::BadReturnType => {
576 bug!("no return type expectations but got BadReturnType")
582 fn suggest_use_candidates(&self,
583 err: &mut DiagnosticBuilder<'_>,
585 candidates: Vec<DefId>) {
586 let module_did = self.tcx.hir().get_module_parent(self.body_id);
587 let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
588 let krate = self.tcx.hir().krate();
589 let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
590 if let Some(span) = span {
591 let path_strings = candidates.iter().map(|did| {
592 // Produce an additional newline to separate the new use statement
593 // from the directly following item.
594 let additional_newline = if found_use {
601 with_crate_prefix(|| self.tcx.def_path_str(*did)),
606 err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
608 let limit = if candidates.len() == 5 { 5 } else { 4 };
609 for (i, trait_did) in candidates.iter().take(limit).enumerate() {
610 if candidates.len() > 1 {
613 "\ncandidate #{}: `use {};`",
615 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
622 with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
627 if candidates.len() > limit {
628 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
634 fn suggest_valid_traits(&self,
635 err: &mut DiagnosticBuilder<'_>,
636 valid_out_of_scope_traits: Vec<DefId>) -> bool {
637 if !valid_out_of_scope_traits.is_empty() {
638 let mut candidates = valid_out_of_scope_traits;
641 err.help("items from traits can only be used if the trait is in scope");
642 let msg = format!("the following {traits_are} implemented but not in scope, \
643 perhaps add a `use` for {one_of_them}:",
644 traits_are = if candidates.len() == 1 {
649 one_of_them = if candidates.len() == 1 {
655 self.suggest_use_candidates(err, msg, candidates);
662 fn suggest_traits_to_import<'b>(
664 err: &mut DiagnosticBuilder<'_>,
667 item_name: ast::Ident,
668 source: SelfSource<'b>,
669 valid_out_of_scope_traits: Vec<DefId>,
671 if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
675 let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
677 // There are no traits implemented, so lets suggest some traits to
678 // implement, by finding ones that have the item name, and are
679 // legal to implement.
680 let mut candidates = all_traits(self.tcx)
683 // We approximate the coherence rules to only suggest
684 // traits that are legal to implement by requiring that
685 // either the type or trait is local. Multi-dispatch means
686 // this isn't perfect (that is, there are cases when
687 // implementing a trait would be legal but is rejected
689 (type_is_local || info.def_id.is_local()) &&
690 self.associated_item(info.def_id, item_name, Namespace::Value)
692 // We only want to suggest public or local traits (#45781).
693 item.vis == ty::Visibility::Public || info.def_id.is_local()
697 .collect::<Vec<_>>();
699 if !candidates.is_empty() {
700 // Sort from most relevant to least relevant.
701 candidates.sort_by(|a, b| a.cmp(b).reverse());
704 let param_type = match rcvr_ty.sty {
705 ty::Param(param) => Some(param),
706 ty::Ref(_, ty, _) => match ty.sty {
707 ty::Param(param) => Some(param),
712 err.help(if param_type.is_some() {
713 "items from traits can only be used if the type parameter is bounded by the trait"
715 "items from traits can only be used if the trait is implemented and in scope"
717 let mut msg = format!(
718 "the following {traits_define} an item `{name}`, perhaps you need to {action} \
720 traits_define = if candidates.len() == 1 {
725 action = if let Some(param) = param_type {
726 format!("restrict type parameter `{}` with", param)
728 "implement".to_string()
730 one_of_them = if candidates.len() == 1 {
737 // Obtain the span for `param` and use it for a structured suggestion.
738 let mut suggested = false;
739 if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) {
740 let table = table.borrow();
741 if let Some(did) = table.local_id_root {
742 let generics = self.tcx.generics_of(did);
743 let type_param = generics.type_param(param, self.tcx);
744 let hir = &self.tcx.hir();
745 if let Some(id) = hir.as_local_hir_id(type_param.def_id) {
746 // Get the `hir::Param` to verify whether it already has any bounds.
747 // We do this to avoid suggesting code that ends up as `T: FooBar`,
748 // instead we suggest `T: Foo + Bar` in that case.
749 let mut has_bounds = false;
750 let mut impl_trait = false;
751 if let Node::GenericParam(ref param) = hir.get(id) {
753 hir::GenericParamKind::Type { synthetic: Some(_), .. } => {
754 // We've found `fn foo(x: impl Trait)` instead of
755 // `fn foo<T>(x: T)`. We want to suggest the correct
756 // `fn foo(x: impl Trait + TraitBound)` instead of
757 // `fn foo<T: TraitBound>(x: T)`. (#63706)
759 has_bounds = param.bounds.len() > 1;
762 has_bounds = !param.bounds.is_empty();
766 let sp = hir.span(id);
767 // `sp` only covers `T`, change it so that it covers
768 // `T:` when appropriate
769 let sp = if has_bounds {
773 .next_point(self.tcx.sess.source_map().next_point(sp)))
778 // FIXME: contrast `t.def_id` against `param.bounds` to not suggest traits
779 // already there. That can happen when the cause is that we're in a const
780 // scope or associated function used as a method.
781 err.span_suggestions(
784 candidates.iter().map(|t| format!(
787 if impl_trait { " +" } else { ":" },
788 self.tcx.def_path_str(t.def_id),
789 if has_bounds { " +"} else { "" },
791 Applicability::MaybeIncorrect,
799 for (i, trait_info) in candidates.iter().enumerate() {
800 msg.push_str(&format!(
801 "\ncandidate #{}: `{}`",
803 self.tcx.def_path_str(trait_info.def_id),
811 /// Checks whether there is a local type somewhere in the chain of
812 /// autoderefs of `rcvr_ty`.
813 fn type_derefs_to_local(&self,
816 source: SelfSource<'_>) -> bool {
817 fn is_local(ty: Ty<'_>) -> bool {
819 ty::Adt(def, _) => def.did.is_local(),
820 ty::Foreign(did) => did.is_local(),
822 ty::Dynamic(ref tr, ..) =>
823 tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false),
825 ty::Param(_) => true,
827 // Everything else (primitive types, etc.) is effectively
828 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
829 // the noise from these sort of types is usually just really
830 // annoying, rather than any sort of help).
835 // This occurs for UFCS desugaring of `T::method`, where there is no
836 // receiver expression for the method call, and thus no autoderef.
837 if let SelfSource::QPath(_) = source {
838 return is_local(self.resolve_type_vars_with_obligations(rcvr_ty));
841 self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
845 #[derive(Copy, Clone)]
846 pub enum SelfSource<'a> {
848 MethodCall(&'a hir::Expr /* rcvr */),
851 #[derive(Copy, Clone)]
852 pub struct TraitInfo {
856 impl PartialEq for TraitInfo {
857 fn eq(&self, other: &TraitInfo) -> bool {
858 self.cmp(other) == Ordering::Equal
861 impl Eq for TraitInfo {}
862 impl PartialOrd for TraitInfo {
863 fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
864 Some(self.cmp(other))
867 impl Ord for TraitInfo {
868 fn cmp(&self, other: &TraitInfo) -> Ordering {
869 // Local crates are more important than remote ones (local:
870 // `cnum == 0`), and otherwise we throw in the defid for totality.
872 let lhs = (other.def_id.krate, other.def_id);
873 let rhs = (self.def_id.krate, self.def_id);
878 /// Retrieves all traits in this crate and any dependent crates.
879 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
880 tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
883 /// Computes all traits in this crate and any dependent crates.
884 fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
885 use hir::itemlikevisit;
887 let mut traits = vec![];
891 struct Visitor<'a, 'tcx> {
892 map: &'a hir_map::Map<'tcx>,
893 traits: &'a mut Vec<DefId>,
896 impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
897 fn visit_item(&mut self, i: &'v hir::Item) {
899 hir::ItemKind::Trait(..) |
900 hir::ItemKind::TraitAlias(..) => {
901 let def_id = self.map.local_def_id(i.hir_id);
902 self.traits.push(def_id);
908 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
910 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {}
913 tcx.hir().krate().visit_all_item_likes(&mut Visitor {
920 let mut external_mods = FxHashSet::default();
921 fn handle_external_res(
923 traits: &mut Vec<DefId>,
924 external_mods: &mut FxHashSet<DefId>,
928 Res::Def(DefKind::Trait, def_id) |
929 Res::Def(DefKind::TraitAlias, def_id) => {
932 Res::Def(DefKind::Mod, def_id) => {
933 if !external_mods.insert(def_id) {
936 for child in tcx.item_children(def_id).iter() {
937 handle_external_res(tcx, traits, external_mods, child.res)
943 for &cnum in tcx.crates().iter() {
946 index: CRATE_DEF_INDEX,
948 handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
954 pub fn provide(providers: &mut ty::query::Providers<'_>) {
955 providers.all_traits = |tcx, cnum| {
956 assert_eq!(cnum, LOCAL_CRATE);
957 &tcx.arena.alloc(compute_all_traits(tcx))[..]
961 struct UsePlacementFinder<'tcx> {
962 target_module: hir::HirId,
968 impl UsePlacementFinder<'tcx> {
971 krate: &'tcx hir::Crate,
972 target_module: hir::HirId,
973 ) -> (Option<Span>, bool) {
974 let mut finder = UsePlacementFinder {
980 hir::intravisit::walk_crate(&mut finder, krate);
981 (finder.span, finder.found_use)
985 impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
988 module: &'tcx hir::Mod,
992 if self.span.is_some() {
995 if hir_id != self.target_module {
996 hir::intravisit::walk_mod(self, module, hir_id);
999 // Find a `use` statement.
1000 for item_id in &module.item_ids {
1001 let item = self.tcx.hir().expect_item(item_id.id);
1003 hir::ItemKind::Use(..) => {
1004 // Don't suggest placing a `use` before the prelude
1005 // import or other generated ones.
1006 if !item.span.from_expansion() {
1007 self.span = Some(item.span.shrink_to_lo());
1008 self.found_use = true;
1012 // Don't place `use` before `extern crate`...
1013 hir::ItemKind::ExternCrate(_) => {}
1014 // ...but do place them before the first other item.
1015 _ => if self.span.map_or(true, |span| item.span < span ) {
1016 if !item.span.from_expansion() {
1017 // Don't insert between attributes and an item.
1018 if item.attrs.is_empty() {
1019 self.span = Some(item.span.shrink_to_lo());
1021 // Find the first attribute on the item.
1022 for attr in &item.attrs {
1023 if self.span.map_or(true, |span| attr.span < span) {
1024 self.span = Some(attr.span.shrink_to_lo());
1034 fn nested_visit_map<'this>(
1036 ) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> {
1037 hir::intravisit::NestedVisitorMap::None