use std::cmp::Reverse;
+use std::ptr;
use log::debug;
-use rustc::bug;
-use rustc::session::Session;
-use rustc::ty::{self, DefIdTree};
use rustc_ast::ast::{self, Ident, Path};
use rustc_ast::util::lev_distance::find_best_match_for_name;
use rustc_ast_pretty::pprust;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_middle::bug;
+use rustc_middle::ty::{self, DefIdTree};
+use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Symbol};
use crate::imports::{Import, ImportKind, ImportResolver};
use crate::path_names_to_string;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
-use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
+use crate::{
+ BindingError, CrateLint, HasGenericParams, MacroRulesScope, Module, ModuleOrUniformRoot,
+};
use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
/// `source_map` functions and this function to something more robust.
fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
let impl_span = sm.span_until_char(impl_span, '<');
- let impl_span = sm.span_until_whitespace(impl_span);
- impl_span
+ sm.span_until_whitespace(impl_span)
}
impl<'a> Resolver<'a> {
}
}
}
- Scope::MacroRules(legacy_scope) => {
- if let LegacyScope::Binding(legacy_binding) = legacy_scope {
- let res = legacy_binding.binding.res();
+ Scope::MacroRules(macro_rules_scope) => {
+ if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope {
+ let res = macro_rules_binding.binding.res();
if filter_fn(res) {
suggestions
- .push(TypoSuggestion::from_res(legacy_binding.ident.name, res))
+ .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res))
}
}
}
let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
err.span_note(ident.span, &msg);
}
- if self.macro_names.contains(&ident.modern()) {
+ if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
err.help("have you added the `#[macro_use]` on the module/import?");
}
}
_ => Some(
self.session
.source_map()
- .def_span(self.cstore().get_span_untracked(def_id, self.session)),
+ .guess_head_span(self.cstore().get_span_untracked(def_id, self.session)),
),
});
if let Some(span) = def_span {
err.span_label(
- span,
+ self.session.source_map().guess_head_span(span),
&format!(
"similarly named {} `{}` defined here",
suggestion.res.descr(),
err.emit();
}
- crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
- let PrivacyError { ident, binding, .. } = *privacy_error;
- let session = &self.session;
- let mk_struct_span_error = |is_constructor| {
- let mut descr = binding.res().descr().to_string();
- if is_constructor {
- descr += " constructor";
- }
- if binding.is_import() {
- descr += " import";
- }
-
- let mut err =
- struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
-
- err.span_label(ident.span, &format!("this {} is private", descr));
- err.span_note(
- session.source_map().def_span(binding.span),
- &format!("the {} `{}` is defined here", descr, ident),
- );
-
- err
- };
-
- let mut err = if let NameBindingKind::Res(
+ /// If the binding refers to a tuple struct constructor with fields,
+ /// returns the span of its fields.
+ fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
+ if let NameBindingKind::Res(
Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
_,
) = binding.kind
{
let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
if let Some(fields) = self.field_names.get(&def_id) {
- let mut err = mk_struct_span_error(true);
let first_field = fields.first().expect("empty field list in the map");
- err.span_label(
- fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
- "a constructor is private if any of the fields is private",
- );
- err
- } else {
- mk_struct_span_error(false)
+ return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)));
}
- } else {
- mk_struct_span_error(false)
- };
+ }
+ None
+ }
+
+ crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+ let PrivacyError { ident, binding, .. } = *privacy_error;
+
+ let res = binding.res();
+ let ctor_fields_span = self.ctor_fields_span(binding);
+ let plain_descr = res.descr().to_string();
+ let nonimport_descr =
+ if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
+ let import_descr = nonimport_descr.clone() + " import";
+ let get_descr =
+ |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
+
+ // Print the primary message.
+ let descr = get_descr(binding);
+ let mut err =
+ struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
+ err.span_label(ident.span, &format!("private {}", descr));
+ if let Some(span) = ctor_fields_span {
+ err.span_label(span, "a constructor is private if any of the fields is private");
+ }
+
+ // Print the whole import chain to make it easier to see what happens.
+ let first_binding = binding;
+ let mut next_binding = Some(binding);
+ let mut next_ident = ident;
+ while let Some(binding) = next_binding {
+ let name = next_ident;
+ next_binding = match binding.kind {
+ _ if res == Res::Err => None,
+ NameBindingKind::Import { binding, import, .. } => match import.kind {
+ _ if binding.span.is_dummy() => None,
+ ImportKind::Single { source, .. } => {
+ next_ident = source;
+ Some(binding)
+ }
+ ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding),
+ ImportKind::ExternCrate { .. } => None,
+ },
+ _ => None,
+ };
+
+ let first = ptr::eq(binding, first_binding);
+ let descr = get_descr(binding);
+ let msg = format!(
+ "{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
+ and_refers_to = if first { "" } else { "...and refers to " },
+ item = descr,
+ name = name,
+ which = if first { "" } else { " which" },
+ dots = if next_binding.is_some() { "..." } else { "" },
+ );
+ let def_span = self.session.source_map().guess_head_span(binding.span);
+ let mut note_span = MultiSpan::from_span(def_span);
+ if !first && binding.vis == ty::Visibility::Public {
+ note_span.push_span_label(def_span, "consider importing it directly".into());
+ }
+ err.span_note(note_span, &msg);
+ }
err.emit();
}
/// Suggest a missing `self::` if that resolves to an correct module.
///
- /// ```
+ /// ```text
/// |
/// LL | use foo::Bar;
/// | ^^^ did you mean `self::foo`?
/// Suggests a missing `super::` if that resolves to an correct module.
///
- /// ```
+ /// ```text
/// |
/// LL | use foo::Bar;
/// | ^^^ did you mean `super::foo`?
/// Suggests a missing external crate name if that resolves to an correct module.
///
- /// ```
+ /// ```text
/// |
/// LL | use foobar::Baz;
/// | ^^^^^^ did you mean `baz::foobar`?