diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-08-08 23:32:58 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-08-10 13:16:06 +0300 |
| commit | 9c86ce76e51439a39765343f2f9ac03e12f04898 (patch) | |
| tree | f300e8da57f0653f0fd4e19b3fb6716e19a43511 | |
| parent | 6a347f3701665a2e01f1f762d6be3b201b73bf42 (diff) | |
| download | rust-9c86ce76e51439a39765343f2f9ac03e12f04898.tar.gz rust-9c86ce76e51439a39765343f2f9ac03e12f04898.zip | |
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`
| -rw-r--r-- | src/librustc_resolve/build_reduced_graph.rs | 13 | ||||
| -rw-r--r-- | src/librustc_resolve/check_unused.rs | 172 | ||||
| -rw-r--r-- | src/librustc_resolve/diagnostics.rs | 285 | ||||
| -rw-r--r-- | src/librustc_resolve/late.rs | 40 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 313 | ||||
| -rw-r--r-- | src/librustc_resolve/macros.rs | 5 | ||||
| -rw-r--r-- | src/librustc_resolve/resolve_imports.rs | 5 |
7 files changed, 411 insertions, 422 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 25d80021269..a6fbb0babbe 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 922da7eef7a..96d44b4b4c0 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -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: 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 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); - 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, + 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 } - }).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() - }); + UnusedSpanResult::NestedPartialUnused(spans, remove) => { + for fix in &remove { + fixes.push((*fix, String::new())); + } + spans + } + }; - 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" - }; + 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() + }); - 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 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), + ); + } } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 3a39307849e..01a4a3c4bb2 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -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, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index fe0760364f3..0f68e0c054a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -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. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4aa3e2f9167..a2b1873c4f2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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 => { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index fed8e555d2b..78edb685edd 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -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 }); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 2ae2b1f3fc3..aef586fe43c 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -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, }); |
