use self::TargetLint::*;
-use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
+use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
-use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
-use rustc_ast as ast;
+use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync;
-use rustc_errors::{
- add_elided_lifetime_in_path_suggestion, struct_span_err, Applicability, SuggestionStyle,
-};
+use rustc_errors::{struct_span_err, Applicability, SuggestionStyle};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_middle::middle::stability;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
+use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt};
use rustc_serialize::json::Json;
use rustc_session::lint::{BuiltinLintDiagnostics, ExternDepSpec};
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
use rustc_session::Session;
use rustc_span::lev_distance::find_best_match_for_name;
-use rustc_span::{symbol::Symbol, BytePos, MultiSpan, Span, DUMMY_SP};
+use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
use rustc_target::abi;
use tracing::debug;
sess: &Session,
lint_name: &str,
level: Level,
- crate_attrs: &[ast::Attribute],
+ registered_tools: &RegisteredTools,
) {
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower() && level == Level::ForceWarn {
)
.emit();
}
- let db = match self.check_lint_name(sess, lint_name_only, tool_name, crate_attrs) {
+ let db = match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Ok(_) => None,
CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
CheckLintNameResult::NoLint(suggestion) => {
lint_name,
self.lint_groups.keys().collect::<Vec<_>>()
);
- let lint_name_str = &*lint_name.as_str();
- self.lint_groups.contains_key(&lint_name_str) || {
+ let lint_name_str = lint_name.as_str();
+ self.lint_groups.contains_key(lint_name_str) || {
let warnings_name_str = crate::WARNINGS.name_lower();
- lint_name_str == &*warnings_name_str
+ lint_name_str == warnings_name_str
}
}
/// printing duplicate warnings.
pub fn check_lint_name(
&self,
- sess: &Session,
lint_name: &str,
tool_name: Option<Symbol>,
- crate_attrs: &[ast::Attribute],
+ registered_tools: &RegisteredTools,
) -> CheckLintNameResult<'_> {
if let Some(tool_name) = tool_name {
- if !is_known_lint_tool(tool_name, sess, crate_attrs) {
+ // FIXME: rustc and rustdoc are considered tools for lints, but not for attributes.
+ if tool_name != sym::rustc
+ && tool_name != sym::rustdoc
+ && !registered_tools.contains(&Ident::with_dummy_span(tool_name))
+ {
return CheckLintNameResult::NoTool;
}
}
pub only_module: bool,
}
-/// Context for lint checking of the AST, after expansion, before lowering to
-/// HIR.
+/// Context for lint checking of the AST, after expansion, before lowering to HIR.
pub struct EarlyContext<'a> {
- /// Type context we're checking in.
- pub sess: &'a Session,
-
- /// The crate being checked.
- pub krate: &'a ast::Crate,
-
pub builder: LintLevelsBuilder<'a>,
-
- /// The store of registered lints and the lint levels.
- pub lint_store: &'a LintStore,
-
pub buffered: LintBuffer,
}
}
},
BuiltinLintDiagnostics::Normal => (),
- BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
- let (sugg, app) = match sess.source_map().span_to_snippet(span) {
- Ok(s) if is_global => {
- (format!("dyn ({})", s), Applicability::MachineApplicable)
- }
- Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
- Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
- };
- db.span_suggestion(span, "use `dyn`", sugg, app);
- }
BuiltinLintDiagnostics::AbsPathWithModule(span) => {
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
Ok(ref s) => {
) => {
db.span_note(span_def, "the macro is defined here");
}
- BuiltinLintDiagnostics::ElidedLifetimesInPaths(
- n,
- path_span,
- incl_angl_brckt,
- insertion_span,
- anon_lts,
- ) => {
- add_elided_lifetime_in_path_suggestion(
- sess.source_map(),
- &mut db,
- n,
- path_span,
- incl_angl_brckt,
- insertion_span,
- anon_lts,
- );
- }
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect);
}
- BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
+ BuiltinLintDiagnostics::UnusedImports(message, replaces, in_test_module) => {
if !replaces.is_empty() {
db.tool_only_multipart_suggestion(
&message,
Applicability::MachineApplicable,
);
}
+
+ if let Some(span) = in_test_module {
+ let def_span = self.sess().source_map().guess_head_span(span);
+ db.span_help(
+ span.shrink_to_lo().to(def_span),
+ "consider adding a `#[cfg(test)]` to the containing module",
+ );
+ }
}
BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
for (span, is_imported) in spans {
}
BuiltinLintDiagnostics::NamedAsmLabel(help) => {
db.help(&help);
- db.note("see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information");
+ db.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
}
}
// Rewrap `db`, and pass control to the user.
}
impl<'a> EarlyContext<'a> {
- pub fn new(
+ pub(crate) fn new(
sess: &'a Session,
+ warn_about_weird_lints: bool,
lint_store: &'a LintStore,
- krate: &'a ast::Crate,
- crate_attrs: &'a [ast::Attribute],
+ registered_tools: &'a RegisteredTools,
buffered: LintBuffer,
- warn_about_weird_lints: bool,
) -> EarlyContext<'a> {
EarlyContext {
- sess,
- krate,
- lint_store,
- builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, crate_attrs),
+ builder: LintLevelsBuilder::new(
+ sess,
+ warn_about_weird_lints,
+ lint_store,
+ registered_tools,
+ ),
buffered,
}
}
/// Gets the overall compiler `Session` object.
fn sess(&self) -> &Session {
- &self.sess
+ &self.builder.sess()
}
fn lints(&self) -> &LintStore {
- &*self.lint_store
+ self.builder.lint_store()
}
fn lookup<S: Into<MultiSpan>>(
) -> Result<Self::Path, Self::Error> {
let mut path = print_prefix(self)?;
- // Skip `::{{constructor}}` on tuple/unit structs.
- if let DefPathData::Ctor = disambiguated_data.data {
+ // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
+ if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
return Ok(path);
}