mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
use structured suggestions for E0432
This commit is contained in:
parent
e1b8898cfb
commit
4bbe8839dd
@ -137,6 +137,9 @@ impl Ord for BindingError {
|
||||
}
|
||||
}
|
||||
|
||||
/// A span, message, replacement text, and applicability.
|
||||
type Suggestion = (Span, String, String, Applicability);
|
||||
|
||||
enum ResolutionError<'a> {
|
||||
/// Error E0401: can't use type or const parameters from outer function.
|
||||
GenericParamsFromOuterFunction(Def),
|
||||
@ -166,7 +169,7 @@ enum ResolutionError<'a> {
|
||||
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
|
||||
SelfImportOnlyInImportListWithNonEmptyPrefix,
|
||||
/// Error E0433: failed to resolve.
|
||||
FailedToResolve(&'a str),
|
||||
FailedToResolve { label: String, suggestion: Option<Suggestion> },
|
||||
/// Error E0434: can't capture dynamic environment in a fn item.
|
||||
CannotCaptureDynamicEnvironmentInFnItem,
|
||||
/// Error E0435: attempt to use a non-constant value in a constant.
|
||||
@ -380,10 +383,15 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
|
||||
err.span_label(span, "can only appear in an import list with a non-empty prefix");
|
||||
err
|
||||
}
|
||||
ResolutionError::FailedToResolve(msg) => {
|
||||
ResolutionError::FailedToResolve { label, suggestion } => {
|
||||
let mut err = struct_span_err!(resolver.session, span, E0433,
|
||||
"failed to resolve: {}", msg);
|
||||
err.span_label(span, msg);
|
||||
"failed to resolve: {}", &label);
|
||||
err.span_label(span, label);
|
||||
|
||||
if let Some((span, msg, suggestion, applicability)) = suggestion {
|
||||
err.span_suggestion(span, &msg, suggestion, applicability);
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
||||
@ -1050,7 +1058,12 @@ enum PathResult<'a> {
|
||||
Module(ModuleOrUniformRoot<'a>),
|
||||
NonModule(PathResolution),
|
||||
Indeterminate,
|
||||
Failed(Span, String, bool /* is the error from the last segment? */),
|
||||
Failed {
|
||||
span: Span,
|
||||
label: String,
|
||||
suggestion: Option<Suggestion>,
|
||||
is_error_from_last_segment: bool,
|
||||
},
|
||||
}
|
||||
|
||||
enum ModuleKind {
|
||||
@ -1775,13 +1788,18 @@ impl<'a> Resolver<'a> {
|
||||
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
|
||||
path_res.base_def(),
|
||||
PathResult::NonModule(..) => {
|
||||
let msg = "type-relative paths are not supported in this context";
|
||||
error_callback(self, span, ResolutionError::FailedToResolve(msg));
|
||||
error_callback(self, span, ResolutionError::FailedToResolve {
|
||||
label: String::from("type-relative paths are not supported in this context"),
|
||||
suggestion: None,
|
||||
});
|
||||
Def::Err
|
||||
}
|
||||
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
|
||||
PathResult::Failed(span, msg, _) => {
|
||||
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
|
||||
PathResult::Failed { span, label, suggestion, .. } => {
|
||||
error_callback(self, span, ResolutionError::FailedToResolve {
|
||||
label,
|
||||
suggestion,
|
||||
});
|
||||
Def::Err
|
||||
}
|
||||
};
|
||||
@ -3429,7 +3447,7 @@ impl<'a> Resolver<'a> {
|
||||
// Such behavior is required for backward compatibility.
|
||||
// The same fallback is used when `a` resolves to nothing.
|
||||
PathResult::Module(ModuleOrUniformRoot::Module(_)) |
|
||||
PathResult::Failed(..)
|
||||
PathResult::Failed { .. }
|
||||
if (ns == TypeNS || path.len() > 1) &&
|
||||
self.primitive_type_table.primitive_types
|
||||
.contains_key(&path[0].ident.name) => {
|
||||
@ -3438,11 +3456,11 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
||||
PathResolution::new(module.def().unwrap()),
|
||||
PathResult::Failed(span, msg, false) => {
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
||||
PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve { label, suggestion });
|
||||
err_path_resolution()
|
||||
}
|
||||
PathResult::Module(..) | PathResult::Failed(..) => return None,
|
||||
PathResult::Module(..) | PathResult::Failed { .. } => return None,
|
||||
PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
|
||||
};
|
||||
|
||||
@ -3550,7 +3568,12 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
let msg = "there are too many initial `super`s.".to_string();
|
||||
return PathResult::Failed(ident.span, msg, false);
|
||||
return PathResult::Failed {
|
||||
span: ident.span,
|
||||
label: msg,
|
||||
suggestion: None,
|
||||
is_error_from_last_segment: false,
|
||||
};
|
||||
}
|
||||
if i == 0 {
|
||||
if name == keywords::SelfLower.name() {
|
||||
@ -3587,12 +3610,17 @@ impl<'a> Resolver<'a> {
|
||||
} else {
|
||||
format!("`{}`", name)
|
||||
};
|
||||
let msg = if i == 1 && path[0].ident.name == keywords::PathRoot.name() {
|
||||
let label = if i == 1 && path[0].ident.name == keywords::PathRoot.name() {
|
||||
format!("global paths cannot start with {}", name_str)
|
||||
} else {
|
||||
format!("{} in paths can only be used in start position", name_str)
|
||||
};
|
||||
return PathResult::Failed(ident.span, msg, false);
|
||||
return PathResult::Failed {
|
||||
span: ident.span,
|
||||
label,
|
||||
suggestion: None,
|
||||
is_error_from_last_segment: false,
|
||||
};
|
||||
}
|
||||
|
||||
let binding = if let Some(module) = module {
|
||||
@ -3653,9 +3681,12 @@ impl<'a> Resolver<'a> {
|
||||
def, path.len() - i - 1
|
||||
));
|
||||
} else {
|
||||
return PathResult::Failed(ident.span,
|
||||
format!("not a module `{}`", ident),
|
||||
is_last);
|
||||
return PathResult::Failed {
|
||||
span: ident.span,
|
||||
label: format!("not a module `{}`", ident),
|
||||
suggestion: None,
|
||||
is_error_from_last_segment: is_last,
|
||||
};
|
||||
}
|
||||
}
|
||||
Err(Undetermined) => return PathResult::Indeterminate,
|
||||
@ -3671,7 +3702,7 @@ impl<'a> Resolver<'a> {
|
||||
Some(ModuleOrUniformRoot::Module(module)) => module.def(),
|
||||
_ => None,
|
||||
};
|
||||
let msg = if module_def == self.graph_root.def() {
|
||||
let (label, suggestion) = if module_def == self.graph_root.def() {
|
||||
let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
|
||||
let mut candidates =
|
||||
self.lookup_import_candidates(ident, TypeNS, is_mod);
|
||||
@ -3679,19 +3710,32 @@ impl<'a> Resolver<'a> {
|
||||
(c.path.segments.len(), c.path.to_string())
|
||||
});
|
||||
if let Some(candidate) = candidates.get(0) {
|
||||
format!("did you mean `{}`?", candidate.path)
|
||||
(
|
||||
String::from("unresolved import"),
|
||||
Some((
|
||||
ident.span,
|
||||
String::from("a similar path exists"),
|
||||
candidate.path.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)),
|
||||
)
|
||||
} else if !ident.is_reserved() {
|
||||
format!("maybe a missing `extern crate {};`?", ident)
|
||||
(format!("maybe a missing `extern crate {};`?", ident), None)
|
||||
} else {
|
||||
// the parser will already have complained about the keyword being used
|
||||
return PathResult::NonModule(err_path_resolution());
|
||||
}
|
||||
} else if i == 0 {
|
||||
format!("use of undeclared type or module `{}`", ident)
|
||||
(format!("use of undeclared type or module `{}`", ident), None)
|
||||
} else {
|
||||
format!("could not find `{}` in `{}`", ident, path[i - 1].ident)
|
||||
(format!("could not find `{}` in `{}`", ident, path[i - 1].ident), None)
|
||||
};
|
||||
return PathResult::Failed {
|
||||
span: ident.span,
|
||||
label,
|
||||
suggestion,
|
||||
is_error_from_last_segment: is_last,
|
||||
};
|
||||
return PathResult::Failed(ident.span, msg, is_last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -426,9 +426,9 @@ impl<'a> Resolver<'a> {
|
||||
Ok(path_res.base_def())
|
||||
}
|
||||
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
||||
PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
PathResult::NonModule(..)
|
||||
| PathResult::Indeterminate
|
||||
| PathResult::Failed { .. } => Err(Determinacy::Determined),
|
||||
PathResult::Module(..) => unreachable!(),
|
||||
};
|
||||
|
||||
@ -990,14 +990,17 @@ impl<'a> Resolver<'a> {
|
||||
let def = path_res.base_def();
|
||||
check_consistency(self, &path, path_span, kind, initial_def, def);
|
||||
}
|
||||
path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => {
|
||||
let (span, msg) = if let PathResult::Failed(span, msg, ..) = path_res {
|
||||
(span, msg)
|
||||
path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => {
|
||||
let (span, label) = if let PathResult::Failed { span, label, .. } = path_res {
|
||||
(span, label)
|
||||
} else {
|
||||
(path_span, format!("partially resolved path in {} {}",
|
||||
kind.article(), kind.descr()))
|
||||
};
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve {
|
||||
label,
|
||||
suggestion: None
|
||||
});
|
||||
}
|
||||
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
|
||||
}
|
||||
|
@ -6,9 +6,11 @@ use crate::Namespace::{self, TypeNS, MacroNS};
|
||||
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
||||
use crate::{Resolver, Segment};
|
||||
use crate::{names_to_string, module_to_string};
|
||||
use crate::{resolve_error, ResolutionError};
|
||||
use crate::{resolve_error, ResolutionError, Suggestion};
|
||||
use crate::macros::ParentScope;
|
||||
|
||||
use errors::Applicability;
|
||||
|
||||
use rustc_data_structures::ptr_key::PtrKey;
|
||||
use rustc::ty;
|
||||
use rustc::lint::builtin::BuiltinLintDiagnostics;
|
||||
@ -27,7 +29,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax::{struct_span_err, unwrap_or};
|
||||
use syntax_pos::{MultiSpan, Span};
|
||||
|
||||
use log::debug;
|
||||
use log::*;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::{mem, ptr};
|
||||
@ -623,6 +625,16 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
|
||||
/// import errors within the same use tree into a single diagnostic.
|
||||
#[derive(Debug, Clone)]
|
||||
struct UnresolvedImportError {
|
||||
span: Span,
|
||||
label: Option<String>,
|
||||
note: Option<String>,
|
||||
suggestion: Option<Suggestion>,
|
||||
}
|
||||
|
||||
pub struct ImportResolver<'a, 'b: 'a> {
|
||||
pub resolver: &'a mut Resolver<'b>,
|
||||
}
|
||||
@ -675,14 +687,14 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
self.finalize_resolutions_in(module);
|
||||
}
|
||||
|
||||
let mut errors = false;
|
||||
let mut has_errors = false;
|
||||
let mut seen_spans = FxHashSet::default();
|
||||
let mut error_vec = Vec::new();
|
||||
let mut errors = vec![];
|
||||
let mut prev_root_id: NodeId = NodeId::from_u32(0);
|
||||
for i in 0 .. self.determined_imports.len() {
|
||||
let import = self.determined_imports[i];
|
||||
if let Some((span, err, note)) = self.finalize_import(import) {
|
||||
errors = true;
|
||||
if let Some(err) = self.finalize_import(import) {
|
||||
has_errors = true;
|
||||
|
||||
if let SingleImport { source, ref source_bindings, .. } = import.subclass {
|
||||
if source.name == "self" {
|
||||
@ -696,37 +708,36 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
// If the error is a single failed import then create a "fake" import
|
||||
// resolution for it so that later resolve stages won't complain.
|
||||
self.import_dummy_binding(import);
|
||||
if prev_root_id.as_u32() != 0 &&
|
||||
prev_root_id.as_u32() != import.root_id.as_u32() &&
|
||||
!error_vec.is_empty(){
|
||||
// in case of new import line, throw diagnostic message
|
||||
// for previous line.
|
||||
let mut empty_vec = vec![];
|
||||
mem::swap(&mut empty_vec, &mut error_vec);
|
||||
self.throw_unresolved_import_error(empty_vec, None);
|
||||
if prev_root_id.as_u32() != 0
|
||||
&& prev_root_id.as_u32() != import.root_id.as_u32()
|
||||
&& !errors.is_empty() {
|
||||
// In the case of a new import line, throw a diagnostic message
|
||||
// for the previous line.
|
||||
self.throw_unresolved_import_error(errors, None);
|
||||
errors = vec![];
|
||||
}
|
||||
if !seen_spans.contains(&span) {
|
||||
if !seen_spans.contains(&err.span) {
|
||||
let path = import_path_to_string(
|
||||
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
||||
&import.subclass,
|
||||
span,
|
||||
err.span,
|
||||
);
|
||||
error_vec.push((span, path, err, note));
|
||||
seen_spans.insert(span);
|
||||
seen_spans.insert(err.span);
|
||||
errors.push((path, err));
|
||||
prev_root_id = import.root_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !error_vec.is_empty() {
|
||||
self.throw_unresolved_import_error(error_vec.clone(), None);
|
||||
if !errors.is_empty() {
|
||||
self.throw_unresolved_import_error(errors.clone(), None);
|
||||
}
|
||||
|
||||
// Report unresolved imports only if no hard error was already reported
|
||||
// to avoid generating multiple errors on the same import.
|
||||
if !errors {
|
||||
if !has_errors {
|
||||
for import in &self.indeterminate_imports {
|
||||
self.throw_unresolved_import_error(error_vec, Some(MultiSpan::from(import.span)));
|
||||
self.throw_unresolved_import_error(errors, Some(MultiSpan::from(import.span)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -734,44 +745,58 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
|
||||
fn throw_unresolved_import_error(
|
||||
&self,
|
||||
error_vec: Vec<(Span, String, String, Option<String>)>,
|
||||
errors: Vec<(String, UnresolvedImportError)>,
|
||||
span: Option<MultiSpan>,
|
||||
) {
|
||||
let max_span_label_msg_count = 10; // upper limit on number of span_label message.
|
||||
let (span, msg, note) = if error_vec.is_empty() {
|
||||
/// Upper limit on the number of `span_label` messages.
|
||||
const MAX_LABEL_COUNT: usize = 10;
|
||||
|
||||
let (span, msg, note) = if errors.is_empty() {
|
||||
(span.unwrap(), "unresolved import".to_string(), None)
|
||||
} else {
|
||||
let span = MultiSpan::from_spans(
|
||||
error_vec.clone().into_iter()
|
||||
.map(|elem: (Span, String, String, Option<String>)| elem.0)
|
||||
.collect()
|
||||
errors
|
||||
.iter()
|
||||
.map(|(_, err)| err.span)
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let note: Option<String> = error_vec.clone().into_iter()
|
||||
.filter_map(|elem: (Span, String, String, Option<String>)| elem.3)
|
||||
let note = errors
|
||||
.iter()
|
||||
.filter_map(|(_, err)| err.note.as_ref())
|
||||
.last();
|
||||
|
||||
let path_vec: Vec<String> = error_vec.clone().into_iter()
|
||||
.map(|elem: (Span, String, String, Option<String>)| format!("`{}`", elem.1))
|
||||
.collect();
|
||||
let path = path_vec.join(", ");
|
||||
let paths = errors
|
||||
.iter()
|
||||
.map(|(path, _)| format!("`{}`", path))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let msg = format!(
|
||||
"unresolved import{} {}",
|
||||
if path_vec.len() > 1 { "s" } else { "" },
|
||||
path
|
||||
if paths.len() > 1 { "s" } else { "" },
|
||||
paths.join(", "),
|
||||
);
|
||||
|
||||
(span, msg, note)
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
|
||||
for span_error in error_vec.into_iter().take(max_span_label_msg_count) {
|
||||
err.span_label(span_error.0, span_error.2);
|
||||
let mut diag = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
|
||||
|
||||
if let Some(note) = ¬e {
|
||||
diag.note(note);
|
||||
}
|
||||
if let Some(note) = note {
|
||||
err.note(¬e);
|
||||
|
||||
for (_, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
|
||||
if let Some(label) = err.label {
|
||||
diag.span_label(err.span, label);
|
||||
}
|
||||
|
||||
if let Some((span, msg, suggestion, applicability)) = err.suggestion {
|
||||
diag.span_suggestion(span, &msg, suggestion, applicability);
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
/// Attempts to resolve the given import, returning true if its resolution is determined.
|
||||
@ -802,7 +827,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
match path_res {
|
||||
PathResult::Module(module) => module,
|
||||
PathResult::Indeterminate => return false,
|
||||
PathResult::NonModule(..) | PathResult::Failed(..) => return true,
|
||||
PathResult::NonModule(..) | PathResult::Failed { .. } => return true,
|
||||
}
|
||||
};
|
||||
|
||||
@ -866,11 +891,14 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
!indeterminate
|
||||
}
|
||||
|
||||
// If appropriate, returns an error to report.
|
||||
/// Performs final import resolution, consistency checks and error reporting.
|
||||
///
|
||||
/// Optionally returns an unresolved import error. This error is buffered and used to
|
||||
/// consolidate multiple unresolved import errors into a single diagnostic.
|
||||
fn finalize_import(
|
||||
&mut self,
|
||||
directive: &'b ImportDirective<'b>
|
||||
) -> Option<(Span, String, Option<String>)> {
|
||||
) -> Option<UnresolvedImportError> {
|
||||
self.current_module = directive.parent_scope.module;
|
||||
|
||||
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
|
||||
@ -896,25 +924,48 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
|
||||
module
|
||||
}
|
||||
PathResult::Failed(span, msg, false) => {
|
||||
PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
|
||||
if no_ambiguity {
|
||||
assert!(directive.imported_module.get().is_none());
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve {
|
||||
label,
|
||||
suggestion,
|
||||
});
|
||||
}
|
||||
return None;
|
||||
}
|
||||
PathResult::Failed(span, msg, true) => {
|
||||
PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => {
|
||||
if no_ambiguity {
|
||||
assert!(directive.imported_module.get().is_none());
|
||||
return Some(match self.make_path_suggestion(span, directive.module_path.clone(),
|
||||
&directive.parent_scope) {
|
||||
Some((suggestion, note)) => (
|
||||
span,
|
||||
format!("did you mean `{}`?", Segment::names_to_string(&suggestion)),
|
||||
note,
|
||||
),
|
||||
None => (span, msg, None),
|
||||
});
|
||||
let err = match self.make_path_suggestion(
|
||||
span,
|
||||
directive.module_path.clone(),
|
||||
&directive.parent_scope,
|
||||
) {
|
||||
Some((suggestion, note)) => {
|
||||
UnresolvedImportError {
|
||||
span,
|
||||
label: None,
|
||||
note,
|
||||
suggestion: Some((
|
||||
span,
|
||||
String::from("a similar path exists"),
|
||||
Segment::names_to_string(&suggestion),
|
||||
Applicability::MaybeIncorrect,
|
||||
)),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
UnresolvedImportError {
|
||||
span,
|
||||
label: Some(label),
|
||||
note: None,
|
||||
suggestion,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Some(err);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
@ -950,11 +1001,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
if module.def_id() == directive.parent_scope.module.def_id() {
|
||||
// Importing a module into itself is not allowed.
|
||||
return Some((
|
||||
directive.span,
|
||||
"Cannot glob-import a module into itself.".to_string(),
|
||||
None,
|
||||
));
|
||||
return Some(UnresolvedImportError {
|
||||
span: directive.span,
|
||||
label: Some(String::from("cannot glob-import a module into itself")),
|
||||
note: None,
|
||||
suggestion: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
if !is_prelude &&
|
||||
@ -1059,31 +1111,42 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
_ => Some(&i.name),
|
||||
}
|
||||
});
|
||||
|
||||
let lev_suggestion =
|
||||
match find_best_match_for_name(names, &ident.as_str(), None) {
|
||||
Some(name) => format!(". Did you mean to use `{}`?", name),
|
||||
None => String::new(),
|
||||
};
|
||||
let msg = match module {
|
||||
find_best_match_for_name(names, &ident.as_str(), None).map(|suggestion| {
|
||||
(
|
||||
ident.span,
|
||||
String::from("a similar name exists in the module"),
|
||||
suggestion.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
});
|
||||
|
||||
let label = match module {
|
||||
ModuleOrUniformRoot::Module(module) => {
|
||||
let module_str = module_to_string(module);
|
||||
if let Some(module_str) = module_str {
|
||||
format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
|
||||
format!("no `{}` in `{}`", ident, module_str)
|
||||
} else {
|
||||
format!("no `{}` in the root{}", ident, lev_suggestion)
|
||||
format!("no `{}` in the root", ident)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if !ident.is_path_segment_keyword() {
|
||||
format!("no `{}` external crate{}", ident, lev_suggestion)
|
||||
format!("no `{}` external crate", ident)
|
||||
} else {
|
||||
// HACK(eddyb) this shows up for `self` & `super`, which
|
||||
// should work instead - for now keep the same error message.
|
||||
format!("no `{}` in the root{}", ident, lev_suggestion)
|
||||
format!("no `{}` in the root", ident)
|
||||
}
|
||||
}
|
||||
};
|
||||
Some((directive.span, msg, None))
|
||||
Some(UnresolvedImportError {
|
||||
span: directive.span,
|
||||
label: Some(label),
|
||||
note: None,
|
||||
suggestion: lev_suggestion,
|
||||
})
|
||||
} else {
|
||||
// `resolve_ident_in_module` reported a privacy error.
|
||||
self.import_dummy_binding(directive);
|
||||
|
@ -8,7 +8,10 @@ error[E0432]: unresolved import `prelude`
|
||||
--> $DIR/issue-55897.rs:1:5
|
||||
|
|
||||
LL | use prelude::*; //~ ERROR unresolved import `prelude`
|
||||
| ^^^^^^^ did you mean `std::prelude`?
|
||||
| ^^^^^^^
|
||||
| |
|
||||
| unresolved import
|
||||
| help: a similar path exists: `std::prelude`
|
||||
|
||||
error: cannot determine resolution for the macro `env`
|
||||
--> $DIR/issue-55897.rs:6:22
|
||||
|
@ -1,6 +1,8 @@
|
||||
use zed::bar;
|
||||
use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
|
||||
//~^ no `baz` in `zed`. Did you mean to use `bar`?
|
||||
//~| no `baz` in `zed`
|
||||
//~| HELP a similar name exists in the module
|
||||
//~| SUGGESTION bar
|
||||
|
||||
|
||||
mod zed {
|
||||
|
@ -2,16 +2,19 @@ error[E0432]: unresolved import `zed::baz`
|
||||
--> $DIR/import.rs:2:5
|
||||
|
|
||||
LL | use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
|
||||
| ^^^^^^^^ no `baz` in `zed`. Did you mean to use `bar`?
|
||||
| ^^^^^---
|
||||
| | |
|
||||
| | help: a similar name exists in the module: `bar`
|
||||
| no `baz` in `zed`
|
||||
|
||||
error[E0432]: unresolved import `foo`
|
||||
--> $DIR/import.rs:8:9
|
||||
--> $DIR/import.rs:10:9
|
||||
|
|
||||
LL | use foo; //~ ERROR unresolved import `foo` [E0432]
|
||||
| ^^^ no `foo` in the root
|
||||
|
||||
error[E0603]: unresolved item `foo` is private
|
||||
--> $DIR/import.rs:13:10
|
||||
--> $DIR/import.rs:15:10
|
||||
|
|
||||
LL | zed::foo(); //~ ERROR `foo` is private
|
||||
| ^^^
|
||||
|
@ -2,7 +2,10 @@ error[E0432]: unresolved import `NonExistent`
|
||||
--> $DIR/issue-55457.rs:1:5
|
||||
|
|
||||
LL | use NonExistent; //~ ERROR unresolved import `NonExistent`
|
||||
| ^^^^^^^^^^^ no `NonExistent` in the root. Did you mean to use `non_existent`?
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| no `NonExistent` in the root
|
||||
| help: a similar name exists in the module: `non_existent`
|
||||
|
||||
error[E0432]: unresolved import `non_existent`
|
||||
--> $DIR/issue-55457.rs:2:5
|
||||
|
@ -2,13 +2,19 @@ error[E0432]: unresolved import `__test`
|
||||
--> $DIR/inaccessible-test-modules.rs:5:5
|
||||
|
|
||||
LL | use __test as x; //~ ERROR unresolved import `__test`
|
||||
| ^^^^^^^^^^^ no `__test` in the root. Did you mean to use `test`?
|
||||
| ------^^^^^
|
||||
| |
|
||||
| no `__test` in the root
|
||||
| help: a similar name exists in the module: `test`
|
||||
|
||||
error[E0432]: unresolved import `__test_reexports`
|
||||
--> $DIR/inaccessible-test-modules.rs:6:5
|
||||
|
|
||||
LL | use __test_reexports as y; //~ ERROR unresolved import `__test_reexports`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ no `__test_reexports` in the root. Did you mean to use `__test_reexports`?
|
||||
| ----------------^^^^^
|
||||
| |
|
||||
| no `__test_reexports` in the root
|
||||
| help: a similar name exists in the module: `__test_reexports`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0432]: unresolved import `self::*`
|
||||
--> $DIR/issue-31212.rs:5:13
|
||||
|
|
||||
LL | pub use self::*; //~ ERROR unresolved
|
||||
| ^^^^^^^ Cannot glob-import a module into itself.
|
||||
| ^^^^^^^ cannot glob-import a module into itself
|
||||
|
||||
error[E0425]: cannot find function `f` in module `foo`
|
||||
--> $DIR/issue-31212.rs:9:10
|
||||
|
@ -1,14 +1,14 @@
|
||||
use self::*; //~ ERROR: unresolved import `self::*` [E0432]
|
||||
//~^ Cannot glob-import a module into itself.
|
||||
//~^ cannot glob-import a module into itself
|
||||
|
||||
mod foo {
|
||||
use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
|
||||
//~^ Cannot glob-import a module into itself.
|
||||
//~^ cannot glob-import a module into itself
|
||||
|
||||
mod bar {
|
||||
use super::bar::*;
|
||||
//~^ ERROR: unresolved import `super::bar::*` [E0432]
|
||||
//~| Cannot glob-import a module into itself.
|
||||
//~| cannot glob-import a module into itself
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,19 +2,19 @@ error[E0432]: unresolved import `self::*`
|
||||
--> $DIR/issue-8208.rs:1:5
|
||||
|
|
||||
LL | use self::*; //~ ERROR: unresolved import `self::*` [E0432]
|
||||
| ^^^^^^^ Cannot glob-import a module into itself.
|
||||
| ^^^^^^^ cannot glob-import a module into itself
|
||||
|
||||
error[E0432]: unresolved import `foo::*`
|
||||
--> $DIR/issue-8208.rs:5:9
|
||||
|
|
||||
LL | use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
|
||||
| ^^^^^^ Cannot glob-import a module into itself.
|
||||
| ^^^^^^ cannot glob-import a module into itself
|
||||
|
||||
error[E0432]: unresolved import `super::bar::*`
|
||||
--> $DIR/issue-8208.rs:9:13
|
||||
|
|
||||
LL | use super::bar::*;
|
||||
| ^^^^^^^^^^^^^ Cannot glob-import a module into itself.
|
||||
| ^^^^^^^^^^^^^ cannot glob-import a module into itself
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -5,19 +5,23 @@ mod a {
|
||||
extern crate alloc;
|
||||
use alloc::HashMap;
|
||||
//~^ ERROR unresolved import `alloc` [E0432]
|
||||
//~| did you mean `self::alloc`?
|
||||
//~| HELP a similar path exists
|
||||
//~| SUGGESTION self::alloc
|
||||
mod b {
|
||||
use alloc::HashMap;
|
||||
//~^ ERROR unresolved import `alloc` [E0432]
|
||||
//~| did you mean `super::alloc`?
|
||||
//~| HELP a similar path exists
|
||||
//~| SUGGESTION super::alloc
|
||||
mod c {
|
||||
use alloc::HashMap;
|
||||
//~^ ERROR unresolved import `alloc` [E0432]
|
||||
//~| did you mean `a::alloc`?
|
||||
//~| HELP a similar path exists
|
||||
//~| SUGGESTION a::alloc
|
||||
mod d {
|
||||
use alloc::HashMap;
|
||||
//~^ ERROR unresolved import `alloc` [E0432]
|
||||
//~| did you mean `a::alloc`?
|
||||
//~| HELP a similar path exists
|
||||
//~| SUGGESTION a::alloc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,31 @@ error[E0432]: unresolved import `alloc`
|
||||
--> $DIR/resolve_self_super_hint.rs:6:9
|
||||
|
|
||||
LL | use alloc::HashMap;
|
||||
| ^^^^^ did you mean `self::alloc`?
|
||||
| ^^^^^ help: a similar path exists: `self::alloc`
|
||||
|
||||
error[E0432]: unresolved import `alloc`
|
||||
--> $DIR/resolve_self_super_hint.rs:10:13
|
||||
--> $DIR/resolve_self_super_hint.rs:11:13
|
||||
|
|
||||
LL | use alloc::HashMap;
|
||||
| ^^^^^ did you mean `super::alloc`?
|
||||
| ^^^^^ help: a similar path exists: `super::alloc`
|
||||
|
||||
error[E0432]: unresolved import `alloc`
|
||||
--> $DIR/resolve_self_super_hint.rs:14:17
|
||||
--> $DIR/resolve_self_super_hint.rs:16:17
|
||||
|
|
||||
LL | use alloc::HashMap;
|
||||
| ^^^^^ did you mean `a::alloc`?
|
||||
| ^^^^^
|
||||
| |
|
||||
| unresolved import
|
||||
| help: a similar path exists: `a::alloc`
|
||||
|
||||
error[E0432]: unresolved import `alloc`
|
||||
--> $DIR/resolve_self_super_hint.rs:18:21
|
||||
--> $DIR/resolve_self_super_hint.rs:21:21
|
||||
|
|
||||
LL | use alloc::HashMap;
|
||||
| ^^^^^ did you mean `a::alloc`?
|
||||
| ^^^^^
|
||||
| |
|
||||
| unresolved import
|
||||
| help: a similar path exists: `a::alloc`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0432]: unresolved import `alloc`
|
||||
--> $DIR/issue-54006.rs:6:5
|
||||
|
|
||||
LL | use alloc::vec;
|
||||
| ^^^^^ did you mean `core::alloc`?
|
||||
| ^^^^^ help: a similar path exists: `core::alloc`
|
||||
|
||||
error: cannot determine resolution for the macro `vec`
|
||||
--> $DIR/issue-54006.rs:10:18
|
||||
|
@ -2,7 +2,10 @@ error[E0432]: unresolved import `foobar`
|
||||
--> $DIR/local-path-suggestions-2015.rs:24:5
|
||||
|
|
||||
LL | use foobar::Baz; //~ ERROR unresolved import `foobar`
|
||||
| ^^^^^^ did you mean `aux_baz::foobar`?
|
||||
| ^^^^^^
|
||||
| |
|
||||
| unresolved import
|
||||
| help: a similar path exists: `aux_baz::foobar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0432]: unresolved import `foo`
|
||||
--> $DIR/local-path-suggestions-2018.rs:10:9
|
||||
|
|
||||
LL | use foo::Bar; //~ ERROR unresolved import `foo`
|
||||
| ^^^ did you mean `crate::foo`?
|
||||
| ^^^ help: a similar path exists: `crate::foo`
|
||||
|
|
||||
= note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
|
||||
|
||||
@ -10,7 +10,7 @@ error[E0432]: unresolved import `foobar`
|
||||
--> $DIR/local-path-suggestions-2018.rs:19:5
|
||||
|
|
||||
LL | use foobar::Baz; //~ ERROR unresolved import `foobar`
|
||||
| ^^^^^^ did you mean `baz::foobar`?
|
||||
| ^^^^^^ help: a similar path exists: `baz::foobar`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,16 +1,20 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
use foo::bar; //~ ERROR unresolved import `foo` [E0432]
|
||||
//~^ maybe a missing `extern crate foo;`?
|
||||
|
||||
use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432]
|
||||
//~^ no `Baz` in `bar`. Did you mean to use `Bar`?
|
||||
//~| no `Baz` in `bar`
|
||||
//~| HELP a similar name exists in the module
|
||||
//~| SUGGESTION Bar
|
||||
|
||||
use food::baz; //~ ERROR unresolved import `food::baz`
|
||||
//~^ no `baz` in `food`. Did you mean to use `bag`?
|
||||
//~| no `baz` in `food`
|
||||
//~| HELP a similar name exists in the module
|
||||
//~| SUGGESTION bag
|
||||
|
||||
use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432]
|
||||
//~^ no `beens` in `food`. Did you mean to use `beans`?
|
||||
//~| no `beens` in `food`
|
||||
//~| HELP a similar name exists in the module
|
||||
//~| SUGGESTION beans
|
||||
|
||||
mod bar {
|
||||
pub struct Bar;
|
||||
@ -32,7 +36,8 @@ mod m {
|
||||
}
|
||||
|
||||
use MyEnum::*; //~ ERROR unresolved import `MyEnum` [E0432]
|
||||
//~^ did you mean `self::MyEnum`?
|
||||
//~| HELP a similar path exists
|
||||
//~| SUGGESTION self::MyEnum
|
||||
}
|
||||
|
||||
mod items {
|
||||
@ -41,7 +46,8 @@ mod items {
|
||||
}
|
||||
|
||||
use Enum::*; //~ ERROR unresolved import `Enum` [E0432]
|
||||
//~^ did you mean `self::Enum`?
|
||||
//~| HELP a similar path exists
|
||||
//~| SUGGESTION self::Enum
|
||||
|
||||
fn item() {}
|
||||
}
|
||||
|
@ -1,38 +1,47 @@
|
||||
error[E0432]: unresolved import `foo`
|
||||
--> $DIR/unresolved-import.rs:3:5
|
||||
--> $DIR/unresolved-import.rs:1:5
|
||||
|
|
||||
LL | use foo::bar; //~ ERROR unresolved import `foo` [E0432]
|
||||
| ^^^ maybe a missing `extern crate foo;`?
|
||||
|
||||
error[E0432]: unresolved import `bar::Baz`
|
||||
--> $DIR/unresolved-import.rs:6:5
|
||||
--> $DIR/unresolved-import.rs:4:5
|
||||
|
|
||||
LL | use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432]
|
||||
| ^^^^^^^^^^^^^ no `Baz` in `bar`. Did you mean to use `Bar`?
|
||||
| ^^^^^---^^^^^
|
||||
| | |
|
||||
| | help: a similar name exists in the module: `Bar`
|
||||
| no `Baz` in `bar`
|
||||
|
||||
error[E0432]: unresolved import `food::baz`
|
||||
--> $DIR/unresolved-import.rs:9:5
|
||||
|
|
||||
LL | use food::baz; //~ ERROR unresolved import `food::baz`
|
||||
| ^^^^^^^^^ no `baz` in `food`. Did you mean to use `bag`?
|
||||
| ^^^^^^---
|
||||
| | |
|
||||
| | help: a similar name exists in the module: `bag`
|
||||
| no `baz` in `food`
|
||||
|
||||
error[E0432]: unresolved import `food::beens`
|
||||
--> $DIR/unresolved-import.rs:12:12
|
||||
--> $DIR/unresolved-import.rs:14:12
|
||||
|
|
||||
LL | use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432]
|
||||
| ^^^^^^^^^^^^ no `beens` in `food`. Did you mean to use `beans`?
|
||||
| -----^^^^^^^
|
||||
| |
|
||||
| no `beens` in `food`
|
||||
| help: a similar name exists in the module: `beans`
|
||||
|
||||
error[E0432]: unresolved import `MyEnum`
|
||||
--> $DIR/unresolved-import.rs:34:9
|
||||
--> $DIR/unresolved-import.rs:38:9
|
||||
|
|
||||
LL | use MyEnum::*; //~ ERROR unresolved import `MyEnum` [E0432]
|
||||
| ^^^^^^ did you mean `self::MyEnum`?
|
||||
| ^^^^^^ help: a similar path exists: `self::MyEnum`
|
||||
|
||||
error[E0432]: unresolved import `Enum`
|
||||
--> $DIR/unresolved-import.rs:43:9
|
||||
--> $DIR/unresolved-import.rs:48:9
|
||||
|
|
||||
LL | use Enum::*; //~ ERROR unresolved import `Enum` [E0432]
|
||||
| ^^^^ did you mean `self::Enum`?
|
||||
| ^^^^ help: a similar path exists: `self::Enum`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -2,7 +2,10 @@ error[E0432]: unresolved import `a::b1::C1`
|
||||
--> $DIR/use-nested-groups-error.rs:9:14
|
||||
|
|
||||
LL | use a::{b1::{C1, C2}, B2};
|
||||
| ^^ no `C1` in `a::b1`. Did you mean to use `C2`?
|
||||
| ^^
|
||||
| |
|
||||
| no `C1` in `a::b1`
|
||||
| help: a similar name exists in the module: `C2`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user