resolve: Turn resolve_error
into a method on Resolver
Rename it to `report_error` and move into `diagnostics.rs` Also turn `check_unused` into a method on `Resolver`
This commit is contained in:
parent
6a347f3701
commit
9c86ce76e5
7 changed files with 417 additions and 428 deletions
|
@ -9,7 +9,7 @@ use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleIm
|
|||
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
|
||||
use crate::{ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
|
||||
use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
|
||||
use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
|
||||
use crate::{ResolutionError, Determinacy};
|
||||
|
||||
use rustc::bug;
|
||||
use rustc::hir::def::{self, *};
|
||||
|
@ -165,8 +165,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
|||
type_ns_only = true;
|
||||
|
||||
if empty_for_self(&module_path) {
|
||||
resolve_error(
|
||||
&self.r,
|
||||
self.r.report_error(
|
||||
use_tree.span,
|
||||
ResolutionError::
|
||||
SelfImportOnlyInImportListWithNonEmptyPrefix
|
||||
|
@ -183,9 +182,9 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
|||
} else {
|
||||
// Disallow `self`
|
||||
if source.ident.name == kw::SelfLower {
|
||||
resolve_error(&self.r,
|
||||
use_tree.span,
|
||||
ResolutionError::SelfImportsOnlyAllowedWithin);
|
||||
self.r.report_error(
|
||||
use_tree.span, ResolutionError::SelfImportsOnlyAllowedWithin
|
||||
);
|
||||
}
|
||||
|
||||
// Disallow `use $crate;`
|
||||
|
@ -283,7 +282,7 @@ impl<'a> BuildReducedGraphVisitor<'_, 'a> {
|
|||
None
|
||||
}).collect::<Vec<_>>();
|
||||
if self_spans.len() > 1 {
|
||||
let mut e = resolve_struct_error(&self.r,
|
||||
let mut e = self.r.into_struct_error(
|
||||
self_spans[0],
|
||||
ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
|
||||
|
||||
|
|
|
@ -221,100 +221,102 @@ fn calc_unused_spans(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(resolver: &mut Resolver<'_>, krate: &ast::Crate) {
|
||||
for directive in resolver.potentially_unused_imports.iter() {
|
||||
match directive.subclass {
|
||||
_ if directive.used.get() ||
|
||||
directive.vis.get() == ty::Visibility::Public ||
|
||||
directive.span.is_dummy() => {
|
||||
if let ImportDirectiveSubclass::MacroUse = directive.subclass {
|
||||
if !directive.span.is_dummy() {
|
||||
resolver.session.buffer_lint(
|
||||
lint::builtin::MACRO_USE_EXTERN_CRATE,
|
||||
directive.id,
|
||||
directive.span,
|
||||
"deprecated `#[macro_use]` directive used to \
|
||||
import macros should be replaced at use sites \
|
||||
with a `use` statement to import the macro \
|
||||
instead",
|
||||
);
|
||||
impl Resolver<'_> {
|
||||
crate fn check_unused(&mut self, krate: &ast::Crate) {
|
||||
for directive in self.potentially_unused_imports.iter() {
|
||||
match directive.subclass {
|
||||
_ if directive.used.get() ||
|
||||
directive.vis.get() == ty::Visibility::Public ||
|
||||
directive.span.is_dummy() => {
|
||||
if let ImportDirectiveSubclass::MacroUse = directive.subclass {
|
||||
if !directive.span.is_dummy() {
|
||||
self.session.buffer_lint(
|
||||
lint::builtin::MACRO_USE_EXTERN_CRATE,
|
||||
directive.id,
|
||||
directive.span,
|
||||
"deprecated `#[macro_use]` directive used to \
|
||||
import macros should be replaced at use sites \
|
||||
with a `use` statement to import the macro \
|
||||
instead",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImportDirectiveSubclass::ExternCrate { .. } => {
|
||||
self.maybe_unused_extern_crates.push((directive.id, directive.span));
|
||||
}
|
||||
ImportDirectiveSubclass::MacroUse => {
|
||||
let lint = lint::builtin::UNUSED_IMPORTS;
|
||||
let msg = "unused `#[macro_use]` import";
|
||||
self.session.buffer_lint(lint, directive.id, directive.span, msg);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
ImportDirectiveSubclass::ExternCrate { .. } => {
|
||||
resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
|
||||
}
|
||||
ImportDirectiveSubclass::MacroUse => {
|
||||
let lint = lint::builtin::UNUSED_IMPORTS;
|
||||
let msg = "unused `#[macro_use]` import";
|
||||
resolver.session.buffer_lint(lint, directive.id, directive.span, msg);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut visitor = UnusedImportCheckVisitor {
|
||||
r: self,
|
||||
unused_imports: Default::default(),
|
||||
base_use_tree: None,
|
||||
base_id: ast::DUMMY_NODE_ID,
|
||||
item_span: DUMMY_SP,
|
||||
};
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
|
||||
for unused in visitor.unused_imports.values() {
|
||||
let mut fixes = Vec::new();
|
||||
let mut spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) {
|
||||
UnusedSpanResult::Used => continue,
|
||||
UnusedSpanResult::FlatUnused(span, remove) => {
|
||||
fixes.push((remove, String::new()));
|
||||
vec![span]
|
||||
}
|
||||
UnusedSpanResult::NestedFullUnused(spans, remove) => {
|
||||
fixes.push((remove, String::new()));
|
||||
spans
|
||||
}
|
||||
UnusedSpanResult::NestedPartialUnused(spans, remove) => {
|
||||
for fix in &remove {
|
||||
fixes.push((*fix, String::new()));
|
||||
}
|
||||
spans
|
||||
}
|
||||
};
|
||||
|
||||
let len = spans.len();
|
||||
spans.sort();
|
||||
let ms = MultiSpan::from_spans(spans.clone());
|
||||
let mut span_snippets = spans.iter()
|
||||
.filter_map(|s| {
|
||||
match visitor.r.session.source_map().span_to_snippet(*s) {
|
||||
Ok(s) => Some(format!("`{}`", s)),
|
||||
_ => None,
|
||||
}
|
||||
}).collect::<Vec<String>>();
|
||||
span_snippets.sort();
|
||||
let msg = format!("unused import{}{}",
|
||||
if len > 1 { "s" } else { "" },
|
||||
if !span_snippets.is_empty() {
|
||||
format!(": {}", span_snippets.join(", "))
|
||||
} else {
|
||||
String::new()
|
||||
});
|
||||
|
||||
let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
|
||||
"remove the whole `use` item"
|
||||
} else if spans.len() > 1 {
|
||||
"remove the unused imports"
|
||||
} else {
|
||||
"remove the unused import"
|
||||
};
|
||||
|
||||
visitor.r.session.buffer_lint_with_diagnostic(
|
||||
lint::builtin::UNUSED_IMPORTS,
|
||||
unused.use_tree_id,
|
||||
ms,
|
||||
&msg,
|
||||
lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = UnusedImportCheckVisitor {
|
||||
r: resolver,
|
||||
unused_imports: Default::default(),
|
||||
base_use_tree: None,
|
||||
base_id: ast::DUMMY_NODE_ID,
|
||||
item_span: DUMMY_SP,
|
||||
};
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
|
||||
for unused in visitor.unused_imports.values() {
|
||||
let mut fixes = Vec::new();
|
||||
let mut spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) {
|
||||
UnusedSpanResult::Used => continue,
|
||||
UnusedSpanResult::FlatUnused(span, remove) => {
|
||||
fixes.push((remove, String::new()));
|
||||
vec![span]
|
||||
}
|
||||
UnusedSpanResult::NestedFullUnused(spans, remove) => {
|
||||
fixes.push((remove, String::new()));
|
||||
spans
|
||||
}
|
||||
UnusedSpanResult::NestedPartialUnused(spans, remove) => {
|
||||
for fix in &remove {
|
||||
fixes.push((*fix, String::new()));
|
||||
}
|
||||
spans
|
||||
}
|
||||
};
|
||||
|
||||
let len = spans.len();
|
||||
spans.sort();
|
||||
let ms = MultiSpan::from_spans(spans.clone());
|
||||
let mut span_snippets = spans.iter()
|
||||
.filter_map(|s| {
|
||||
match visitor.r.session.source_map().span_to_snippet(*s) {
|
||||
Ok(s) => Some(format!("`{}`", s)),
|
||||
_ => None,
|
||||
}
|
||||
}).collect::<Vec<String>>();
|
||||
span_snippets.sort();
|
||||
let msg = format!("unused import{}{}",
|
||||
if len > 1 { "s" } else { "" },
|
||||
if !span_snippets.is_empty() {
|
||||
format!(": {}", span_snippets.join(", "))
|
||||
} else {
|
||||
String::new()
|
||||
});
|
||||
|
||||
let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
|
||||
"remove the whole `use` item"
|
||||
} else if spans.len() > 1 {
|
||||
"remove the unused imports"
|
||||
} else {
|
||||
"remove the unused import"
|
||||
};
|
||||
|
||||
visitor.r.session.buffer_lint_with_diagnostic(
|
||||
lint::builtin::UNUSED_IMPORTS,
|
||||
unused.use_tree_id,
|
||||
ms,
|
||||
&msg,
|
||||
lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::cmp::Reverse;
|
||||
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||
use log::debug;
|
||||
use rustc::bug;
|
||||
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
|
||||
use rustc::hir::def::Namespace::{self, *};
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
|
@ -11,14 +12,16 @@ use rustc::util::nodemap::FxHashSet;
|
|||
use syntax::ast::{self, Ident, Path};
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::feature_gate::BUILTIN_ATTRIBUTES;
|
||||
use syntax::source_map::SourceMap;
|
||||
use syntax::struct_span_err;
|
||||
use syntax::symbol::{Symbol, kw};
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax_pos::{BytePos, Span};
|
||||
use syntax_pos::{BytePos, Span, MultiSpan};
|
||||
|
||||
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
|
||||
use crate::{path_names_to_string, KNOWN_TOOLS};
|
||||
use crate::{CrateLint, LegacyScope, Module, ModuleOrUniformRoot};
|
||||
use crate::{PathResult, ParentScope, Resolver, Scope, ScopeSet, Segment};
|
||||
use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
|
||||
|
||||
type Res = def::Res<ast::NodeId>;
|
||||
|
||||
|
@ -42,6 +45,19 @@ crate struct ImportSuggestion {
|
|||
pub path: Path,
|
||||
}
|
||||
|
||||
/// Adjust the impl span so that just the `impl` keyword is taken by removing
|
||||
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
|
||||
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
|
||||
///
|
||||
/// *Attention*: the method used is very fragile since it essentially duplicates the work of the
|
||||
/// parser. If you need to use this function or something similar, please consider updating the
|
||||
/// `source_map` functions and this function to something more robust.
|
||||
fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
|
||||
let impl_span = cm.span_until_char(impl_span, '<');
|
||||
let impl_span = cm.span_until_whitespace(impl_span);
|
||||
impl_span
|
||||
}
|
||||
|
||||
crate fn add_typo_suggestion(
|
||||
err: &mut DiagnosticBuilder<'_>, suggestion: Option<TypoSuggestion>, span: Span
|
||||
) -> bool {
|
||||
|
@ -71,6 +87,269 @@ crate fn add_module_candidates(
|
|||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
/// Combines an error with provided span and emits it.
|
||||
///
|
||||
/// This takes the error provided, combines it with the span and any additional spans inside the
|
||||
/// error and emits it.
|
||||
crate fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) {
|
||||
self.into_struct_error(span, resolution_error).emit();
|
||||
}
|
||||
|
||||
crate fn into_struct_error(
|
||||
&self, span: Span, resolution_error: ResolutionError<'_>
|
||||
) -> DiagnosticBuilder<'_> {
|
||||
match resolution_error {
|
||||
ResolutionError::GenericParamsFromOuterFunction(outer_res) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0401,
|
||||
"can't use generic parameters from outer function",
|
||||
);
|
||||
err.span_label(span, format!("use of generic parameter from outer function"));
|
||||
|
||||
let cm = self.session.source_map();
|
||||
match outer_res {
|
||||
Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
|
||||
if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| {
|
||||
self.definitions.opt_span(def_id)
|
||||
}) {
|
||||
err.span_label(
|
||||
reduce_impl_span_to_impl_keyword(cm, impl_span),
|
||||
"`Self` type implicitly declared here, by this `impl`",
|
||||
);
|
||||
}
|
||||
match (maybe_trait_defid, maybe_impl_defid) {
|
||||
(Some(_), None) => {
|
||||
err.span_label(span, "can't use `Self` here");
|
||||
}
|
||||
(_, Some(_)) => {
|
||||
err.span_label(span, "use a type here instead");
|
||||
}
|
||||
(None, None) => bug!("`impl` without trait nor type?"),
|
||||
}
|
||||
return err;
|
||||
},
|
||||
Res::Def(DefKind::TyParam, def_id) => {
|
||||
if let Some(span) = self.definitions.opt_span(def_id) {
|
||||
err.span_label(span, "type parameter from outer function");
|
||||
}
|
||||
}
|
||||
Res::Def(DefKind::ConstParam, def_id) => {
|
||||
if let Some(span) = self.definitions.opt_span(def_id) {
|
||||
err.span_label(span, "const parameter from outer function");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
bug!("GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
|
||||
DefKind::TyParam");
|
||||
}
|
||||
}
|
||||
|
||||
// Try to retrieve the span of the function signature and generate a new message
|
||||
// with a local type or const parameter.
|
||||
let sugg_msg = &format!("try using a local generic parameter instead");
|
||||
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
|
||||
// Suggest the modification to the user
|
||||
err.span_suggestion(
|
||||
sugg_span,
|
||||
sugg_msg,
|
||||
new_snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if let Some(sp) = cm.generate_fn_name_span(span) {
|
||||
err.span_label(sp,
|
||||
format!("try adding a local generic parameter in this method instead"));
|
||||
} else {
|
||||
err.help(&format!("try using a local generic parameter instead"));
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0403,
|
||||
"the name `{}` is already used for a generic \
|
||||
parameter in this list of generic parameters",
|
||||
name);
|
||||
err.span_label(span, "already used");
|
||||
err.span_label(first_use_span, format!("first use of `{}`", name));
|
||||
err
|
||||
}
|
||||
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0407,
|
||||
"method `{}` is not a member of trait `{}`",
|
||||
method,
|
||||
trait_);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
err
|
||||
}
|
||||
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0437,
|
||||
"type `{}` is not a member of trait `{}`",
|
||||
type_,
|
||||
trait_);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0438,
|
||||
"const `{}` is not a member of trait `{}`",
|
||||
const_,
|
||||
trait_);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
err
|
||||
}
|
||||
ResolutionError::VariableNotBoundInPattern(binding_error) => {
|
||||
let target_sp = binding_error.target.iter().cloned().collect::<Vec<_>>();
|
||||
let msp = MultiSpan::from_spans(target_sp.clone());
|
||||
let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
|
||||
let mut err = self.session.struct_span_err_with_code(
|
||||
msp,
|
||||
&msg,
|
||||
DiagnosticId::Error("E0408".into()),
|
||||
);
|
||||
for sp in target_sp {
|
||||
err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
|
||||
}
|
||||
let origin_sp = binding_error.origin.iter().cloned();
|
||||
for sp in origin_sp {
|
||||
err.span_label(sp, "variable not in all patterns");
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::VariableBoundWithDifferentMode(variable_name,
|
||||
first_binding_span) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0409,
|
||||
"variable `{}` is bound in inconsistent \
|
||||
ways within the same match arm",
|
||||
variable_name);
|
||||
err.span_label(span, "bound in different ways");
|
||||
err.span_label(first_binding_span, "first binding");
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0415,
|
||||
"identifier `{}` is bound more than once in this parameter list",
|
||||
identifier);
|
||||
err.span_label(span, "used as parameter more than once");
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0416,
|
||||
"identifier `{}` is bound more than once in the same pattern",
|
||||
identifier);
|
||||
err.span_label(span, "used in a pattern more than once");
|
||||
err
|
||||
}
|
||||
ResolutionError::UndeclaredLabel(name, lev_candidate) => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0426,
|
||||
"use of undeclared label `{}`",
|
||||
name);
|
||||
if let Some(lev_candidate) = lev_candidate {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"a label with a similar name exists in this scope",
|
||||
lev_candidate.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(span, format!("undeclared label `{}`", name));
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
||||
struct_span_err!(self.session,
|
||||
span,
|
||||
E0429,
|
||||
"{}",
|
||||
"`self` imports are only allowed within a { } list")
|
||||
}
|
||||
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
|
||||
let mut err = struct_span_err!(self.session, span, E0430,
|
||||
"`self` import can only appear once in an import list");
|
||||
err.span_label(span, "can only appear once in an import list");
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
|
||||
let mut err = struct_span_err!(self.session, span, E0431,
|
||||
"`self` import can only appear in an import list with \
|
||||
a non-empty prefix");
|
||||
err.span_label(span, "can only appear in an import list with a non-empty prefix");
|
||||
err
|
||||
}
|
||||
ResolutionError::FailedToResolve { label, suggestion } => {
|
||||
let mut err = struct_span_err!(self.session, span, E0433,
|
||||
"failed to resolve: {}", &label);
|
||||
err.span_label(span, label);
|
||||
|
||||
if let Some((suggestions, msg, applicability)) = suggestion {
|
||||
err.multipart_suggestion(&msg, suggestions, applicability);
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
||||
let mut err = struct_span_err!(self.session,
|
||||
span,
|
||||
E0434,
|
||||
"{}",
|
||||
"can't capture dynamic environment in a fn item");
|
||||
err.help("use the `|| { ... }` closure form instead");
|
||||
err
|
||||
}
|
||||
ResolutionError::AttemptToUseNonConstantValueInConstant => {
|
||||
let mut err = struct_span_err!(self.session, span, E0435,
|
||||
"attempt to use a non-constant value in a constant");
|
||||
err.span_label(span, "non-constant value");
|
||||
err
|
||||
}
|
||||
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
|
||||
let shadows_what = binding.descr();
|
||||
let mut err = struct_span_err!(self.session, span, E0530, "{}s cannot shadow {}s",
|
||||
what_binding, shadows_what);
|
||||
err.span_label(span, format!("cannot be named the same as {} {}",
|
||||
binding.article(), shadows_what));
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
|
||||
err.span_label(binding.span, msg);
|
||||
err
|
||||
}
|
||||
ResolutionError::ForwardDeclaredTyParam => {
|
||||
let mut err = struct_span_err!(self.session, span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers");
|
||||
err.span_label(
|
||||
span, "defaulted type parameters cannot be forward declared".to_string());
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstParamDependentOnTypeParam => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
span,
|
||||
E0671,
|
||||
"const parameters cannot depend on type parameters"
|
||||
);
|
||||
err.span_label(span, format!("const parameter depends on type parameter"));
|
||||
err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lookup typo candidate in scope for a macro or import.
|
||||
fn early_lookup_typo_candidate(
|
||||
&mut self,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use GenericParameters::*;
|
||||
|
||||
use crate::{path_names_to_string, resolve_error};
|
||||
use crate::{AliasPossibility, BindingError, CrateLint, LexicalScopeBinding, Module};
|
||||
use crate::{ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
|
||||
use crate::{path_names_to_string, AliasPossibility, BindingError, CrateLint, LexicalScopeBinding};
|
||||
use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
|
||||
use crate::{PathSource, ResolutionError, Resolver, Rib, RibKind, Segment, UseError};
|
||||
use crate::RibKind::*;
|
||||
|
||||
|
@ -582,7 +581,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
ident.name,
|
||||
*span,
|
||||
);
|
||||
resolve_error(&self.r, param.ident.span, err);
|
||||
self.r.report_error(param.ident.span, err);
|
||||
}
|
||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||
|
||||
|
@ -604,7 +603,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
ident.name,
|
||||
*span,
|
||||
);
|
||||
resolve_error(&self.r, param.ident.span, err);
|
||||
self.r.report_error(param.ident.span, err);
|
||||
}
|
||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||
|
||||
|
@ -873,7 +872,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
span,
|
||||
).is_err() {
|
||||
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
|
||||
resolve_error(&self.r, span, err(ident.name, &path_names_to_string(path)));
|
||||
self.r.report_error(span, err(ident.name, &path_names_to_string(path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -971,15 +970,14 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
let mut missing_vars = missing_vars.iter().collect::<Vec<_>>();
|
||||
missing_vars.sort();
|
||||
for (_, v) in missing_vars {
|
||||
resolve_error(&self.r,
|
||||
*v.origin.iter().next().unwrap(),
|
||||
ResolutionError::VariableNotBoundInPattern(v));
|
||||
self.r.report_error(
|
||||
*v.origin.iter().next().unwrap(), ResolutionError::VariableNotBoundInPattern(v)
|
||||
);
|
||||
}
|
||||
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
|
||||
inconsistent_vars.sort();
|
||||
for (name, v) in inconsistent_vars {
|
||||
let err = ResolutionError::VariableBoundWithDifferentMode(*name, v.1);
|
||||
resolve_error(&self.r, v.0, err);
|
||||
self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1067,8 +1065,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
match bindings.get(&ident).cloned() {
|
||||
Some(id) if id == outer_pat_id => {
|
||||
// `Variant(a, a)`, error
|
||||
resolve_error(
|
||||
&self.r,
|
||||
self.r.report_error(
|
||||
ident.span,
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
|
||||
&ident.as_str())
|
||||
|
@ -1076,8 +1073,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
}
|
||||
Some(..) if pat_src == PatternSource::FnParam => {
|
||||
// `fn f(a: u8, a: u8)`, error
|
||||
resolve_error(
|
||||
&self.r,
|
||||
self.r.report_error(
|
||||
ident.span,
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
|
||||
&ident.as_str())
|
||||
|
@ -1141,8 +1137,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
// to something unusable as a pattern (e.g., constructor function),
|
||||
// but we still conservatively report an error, see
|
||||
// issues/33118#issuecomment-233962221 for one reason why.
|
||||
resolve_error(
|
||||
&self.r,
|
||||
self.r.report_error(
|
||||
ident.span,
|
||||
ResolutionError::BindingShadowsSomethingUnacceptable(
|
||||
pat_src.descr(), ident.name, binding.unwrap())
|
||||
|
@ -1448,8 +1443,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
|
||||
PartialRes::new(module.res().unwrap()),
|
||||
PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
|
||||
let err = ResolutionError::FailedToResolve { label, suggestion };
|
||||
resolve_error(&self.r, span, err);
|
||||
self.r.report_error(span, ResolutionError::FailedToResolve { label, suggestion });
|
||||
PartialRes::new(Res::Err)
|
||||
}
|
||||
PathResult::Module(..) | PathResult::Failed { .. } => return None,
|
||||
|
@ -1539,10 +1533,10 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
|||
find_best_match_for_name(names, &*ident.as_str(), None)
|
||||
});
|
||||
self.r.record_partial_res(expr.id, PartialRes::new(Res::Err));
|
||||
resolve_error(&self.r,
|
||||
label.ident.span,
|
||||
ResolutionError::UndeclaredLabel(&label.ident.as_str(),
|
||||
close_match));
|
||||
self.r.report_error(
|
||||
label.ident.span,
|
||||
ResolutionError::UndeclaredLabel(&label.ident.as_str(), close_match),
|
||||
);
|
||||
}
|
||||
Some(node_id) => {
|
||||
// Since this res is a label, it is never read.
|
||||
|
|
|
@ -33,7 +33,6 @@ use rustc::{bug, span_bug};
|
|||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
|
||||
use syntax::source_map::SourceMap;
|
||||
use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
|
||||
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
|
||||
use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
|
||||
|
@ -45,8 +44,8 @@ use syntax::ast::{CRATE_NODE_ID, Crate, Expr, ExprKind};
|
|||
use syntax::ast::{ItemKind, Path};
|
||||
use syntax::{span_err, struct_span_err, unwrap_or};
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
|
||||
use log::debug;
|
||||
|
||||
|
@ -200,285 +199,6 @@ enum ResolutionError<'a> {
|
|||
ConstParamDependentOnTypeParam,
|
||||
}
|
||||
|
||||
/// Combines an error with provided span and emits it.
|
||||
///
|
||||
/// This takes the error provided, combines it with the span and any additional spans inside the
|
||||
/// error and emits it.
|
||||
fn resolve_error(resolver: &Resolver<'_>,
|
||||
span: Span,
|
||||
resolution_error: ResolutionError<'_>) {
|
||||
resolve_struct_error(resolver, span, resolution_error).emit();
|
||||
}
|
||||
|
||||
fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
|
||||
span: Span,
|
||||
resolution_error: ResolutionError<'a>)
|
||||
-> DiagnosticBuilder<'sess> {
|
||||
match resolution_error {
|
||||
ResolutionError::GenericParamsFromOuterFunction(outer_res) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0401,
|
||||
"can't use generic parameters from outer function",
|
||||
);
|
||||
err.span_label(span, format!("use of generic parameter from outer function"));
|
||||
|
||||
let cm = resolver.session.source_map();
|
||||
match outer_res {
|
||||
Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
|
||||
if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| {
|
||||
resolver.definitions.opt_span(def_id)
|
||||
}) {
|
||||
err.span_label(
|
||||
reduce_impl_span_to_impl_keyword(cm, impl_span),
|
||||
"`Self` type implicitly declared here, by this `impl`",
|
||||
);
|
||||
}
|
||||
match (maybe_trait_defid, maybe_impl_defid) {
|
||||
(Some(_), None) => {
|
||||
err.span_label(span, "can't use `Self` here");
|
||||
}
|
||||
(_, Some(_)) => {
|
||||
err.span_label(span, "use a type here instead");
|
||||
}
|
||||
(None, None) => bug!("`impl` without trait nor type?"),
|
||||
}
|
||||
return err;
|
||||
},
|
||||
Res::Def(DefKind::TyParam, def_id) => {
|
||||
if let Some(span) = resolver.definitions.opt_span(def_id) {
|
||||
err.span_label(span, "type parameter from outer function");
|
||||
}
|
||||
}
|
||||
Res::Def(DefKind::ConstParam, def_id) => {
|
||||
if let Some(span) = resolver.definitions.opt_span(def_id) {
|
||||
err.span_label(span, "const parameter from outer function");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
bug!("GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
|
||||
DefKind::TyParam");
|
||||
}
|
||||
}
|
||||
|
||||
// Try to retrieve the span of the function signature and generate a new message with
|
||||
// a local type or const parameter.
|
||||
let sugg_msg = &format!("try using a local generic parameter instead");
|
||||
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
|
||||
// Suggest the modification to the user
|
||||
err.span_suggestion(
|
||||
sugg_span,
|
||||
sugg_msg,
|
||||
new_snippet,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if let Some(sp) = cm.generate_fn_name_span(span) {
|
||||
err.span_label(sp,
|
||||
format!("try adding a local generic parameter in this method instead"));
|
||||
} else {
|
||||
err.help(&format!("try using a local generic parameter instead"));
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0403,
|
||||
"the name `{}` is already used for a generic \
|
||||
parameter in this list of generic parameters",
|
||||
name);
|
||||
err.span_label(span, "already used");
|
||||
err.span_label(first_use_span, format!("first use of `{}`", name));
|
||||
err
|
||||
}
|
||||
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0407,
|
||||
"method `{}` is not a member of trait `{}`",
|
||||
method,
|
||||
trait_);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
err
|
||||
}
|
||||
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0437,
|
||||
"type `{}` is not a member of trait `{}`",
|
||||
type_,
|
||||
trait_);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0438,
|
||||
"const `{}` is not a member of trait `{}`",
|
||||
const_,
|
||||
trait_);
|
||||
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
||||
err
|
||||
}
|
||||
ResolutionError::VariableNotBoundInPattern(binding_error) => {
|
||||
let target_sp = binding_error.target.iter().cloned().collect::<Vec<_>>();
|
||||
let msp = MultiSpan::from_spans(target_sp.clone());
|
||||
let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
|
||||
let mut err = resolver.session.struct_span_err_with_code(
|
||||
msp,
|
||||
&msg,
|
||||
DiagnosticId::Error("E0408".into()),
|
||||
);
|
||||
for sp in target_sp {
|
||||
err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
|
||||
}
|
||||
let origin_sp = binding_error.origin.iter().cloned();
|
||||
for sp in origin_sp {
|
||||
err.span_label(sp, "variable not in all patterns");
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::VariableBoundWithDifferentMode(variable_name,
|
||||
first_binding_span) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0409,
|
||||
"variable `{}` is bound in inconsistent \
|
||||
ways within the same match arm",
|
||||
variable_name);
|
||||
err.span_label(span, "bound in different ways");
|
||||
err.span_label(first_binding_span, "first binding");
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0415,
|
||||
"identifier `{}` is bound more than once in this parameter list",
|
||||
identifier);
|
||||
err.span_label(span, "used as parameter more than once");
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0416,
|
||||
"identifier `{}` is bound more than once in the same pattern",
|
||||
identifier);
|
||||
err.span_label(span, "used in a pattern more than once");
|
||||
err
|
||||
}
|
||||
ResolutionError::UndeclaredLabel(name, lev_candidate) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0426,
|
||||
"use of undeclared label `{}`",
|
||||
name);
|
||||
if let Some(lev_candidate) = lev_candidate {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"a label with a similar name exists in this scope",
|
||||
lev_candidate.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_label(span, format!("undeclared label `{}`", name));
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0429,
|
||||
"{}",
|
||||
"`self` imports are only allowed within a { } list")
|
||||
}
|
||||
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
|
||||
let mut err = struct_span_err!(resolver.session, span, E0430,
|
||||
"`self` import can only appear once in an import list");
|
||||
err.span_label(span, "can only appear once in an import list");
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
|
||||
let mut err = struct_span_err!(resolver.session, span, E0431,
|
||||
"`self` import can only appear in an import list with \
|
||||
a non-empty prefix");
|
||||
err.span_label(span, "can only appear in an import list with a non-empty prefix");
|
||||
err
|
||||
}
|
||||
ResolutionError::FailedToResolve { label, suggestion } => {
|
||||
let mut err = struct_span_err!(resolver.session, span, E0433,
|
||||
"failed to resolve: {}", &label);
|
||||
err.span_label(span, label);
|
||||
|
||||
if let Some((suggestions, msg, applicability)) = suggestion {
|
||||
err.multipart_suggestion(&msg, suggestions, applicability);
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0434,
|
||||
"{}",
|
||||
"can't capture dynamic environment in a fn item");
|
||||
err.help("use the `|| { ... }` closure form instead");
|
||||
err
|
||||
}
|
||||
ResolutionError::AttemptToUseNonConstantValueInConstant => {
|
||||
let mut err = struct_span_err!(resolver.session, span, E0435,
|
||||
"attempt to use a non-constant value in a constant");
|
||||
err.span_label(span, "non-constant value");
|
||||
err
|
||||
}
|
||||
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
|
||||
let shadows_what = binding.descr();
|
||||
let mut err = struct_span_err!(resolver.session, span, E0530, "{}s cannot shadow {}s",
|
||||
what_binding, shadows_what);
|
||||
err.span_label(span, format!("cannot be named the same as {} {}",
|
||||
binding.article(), shadows_what));
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
|
||||
err.span_label(binding.span, msg);
|
||||
err
|
||||
}
|
||||
ResolutionError::ForwardDeclaredTyParam => {
|
||||
let mut err = struct_span_err!(resolver.session, span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers");
|
||||
err.span_label(
|
||||
span, "defaulted type parameters cannot be forward declared".to_string());
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstParamDependentOnTypeParam => {
|
||||
let mut err = struct_span_err!(
|
||||
resolver.session,
|
||||
span,
|
||||
E0671,
|
||||
"const parameters cannot depend on type parameters"
|
||||
);
|
||||
err.span_label(span, format!("const parameter depends on type parameter"));
|
||||
err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the impl span so that just the `impl` keyword is taken by removing
|
||||
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
|
||||
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
|
||||
///
|
||||
/// *Attention*: the method used is very fragile since it essentially duplicates the work of the
|
||||
/// parser. If you need to use this function or something similar, please consider updating the
|
||||
/// `source_map` functions and this function to something more robust.
|
||||
fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
|
||||
let impl_span = cm.span_until_char(impl_span, '<');
|
||||
let impl_span = cm.span_until_whitespace(impl_span);
|
||||
impl_span
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
enum AliasPossibility {
|
||||
No,
|
||||
|
@ -1503,7 +1223,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
|||
match self.resolve_ast_path_inner(path, is_value) {
|
||||
Ok(r) => r,
|
||||
Err((span, error)) => {
|
||||
resolve_error(self, span, error);
|
||||
self.report_error(span, error);
|
||||
Res::Err
|
||||
}
|
||||
}
|
||||
|
@ -1736,7 +1456,7 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
self.late_resolve_crate(krate);
|
||||
|
||||
check_unused::check_crate(self, krate);
|
||||
self.check_unused(krate);
|
||||
self.report_errors(krate);
|
||||
self.crate_loader.postprocess(krate);
|
||||
}
|
||||
|
@ -2581,7 +2301,7 @@ impl<'a> Resolver<'a> {
|
|||
// An invalid forward use of a type parameter from a previous default.
|
||||
if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind {
|
||||
if record_used {
|
||||
resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam);
|
||||
self.report_error(span, ResolutionError::ForwardDeclaredTyParam);
|
||||
}
|
||||
assert_eq!(res, Res::Err);
|
||||
return Res::Err;
|
||||
|
@ -2590,7 +2310,7 @@ impl<'a> Resolver<'a> {
|
|||
// An invalid use of a type parameter as the type of a const parameter.
|
||||
if let TyParamAsConstParamTy = all_ribs[rib_index].kind {
|
||||
if record_used {
|
||||
resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
|
||||
self.report_error(span, ResolutionError::ConstParamDependentOnTypeParam);
|
||||
}
|
||||
assert_eq!(res, Res::Err);
|
||||
return Res::Err;
|
||||
|
@ -2622,14 +2342,14 @@ impl<'a> Resolver<'a> {
|
|||
ConstantItemRibKind => {
|
||||
// Still doesn't deal with upvars
|
||||
if record_used {
|
||||
resolve_error(self, span, AttemptToUseNonConstantValueInConstant);
|
||||
self.report_error(span, AttemptToUseNonConstantValueInConstant);
|
||||
}
|
||||
return Res::Err;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(res_err) = res_err {
|
||||
resolve_error(self, span, res_err);
|
||||
self.report_error(span, res_err);
|
||||
return Res::Err;
|
||||
}
|
||||
}
|
||||
|
@ -2644,10 +2364,8 @@ impl<'a> Resolver<'a> {
|
|||
ItemRibKind | FnItemRibKind => {
|
||||
// This was an attempt to use a type parameter outside its scope.
|
||||
if record_used {
|
||||
resolve_error(
|
||||
self,
|
||||
span,
|
||||
ResolutionError::GenericParamsFromOuterFunction(res),
|
||||
self.report_error(
|
||||
span, ResolutionError::GenericParamsFromOuterFunction(res)
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
@ -2667,10 +2385,8 @@ impl<'a> Resolver<'a> {
|
|||
if let ItemRibKind | FnItemRibKind = rib.kind {
|
||||
// This was an attempt to use a const parameter outside its scope.
|
||||
if record_used {
|
||||
resolve_error(
|
||||
self,
|
||||
span,
|
||||
ResolutionError::GenericParamsFromOuterFunction(res),
|
||||
self.report_error(
|
||||
span, ResolutionError::GenericParamsFromOuterFunction(res)
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
@ -2773,8 +2489,9 @@ impl<'a> Resolver<'a> {
|
|||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::Failed { span, label, suggestion, .. } => {
|
||||
let err = ResolutionError::FailedToResolve { label, suggestion };
|
||||
resolve_error(self, span, err);
|
||||
self.report_error(
|
||||
span, ResolutionError::FailedToResolve { label, suggestion }
|
||||
);
|
||||
ty::Visibility::Public
|
||||
}
|
||||
PathResult::Indeterminate => {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
|
||||
use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak};
|
||||
use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
|
||||
use crate::{resolve_error, KNOWN_TOOLS};
|
||||
use crate::ModuleOrUniformRoot;
|
||||
use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
|
||||
use crate::Namespace::*;
|
||||
use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
|
||||
use crate::resolve_imports::ImportResolver;
|
||||
|
@ -768,7 +767,7 @@ impl<'a> Resolver<'a> {
|
|||
(path_span, format!("partially resolved path in {} {}",
|
||||
kind.article(), kind.descr()))
|
||||
};
|
||||
resolve_error(self, span, ResolutionError::FailedToResolve {
|
||||
self.report_error(span, ResolutionError::FailedToResolve {
|
||||
label,
|
||||
suggestion: None
|
||||
});
|
||||
|
|
|
@ -5,9 +5,8 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope
|
|||
use crate::Determinacy::{self, *};
|
||||
use crate::Namespace::{self, TypeNS, MacroNS};
|
||||
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
||||
use crate::{Resolver, Segment};
|
||||
use crate::{Resolver, ResolutionError, Segment};
|
||||
use crate::{names_to_string, module_to_string};
|
||||
use crate::{resolve_error, ResolutionError};
|
||||
use crate::ModuleKind;
|
||||
use crate::build_reduced_graph::BuildReducedGraphVisitor;
|
||||
use crate::diagnostics::Suggestion;
|
||||
|
@ -913,7 +912,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||
PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
|
||||
if no_ambiguity {
|
||||
assert!(directive.imported_module.get().is_none());
|
||||
resolve_error(&self.r, span, ResolutionError::FailedToResolve {
|
||||
self.r.report_error(span, ResolutionError::FailedToResolve {
|
||||
label,
|
||||
suggestion,
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue