diff --git a/src/doc/rustc-ux-guidelines.md b/src/doc/rustc-ux-guidelines.md index 93e94e5586302..e3684fc9f320a 100644 --- a/src/doc/rustc-ux-guidelines.md +++ b/src/doc/rustc-ux-guidelines.md @@ -61,17 +61,17 @@ for details on how to format and write long error codes. * All of them are accessible [online](http://doc.rust-lang.org/error-index.html), which are auto-generated from rustc source code in different places: - [librustc](https://github.com/rust-lang/rust/blob/master/src/librustc/diagnostics.rs), - [libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/diagnostics.rs), - [librustc_borrowck](https://github.com/rust-lang/rust/blob/master/src/librustc_borrowck/diagnostics.rs), - [librustc_metadata](https://github.com/rust-lang/rust/blob/master/src/librustc_metadata/diagnostics.rs), - [librustc_mir](https://github.com/rust-lang/rust/blob/master/src/librustc_mir/diagnostics.rs), - [librustc_passes](https://github.com/rust-lang/rust/blob/master/src/librustc_passes/diagnostics.rs), - [librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/diagnostics.rs), - [librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/diagnostics.rs), - [librustc_codegen_llvm](https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/diagnostics.rs), - [librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/diagnostics.rs), - [librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/diagnostics.rs). + [librustc](https://github.com/rust-lang/rust/blob/master/src/librustc/error_codes.rs), + [libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/error_codes.rs), + [librustc_borrowck](https://github.com/rust-lang/rust/blob/master/src/librustc_borrowck/error_codes.rs), + [librustc_metadata](https://github.com/rust-lang/rust/blob/master/src/librustc_metadata/error_codes.rs), + [librustc_mir](https://github.com/rust-lang/rust/blob/master/src/librustc_mir/error_codes.rs), + [librustc_passes](https://github.com/rust-lang/rust/blob/master/src/librustc_passes/error_codes.rs), + [librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/error_codes.rs), + [librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/error_codes.rs), + [librustc_codegen_llvm](https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/error_codes.rs), + [librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/error_codes.rs), + [librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/error_codes.rs). * Explanations have full markdown support. Use it, especially to highlight code with backticks. * When talking about the compiler, call it `the compiler`, not `Rust` or diff --git a/src/librustc/diagnostics.rs b/src/librustc/error_codes.rs similarity index 100% rename from src/librustc/diagnostics.rs rename to src/librustc/error_codes.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 4cbf8e3ecfc66..1bd44b13b669c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -99,7 +99,7 @@ mod macros; // N.B., this module needs to be declared first so diagnostics are // registered before they are used. -pub mod diagnostics; +pub mod error_codes; #[macro_use] pub mod query; diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/error_codes.rs similarity index 100% rename from src/librustc_borrowck/diagnostics.rs rename to src/librustc_borrowck/error_codes.rs diff --git a/src/librustc_codegen_llvm/diagnostics.rs b/src/librustc_codegen_llvm/error_codes.rs similarity index 100% rename from src/librustc_codegen_llvm/diagnostics.rs rename to src/librustc_codegen_llvm/error_codes.rs diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index da91217e95e3d..c2eee59fbb0ac 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -70,7 +70,7 @@ use rustc_mir::monomorphize; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_utils::codegen_backend::CodegenBackend; -mod diagnostics; +mod error_codes; mod back { mod archive; diff --git a/src/librustc_codegen_ssa/diagnostics.rs b/src/librustc_codegen_ssa/error_codes.rs similarity index 100% rename from src/librustc_codegen_ssa/diagnostics.rs rename to src/librustc_codegen_ssa/error_codes.rs diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index c6e689f2e83c3..49e9f6fe38ad1 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -41,7 +41,7 @@ use syntax_pos::symbol::Symbol; // N.B., this module needs to be declared first so diagnostics are // registered before they are used. -mod diagnostics; +mod error_codes; pub mod common; pub mod traits; diff --git a/src/librustc_lint/diagnostics.rs b/src/librustc_lint/error_codes.rs similarity index 100% rename from src/librustc_lint/diagnostics.rs rename to src/librustc_lint/error_codes.rs diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index ff5e4f02554cc..3f6348ec8dd75 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -25,7 +25,7 @@ #[macro_use] extern crate rustc; -mod diagnostics; +mod error_codes; mod nonstandard_style; pub mod builtin; mod types; diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/error_codes.rs similarity index 100% rename from src/librustc_metadata/diagnostics.rs rename to src/librustc_metadata/error_codes.rs diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index d052e13f9c0a7..4f84ca69b7f18 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,7 +26,7 @@ extern crate rustc; #[macro_use] extern crate rustc_data_structures; -mod diagnostics; +mod error_codes; mod index_builder; mod index; diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/error_codes.rs similarity index 100% rename from src/librustc_mir/diagnostics.rs rename to src/librustc_mir/error_codes.rs diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a16eaf011c86e..d382e53e91846 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -40,7 +40,7 @@ extern crate serialize as rustc_serialize; // used by deriving #[macro_use] extern crate syntax; -mod diagnostics; +mod error_codes; mod borrow_check; mod build; diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/error_codes.rs similarity index 100% rename from src/librustc_passes/diagnostics.rs rename to src/librustc_passes/error_codes.rs diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index db8fcaa569389..7c48feecb2110 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -19,7 +19,7 @@ extern crate rustc; use rustc::ty::query::Providers; -mod diagnostics; +mod error_codes; pub mod ast_validation; pub mod rvalue_promotion; diff --git a/src/librustc_plugin/diagnostics.rs b/src/librustc_plugin/error_codes.rs similarity index 100% rename from src/librustc_plugin/diagnostics.rs rename to src/librustc_plugin/error_codes.rs diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 351ba7f04d3b1..3775dbb79c6fd 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -61,7 +61,7 @@ pub use registry::Registry; -mod diagnostics; +mod error_codes; pub mod registry; pub mod load; pub mod build; diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/error_codes.rs similarity index 100% rename from src/librustc_privacy/diagnostics.rs rename to src/librustc_privacy/error_codes.rs diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ef315c5f95502..edb3efb78a39c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -33,7 +33,7 @@ use syntax_pos::Span; use std::{cmp, fmt, mem}; use std::marker::PhantomData; -mod diagnostics; +mod error_codes; //////////////////////////////////////////////////////////////////////////////// /// Generic infrastructure used to implement specific visitors below. diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 5c095994a1bbd..9e3894dab0da0 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1,1672 +1,856 @@ -#![allow(non_snake_case)] - -use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics}; - -// Error messages for EXXXX errors. Each message should start and end with a -// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and -// use `gq` to wrap paragraphs. Use `:set tw=0` to disable. -register_long_diagnostics! { - -E0128: r##" -Type parameter defaults can only use parameters that occur before them. -Erroneous code example: - -```compile_fail,E0128 -struct Foo { - field1: T, - filed2: U, -} -// error: type parameters with a default cannot use forward declared -// identifiers -``` - -Since type parameters are evaluated in-order, you may be able to fix this issue -by doing: - -``` -struct Foo { - field1: T, - filed2: U, -} -``` - -Please also verify that this wasn't because of a name-clash and rename the type -parameter if so. -"##, - -E0154: r##" -#### Note: this error code is no longer emitted by the compiler. - -Imports (`use` statements) are not allowed after non-item statements, such as -variable declarations and expression statements. - -Here is an example that demonstrates the error: - -``` -fn f() { - // Variable declaration before import - let x = 0; - use std::io::Read; - // ... -} -``` - -The solution is to declare the imports at the top of the block, function, or -file. - -Here is the previous example again, with the correct order: - -``` -fn f() { - use std::io::Read; - let x = 0; - // ... -} -``` - -See the Declaration Statements section of the reference for more information -about what constitutes an Item declaration and what does not: - -https://doc.rust-lang.org/reference.html#statements -"##, - -E0251: r##" -#### Note: this error code is no longer emitted by the compiler. - -Two items of the same name cannot be imported without rebinding one of the -items under a new local name. - -An example of this error: - -``` -use foo::baz; -use bar::*; // error, do `use foo::baz as quux` instead on the previous line - -fn main() {} - -mod foo { - pub struct baz; -} - -mod bar { - pub mod baz {} -} -``` -"##, - -E0252: r##" -Two items of the same name cannot be imported without rebinding one of the -items under a new local name. - -Erroneous code example: - -```compile_fail,E0252 -use foo::baz; -use bar::baz; // error, do `use bar::baz as quux` instead - -fn main() {} - -mod foo { - pub struct baz; -} - -mod bar { - pub mod baz {} -} -``` - -You can use aliases in order to fix this error. Example: - -``` -use foo::baz as foo_baz; -use bar::baz; // ok! - -fn main() {} - -mod foo { - pub struct baz; -} - -mod bar { - pub mod baz {} -} -``` - -Or you can reference the item with its parent: - -``` -use bar::baz; - -fn main() { - let x = foo::baz; // ok! -} +use std::cmp::Reverse; + +use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use log::debug; +use rustc::hir::def::{self, CtorKind, Namespace::*}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::session::{Session, config::nightly_options}; +use syntax::ast::{self, Expr, ExprKind, Ident}; +use syntax::ext::base::MacroKind; +use syntax::symbol::{Symbol, keywords}; +use syntax_pos::{BytePos, Span}; + +type Def = def::Def; + +use crate::macros::ParentScope; +use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; +use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string}; +use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult, + PathSource, Resolver, Segment, Suggestion}; + +impl<'a> Resolver<'a> { + /// Handles error reporting for `smart_resolve_path_fragment` function. + /// Creates base error and amends it with one short label and possibly some longer helps/notes. + pub(crate) fn smart_resolve_report_errors( + &mut self, + path: &[Segment], + span: Span, + source: PathSource<'_>, + def: Option, + ) -> (DiagnosticBuilder<'a>, Vec) { + let ident_span = path.last().map_or(span, |ident| ident.ident.span); + let ns = source.namespace(); + let is_expected = &|def| source.is_expected(def); + let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; + + // Make the base error. + let expected = source.descr_expected(); + let path_str = Segment::names_to_string(path); + let item_str = path.last().unwrap().ident; + let code = source.error_code(def.is_some()); + let (base_msg, fallback_label, base_span) = if let Some(def) = def { + (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), + format!("not a {}", expected), + span) + } else { + let item_span = path.last().unwrap().ident.span; + let (mod_prefix, mod_str) = if path.len() == 1 { + (String::new(), "this scope".to_string()) + } else if path.len() == 2 && path[0].ident.name == keywords::PathRoot.name() { + (String::new(), "the crate root".to_string()) + } else { + let mod_path = &path[..path.len() - 1]; + let mod_prefix = match self.resolve_path_without_parent_scope( + mod_path, Some(TypeNS), false, span, CrateLint::No + ) { + PathResult::Module(ModuleOrUniformRoot::Module(module)) => + module.def(), + _ => None, + }.map_or(String::new(), |def| format!("{} ", def.kind_name())); + (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) + }; + (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), + format!("not found in {}", mod_str), + item_span) + }; + + let code = DiagnosticId::Error(code.into()); + let mut err = self.session.struct_span_err_with_code(base_span, &base_msg, code); + + // Emit help message for fake-self from other languages (e.g., `this` in Javascript). + if ["this", "my"].contains(&&*item_str.as_str()) + && self.self_value_is_available(path[0].ident.span, span) { + err.span_suggestion( + span, + "did you mean", + "self".to_string(), + Applicability::MaybeIncorrect, + ); + } -mod foo { - pub struct baz; -} + // Emit special messages for unresolved `Self` and `self`. + if is_self_type(path, ns) { + __diagnostic_used!(E0411); + err.code(DiagnosticId::Error("E0411".into())); + err.span_label(span, format!("`Self` is only available in impls, traits, \ + and type definitions")); + return (err, Vec::new()); + } + if is_self_value(path, ns) { + debug!("smart_resolve_path_fragment: E0424, source={:?}", source); + + __diagnostic_used!(E0424); + err.code(DiagnosticId::Error("E0424".into())); + err.span_label(span, match source { + PathSource::Pat => { + format!("`self` value is a keyword \ + and may not be bound to \ + variables or shadowed") + } + _ => { + format!("`self` value is a keyword \ + only available in methods \ + with `self` parameter") + } + }); + return (err, Vec::new()); + } -mod bar { - pub mod baz {} -} -``` -"##, + // Try to lookup name in more relaxed fashion for better error reporting. + let ident = path.last().unwrap().ident; + let candidates = self.lookup_import_candidates(ident, ns, is_expected) + .drain(..) + .filter(|ImportSuggestion { did, .. }| { + match (did, def.and_then(|def| def.opt_def_id())) { + (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, + _ => true, + } + }) + .collect::>(); + if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { + let enum_candidates = + self.lookup_import_candidates(ident, ns, is_enum_variant); + let mut enum_candidates = enum_candidates.iter() + .map(|suggestion| { + import_candidate_to_enum_paths(&suggestion) + }).collect::>(); + enum_candidates.sort(); + + if !enum_candidates.is_empty() { + // Contextualize for E0412 "cannot find type", but don't belabor the point + // (that it's a variant) for E0573 "expected type, found variant". + let preamble = if def.is_none() { + let others = match enum_candidates.len() { + 1 => String::new(), + 2 => " and 1 other".to_owned(), + n => format!(" and {} others", n) + }; + format!("there is an enum variant `{}`{}; ", + enum_candidates[0].0, others) + } else { + String::new() + }; + let msg = format!("{}try using the variant's enum", preamble); + + err.span_suggestions( + span, + &msg, + enum_candidates.into_iter() + .map(|(_variant_path, enum_ty_path)| enum_ty_path) + // Variants re-exported in prelude doesn't mean `prelude::v1` is the + // type name! + // FIXME: is there a more principled way to do this that + // would work for other re-exports? + .filter(|enum_ty_path| enum_ty_path != "std::prelude::v1") + // Also write `Option` rather than `std::prelude::v1::Option`. + .map(|enum_ty_path| { + // FIXME #56861: DRY-er prelude filtering. + enum_ty_path.trim_start_matches("std::prelude::v1::").to_owned() + }), + Applicability::MachineApplicable, + ); + } + } + if path.len() == 1 && self.self_type_is_available(span) { + if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) { + let self_is_available = self.self_value_is_available(path[0].ident.span, span); + match candidate { + AssocSuggestion::Field => { + err.span_suggestion( + span, + "try", + format!("self.{}", path_str), + Applicability::MachineApplicable, + ); + if !self_is_available { + err.span_label(span, format!("`self` value is a keyword \ + only available in \ + methods with `self` parameter")); + } + } + AssocSuggestion::MethodWithSelf if self_is_available => { + err.span_suggestion( + span, + "try", + format!("self.{}", path_str), + Applicability::MachineApplicable, + ); + } + AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { + err.span_suggestion( + span, + "try", + format!("Self::{}", path_str), + Applicability::MachineApplicable, + ); + } + } + return (err, candidates); + } + } -E0253: r##" -Attempt was made to import an unimportable value. This can happen when trying -to import a method from a trait. + let mut levenshtein_worked = false; + + // Try Levenshtein algorithm. + let suggestion = self.lookup_typo_candidate(path, ns, is_expected, span); + if let Some(suggestion) = suggestion { + let msg = format!( + "{} {} with a similar name exists", + suggestion.article, suggestion.kind + ); + err.span_suggestion( + ident_span, + &msg, + suggestion.candidate.to_string(), + Applicability::MaybeIncorrect, + ); + + levenshtein_worked = true; + } -Erroneous code example: + // Try context-dependent help if relaxed lookup didn't work. + if let Some(def) = def { + if self.smart_resolve_context_dependent_help(&mut err, + span, + source, + def, + &path_str, + &fallback_label) { + return (err, candidates); + } + } -```compile_fail,E0253 -mod foo { - pub trait MyTrait { - fn do_something(); + // Fallback label. + if !levenshtein_worked { + err.span_label(base_span, fallback_label); + self.type_ascription_suggestion(&mut err, base_span); + } + (err, candidates) } -} - -use foo::MyTrait::do_something; -// error: `do_something` is not directly importable - -fn main() {} -``` - -It's invalid to directly import methods belonging to a trait or concrete type. -"##, - -E0254: r##" -Attempt was made to import an item whereas an extern crate with this name has -already been imported. - -Erroneous code example: -```compile_fail,E0254 -extern crate core; - -mod foo { - pub trait core { - fn do_something(); + /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment` + /// function. + /// Returns `true` if able to provide context-dependent help. + fn smart_resolve_context_dependent_help( + &mut self, + err: &mut DiagnosticBuilder<'a>, + span: Span, + source: PathSource<'_>, + def: Def, + path_str: &str, + fallback_label: &str, + ) -> bool { + let ns = source.namespace(); + let is_expected = &|def| source.is_expected(def); + + let path_sep = |err: &mut DiagnosticBuilder<'_>, expr: &Expr| match expr.node { + ExprKind::Field(_, ident) => { + err.span_suggestion( + expr.span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, ident), + Applicability::MaybeIncorrect, + ); + true + } + ExprKind::MethodCall(ref segment, ..) => { + let span = expr.span.with_hi(segment.ident.span.hi()); + err.span_suggestion( + span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, segment.ident), + Applicability::MaybeIncorrect, + ); + true + } + _ => false, + }; + + match (def, source) { + (Def::Macro(..), _) => { + err.span_suggestion( + span, + "use `!` to invoke the macro", + format!("{}!", path_str), + Applicability::MaybeIncorrect, + ); + if path_str == "try" && span.rust_2015() { + err.note("if you want the `try` keyword, you need to be in the 2018 edition"); + } + } + (Def::TyAlias(..), PathSource::Trait(_)) => { + err.span_label(span, "type aliases cannot be used as traits"); + if nightly_options::is_nightly_build() { + err.note("did you mean to use a trait alias?"); + } + } + (Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) { + return false; + }, + (Def::Enum(..), PathSource::TupleStruct) + | (Def::Enum(..), PathSource::Expr(..)) => { + if let Some(variants) = self.collect_enum_variants(def) { + if !variants.is_empty() { + let msg = if variants.len() == 1 { + "try using the enum's variant" + } else { + "try using one of the enum's variants" + }; + + err.span_suggestions( + span, + msg, + variants.iter().map(path_names_to_string), + Applicability::MaybeIncorrect, + ); + } + } else { + err.note("did you mean to use one of the enum's variants?"); + } + }, + (Def::Struct(def_id), _) if ns == ValueNS => { + if let Some((ctor_def, ctor_vis)) + = self.struct_constructors.get(&def_id).cloned() { + let accessible_ctor = self.is_accessible(ctor_vis); + if is_expected(ctor_def) && !accessible_ctor { + err.span_label( + span, + format!("constructor is not visible here due to private fields"), + ); + } + } else { + // HACK(estebank): find a better way to figure out that this was a + // parser issue where a struct literal is being used on an expression + // where a brace being opened means a block is being started. Look + // ahead for the next text to see if `span` is followed by a `{`. + let sm = self.session.source_map(); + let mut sp = span; + loop { + sp = sm.next_point(sp); + match sm.span_to_snippet(sp) { + Ok(ref snippet) => { + if snippet.chars().any(|c| { !c.is_whitespace() }) { + break; + } + } + _ => break, + } + } + let followed_by_brace = match sm.span_to_snippet(sp) { + Ok(ref snippet) if snippet == "{" => true, + _ => false, + }; + // In case this could be a struct literal that needs to be surrounded + // by parenthesis, find the appropriate span. + let mut i = 0; + let mut closing_brace = None; + loop { + sp = sm.next_point(sp); + match sm.span_to_snippet(sp) { + Ok(ref snippet) => { + if snippet == "}" { + let sp = span.to(sp); + if let Ok(snippet) = sm.span_to_snippet(sp) { + closing_brace = Some((sp, snippet)); + } + break; + } + } + _ => break, + } + i += 1; + // The bigger the span, the more likely we're incorrect -- + // bound it to 100 chars long. + if i > 100 { + break; + } + } + match source { + PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) { + err.span_label( + span, + format!("did you mean `{} {{ /* fields */ }}`?", path_str), + ); + } + PathSource::Expr(None) if followed_by_brace == true => { + if let Some((sp, snippet)) = closing_brace { + err.span_suggestion( + sp, + "surround the struct literal with parenthesis", + format!("({})", snippet), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label( + span, + format!("did you mean `({} {{ /* fields */ }})`?", path_str), + ); + } + }, + _ => { + err.span_label( + span, + format!("did you mean `{} {{ /* fields */ }}`?", path_str), + ); + }, + } + } + } + (Def::Union(..), _) | + (Def::Variant(..), _) | + (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => { + err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); + } + (Def::SelfTy(..), _) if ns == ValueNS => { + err.span_label(span, fallback_label); + err.note("can't use `Self` as a constructor, you must use the implemented struct"); + } + (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => { + err.note("can't use a type alias as a constructor"); + } + _ => return false, + } + true } } -use foo::core; // error: an extern crate named `core` has already - // been imported in this module - -fn main() {} -``` - -To fix this issue, you have to rename at least one of the two imports. -Example: - -``` -extern crate core as libcore; // ok! +impl<'a, 'b:'a> ImportResolver<'a, 'b> { + /// Adds suggestions for a path that cannot be resolved. + pub(crate) fn make_path_suggestion( + &mut self, + span: Span, + mut path: Vec, + parent_scope: &ParentScope<'b>, + ) -> Option<(Vec, Vec)> { + debug!("make_path_suggestion: span={:?} path={:?}", span, path); + + match (path.get(0), path.get(1)) { + // `{{root}}::ident::...` on both editions. + // On 2015 `{{root}}` is usually added implicitly. + (Some(fst), Some(snd)) if fst.ident.name == keywords::PathRoot.name() && + !snd.ident.is_path_segment_keyword() => {} + // `ident::...` on 2018. + (Some(fst), _) if fst.ident.span.rust_2018() && + !fst.ident.is_path_segment_keyword() => { + // Insert a placeholder that's later replaced by `self`/`super`/etc. + path.insert(0, Segment::from_ident(keywords::Invalid.ident())); + } + _ => return None, + } -mod foo { - pub trait core { - fn do_something(); + self.make_missing_self_suggestion(span, path.clone(), parent_scope) + .or_else(|| self.make_missing_crate_suggestion(span, path.clone(), parent_scope)) + .or_else(|| self.make_missing_super_suggestion(span, path.clone(), parent_scope)) + .or_else(|| self.make_external_crate_suggestion(span, path, parent_scope)) } -} - -use foo::core; - -fn main() {} -``` -"##, - -E0255: r##" -You can't import a value whose name is the same as another value defined in the -module. - -Erroneous code example: - -```compile_fail,E0255 -use bar::foo; // error: an item named `foo` is already in scope - -fn foo() {} - -mod bar { - pub fn foo() {} -} - -fn main() {} -``` - -You can use aliases in order to fix this error. Example: - -``` -use bar::foo as bar_foo; // ok! - -fn foo() {} - -mod bar { - pub fn foo() {} -} - -fn main() {} -``` - -Or you can reference the item with its parent: - -``` -fn foo() {} - -mod bar { - pub fn foo() {} -} - -fn main() { - bar::foo(); // we get the item by referring to its parent -} -``` -"##, - -E0256: r##" -#### Note: this error code is no longer emitted by the compiler. - -You can't import a type or module when the name of the item being imported is -the same as another type or submodule defined in the module. - -An example of this error: - -```compile_fail -use foo::Bar; // error - -type Bar = u32; - -mod foo { - pub mod Bar { } -} - -fn main() {} -``` -"##, - -E0259: r##" -The name chosen for an external crate conflicts with another external crate -that has been imported into the current module. - -Erroneous code example: - -```compile_fail,E0259 -extern crate core; -extern crate std as core; - -fn main() {} -``` - -The solution is to choose a different name that doesn't conflict with any -external crate imported into the current module. - -Correct example: - -``` -extern crate core; -extern crate std as other_name; - -fn main() {} -``` -"##, - -E0260: r##" -The name for an item declaration conflicts with an external crate's name. - -Erroneous code example: - -```compile_fail,E0260 -extern crate core; - -struct core; - -fn main() {} -``` - -There are two possible solutions: - -Solution #1: Rename the item. - -``` -extern crate core; - -struct xyz; -``` - -Solution #2: Import the crate with a different name. - -``` -extern crate core as xyz; - -struct abc; -``` - -See the Declaration Statements section of the reference for more information -about what constitutes an Item declaration and what does not: - -https://doc.rust-lang.org/reference.html#statements -"##, - -E0364: r##" -Private items cannot be publicly re-exported. This error indicates that you -attempted to `pub use` a type or value that was not itself public. - -Erroneous code example: - -```compile_fail -mod foo { - const X: u32 = 1; -} - -pub use foo::X; - -fn main() {} -``` -The solution to this problem is to ensure that the items that you are -re-exporting are themselves marked with `pub`: - -``` -mod foo { - pub const X: u32 = 1; -} - -pub use foo::X; - -fn main() {} -``` - -See the 'Use Declarations' section of the reference for more information on -this topic: - -https://doc.rust-lang.org/reference.html#use-declarations -"##, - -E0365: r##" -Private modules cannot be publicly re-exported. This error indicates that you -attempted to `pub use` a module that was not itself public. - -Erroneous code example: - -```compile_fail,E0365 -mod foo { - pub const X: u32 = 1; -} - -pub use foo as foo2; - -fn main() {} -``` - -The solution to this problem is to ensure that the module that you are -re-exporting is itself marked with `pub`: - -``` -pub mod foo { - pub const X: u32 = 1; -} - -pub use foo as foo2; - -fn main() {} -``` - -See the 'Use Declarations' section of the reference for more information -on this topic: - -https://doc.rust-lang.org/reference.html#use-declarations -"##, - -E0401: r##" -Inner items do not inherit type or const parameters from the functions -they are embedded in. - -Erroneous code example: - -```compile_fail,E0401 -fn foo(x: T) { - fn bar(y: T) { // T is defined in the "outer" function - // .. + /// Suggest a missing `self::` if that resolves to an correct module. + /// + /// ``` + /// | + /// LL | use foo::Bar; + /// | ^^^ did you mean `self::foo`? + /// ``` + fn make_missing_self_suggestion( + &mut self, + span: Span, + mut path: Vec, + parent_scope: &ParentScope<'b>, + ) -> Option<(Vec, Vec)> { + // Replace first ident with `self` and check if that is valid. + path[0].ident.name = keywords::SelfLower.name(); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); + debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); + if let PathResult::Module(..) = result { + Some((path, Vec::new())) + } else { + None + } } - bar(x); -} -``` -Nor will this: - -```compile_fail,E0401 -fn foo(x: T) { - type MaybeT = Option; - // ... -} -``` - -Or this: - -```compile_fail,E0401 -fn foo(x: T) { - struct Foo { - x: T, + /// Suggests a missing `crate::` if that resolves to an correct module. + /// + /// ``` + /// | + /// LL | use foo::Bar; + /// | ^^^ did you mean `crate::foo`? + /// ``` + fn make_missing_crate_suggestion( + &mut self, + span: Span, + mut path: Vec, + parent_scope: &ParentScope<'b>, + ) -> Option<(Vec, Vec)> { + // Replace first ident with `crate` and check if that is valid. + path[0].ident.name = keywords::Crate.name(); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); + debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); + if let PathResult::Module(..) = result { + Some(( + path, + vec![ + "`use` statements changed in Rust 2018; read more at \ + ".to_string() + ], + )) + } else { + None + } } - // ... -} -``` - -Items inside functions are basically just like top-level items, except -that they can only be used from the function they are in. - -There are a couple of solutions for this. -If the item is a function, you may use a closure: + /// Suggests a missing `super::` if that resolves to an correct module. + /// + /// ``` + /// | + /// LL | use foo::Bar; + /// | ^^^ did you mean `super::foo`? + /// ``` + fn make_missing_super_suggestion( + &mut self, + span: Span, + mut path: Vec, + parent_scope: &ParentScope<'b>, + ) -> Option<(Vec, Vec)> { + // Replace first ident with `crate` and check if that is valid. + path[0].ident.name = keywords::Super.name(); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); + debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); + if let PathResult::Module(..) = result { + Some((path, Vec::new())) + } else { + None + } + } -``` -fn foo(x: T) { - let bar = |y: T| { // explicit type annotation may not be necessary - // .. - }; - bar(x); -} -``` + /// Suggests a missing external crate name if that resolves to an correct module. + /// + /// ``` + /// | + /// LL | use foobar::Baz; + /// | ^^^^^^ did you mean `baz::foobar`? + /// ``` + /// + /// Used when importing a submodule of an external crate but missing that crate's + /// name as the first part of path. + fn make_external_crate_suggestion( + &mut self, + span: Span, + mut path: Vec, + parent_scope: &ParentScope<'b>, + ) -> Option<(Vec, Vec)> { + if path[1].ident.span.rust_2015() { + return None; + } -For a generic item, you can copy over the parameters: + // Sort extern crate names in reverse order to get + // 1) some consistent ordering for emitted dignostics, and + // 2) `std` suggestions before `core` suggestions. + let mut extern_crate_names = + self.resolver.extern_prelude.iter().map(|(ident, _)| ident.name).collect::>(); + extern_crate_names.sort_by_key(|name| Reverse(name.as_str())); + + for name in extern_crate_names.into_iter() { + // Replace first ident with a crate name and check if that is valid. + path[0].ident.name = name; + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); + debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", + name, path, result); + if let PathResult::Module(..) = result { + return Some((path, Vec::new())); + } + } -``` -fn foo(x: T) { - fn bar(y: T) { - // .. + None } - bar(x); -} -``` -``` -fn foo(x: T) { - type MaybeT = Option; -} -``` + /// Suggests importing a macro from the root of the crate rather than a module within + /// the crate. + /// + /// ``` + /// help: a macro with this name exists at the root of the crate + /// | + /// LL | use issue_59764::makro; + /// | ^^^^^^^^^^^^^^^^^^ + /// | + /// = note: this could be because a macro annotated with `#[macro_export]` will be exported + /// at the root of the crate instead of the module where it is defined + /// ``` + pub(crate) fn check_for_module_export_macro( + &self, + directive: &'b ImportDirective<'b>, + module: ModuleOrUniformRoot<'b>, + ident: Ident, + ) -> Option<(Option, Vec)> { + let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module { + module + } else { + return None; + }; + + while let Some(parent) = crate_module.parent { + crate_module = parent; + } -Be sure to copy over any bounds as well: + if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) { + // Don't make a suggestion if the import was already from the root of the + // crate. + return None; + } -``` -fn foo(x: T) { - fn bar(y: T) { - // .. + let resolutions = crate_module.resolutions.borrow(); + let resolution = resolutions.get(&(ident, MacroNS))?; + let binding = resolution.borrow().binding()?; + if let Def::Macro(_, MacroKind::Bang) = binding.def() { + let module_name = crate_module.kind.name().unwrap(); + let import = match directive.subclass { + ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target => + format!("{} as {}", source, target), + _ => format!("{}", ident), + }; + + let mut corrections: Vec<(Span, String)> = Vec::new(); + if !directive.is_nested() { + // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove + // intermediate segments. + corrections.push((directive.span, format!("{}::{}", module_name, import))); + } else { + // Find the binding span (and any trailing commas and spaces). + // ie. `use a::b::{c, d, e};` + // ^^^ + let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( + self.resolver.session, directive.span, directive.use_span, + ); + debug!("check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", + found_closing_brace, binding_span); + + let mut removal_span = binding_span; + if found_closing_brace { + // If the binding span ended with a closing brace, as in the below example: + // ie. `use a::b::{c, d};` + // ^ + // Then expand the span of characters to remove to include the previous + // binding's trailing comma. + // ie. `use a::b::{c, d};` + // ^^^ + if let Some(previous_span) = extend_span_to_previous_binding( + self.resolver.session, binding_span, + ) { + debug!("check_for_module_export_macro: previous_span={:?}", previous_span); + removal_span = removal_span.with_lo(previous_span.lo()); + } + } + debug!("check_for_module_export_macro: removal_span={:?}", removal_span); + + // Remove the `removal_span`. + corrections.push((removal_span, "".to_string())); + + // Find the span after the crate name and if it has nested imports immediatately + // after the crate name already. + // ie. `use a::b::{c, d};` + // ^^^^^^^^^ + // or `use a::{b, c, d}};` + // ^^^^^^^^^^^ + let (has_nested, after_crate_name) = find_span_immediately_after_crate_name( + self.resolver.session, module_name, directive.use_span, + ); + debug!("check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", + has_nested, after_crate_name); + + let source_map = self.resolver.session.source_map(); + + // Add the import to the start, with a `{` if required. + let start_point = source_map.start_point(after_crate_name); + if let Ok(start_snippet) = source_map.span_to_snippet(start_point) { + corrections.push(( + start_point, + if has_nested { + // In this case, `start_snippet` must equal '{'. + format!("{}{}, ", start_snippet, import) + } else { + // In this case, add a `{`, then the moved import, then whatever + // was there before. + format!("{{{}, {}", import, start_snippet) + } + )); + } + + // Add a `};` to the end if nested, matching the `{` added at the start. + if !has_nested { + corrections.push((source_map.end_point(after_crate_name), + "};".to_string())); + } + } + + let suggestion = Some(( + corrections, + String::from("a macro with this name exists at the root of the crate"), + Applicability::MaybeIncorrect, + )); + let note = vec![ + "this could be because a macro annotated with `#[macro_export]` will be exported \ + at the root of the crate instead of the module where it is defined".to_string(), + ]; + Some((suggestion, note)) + } else { + None + } } - bar(x); } -``` -``` -fn foo(x: T) { - struct Foo { - x: T, +/// Given a `binding_span` of a binding within a use statement: +/// +/// ``` +/// use foo::{a, b, c}; +/// ^ +/// ``` +/// +/// then return the span until the next binding or the end of the statement: +/// +/// ``` +/// use foo::{a, b, c}; +/// ^^^ +/// ``` +pub(crate) fn find_span_of_binding_until_next_binding( + sess: &Session, + binding_span: Span, + use_span: Span, +) -> (bool, Span) { + let source_map = sess.source_map(); + + // Find the span of everything after the binding. + // ie. `a, e};` or `a};` + let binding_until_end = binding_span.with_hi(use_span.hi()); + + // Find everything after the binding but not including the binding. + // ie. `, e};` or `};` + let after_binding_until_end = binding_until_end.with_lo(binding_span.hi()); + + // Keep characters in the span until we encounter something that isn't a comma or + // whitespace. + // ie. `, ` or ``. + // + // Also note whether a closing brace character was encountered. If there + // was, then later go backwards to remove any trailing commas that are left. + let mut found_closing_brace = false; + let after_binding_until_next_binding = source_map.span_take_while( + after_binding_until_end, + |&ch| { + if ch == '}' { found_closing_brace = true; } + ch == ' ' || ch == ',' + } + ); + + // Combine the two spans. + // ie. `a, ` or `a`. + // + // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };` + let span = binding_span.with_hi(after_binding_until_next_binding.hi()); + + (found_closing_brace, span) +} + +/// Given a `binding_span`, return the span through to the comma or opening brace of the previous +/// binding. +/// +/// ``` +/// use foo::a::{a, b, c}; +/// ^^--- binding span +/// | +/// returned span +/// +/// use foo::{a, b, c}; +/// --- binding span +/// ``` +pub(crate) fn extend_span_to_previous_binding( + sess: &Session, + binding_span: Span, +) -> Option { + let source_map = sess.source_map(); + + // `prev_source` will contain all of the source that came before the span. + // Then split based on a command and take the first (ie. closest to our span) + // snippet. In the example, this is a space. + let prev_source = source_map.span_to_prev_source(binding_span).ok()?; + + let prev_comma = prev_source.rsplit(',').collect::>(); + let prev_starting_brace = prev_source.rsplit('{').collect::>(); + if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 { + return None; } -} -``` -This may require additional type hints in the function body. + let prev_comma = prev_comma.first().unwrap(); + let prev_starting_brace = prev_starting_brace.first().unwrap(); -In case the item is a function inside an `impl`, defining a private helper -function might be easier: - -``` -# struct Foo(T); -impl Foo { - pub fn foo(&self, x: T) { - self.bar(x); - } - - fn bar(&self, y: T) { - // .. + // If the amount of source code before the comma is greater than + // the amount of source code before the starting brace then we've only + // got one item in the nested item (eg. `issue_52891::{self}`). + if prev_comma.len() > prev_starting_brace.len() { + return None; } -} -``` - -For default impls in traits, the private helper solution won't work, however -closures or copying the parameters should still work. -"##, - -E0403: r##" -Some type parameters have the same name. - -Erroneous code example: - -```compile_fail,E0403 -fn foo(s: T, u: T) {} // error: the name `T` is already used for a type - // parameter in this type parameter list -``` - -Please verify that none of the type parameters are misspelled, and rename any -clashing parameters. Example: - -``` -fn foo(s: T, u: Y) {} // ok! -``` -"##, - -E0404: r##" -You tried to use something which is not a trait in a trait position, such as -a bound or `impl`. - -Erroneous code example: - -```compile_fail,E0404 -struct Foo; -struct Bar; - -impl Foo for Bar {} // error: `Foo` is not a trait -``` - -Another erroneous code example: - -```compile_fail,E0404 -struct Foo; - -fn bar(t: T) {} // error: `Foo` is not a trait -``` - -Please verify that you didn't misspell the trait's name or otherwise use the -wrong identifier. Example: - -``` -trait Foo { - // some functions -} -struct Bar; - -impl Foo for Bar { // ok! - // functions implementation -} -``` - -or - -``` -trait Foo { - // some functions -} - -fn bar(t: T) {} // ok! -``` - -"##, - -E0405: r##" -The code refers to a trait that is not in scope. - -Erroneous code example: - -```compile_fail,E0405 -struct Foo; - -impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope -``` - -Please verify that the name of the trait wasn't misspelled and ensure that it -was imported. Example: - -``` -# #[cfg(for_demonstration_only)] -// solution 1: -use some_file::SomeTrait; - -// solution 2: -trait SomeTrait { - // some functions -} - -struct Foo; - -impl SomeTrait for Foo { // ok! - // implements functions -} -``` -"##, - -E0407: r##" -A definition of a method not in the implemented trait was given in a trait -implementation. - -Erroneous code example: - -```compile_fail,E0407 -trait Foo { - fn a(); -} - -struct Bar; - -impl Foo for Bar { - fn a() {} - fn b() {} // error: method `b` is not a member of trait `Foo` -} -``` - -Please verify you didn't misspell the method name and you used the correct -trait. First example: - -``` -trait Foo { - fn a(); - fn b(); -} - -struct Bar; - -impl Foo for Bar { - fn a() {} - fn b() {} // ok! -} -``` - -Second example: - -``` -trait Foo { - fn a(); -} - -struct Bar; - -impl Foo for Bar { - fn a() {} -} - -impl Bar { - fn b() {} -} -``` -"##, - -E0408: r##" -An "or" pattern was used where the variable bindings are not consistently bound -across patterns. - -Erroneous code example: - -```compile_fail,E0408 -match x { - Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is - // not bound in pattern #2 - _ => () -} -``` - -Here, `y` is bound to the contents of the `Some` and can be used within the -block corresponding to the match arm. However, in case `x` is `None`, we have -not specified what `y` is, and the block will use a nonexistent variable. - -To fix this error, either split into multiple match arms: - -``` -let x = Some(1); -match x { - Some(y) => { /* use y */ } - None => { /* ... */ } -} -``` - -or, bind the variable to a field of the same type in all sub-patterns of the -or pattern: - -``` -let x = (0, 2); -match x { - (0, y) | (y, 0) => { /* use y */} - _ => {} -} -``` - -In this example, if `x` matches the pattern `(0, _)`, the second field is set -to `y`. If it matches `(_, 0)`, the first field is set to `y`; so in all -cases `y` is set to some value. -"##, - -E0409: r##" -An "or" pattern was used where the variable bindings are not consistently bound -across patterns. - -Erroneous code example: - -```compile_fail,E0409 -let x = (0, 2); -match x { - (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with - // different mode in pattern #2 - // than in pattern #1 - _ => () -} -``` - -Here, `y` is bound by-value in one case and by-reference in the other. - -To fix this error, just use the same mode in both cases. -Generally using `ref` or `ref mut` where not already used will fix this: - -``` -let x = (0, 2); -match x { - (0, ref y) | (ref y, 0) => { /* use y */} - _ => () -} -``` - -Alternatively, split the pattern: - -``` -let x = (0, 2); -match x { - (y, 0) => { /* use y */ } - (0, ref y) => { /* use y */} - _ => () -} -``` -"##, - -E0411: r##" -The `Self` keyword was used outside an impl, trait, or type definition. - -Erroneous code example: -```compile_fail,E0411 -::foo; // error: use of `Self` outside of an impl, trait, or type - // definition -``` - -The `Self` keyword represents the current type, which explains why it can only -be used inside an impl, trait, or type definition. It gives access to the -associated items of a type: - -``` -trait Foo { - type Bar; -} - -trait Baz : Foo { - fn bar() -> Self::Bar; // like this -} -``` - -However, be careful when two types have a common associated type: - -```compile_fail -trait Foo { - type Bar; -} - -trait Foo2 { - type Bar; -} - -trait Baz : Foo + Foo2 { - fn bar() -> Self::Bar; - // error: ambiguous associated type `Bar` in bounds of `Self` -} -``` - -This problem can be solved by specifying from which trait we want to use the -`Bar` type: - -``` -trait Foo { - type Bar; -} - -trait Foo2 { - type Bar; -} - -trait Baz : Foo + Foo2 { - fn bar() -> ::Bar; // ok! -} -``` -"##, - -E0412: r##" -The type name used is not in scope. - -Erroneous code examples: - -```compile_fail,E0412 -impl Something {} // error: type name `Something` is not in scope - -// or: - -trait Foo { - fn bar(N); // error: type name `N` is not in scope -} - -// or: - -fn foo(x: T) {} // type name `T` is not in scope -``` - -To fix this error, please verify you didn't misspell the type name, you did -declare it or imported it into the scope. Examples: - -``` -struct Something; - -impl Something {} // ok! - -// or: - -trait Foo { - type N; - - fn bar(_: Self::N); // ok! -} - -// or: - -fn foo(x: T) {} // ok! -``` - -Another case that causes this error is when a type is imported into a parent -module. To fix this, you can follow the suggestion and use File directly or -`use super::File;` which will import the types from the parent namespace. An -example that causes this error is below: - -```compile_fail,E0412 -use std::fs::File; - -mod foo { - fn some_function(f: File) {} -} -``` - -``` -use std::fs::File; - -mod foo { - // either - use super::File; - // or - // use std::fs::File; - fn foo(f: File) {} -} -# fn main() {} // don't insert it for us; that'll break imports -``` -"##, - -E0415: r##" -More than one function parameter have the same name. - -Erroneous code example: - -```compile_fail,E0415 -fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than - // once in this parameter list -``` - -Please verify you didn't misspell parameters' name. Example: - -``` -fn foo(f: i32, g: i32) {} // ok! -``` -"##, - -E0416: r##" -An identifier is bound more than once in a pattern. - -Erroneous code example: - -```compile_fail,E0416 -match (1, 2) { - (x, x) => {} // error: identifier `x` is bound more than once in the - // same pattern -} -``` - -Please verify you didn't misspell identifiers' name. Example: - -``` -match (1, 2) { - (x, y) => {} // ok! -} -``` - -Or maybe did you mean to unify? Consider using a guard: - -``` -# let (A, B, C) = (1, 2, 3); -match (A, B, C) { - (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } - (y, z, see) => { /* A and B unequal; do another thing */ } -} -``` -"##, - -E0422: r##" -You are trying to use an identifier that is either undefined or not a struct. -Erroneous code example: - -```compile_fail,E0422 -fn main () { - let x = Foo { x: 1, y: 2 }; -} -``` - -In this case, `Foo` is undefined, so it inherently isn't anything, and -definitely not a struct. - -```compile_fail -fn main () { - let foo = 1; - let x = foo { x: 1, y: 2 }; -} -``` - -In this case, `foo` is defined, but is not a struct, so Rust can't use it as -one. -"##, - -E0423: r##" -An identifier was used like a function name or a value was expected and the -identifier exists but it belongs to a different namespace. - -For (an erroneous) example, here a `struct` variant name were used as a -function: - -```compile_fail,E0423 -struct Foo { a: bool }; - -let f = Foo(); -// error: expected function, found `Foo` -// `Foo` is a struct name, but this expression uses it like a function name -``` - -Please verify you didn't misspell the name of what you actually wanted to use -here. Example: - -``` -fn Foo() -> u32 { 0 } - -let f = Foo(); // ok! -``` - -It is common to forget the trailing `!` on macro invocations, which would also -yield this error: - -```compile_fail,E0423 -println(""); -// error: expected function, found macro `println` -// did you mean `println!(...)`? (notice the trailing `!`) -``` - -Another case where this error is emitted is when a value is expected, but -something else is found: - -```compile_fail,E0423 -pub mod a { - pub const I: i32 = 1; -} - -fn h1() -> i32 { - a.I - //~^ ERROR expected value, found module `a` - // did you mean `a::I`? -} -``` -"##, - -E0424: r##" -The `self` keyword was used in a static method. - -Erroneous code example: - -```compile_fail,E0424 -struct Foo; - -impl Foo { - fn bar(self) {} - - fn foo() { - self.bar(); // error: `self` is not available in a static method. - } -} -``` - -Please check if the method's argument list should have contained `self`, -`&self`, or `&mut self` (in case you didn't want to create a static -method), and add it if so. Example: - -``` -struct Foo; - -impl Foo { - fn bar(self) {} - - fn foo(self) { - self.bar(); // ok! - } -} -``` -"##, - -E0425: r##" -An unresolved name was used. - -Erroneous code examples: - -```compile_fail,E0425 -something_that_doesnt_exist::foo; -// error: unresolved name `something_that_doesnt_exist::foo` - -// or: - -trait Foo { - fn bar() { - Self; // error: unresolved name `Self` - } -} - -// or: - -let x = unknown_variable; // error: unresolved name `unknown_variable` -``` - -Please verify that the name wasn't misspelled and ensure that the -identifier being referred to is valid for the given situation. Example: - -``` -enum something_that_does_exist { - Foo, -} -``` - -Or: - -``` -mod something_that_does_exist { - pub static foo : i32 = 0i32; -} - -something_that_does_exist::foo; // ok! -``` - -Or: - -``` -let unknown_variable = 12u32; -let x = unknown_variable; // ok! -``` - -If the item is not defined in the current module, it must be imported using a -`use` statement, like so: - -``` -# mod foo { pub fn bar() {} } -# fn main() { -use foo::bar; -bar(); -# } -``` - -If the item you are importing is not defined in some super-module of the -current module, then it must also be declared as public (e.g., `pub fn`). -"##, - -E0426: r##" -An undeclared label was used. - -Erroneous code example: - -```compile_fail,E0426 -loop { - break 'a; // error: use of undeclared label `'a` -} -``` - -Please verify you spelt or declare the label correctly. Example: - -``` -'a: loop { - break 'a; // ok! -} -``` -"##, - -E0428: r##" -A type or module has been defined more than once. - -Erroneous code example: - -```compile_fail,E0428 -struct Bar; -struct Bar; // error: duplicate definition of value `Bar` -``` - -Please verify you didn't misspell the type/module's name or remove/rename the -duplicated one. Example: - -``` -struct Bar; -struct Bar2; // ok! -``` -"##, - -E0429: r##" -The `self` keyword cannot appear alone as the last segment in a `use` -declaration. - -Erroneous code example: - -```compile_fail,E0429 -use std::fmt::self; // error: `self` imports are only allowed within a { } list -``` - -To use a namespace itself in addition to some of its members, `self` may appear -as part of a brace-enclosed list of imports: - -``` -use std::fmt::{self, Debug}; -``` - -If you only want to import the namespace, do so directly: - -``` -use std::fmt; -``` -"##, - -E0430: r##" -The `self` import appears more than once in the list. - -Erroneous code example: - -```compile_fail,E0430 -use something::{self, self}; // error: `self` import can only appear once in - // the list -``` - -Please verify you didn't misspell the import name or remove the duplicated -`self` import. Example: - -``` -# mod something {} -# fn main() { -use something::{self}; // ok! -# } -``` -"##, - -E0431: r##" -An invalid `self` import was made. - -Erroneous code example: - -```compile_fail,E0431 -use {self}; // error: `self` import can only appear in an import list with a - // non-empty prefix -``` - -You cannot import the current module into itself, please remove this import -or verify you didn't misspell it. -"##, - -E0432: r##" -An import was unresolved. - -Erroneous code example: - -```compile_fail,E0432 -use something::Foo; // error: unresolved import `something::Foo`. -``` - -Paths in `use` statements are relative to the crate root. To import items -relative to the current and parent modules, use the `self::` and `super::` -prefixes, respectively. Also verify that you didn't misspell the import -name and that the import exists in the module from where you tried to -import it. Example: - -``` -use self::something::Foo; // ok! - -mod something { - pub struct Foo; -} -# fn main() {} -``` - -Or, if you tried to use a module from an external crate, you may have missed -the `extern crate` declaration (which is usually placed in the crate root): - -``` -extern crate core; // Required to use the `core` crate - -use core::any; -# fn main() {} -``` -"##, - -E0433: r##" -An undeclared type or module was used. - -Erroneous code example: - -```compile_fail,E0433 -let map = HashMap::new(); -// error: failed to resolve: use of undeclared type or module `HashMap` -``` - -Please verify you didn't misspell the type/module's name or that you didn't -forget to import it: - - -``` -use std::collections::HashMap; // HashMap has been imported. -let map: HashMap = HashMap::new(); // So it can be used! -``` -"##, - -E0434: r##" -This error indicates that a variable usage inside an inner function is invalid -because the variable comes from a dynamic environment. Inner functions do not -have access to their containing environment. - -Erroneous code example: - -```compile_fail,E0434 -fn foo() { - let y = 5; - fn bar() -> u32 { - y // error: can't capture dynamic environment in a fn item; use the - // || { ... } closure form instead. - } -} -``` - -Functions do not capture local variables. To fix this error, you can replace the -function with a closure: - -``` -fn foo() { - let y = 5; - let bar = || { - y - }; -} -``` - -or replace the captured variable with a constant or a static item: - -``` -fn foo() { - static mut X: u32 = 4; - const Y: u32 = 5; - fn bar() -> u32 { - unsafe { - X = 3; + Some(binding_span.with_lo(BytePos( + // Take away the number of bytes for the characters we've found and an + // extra for the comma. + binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1 + ))) +} + +/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if +/// it is a nested use tree. +/// +/// ``` +/// use foo::a::{b, c}; +/// ^^^^^^^^^^ // false +/// +/// use foo::{a, b, c}; +/// ^^^^^^^^^^ // true +/// +/// use foo::{a, b::{c, d}}; +/// ^^^^^^^^^^^^^^^ // true +/// ``` +fn find_span_immediately_after_crate_name( + sess: &Session, + module_name: Symbol, + use_span: Span, +) -> (bool, Span) { + debug!("find_span_immediately_after_crate_name: module_name={:?} use_span={:?}", + module_name, use_span); + let source_map = sess.source_map(); + + // Using `use issue_59764::foo::{baz, makro};` as an example throughout.. + let mut num_colons = 0; + // Find second colon.. `use issue_59764:` + let until_second_colon = source_map.span_take_while(use_span, |c| { + if *c == ':' { num_colons += 1; } + match c { + ':' if num_colons == 2 => false, + _ => true, } - Y - } -} -``` -"##, - -E0435: r##" -A non-constant value was used in a constant expression. - -Erroneous code example: - -```compile_fail,E0435 -let foo = 42; -let a: [u8; foo]; // error: attempt to use a non-constant value in a constant -``` - -To fix this error, please replace the value with a constant. Example: - -``` -let a: [u8; 42]; // ok! -``` - -Or: - -``` -const FOO: usize = 42; -let a: [u8; FOO]; // ok! -``` -"##, - -E0437: r##" -Trait implementations can only implement associated types that are members of -the trait in question. This error indicates that you attempted to implement -an associated type whose name does not match the name of any associated type -in the trait. - -Erroneous code example: - -```compile_fail,E0437 -trait Foo {} - -impl Foo for i32 { - type Bar = bool; -} -``` - -The solution to this problem is to remove the extraneous associated type: - -``` -trait Foo {} - -impl Foo for i32 {} -``` -"##, - -E0438: r##" -Trait implementations can only implement associated constants that are -members of the trait in question. This error indicates that you -attempted to implement an associated constant whose name does not -match the name of any associated constant in the trait. - -Erroneous code example: - -```compile_fail,E0438 -trait Foo {} - -impl Foo for i32 { - const BAR: bool = true; -} -``` - -The solution to this problem is to remove the extraneous associated constant: - -``` -trait Foo {} - -impl Foo for i32 {} -``` -"##, - -E0466: r##" -Macro import declarations were malformed. - -Erroneous code examples: - -```compile_fail,E0466 -#[macro_use(a_macro(another_macro))] // error: invalid import declaration -extern crate core as some_crate; - -#[macro_use(i_want = "some_macros")] // error: invalid import declaration -extern crate core as another_crate; -``` - -This is a syntax error at the level of attribute declarations. The proper -syntax for macro imports is the following: - -```ignore (cannot-doctest-multicrate-project) -// In some_crate: -#[macro_export] -macro_rules! get_tacos { - ... -} - -#[macro_export] -macro_rules! get_pimientos { - ... -} - -// In your crate: -#[macro_use(get_tacos, get_pimientos)] // It imports `get_tacos` and -extern crate some_crate; // `get_pimientos` macros from some_crate -``` - -If you would like to import all exported macros, write `macro_use` with no -arguments. -"##, - -E0468: r##" -A non-root module attempts to import macros from another crate. - -Example of erroneous code: - -```compile_fail,E0468 -mod foo { - #[macro_use(debug_assert)] // error: must be at crate root to import - extern crate core; // macros from another crate - fn run_macro() { debug_assert!(true); } -} -``` - -Only `extern crate` imports at the crate root level are allowed to import -macros. - -Either move the macro import to crate root or do without the foreign macros. -This will work: - -``` -#[macro_use(debug_assert)] -extern crate core; - -mod foo { - fn run_macro() { debug_assert!(true); } -} -# fn main() {} -``` -"##, - -E0469: r##" -A macro listed for import was not found. - -Erroneous code example: - -```compile_fail,E0469 -#[macro_use(drink, be_merry)] // error: imported macro not found -extern crate alloc; - -fn main() { - // ... -} -``` - -Either the listed macro is not contained in the imported crate, or it is not -exported from the given crate. - -This could be caused by a typo. Did you misspell the macro's name? - -Double-check the names of the macros listed for import, and that the crate -in question exports them. - -A working version would be: - -```ignore (cannot-doctest-multicrate-project) -// In some_crate crate: -#[macro_export] -macro_rules! eat { - ... -} - -#[macro_export] -macro_rules! drink { - ... -} - -// In your crate: -#[macro_use(eat, drink)] -extern crate some_crate; //ok! -``` -"##, - -E0530: r##" -A binding shadowed something it shouldn't. - -Erroneous code example: - -```compile_fail,E0530 -static TEST: i32 = 0; - -let r: (i32, i32) = (0, 0); -match r { - TEST => {} // error: match bindings cannot shadow statics -} -``` - -To fix this error, just change the binding's name in order to avoid shadowing -one of the following: - -* struct name -* struct/enum variant -* static -* const -* associated const - -Fixed example: - -``` -static TEST: i32 = 0; - -let r: (i32, i32) = (0, 0); -match r { - something => {} // ok! -} -``` -"##, - -E0532: r##" -Pattern arm did not match expected kind. - -Erroneous code example: - -```compile_fail,E0532 -enum State { - Succeeded, - Failed(String), -} - -fn print_on_failure(state: &State) { - match *state { - // error: expected unit struct/variant or constant, found tuple - // variant `State::Failed` - State::Failed => println!("Failed"), - _ => () - } -} -``` - -To fix this error, ensure the match arm kind is the same as the expression -matched. - -Fixed example: - -``` -enum State { - Succeeded, - Failed(String), -} - -fn print_on_failure(state: &State) { - match *state { - State::Failed(ref msg) => println!("Failed with {}", msg), - _ => () - } -} -``` -"##, - -E0603: r##" -A private item was used outside its scope. - -Erroneous code example: - -```compile_fail,E0603 -mod SomeModule { - const PRIVATE: u32 = 0x_a_bad_1dea_u32; // This const is private, so we - // can't use it outside of the - // `SomeModule` module. -} - -println!("const value: {}", SomeModule::PRIVATE); // error: constant `PRIVATE` - // is private -``` - -In order to fix this error, you need to make the item public by using the `pub` -keyword. Example: - -``` -mod SomeModule { - pub const PRIVATE: u32 = 0x_a_bad_1dea_u32; // We set it public by using the - // `pub` keyword. -} - -println!("const value: {}", SomeModule::PRIVATE); // ok! -``` -"##, - -E0659: r##" -An item usage is ambiguous. - -Erroneous code example: - -```compile_fail,E0659 -pub mod moon { - pub fn foo() {} -} - -pub mod earth { - pub fn foo() {} -} - -mod collider { - pub use moon::*; - pub use earth::*; -} - -fn main() { - collider::foo(); // ERROR: `foo` is ambiguous -} -``` - -This error generally appears when two items with the same name are imported into -a module. Here, the `foo` functions are imported and reexported from the -`collider` module and therefore, when we're using `collider::foo()`, both -functions collide. - -To solve this error, the best solution is generally to keep the path before the -item when using it. Example: - -``` -pub mod moon { - pub fn foo() {} -} - -pub mod earth { - pub fn foo() {} -} - -mod collider { - pub use moon; - pub use earth; -} - -fn main() { - collider::moon::foo(); // ok! - collider::earth::foo(); // ok! -} -``` -"##, - -} - -register_diagnostics! { -// E0153, unused error code -// E0157, unused error code -// E0257, -// E0258, -// E0402, // cannot use an outer type parameter in this context -// E0406, merged into 420 -// E0410, merged into 408 -// E0413, merged into 530 -// E0414, merged into 530 -// E0417, merged into 532 -// E0418, merged into 532 -// E0419, merged into 531 -// E0420, merged into 532 -// E0421, merged into 531 - E0531, // unresolved pattern path kind `name` -// E0427, merged into 530 -// E0467, removed -// E0470, removed - E0573, - E0574, - E0575, - E0576, - E0577, - E0578, + }); + // Find everything after the second colon.. `foo::{baz, makro};` + let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1)); + + let mut found_a_non_whitespace_character = false; + // Find the first non-whitespace character in `from_second_colon`.. `f` + let after_second_colon = source_map.span_take_while(from_second_colon, |c| { + if found_a_non_whitespace_character { return false; } + if !c.is_whitespace() { found_a_non_whitespace_character = true; } + true + }); + + // Find the first `{` in from_second_colon.. `foo::{` + let next_left_bracket = source_map.span_through_char(from_second_colon, '{'); + + (next_left_bracket == after_second_colon, from_second_colon) } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs new file mode 100644 index 0000000000000..5c095994a1bbd --- /dev/null +++ b/src/librustc_resolve/error_codes.rs @@ -0,0 +1,1672 @@ +#![allow(non_snake_case)] + +use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics}; + +// Error messages for EXXXX errors. Each message should start and end with a +// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and +// use `gq` to wrap paragraphs. Use `:set tw=0` to disable. +register_long_diagnostics! { + +E0128: r##" +Type parameter defaults can only use parameters that occur before them. +Erroneous code example: + +```compile_fail,E0128 +struct Foo { + field1: T, + filed2: U, +} +// error: type parameters with a default cannot use forward declared +// identifiers +``` + +Since type parameters are evaluated in-order, you may be able to fix this issue +by doing: + +``` +struct Foo { + field1: T, + filed2: U, +} +``` + +Please also verify that this wasn't because of a name-clash and rename the type +parameter if so. +"##, + +E0154: r##" +#### Note: this error code is no longer emitted by the compiler. + +Imports (`use` statements) are not allowed after non-item statements, such as +variable declarations and expression statements. + +Here is an example that demonstrates the error: + +``` +fn f() { + // Variable declaration before import + let x = 0; + use std::io::Read; + // ... +} +``` + +The solution is to declare the imports at the top of the block, function, or +file. + +Here is the previous example again, with the correct order: + +``` +fn f() { + use std::io::Read; + let x = 0; + // ... +} +``` + +See the Declaration Statements section of the reference for more information +about what constitutes an Item declaration and what does not: + +https://doc.rust-lang.org/reference.html#statements +"##, + +E0251: r##" +#### Note: this error code is no longer emitted by the compiler. + +Two items of the same name cannot be imported without rebinding one of the +items under a new local name. + +An example of this error: + +``` +use foo::baz; +use bar::*; // error, do `use foo::baz as quux` instead on the previous line + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` +"##, + +E0252: r##" +Two items of the same name cannot be imported without rebinding one of the +items under a new local name. + +Erroneous code example: + +```compile_fail,E0252 +use foo::baz; +use bar::baz; // error, do `use bar::baz as quux` instead + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` + +You can use aliases in order to fix this error. Example: + +``` +use foo::baz as foo_baz; +use bar::baz; // ok! + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` + +Or you can reference the item with its parent: + +``` +use bar::baz; + +fn main() { + let x = foo::baz; // ok! +} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` +"##, + +E0253: r##" +Attempt was made to import an unimportable value. This can happen when trying +to import a method from a trait. + +Erroneous code example: + +```compile_fail,E0253 +mod foo { + pub trait MyTrait { + fn do_something(); + } +} + +use foo::MyTrait::do_something; +// error: `do_something` is not directly importable + +fn main() {} +``` + +It's invalid to directly import methods belonging to a trait or concrete type. +"##, + +E0254: r##" +Attempt was made to import an item whereas an extern crate with this name has +already been imported. + +Erroneous code example: + +```compile_fail,E0254 +extern crate core; + +mod foo { + pub trait core { + fn do_something(); + } +} + +use foo::core; // error: an extern crate named `core` has already + // been imported in this module + +fn main() {} +``` + +To fix this issue, you have to rename at least one of the two imports. +Example: + +``` +extern crate core as libcore; // ok! + +mod foo { + pub trait core { + fn do_something(); + } +} + +use foo::core; + +fn main() {} +``` +"##, + +E0255: r##" +You can't import a value whose name is the same as another value defined in the +module. + +Erroneous code example: + +```compile_fail,E0255 +use bar::foo; // error: an item named `foo` is already in scope + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` + +You can use aliases in order to fix this error. Example: + +``` +use bar::foo as bar_foo; // ok! + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` + +Or you can reference the item with its parent: + +``` +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() { + bar::foo(); // we get the item by referring to its parent +} +``` +"##, + +E0256: r##" +#### Note: this error code is no longer emitted by the compiler. + +You can't import a type or module when the name of the item being imported is +the same as another type or submodule defined in the module. + +An example of this error: + +```compile_fail +use foo::Bar; // error + +type Bar = u32; + +mod foo { + pub mod Bar { } +} + +fn main() {} +``` +"##, + +E0259: r##" +The name chosen for an external crate conflicts with another external crate +that has been imported into the current module. + +Erroneous code example: + +```compile_fail,E0259 +extern crate core; +extern crate std as core; + +fn main() {} +``` + +The solution is to choose a different name that doesn't conflict with any +external crate imported into the current module. + +Correct example: + +``` +extern crate core; +extern crate std as other_name; + +fn main() {} +``` +"##, + +E0260: r##" +The name for an item declaration conflicts with an external crate's name. + +Erroneous code example: + +```compile_fail,E0260 +extern crate core; + +struct core; + +fn main() {} +``` + +There are two possible solutions: + +Solution #1: Rename the item. + +``` +extern crate core; + +struct xyz; +``` + +Solution #2: Import the crate with a different name. + +``` +extern crate core as xyz; + +struct abc; +``` + +See the Declaration Statements section of the reference for more information +about what constitutes an Item declaration and what does not: + +https://doc.rust-lang.org/reference.html#statements +"##, + +E0364: r##" +Private items cannot be publicly re-exported. This error indicates that you +attempted to `pub use` a type or value that was not itself public. + +Erroneous code example: + +```compile_fail +mod foo { + const X: u32 = 1; +} + +pub use foo::X; + +fn main() {} +``` + +The solution to this problem is to ensure that the items that you are +re-exporting are themselves marked with `pub`: + +``` +mod foo { + pub const X: u32 = 1; +} + +pub use foo::X; + +fn main() {} +``` + +See the 'Use Declarations' section of the reference for more information on +this topic: + +https://doc.rust-lang.org/reference.html#use-declarations +"##, + +E0365: r##" +Private modules cannot be publicly re-exported. This error indicates that you +attempted to `pub use` a module that was not itself public. + +Erroneous code example: + +```compile_fail,E0365 +mod foo { + pub const X: u32 = 1; +} + +pub use foo as foo2; + +fn main() {} +``` + +The solution to this problem is to ensure that the module that you are +re-exporting is itself marked with `pub`: + +``` +pub mod foo { + pub const X: u32 = 1; +} + +pub use foo as foo2; + +fn main() {} +``` + +See the 'Use Declarations' section of the reference for more information +on this topic: + +https://doc.rust-lang.org/reference.html#use-declarations +"##, + +E0401: r##" +Inner items do not inherit type or const parameters from the functions +they are embedded in. + +Erroneous code example: + +```compile_fail,E0401 +fn foo(x: T) { + fn bar(y: T) { // T is defined in the "outer" function + // .. + } + bar(x); +} +``` + +Nor will this: + +```compile_fail,E0401 +fn foo(x: T) { + type MaybeT = Option; + // ... +} +``` + +Or this: + +```compile_fail,E0401 +fn foo(x: T) { + struct Foo { + x: T, + } + // ... +} +``` + +Items inside functions are basically just like top-level items, except +that they can only be used from the function they are in. + +There are a couple of solutions for this. + +If the item is a function, you may use a closure: + +``` +fn foo(x: T) { + let bar = |y: T| { // explicit type annotation may not be necessary + // .. + }; + bar(x); +} +``` + +For a generic item, you can copy over the parameters: + +``` +fn foo(x: T) { + fn bar(y: T) { + // .. + } + bar(x); +} +``` + +``` +fn foo(x: T) { + type MaybeT = Option; +} +``` + +Be sure to copy over any bounds as well: + +``` +fn foo(x: T) { + fn bar(y: T) { + // .. + } + bar(x); +} +``` + +``` +fn foo(x: T) { + struct Foo { + x: T, + } +} +``` + +This may require additional type hints in the function body. + +In case the item is a function inside an `impl`, defining a private helper +function might be easier: + +``` +# struct Foo(T); +impl Foo { + pub fn foo(&self, x: T) { + self.bar(x); + } + + fn bar(&self, y: T) { + // .. + } +} +``` + +For default impls in traits, the private helper solution won't work, however +closures or copying the parameters should still work. +"##, + +E0403: r##" +Some type parameters have the same name. + +Erroneous code example: + +```compile_fail,E0403 +fn foo(s: T, u: T) {} // error: the name `T` is already used for a type + // parameter in this type parameter list +``` + +Please verify that none of the type parameters are misspelled, and rename any +clashing parameters. Example: + +``` +fn foo(s: T, u: Y) {} // ok! +``` +"##, + +E0404: r##" +You tried to use something which is not a trait in a trait position, such as +a bound or `impl`. + +Erroneous code example: + +```compile_fail,E0404 +struct Foo; +struct Bar; + +impl Foo for Bar {} // error: `Foo` is not a trait +``` + +Another erroneous code example: + +```compile_fail,E0404 +struct Foo; + +fn bar(t: T) {} // error: `Foo` is not a trait +``` + +Please verify that you didn't misspell the trait's name or otherwise use the +wrong identifier. Example: + +``` +trait Foo { + // some functions +} +struct Bar; + +impl Foo for Bar { // ok! + // functions implementation +} +``` + +or + +``` +trait Foo { + // some functions +} + +fn bar(t: T) {} // ok! +``` + +"##, + +E0405: r##" +The code refers to a trait that is not in scope. + +Erroneous code example: + +```compile_fail,E0405 +struct Foo; + +impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope +``` + +Please verify that the name of the trait wasn't misspelled and ensure that it +was imported. Example: + +``` +# #[cfg(for_demonstration_only)] +// solution 1: +use some_file::SomeTrait; + +// solution 2: +trait SomeTrait { + // some functions +} + +struct Foo; + +impl SomeTrait for Foo { // ok! + // implements functions +} +``` +"##, + +E0407: r##" +A definition of a method not in the implemented trait was given in a trait +implementation. + +Erroneous code example: + +```compile_fail,E0407 +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} // error: method `b` is not a member of trait `Foo` +} +``` + +Please verify you didn't misspell the method name and you used the correct +trait. First example: + +``` +trait Foo { + fn a(); + fn b(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} // ok! +} +``` + +Second example: + +``` +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} +} + +impl Bar { + fn b() {} +} +``` +"##, + +E0408: r##" +An "or" pattern was used where the variable bindings are not consistently bound +across patterns. + +Erroneous code example: + +```compile_fail,E0408 +match x { + Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is + // not bound in pattern #2 + _ => () +} +``` + +Here, `y` is bound to the contents of the `Some` and can be used within the +block corresponding to the match arm. However, in case `x` is `None`, we have +not specified what `y` is, and the block will use a nonexistent variable. + +To fix this error, either split into multiple match arms: + +``` +let x = Some(1); +match x { + Some(y) => { /* use y */ } + None => { /* ... */ } +} +``` + +or, bind the variable to a field of the same type in all sub-patterns of the +or pattern: + +``` +let x = (0, 2); +match x { + (0, y) | (y, 0) => { /* use y */} + _ => {} +} +``` + +In this example, if `x` matches the pattern `(0, _)`, the second field is set +to `y`. If it matches `(_, 0)`, the first field is set to `y`; so in all +cases `y` is set to some value. +"##, + +E0409: r##" +An "or" pattern was used where the variable bindings are not consistently bound +across patterns. + +Erroneous code example: + +```compile_fail,E0409 +let x = (0, 2); +match x { + (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with + // different mode in pattern #2 + // than in pattern #1 + _ => () +} +``` + +Here, `y` is bound by-value in one case and by-reference in the other. + +To fix this error, just use the same mode in both cases. +Generally using `ref` or `ref mut` where not already used will fix this: + +``` +let x = (0, 2); +match x { + (0, ref y) | (ref y, 0) => { /* use y */} + _ => () +} +``` + +Alternatively, split the pattern: + +``` +let x = (0, 2); +match x { + (y, 0) => { /* use y */ } + (0, ref y) => { /* use y */} + _ => () +} +``` +"##, + +E0411: r##" +The `Self` keyword was used outside an impl, trait, or type definition. + +Erroneous code example: + +```compile_fail,E0411 +::foo; // error: use of `Self` outside of an impl, trait, or type + // definition +``` + +The `Self` keyword represents the current type, which explains why it can only +be used inside an impl, trait, or type definition. It gives access to the +associated items of a type: + +``` +trait Foo { + type Bar; +} + +trait Baz : Foo { + fn bar() -> Self::Bar; // like this +} +``` + +However, be careful when two types have a common associated type: + +```compile_fail +trait Foo { + type Bar; +} + +trait Foo2 { + type Bar; +} + +trait Baz : Foo + Foo2 { + fn bar() -> Self::Bar; + // error: ambiguous associated type `Bar` in bounds of `Self` +} +``` + +This problem can be solved by specifying from which trait we want to use the +`Bar` type: + +``` +trait Foo { + type Bar; +} + +trait Foo2 { + type Bar; +} + +trait Baz : Foo + Foo2 { + fn bar() -> ::Bar; // ok! +} +``` +"##, + +E0412: r##" +The type name used is not in scope. + +Erroneous code examples: + +```compile_fail,E0412 +impl Something {} // error: type name `Something` is not in scope + +// or: + +trait Foo { + fn bar(N); // error: type name `N` is not in scope +} + +// or: + +fn foo(x: T) {} // type name `T` is not in scope +``` + +To fix this error, please verify you didn't misspell the type name, you did +declare it or imported it into the scope. Examples: + +``` +struct Something; + +impl Something {} // ok! + +// or: + +trait Foo { + type N; + + fn bar(_: Self::N); // ok! +} + +// or: + +fn foo(x: T) {} // ok! +``` + +Another case that causes this error is when a type is imported into a parent +module. To fix this, you can follow the suggestion and use File directly or +`use super::File;` which will import the types from the parent namespace. An +example that causes this error is below: + +```compile_fail,E0412 +use std::fs::File; + +mod foo { + fn some_function(f: File) {} +} +``` + +``` +use std::fs::File; + +mod foo { + // either + use super::File; + // or + // use std::fs::File; + fn foo(f: File) {} +} +# fn main() {} // don't insert it for us; that'll break imports +``` +"##, + +E0415: r##" +More than one function parameter have the same name. + +Erroneous code example: + +```compile_fail,E0415 +fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than + // once in this parameter list +``` + +Please verify you didn't misspell parameters' name. Example: + +``` +fn foo(f: i32, g: i32) {} // ok! +``` +"##, + +E0416: r##" +An identifier is bound more than once in a pattern. + +Erroneous code example: + +```compile_fail,E0416 +match (1, 2) { + (x, x) => {} // error: identifier `x` is bound more than once in the + // same pattern +} +``` + +Please verify you didn't misspell identifiers' name. Example: + +``` +match (1, 2) { + (x, y) => {} // ok! +} +``` + +Or maybe did you mean to unify? Consider using a guard: + +``` +# let (A, B, C) = (1, 2, 3); +match (A, B, C) { + (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } + (y, z, see) => { /* A and B unequal; do another thing */ } +} +``` +"##, + +E0422: r##" +You are trying to use an identifier that is either undefined or not a struct. +Erroneous code example: + +```compile_fail,E0422 +fn main () { + let x = Foo { x: 1, y: 2 }; +} +``` + +In this case, `Foo` is undefined, so it inherently isn't anything, and +definitely not a struct. + +```compile_fail +fn main () { + let foo = 1; + let x = foo { x: 1, y: 2 }; +} +``` + +In this case, `foo` is defined, but is not a struct, so Rust can't use it as +one. +"##, + +E0423: r##" +An identifier was used like a function name or a value was expected and the +identifier exists but it belongs to a different namespace. + +For (an erroneous) example, here a `struct` variant name were used as a +function: + +```compile_fail,E0423 +struct Foo { a: bool }; + +let f = Foo(); +// error: expected function, found `Foo` +// `Foo` is a struct name, but this expression uses it like a function name +``` + +Please verify you didn't misspell the name of what you actually wanted to use +here. Example: + +``` +fn Foo() -> u32 { 0 } + +let f = Foo(); // ok! +``` + +It is common to forget the trailing `!` on macro invocations, which would also +yield this error: + +```compile_fail,E0423 +println(""); +// error: expected function, found macro `println` +// did you mean `println!(...)`? (notice the trailing `!`) +``` + +Another case where this error is emitted is when a value is expected, but +something else is found: + +```compile_fail,E0423 +pub mod a { + pub const I: i32 = 1; +} + +fn h1() -> i32 { + a.I + //~^ ERROR expected value, found module `a` + // did you mean `a::I`? +} +``` +"##, + +E0424: r##" +The `self` keyword was used in a static method. + +Erroneous code example: + +```compile_fail,E0424 +struct Foo; + +impl Foo { + fn bar(self) {} + + fn foo() { + self.bar(); // error: `self` is not available in a static method. + } +} +``` + +Please check if the method's argument list should have contained `self`, +`&self`, or `&mut self` (in case you didn't want to create a static +method), and add it if so. Example: + +``` +struct Foo; + +impl Foo { + fn bar(self) {} + + fn foo(self) { + self.bar(); // ok! + } +} +``` +"##, + +E0425: r##" +An unresolved name was used. + +Erroneous code examples: + +```compile_fail,E0425 +something_that_doesnt_exist::foo; +// error: unresolved name `something_that_doesnt_exist::foo` + +// or: + +trait Foo { + fn bar() { + Self; // error: unresolved name `Self` + } +} + +// or: + +let x = unknown_variable; // error: unresolved name `unknown_variable` +``` + +Please verify that the name wasn't misspelled and ensure that the +identifier being referred to is valid for the given situation. Example: + +``` +enum something_that_does_exist { + Foo, +} +``` + +Or: + +``` +mod something_that_does_exist { + pub static foo : i32 = 0i32; +} + +something_that_does_exist::foo; // ok! +``` + +Or: + +``` +let unknown_variable = 12u32; +let x = unknown_variable; // ok! +``` + +If the item is not defined in the current module, it must be imported using a +`use` statement, like so: + +``` +# mod foo { pub fn bar() {} } +# fn main() { +use foo::bar; +bar(); +# } +``` + +If the item you are importing is not defined in some super-module of the +current module, then it must also be declared as public (e.g., `pub fn`). +"##, + +E0426: r##" +An undeclared label was used. + +Erroneous code example: + +```compile_fail,E0426 +loop { + break 'a; // error: use of undeclared label `'a` +} +``` + +Please verify you spelt or declare the label correctly. Example: + +``` +'a: loop { + break 'a; // ok! +} +``` +"##, + +E0428: r##" +A type or module has been defined more than once. + +Erroneous code example: + +```compile_fail,E0428 +struct Bar; +struct Bar; // error: duplicate definition of value `Bar` +``` + +Please verify you didn't misspell the type/module's name or remove/rename the +duplicated one. Example: + +``` +struct Bar; +struct Bar2; // ok! +``` +"##, + +E0429: r##" +The `self` keyword cannot appear alone as the last segment in a `use` +declaration. + +Erroneous code example: + +```compile_fail,E0429 +use std::fmt::self; // error: `self` imports are only allowed within a { } list +``` + +To use a namespace itself in addition to some of its members, `self` may appear +as part of a brace-enclosed list of imports: + +``` +use std::fmt::{self, Debug}; +``` + +If you only want to import the namespace, do so directly: + +``` +use std::fmt; +``` +"##, + +E0430: r##" +The `self` import appears more than once in the list. + +Erroneous code example: + +```compile_fail,E0430 +use something::{self, self}; // error: `self` import can only appear once in + // the list +``` + +Please verify you didn't misspell the import name or remove the duplicated +`self` import. Example: + +``` +# mod something {} +# fn main() { +use something::{self}; // ok! +# } +``` +"##, + +E0431: r##" +An invalid `self` import was made. + +Erroneous code example: + +```compile_fail,E0431 +use {self}; // error: `self` import can only appear in an import list with a + // non-empty prefix +``` + +You cannot import the current module into itself, please remove this import +or verify you didn't misspell it. +"##, + +E0432: r##" +An import was unresolved. + +Erroneous code example: + +```compile_fail,E0432 +use something::Foo; // error: unresolved import `something::Foo`. +``` + +Paths in `use` statements are relative to the crate root. To import items +relative to the current and parent modules, use the `self::` and `super::` +prefixes, respectively. Also verify that you didn't misspell the import +name and that the import exists in the module from where you tried to +import it. Example: + +``` +use self::something::Foo; // ok! + +mod something { + pub struct Foo; +} +# fn main() {} +``` + +Or, if you tried to use a module from an external crate, you may have missed +the `extern crate` declaration (which is usually placed in the crate root): + +``` +extern crate core; // Required to use the `core` crate + +use core::any; +# fn main() {} +``` +"##, + +E0433: r##" +An undeclared type or module was used. + +Erroneous code example: + +```compile_fail,E0433 +let map = HashMap::new(); +// error: failed to resolve: use of undeclared type or module `HashMap` +``` + +Please verify you didn't misspell the type/module's name or that you didn't +forget to import it: + + +``` +use std::collections::HashMap; // HashMap has been imported. +let map: HashMap = HashMap::new(); // So it can be used! +``` +"##, + +E0434: r##" +This error indicates that a variable usage inside an inner function is invalid +because the variable comes from a dynamic environment. Inner functions do not +have access to their containing environment. + +Erroneous code example: + +```compile_fail,E0434 +fn foo() { + let y = 5; + fn bar() -> u32 { + y // error: can't capture dynamic environment in a fn item; use the + // || { ... } closure form instead. + } +} +``` + +Functions do not capture local variables. To fix this error, you can replace the +function with a closure: + +``` +fn foo() { + let y = 5; + let bar = || { + y + }; +} +``` + +or replace the captured variable with a constant or a static item: + +``` +fn foo() { + static mut X: u32 = 4; + const Y: u32 = 5; + fn bar() -> u32 { + unsafe { + X = 3; + } + Y + } +} +``` +"##, + +E0435: r##" +A non-constant value was used in a constant expression. + +Erroneous code example: + +```compile_fail,E0435 +let foo = 42; +let a: [u8; foo]; // error: attempt to use a non-constant value in a constant +``` + +To fix this error, please replace the value with a constant. Example: + +``` +let a: [u8; 42]; // ok! +``` + +Or: + +``` +const FOO: usize = 42; +let a: [u8; FOO]; // ok! +``` +"##, + +E0437: r##" +Trait implementations can only implement associated types that are members of +the trait in question. This error indicates that you attempted to implement +an associated type whose name does not match the name of any associated type +in the trait. + +Erroneous code example: + +```compile_fail,E0437 +trait Foo {} + +impl Foo for i32 { + type Bar = bool; +} +``` + +The solution to this problem is to remove the extraneous associated type: + +``` +trait Foo {} + +impl Foo for i32 {} +``` +"##, + +E0438: r##" +Trait implementations can only implement associated constants that are +members of the trait in question. This error indicates that you +attempted to implement an associated constant whose name does not +match the name of any associated constant in the trait. + +Erroneous code example: + +```compile_fail,E0438 +trait Foo {} + +impl Foo for i32 { + const BAR: bool = true; +} +``` + +The solution to this problem is to remove the extraneous associated constant: + +``` +trait Foo {} + +impl Foo for i32 {} +``` +"##, + +E0466: r##" +Macro import declarations were malformed. + +Erroneous code examples: + +```compile_fail,E0466 +#[macro_use(a_macro(another_macro))] // error: invalid import declaration +extern crate core as some_crate; + +#[macro_use(i_want = "some_macros")] // error: invalid import declaration +extern crate core as another_crate; +``` + +This is a syntax error at the level of attribute declarations. The proper +syntax for macro imports is the following: + +```ignore (cannot-doctest-multicrate-project) +// In some_crate: +#[macro_export] +macro_rules! get_tacos { + ... +} + +#[macro_export] +macro_rules! get_pimientos { + ... +} + +// In your crate: +#[macro_use(get_tacos, get_pimientos)] // It imports `get_tacos` and +extern crate some_crate; // `get_pimientos` macros from some_crate +``` + +If you would like to import all exported macros, write `macro_use` with no +arguments. +"##, + +E0468: r##" +A non-root module attempts to import macros from another crate. + +Example of erroneous code: + +```compile_fail,E0468 +mod foo { + #[macro_use(debug_assert)] // error: must be at crate root to import + extern crate core; // macros from another crate + fn run_macro() { debug_assert!(true); } +} +``` + +Only `extern crate` imports at the crate root level are allowed to import +macros. + +Either move the macro import to crate root or do without the foreign macros. +This will work: + +``` +#[macro_use(debug_assert)] +extern crate core; + +mod foo { + fn run_macro() { debug_assert!(true); } +} +# fn main() {} +``` +"##, + +E0469: r##" +A macro listed for import was not found. + +Erroneous code example: + +```compile_fail,E0469 +#[macro_use(drink, be_merry)] // error: imported macro not found +extern crate alloc; + +fn main() { + // ... +} +``` + +Either the listed macro is not contained in the imported crate, or it is not +exported from the given crate. + +This could be caused by a typo. Did you misspell the macro's name? + +Double-check the names of the macros listed for import, and that the crate +in question exports them. + +A working version would be: + +```ignore (cannot-doctest-multicrate-project) +// In some_crate crate: +#[macro_export] +macro_rules! eat { + ... +} + +#[macro_export] +macro_rules! drink { + ... +} + +// In your crate: +#[macro_use(eat, drink)] +extern crate some_crate; //ok! +``` +"##, + +E0530: r##" +A binding shadowed something it shouldn't. + +Erroneous code example: + +```compile_fail,E0530 +static TEST: i32 = 0; + +let r: (i32, i32) = (0, 0); +match r { + TEST => {} // error: match bindings cannot shadow statics +} +``` + +To fix this error, just change the binding's name in order to avoid shadowing +one of the following: + +* struct name +* struct/enum variant +* static +* const +* associated const + +Fixed example: + +``` +static TEST: i32 = 0; + +let r: (i32, i32) = (0, 0); +match r { + something => {} // ok! +} +``` +"##, + +E0532: r##" +Pattern arm did not match expected kind. + +Erroneous code example: + +```compile_fail,E0532 +enum State { + Succeeded, + Failed(String), +} + +fn print_on_failure(state: &State) { + match *state { + // error: expected unit struct/variant or constant, found tuple + // variant `State::Failed` + State::Failed => println!("Failed"), + _ => () + } +} +``` + +To fix this error, ensure the match arm kind is the same as the expression +matched. + +Fixed example: + +``` +enum State { + Succeeded, + Failed(String), +} + +fn print_on_failure(state: &State) { + match *state { + State::Failed(ref msg) => println!("Failed with {}", msg), + _ => () + } +} +``` +"##, + +E0603: r##" +A private item was used outside its scope. + +Erroneous code example: + +```compile_fail,E0603 +mod SomeModule { + const PRIVATE: u32 = 0x_a_bad_1dea_u32; // This const is private, so we + // can't use it outside of the + // `SomeModule` module. +} + +println!("const value: {}", SomeModule::PRIVATE); // error: constant `PRIVATE` + // is private +``` + +In order to fix this error, you need to make the item public by using the `pub` +keyword. Example: + +``` +mod SomeModule { + pub const PRIVATE: u32 = 0x_a_bad_1dea_u32; // We set it public by using the + // `pub` keyword. +} + +println!("const value: {}", SomeModule::PRIVATE); // ok! +``` +"##, + +E0659: r##" +An item usage is ambiguous. + +Erroneous code example: + +```compile_fail,E0659 +pub mod moon { + pub fn foo() {} +} + +pub mod earth { + pub fn foo() {} +} + +mod collider { + pub use moon::*; + pub use earth::*; +} + +fn main() { + collider::foo(); // ERROR: `foo` is ambiguous +} +``` + +This error generally appears when two items with the same name are imported into +a module. Here, the `foo` functions are imported and reexported from the +`collider` module and therefore, when we're using `collider::foo()`, both +functions collide. + +To solve this error, the best solution is generally to keep the path before the +item when using it. Example: + +``` +pub mod moon { + pub fn foo() {} +} + +pub mod earth { + pub fn foo() {} +} + +mod collider { + pub use moon; + pub use earth; +} + +fn main() { + collider::moon::foo(); // ok! + collider::earth::foo(); // ok! +} +``` +"##, + +} + +register_diagnostics! { +// E0153, unused error code +// E0157, unused error code +// E0257, +// E0258, +// E0402, // cannot use an outer type parameter in this context +// E0406, merged into 420 +// E0410, merged into 408 +// E0413, merged into 530 +// E0414, merged into 530 +// E0417, merged into 532 +// E0418, merged into 532 +// E0419, merged into 531 +// E0420, merged into 532 +// E0421, merged into 531 + E0531, // unresolved pattern path kind `name` +// E0427, merged into 530 +// E0467, removed +// E0470, removed + E0573, + E0574, + E0575, + E0576, + E0577, + E0578, +} diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs deleted file mode 100644 index 9e3894dab0da0..0000000000000 --- a/src/librustc_resolve/error_reporting.rs +++ /dev/null @@ -1,856 +0,0 @@ -use std::cmp::Reverse; - -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; -use log::debug; -use rustc::hir::def::{self, CtorKind, Namespace::*}; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; -use rustc::session::{Session, config::nightly_options}; -use syntax::ast::{self, Expr, ExprKind, Ident}; -use syntax::ext::base::MacroKind; -use syntax::symbol::{Symbol, keywords}; -use syntax_pos::{BytePos, Span}; - -type Def = def::Def; - -use crate::macros::ParentScope; -use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; -use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string}; -use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult, - PathSource, Resolver, Segment, Suggestion}; - -impl<'a> Resolver<'a> { - /// Handles error reporting for `smart_resolve_path_fragment` function. - /// Creates base error and amends it with one short label and possibly some longer helps/notes. - pub(crate) fn smart_resolve_report_errors( - &mut self, - path: &[Segment], - span: Span, - source: PathSource<'_>, - def: Option, - ) -> (DiagnosticBuilder<'a>, Vec) { - let ident_span = path.last().map_or(span, |ident| ident.ident.span); - let ns = source.namespace(); - let is_expected = &|def| source.is_expected(def); - let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; - - // Make the base error. - let expected = source.descr_expected(); - let path_str = Segment::names_to_string(path); - let item_str = path.last().unwrap().ident; - let code = source.error_code(def.is_some()); - let (base_msg, fallback_label, base_span) = if let Some(def) = def { - (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), - format!("not a {}", expected), - span) - } else { - let item_span = path.last().unwrap().ident.span; - let (mod_prefix, mod_str) = if path.len() == 1 { - (String::new(), "this scope".to_string()) - } else if path.len() == 2 && path[0].ident.name == keywords::PathRoot.name() { - (String::new(), "the crate root".to_string()) - } else { - let mod_path = &path[..path.len() - 1]; - let mod_prefix = match self.resolve_path_without_parent_scope( - mod_path, Some(TypeNS), false, span, CrateLint::No - ) { - PathResult::Module(ModuleOrUniformRoot::Module(module)) => - module.def(), - _ => None, - }.map_or(String::new(), |def| format!("{} ", def.kind_name())); - (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) - }; - (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), - format!("not found in {}", mod_str), - item_span) - }; - - let code = DiagnosticId::Error(code.into()); - let mut err = self.session.struct_span_err_with_code(base_span, &base_msg, code); - - // Emit help message for fake-self from other languages (e.g., `this` in Javascript). - if ["this", "my"].contains(&&*item_str.as_str()) - && self.self_value_is_available(path[0].ident.span, span) { - err.span_suggestion( - span, - "did you mean", - "self".to_string(), - Applicability::MaybeIncorrect, - ); - } - - // Emit special messages for unresolved `Self` and `self`. - if is_self_type(path, ns) { - __diagnostic_used!(E0411); - err.code(DiagnosticId::Error("E0411".into())); - err.span_label(span, format!("`Self` is only available in impls, traits, \ - and type definitions")); - return (err, Vec::new()); - } - if is_self_value(path, ns) { - debug!("smart_resolve_path_fragment: E0424, source={:?}", source); - - __diagnostic_used!(E0424); - err.code(DiagnosticId::Error("E0424".into())); - err.span_label(span, match source { - PathSource::Pat => { - format!("`self` value is a keyword \ - and may not be bound to \ - variables or shadowed") - } - _ => { - format!("`self` value is a keyword \ - only available in methods \ - with `self` parameter") - } - }); - return (err, Vec::new()); - } - - // Try to lookup name in more relaxed fashion for better error reporting. - let ident = path.last().unwrap().ident; - let candidates = self.lookup_import_candidates(ident, ns, is_expected) - .drain(..) - .filter(|ImportSuggestion { did, .. }| { - match (did, def.and_then(|def| def.opt_def_id())) { - (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, - _ => true, - } - }) - .collect::>(); - if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { - let enum_candidates = - self.lookup_import_candidates(ident, ns, is_enum_variant); - let mut enum_candidates = enum_candidates.iter() - .map(|suggestion| { - import_candidate_to_enum_paths(&suggestion) - }).collect::>(); - enum_candidates.sort(); - - if !enum_candidates.is_empty() { - // Contextualize for E0412 "cannot find type", but don't belabor the point - // (that it's a variant) for E0573 "expected type, found variant". - let preamble = if def.is_none() { - let others = match enum_candidates.len() { - 1 => String::new(), - 2 => " and 1 other".to_owned(), - n => format!(" and {} others", n) - }; - format!("there is an enum variant `{}`{}; ", - enum_candidates[0].0, others) - } else { - String::new() - }; - let msg = format!("{}try using the variant's enum", preamble); - - err.span_suggestions( - span, - &msg, - enum_candidates.into_iter() - .map(|(_variant_path, enum_ty_path)| enum_ty_path) - // Variants re-exported in prelude doesn't mean `prelude::v1` is the - // type name! - // FIXME: is there a more principled way to do this that - // would work for other re-exports? - .filter(|enum_ty_path| enum_ty_path != "std::prelude::v1") - // Also write `Option` rather than `std::prelude::v1::Option`. - .map(|enum_ty_path| { - // FIXME #56861: DRY-er prelude filtering. - enum_ty_path.trim_start_matches("std::prelude::v1::").to_owned() - }), - Applicability::MachineApplicable, - ); - } - } - if path.len() == 1 && self.self_type_is_available(span) { - if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) { - let self_is_available = self.self_value_is_available(path[0].ident.span, span); - match candidate { - AssocSuggestion::Field => { - err.span_suggestion( - span, - "try", - format!("self.{}", path_str), - Applicability::MachineApplicable, - ); - if !self_is_available { - err.span_label(span, format!("`self` value is a keyword \ - only available in \ - methods with `self` parameter")); - } - } - AssocSuggestion::MethodWithSelf if self_is_available => { - err.span_suggestion( - span, - "try", - format!("self.{}", path_str), - Applicability::MachineApplicable, - ); - } - AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { - err.span_suggestion( - span, - "try", - format!("Self::{}", path_str), - Applicability::MachineApplicable, - ); - } - } - return (err, candidates); - } - } - - let mut levenshtein_worked = false; - - // Try Levenshtein algorithm. - let suggestion = self.lookup_typo_candidate(path, ns, is_expected, span); - if let Some(suggestion) = suggestion { - let msg = format!( - "{} {} with a similar name exists", - suggestion.article, suggestion.kind - ); - err.span_suggestion( - ident_span, - &msg, - suggestion.candidate.to_string(), - Applicability::MaybeIncorrect, - ); - - levenshtein_worked = true; - } - - // Try context-dependent help if relaxed lookup didn't work. - if let Some(def) = def { - if self.smart_resolve_context_dependent_help(&mut err, - span, - source, - def, - &path_str, - &fallback_label) { - return (err, candidates); - } - } - - // Fallback label. - if !levenshtein_worked { - err.span_label(base_span, fallback_label); - self.type_ascription_suggestion(&mut err, base_span); - } - (err, candidates) - } - - /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment` - /// function. - /// Returns `true` if able to provide context-dependent help. - fn smart_resolve_context_dependent_help( - &mut self, - err: &mut DiagnosticBuilder<'a>, - span: Span, - source: PathSource<'_>, - def: Def, - path_str: &str, - fallback_label: &str, - ) -> bool { - let ns = source.namespace(); - let is_expected = &|def| source.is_expected(def); - - let path_sep = |err: &mut DiagnosticBuilder<'_>, expr: &Expr| match expr.node { - ExprKind::Field(_, ident) => { - err.span_suggestion( - expr.span, - "use the path separator to refer to an item", - format!("{}::{}", path_str, ident), - Applicability::MaybeIncorrect, - ); - true - } - ExprKind::MethodCall(ref segment, ..) => { - let span = expr.span.with_hi(segment.ident.span.hi()); - err.span_suggestion( - span, - "use the path separator to refer to an item", - format!("{}::{}", path_str, segment.ident), - Applicability::MaybeIncorrect, - ); - true - } - _ => false, - }; - - match (def, source) { - (Def::Macro(..), _) => { - err.span_suggestion( - span, - "use `!` to invoke the macro", - format!("{}!", path_str), - Applicability::MaybeIncorrect, - ); - if path_str == "try" && span.rust_2015() { - err.note("if you want the `try` keyword, you need to be in the 2018 edition"); - } - } - (Def::TyAlias(..), PathSource::Trait(_)) => { - err.span_label(span, "type aliases cannot be used as traits"); - if nightly_options::is_nightly_build() { - err.note("did you mean to use a trait alias?"); - } - } - (Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) { - return false; - }, - (Def::Enum(..), PathSource::TupleStruct) - | (Def::Enum(..), PathSource::Expr(..)) => { - if let Some(variants) = self.collect_enum_variants(def) { - if !variants.is_empty() { - let msg = if variants.len() == 1 { - "try using the enum's variant" - } else { - "try using one of the enum's variants" - }; - - err.span_suggestions( - span, - msg, - variants.iter().map(path_names_to_string), - Applicability::MaybeIncorrect, - ); - } - } else { - err.note("did you mean to use one of the enum's variants?"); - } - }, - (Def::Struct(def_id), _) if ns == ValueNS => { - if let Some((ctor_def, ctor_vis)) - = self.struct_constructors.get(&def_id).cloned() { - let accessible_ctor = self.is_accessible(ctor_vis); - if is_expected(ctor_def) && !accessible_ctor { - err.span_label( - span, - format!("constructor is not visible here due to private fields"), - ); - } - } else { - // HACK(estebank): find a better way to figure out that this was a - // parser issue where a struct literal is being used on an expression - // where a brace being opened means a block is being started. Look - // ahead for the next text to see if `span` is followed by a `{`. - let sm = self.session.source_map(); - let mut sp = span; - loop { - sp = sm.next_point(sp); - match sm.span_to_snippet(sp) { - Ok(ref snippet) => { - if snippet.chars().any(|c| { !c.is_whitespace() }) { - break; - } - } - _ => break, - } - } - let followed_by_brace = match sm.span_to_snippet(sp) { - Ok(ref snippet) if snippet == "{" => true, - _ => false, - }; - // In case this could be a struct literal that needs to be surrounded - // by parenthesis, find the appropriate span. - let mut i = 0; - let mut closing_brace = None; - loop { - sp = sm.next_point(sp); - match sm.span_to_snippet(sp) { - Ok(ref snippet) => { - if snippet == "}" { - let sp = span.to(sp); - if let Ok(snippet) = sm.span_to_snippet(sp) { - closing_brace = Some((sp, snippet)); - } - break; - } - } - _ => break, - } - i += 1; - // The bigger the span, the more likely we're incorrect -- - // bound it to 100 chars long. - if i > 100 { - break; - } - } - match source { - PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) { - err.span_label( - span, - format!("did you mean `{} {{ /* fields */ }}`?", path_str), - ); - } - PathSource::Expr(None) if followed_by_brace == true => { - if let Some((sp, snippet)) = closing_brace { - err.span_suggestion( - sp, - "surround the struct literal with parenthesis", - format!("({})", snippet), - Applicability::MaybeIncorrect, - ); - } else { - err.span_label( - span, - format!("did you mean `({} {{ /* fields */ }})`?", path_str), - ); - } - }, - _ => { - err.span_label( - span, - format!("did you mean `{} {{ /* fields */ }}`?", path_str), - ); - }, - } - } - } - (Def::Union(..), _) | - (Def::Variant(..), _) | - (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => { - err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); - } - (Def::SelfTy(..), _) if ns == ValueNS => { - err.span_label(span, fallback_label); - err.note("can't use `Self` as a constructor, you must use the implemented struct"); - } - (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => { - err.note("can't use a type alias as a constructor"); - } - _ => return false, - } - true - } -} - -impl<'a, 'b:'a> ImportResolver<'a, 'b> { - /// Adds suggestions for a path that cannot be resolved. - pub(crate) fn make_path_suggestion( - &mut self, - span: Span, - mut path: Vec, - parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Vec)> { - debug!("make_path_suggestion: span={:?} path={:?}", span, path); - - match (path.get(0), path.get(1)) { - // `{{root}}::ident::...` on both editions. - // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) if fst.ident.name == keywords::PathRoot.name() && - !snd.ident.is_path_segment_keyword() => {} - // `ident::...` on 2018. - (Some(fst), _) if fst.ident.span.rust_2018() && - !fst.ident.is_path_segment_keyword() => { - // Insert a placeholder that's later replaced by `self`/`super`/etc. - path.insert(0, Segment::from_ident(keywords::Invalid.ident())); - } - _ => return None, - } - - self.make_missing_self_suggestion(span, path.clone(), parent_scope) - .or_else(|| self.make_missing_crate_suggestion(span, path.clone(), parent_scope)) - .or_else(|| self.make_missing_super_suggestion(span, path.clone(), parent_scope)) - .or_else(|| self.make_external_crate_suggestion(span, path, parent_scope)) - } - - /// Suggest a missing `self::` if that resolves to an correct module. - /// - /// ``` - /// | - /// LL | use foo::Bar; - /// | ^^^ did you mean `self::foo`? - /// ``` - fn make_missing_self_suggestion( - &mut self, - span: Span, - mut path: Vec, - parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Vec)> { - // Replace first ident with `self` and check if that is valid. - path[0].ident.name = keywords::SelfLower.name(); - let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); - debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); - if let PathResult::Module(..) = result { - Some((path, Vec::new())) - } else { - None - } - } - - /// Suggests a missing `crate::` if that resolves to an correct module. - /// - /// ``` - /// | - /// LL | use foo::Bar; - /// | ^^^ did you mean `crate::foo`? - /// ``` - fn make_missing_crate_suggestion( - &mut self, - span: Span, - mut path: Vec, - parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Vec)> { - // Replace first ident with `crate` and check if that is valid. - path[0].ident.name = keywords::Crate.name(); - let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); - debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); - if let PathResult::Module(..) = result { - Some(( - path, - vec![ - "`use` statements changed in Rust 2018; read more at \ - ".to_string() - ], - )) - } else { - None - } - } - - /// Suggests a missing `super::` if that resolves to an correct module. - /// - /// ``` - /// | - /// LL | use foo::Bar; - /// | ^^^ did you mean `super::foo`? - /// ``` - fn make_missing_super_suggestion( - &mut self, - span: Span, - mut path: Vec, - parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Vec)> { - // Replace first ident with `crate` and check if that is valid. - path[0].ident.name = keywords::Super.name(); - let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); - debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); - if let PathResult::Module(..) = result { - Some((path, Vec::new())) - } else { - None - } - } - - /// Suggests a missing external crate name if that resolves to an correct module. - /// - /// ``` - /// | - /// LL | use foobar::Baz; - /// | ^^^^^^ did you mean `baz::foobar`? - /// ``` - /// - /// Used when importing a submodule of an external crate but missing that crate's - /// name as the first part of path. - fn make_external_crate_suggestion( - &mut self, - span: Span, - mut path: Vec, - parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Vec)> { - if path[1].ident.span.rust_2015() { - return None; - } - - // Sort extern crate names in reverse order to get - // 1) some consistent ordering for emitted dignostics, and - // 2) `std` suggestions before `core` suggestions. - let mut extern_crate_names = - self.resolver.extern_prelude.iter().map(|(ident, _)| ident.name).collect::>(); - extern_crate_names.sort_by_key(|name| Reverse(name.as_str())); - - for name in extern_crate_names.into_iter() { - // Replace first ident with a crate name and check if that is valid. - path[0].ident.name = name; - let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); - debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", - name, path, result); - if let PathResult::Module(..) = result { - return Some((path, Vec::new())); - } - } - - None - } - - /// Suggests importing a macro from the root of the crate rather than a module within - /// the crate. - /// - /// ``` - /// help: a macro with this name exists at the root of the crate - /// | - /// LL | use issue_59764::makro; - /// | ^^^^^^^^^^^^^^^^^^ - /// | - /// = note: this could be because a macro annotated with `#[macro_export]` will be exported - /// at the root of the crate instead of the module where it is defined - /// ``` - pub(crate) fn check_for_module_export_macro( - &self, - directive: &'b ImportDirective<'b>, - module: ModuleOrUniformRoot<'b>, - ident: Ident, - ) -> Option<(Option, Vec)> { - let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module { - module - } else { - return None; - }; - - while let Some(parent) = crate_module.parent { - crate_module = parent; - } - - if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) { - // Don't make a suggestion if the import was already from the root of the - // crate. - return None; - } - - let resolutions = crate_module.resolutions.borrow(); - let resolution = resolutions.get(&(ident, MacroNS))?; - let binding = resolution.borrow().binding()?; - if let Def::Macro(_, MacroKind::Bang) = binding.def() { - let module_name = crate_module.kind.name().unwrap(); - let import = match directive.subclass { - ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target => - format!("{} as {}", source, target), - _ => format!("{}", ident), - }; - - let mut corrections: Vec<(Span, String)> = Vec::new(); - if !directive.is_nested() { - // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove - // intermediate segments. - corrections.push((directive.span, format!("{}::{}", module_name, import))); - } else { - // Find the binding span (and any trailing commas and spaces). - // ie. `use a::b::{c, d, e};` - // ^^^ - let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( - self.resolver.session, directive.span, directive.use_span, - ); - debug!("check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", - found_closing_brace, binding_span); - - let mut removal_span = binding_span; - if found_closing_brace { - // If the binding span ended with a closing brace, as in the below example: - // ie. `use a::b::{c, d};` - // ^ - // Then expand the span of characters to remove to include the previous - // binding's trailing comma. - // ie. `use a::b::{c, d};` - // ^^^ - if let Some(previous_span) = extend_span_to_previous_binding( - self.resolver.session, binding_span, - ) { - debug!("check_for_module_export_macro: previous_span={:?}", previous_span); - removal_span = removal_span.with_lo(previous_span.lo()); - } - } - debug!("check_for_module_export_macro: removal_span={:?}", removal_span); - - // Remove the `removal_span`. - corrections.push((removal_span, "".to_string())); - - // Find the span after the crate name and if it has nested imports immediatately - // after the crate name already. - // ie. `use a::b::{c, d};` - // ^^^^^^^^^ - // or `use a::{b, c, d}};` - // ^^^^^^^^^^^ - let (has_nested, after_crate_name) = find_span_immediately_after_crate_name( - self.resolver.session, module_name, directive.use_span, - ); - debug!("check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", - has_nested, after_crate_name); - - let source_map = self.resolver.session.source_map(); - - // Add the import to the start, with a `{` if required. - let start_point = source_map.start_point(after_crate_name); - if let Ok(start_snippet) = source_map.span_to_snippet(start_point) { - corrections.push(( - start_point, - if has_nested { - // In this case, `start_snippet` must equal '{'. - format!("{}{}, ", start_snippet, import) - } else { - // In this case, add a `{`, then the moved import, then whatever - // was there before. - format!("{{{}, {}", import, start_snippet) - } - )); - } - - // Add a `};` to the end if nested, matching the `{` added at the start. - if !has_nested { - corrections.push((source_map.end_point(after_crate_name), - "};".to_string())); - } - } - - let suggestion = Some(( - corrections, - String::from("a macro with this name exists at the root of the crate"), - Applicability::MaybeIncorrect, - )); - let note = vec![ - "this could be because a macro annotated with `#[macro_export]` will be exported \ - at the root of the crate instead of the module where it is defined".to_string(), - ]; - Some((suggestion, note)) - } else { - None - } - } -} - -/// Given a `binding_span` of a binding within a use statement: -/// -/// ``` -/// use foo::{a, b, c}; -/// ^ -/// ``` -/// -/// then return the span until the next binding or the end of the statement: -/// -/// ``` -/// use foo::{a, b, c}; -/// ^^^ -/// ``` -pub(crate) fn find_span_of_binding_until_next_binding( - sess: &Session, - binding_span: Span, - use_span: Span, -) -> (bool, Span) { - let source_map = sess.source_map(); - - // Find the span of everything after the binding. - // ie. `a, e};` or `a};` - let binding_until_end = binding_span.with_hi(use_span.hi()); - - // Find everything after the binding but not including the binding. - // ie. `, e};` or `};` - let after_binding_until_end = binding_until_end.with_lo(binding_span.hi()); - - // Keep characters in the span until we encounter something that isn't a comma or - // whitespace. - // ie. `, ` or ``. - // - // Also note whether a closing brace character was encountered. If there - // was, then later go backwards to remove any trailing commas that are left. - let mut found_closing_brace = false; - let after_binding_until_next_binding = source_map.span_take_while( - after_binding_until_end, - |&ch| { - if ch == '}' { found_closing_brace = true; } - ch == ' ' || ch == ',' - } - ); - - // Combine the two spans. - // ie. `a, ` or `a`. - // - // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };` - let span = binding_span.with_hi(after_binding_until_next_binding.hi()); - - (found_closing_brace, span) -} - -/// Given a `binding_span`, return the span through to the comma or opening brace of the previous -/// binding. -/// -/// ``` -/// use foo::a::{a, b, c}; -/// ^^--- binding span -/// | -/// returned span -/// -/// use foo::{a, b, c}; -/// --- binding span -/// ``` -pub(crate) fn extend_span_to_previous_binding( - sess: &Session, - binding_span: Span, -) -> Option { - let source_map = sess.source_map(); - - // `prev_source` will contain all of the source that came before the span. - // Then split based on a command and take the first (ie. closest to our span) - // snippet. In the example, this is a space. - let prev_source = source_map.span_to_prev_source(binding_span).ok()?; - - let prev_comma = prev_source.rsplit(',').collect::>(); - let prev_starting_brace = prev_source.rsplit('{').collect::>(); - if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 { - return None; - } - - let prev_comma = prev_comma.first().unwrap(); - let prev_starting_brace = prev_starting_brace.first().unwrap(); - - // If the amount of source code before the comma is greater than - // the amount of source code before the starting brace then we've only - // got one item in the nested item (eg. `issue_52891::{self}`). - if prev_comma.len() > prev_starting_brace.len() { - return None; - } - - Some(binding_span.with_lo(BytePos( - // Take away the number of bytes for the characters we've found and an - // extra for the comma. - binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1 - ))) -} - -/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if -/// it is a nested use tree. -/// -/// ``` -/// use foo::a::{b, c}; -/// ^^^^^^^^^^ // false -/// -/// use foo::{a, b, c}; -/// ^^^^^^^^^^ // true -/// -/// use foo::{a, b::{c, d}}; -/// ^^^^^^^^^^^^^^^ // true -/// ``` -fn find_span_immediately_after_crate_name( - sess: &Session, - module_name: Symbol, - use_span: Span, -) -> (bool, Span) { - debug!("find_span_immediately_after_crate_name: module_name={:?} use_span={:?}", - module_name, use_span); - let source_map = sess.source_map(); - - // Using `use issue_59764::foo::{baz, makro};` as an example throughout.. - let mut num_colons = 0; - // Find second colon.. `use issue_59764:` - let until_second_colon = source_map.span_take_while(use_span, |c| { - if *c == ':' { num_colons += 1; } - match c { - ':' if num_colons == 2 => false, - _ => true, - } - }); - // Find everything after the second colon.. `foo::{baz, makro};` - let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1)); - - let mut found_a_non_whitespace_character = false; - // Find the first non-whitespace character in `from_second_colon`.. `f` - let after_second_colon = source_map.span_take_while(from_second_colon, |c| { - if found_a_non_whitespace_character { return false; } - if !c.is_whitespace() { found_a_non_whitespace_character = true; } - true - }); - - // Find the first `{` in from_second_colon.. `foo::{` - let next_left_bracket = source_map.span_through_char(from_second_colon, '{'); - - (next_left_bracket == after_second_colon, from_second_colon) -} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 83416eaa06274..08b2f1a0f16fc 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -65,7 +65,7 @@ use std::mem::replace; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; -use error_reporting::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; +use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{InvocationData, LegacyBinding, ParentScope}; @@ -73,8 +73,8 @@ type Def = def::Def; // N.B., this module needs to be declared first so diagnostics are // registered before they are used. +mod error_codes; mod diagnostics; -mod error_reporting; mod macros; mod check_unused; mod build_reduced_graph; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/error_codes.rs similarity index 100% rename from src/librustc_typeck/diagnostics.rs rename to src/librustc_typeck/error_codes.rs diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4320e28d676ed..9bc221fac1b0b 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -81,7 +81,7 @@ This API is completely unstable and subject to change. // N.B., this module needs to be declared first so diagnostics are // registered before they are used. -mod diagnostics; +mod error_codes; mod astconv; mod check; diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/error_codes.rs similarity index 100% rename from src/libsyntax/diagnostic_list.rs rename to src/libsyntax/error_codes.rs diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 1486909b27692..db10ab7af5a72 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -114,7 +114,7 @@ pub mod diagnostics { // N.B., this module needs to be declared first so diagnostics are // registered before they are used. -pub mod diagnostic_list; +pub mod error_codes; pub mod util { pub mod lev_distance; diff --git a/src/libsyntax_ext/diagnostics.rs b/src/libsyntax_ext/error_codes.rs similarity index 100% rename from src/libsyntax_ext/diagnostics.rs rename to src/libsyntax_ext/error_codes.rs diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 8371d27207589..508f740cac927 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -17,7 +17,7 @@ extern crate proc_macro; -mod diagnostics; +mod error_codes; mod asm; mod assert; diff --git a/src/tools/tidy/src/errors.rs b/src/tools/tidy/src/errors.rs index 76ebc9b601099..ef1000ee5065a 100644 --- a/src/tools/tidy/src/errors.rs +++ b/src/tools/tidy/src/errors.rs @@ -15,7 +15,7 @@ pub fn check(path: &Path, bad: &mut bool) { &mut |path| super::filter_dirs(path) || path.ends_with("src/test"), &mut |file| { let filename = file.file_name().unwrap().to_string_lossy(); - if filename != "diagnostics.rs" && filename != "diagnostic_list.rs" { + if filename != "error_codes.rs" { return }