summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_lint/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_lint/src/context.rs')
-rw-r--r--compiler/rustc_lint/src/context.rs170
1 files changed, 99 insertions, 71 deletions
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index f73797415..3c5cde430 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -16,10 +16,6 @@
use self::TargetLint::*;
-use crate::errors::{
- CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel,
- UnsupportedGroup,
-};
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
@@ -124,9 +120,10 @@ pub enum CheckLintNameResult<'a> {
NoLint(Option<Symbol>),
/// The lint refers to a tool that has not been registered.
NoTool,
- /// The lint is either renamed or removed. This is the warning
- /// message, and an optional new name (`None` if removed).
- Warning(String, Option<String>),
+ /// The lint has been renamed to a new name.
+ Renamed(String),
+ /// The lint has been removed due to the given reason.
+ Removed(String),
/// The lint is from a tool. If the Option is None, then either
/// the lint does not exist in the tool or the code was not
/// compiled with the tool and therefore the lint was never
@@ -329,51 +326,6 @@ impl LintStore {
}
}
- /// Checks the validity of lint names derived from the command line.
- pub fn check_lint_name_cmdline(
- &self,
- sess: &Session,
- lint_name: &str,
- level: Level,
- registered_tools: &RegisteredTools,
- ) {
- let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
- if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn(_)) {
- sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
- return;
- }
- let lint_name = lint_name.to_string();
- match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
- CheckLintNameResult::Warning(msg, _) => {
- sess.emit_warning(CheckNameWarning {
- msg,
- sub: RequestedLevel { level, lint_name },
- });
- }
- CheckLintNameResult::NoLint(suggestion) => {
- sess.emit_err(CheckNameUnknown {
- lint_name: lint_name.clone(),
- suggestion,
- sub: RequestedLevel { level, lint_name },
- });
- }
- CheckLintNameResult::Tool(Err((Some(_), new_name))) => {
- sess.emit_warning(CheckNameDeprecated {
- lint_name: lint_name.clone(),
- new_name,
- sub: RequestedLevel { level, lint_name },
- });
- }
- CheckLintNameResult::NoTool => {
- sess.emit_err(CheckNameUnknownTool {
- tool_name: tool_name.unwrap(),
- sub: RequestedLevel { level, lint_name },
- });
- }
- _ => {}
- };
- }
-
/// True if this symbol represents a lint group name.
pub fn is_lint_group(&self, lint_name: Symbol) -> bool {
debug!(
@@ -445,14 +397,8 @@ impl LintStore {
}
}
match self.by_name.get(&complete_name) {
- Some(Renamed(new_name, _)) => CheckLintNameResult::Warning(
- format!("lint `{complete_name}` has been renamed to `{new_name}`"),
- Some(new_name.to_owned()),
- ),
- Some(Removed(reason)) => CheckLintNameResult::Warning(
- format!("lint `{complete_name}` has been removed: {reason}"),
- None,
- ),
+ Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(new_name.to_string()),
+ Some(Removed(reason)) => CheckLintNameResult::Removed(reason.to_string()),
None => match self.lint_groups.get(&*complete_name) {
// If neither the lint, nor the lint group exists check if there is a `clippy::`
// variant of this lint
@@ -966,6 +912,14 @@ pub trait LintContext: Sized {
Applicability::MachineApplicable
);
}
+ BuiltinLintDiagnostics::AssociatedConstElidedLifetime { elided, span } => {
+ db.span_suggestion_verbose(
+ if elided { span.shrink_to_hi() } else { span },
+ "use the `'static` lifetime",
+ if elided { "'static " } else { "'static" },
+ Applicability::MachineApplicable
+ );
+ }
}
// Rewrap `db`, and pass control to the user.
decorate(db)
@@ -1361,6 +1315,91 @@ impl<'tcx> LateContext<'tcx> {
tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
})
}
+
+ /// If the given expression is a local binding, find the initializer expression.
+ /// If that initializer expression is another local binding, find its initializer again.
+ ///
+ /// This process repeats as long as possible (but usually no more than once).
+ /// Type-check adjustments are not taken in account in this function.
+ ///
+ /// Examples:
+ /// ```
+ /// let abc = 1;
+ /// let def = abc + 2;
+ /// // ^^^^^^^ output
+ /// let def = def;
+ /// dbg!(def);
+ /// // ^^^ input
+ /// ```
+ pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> {
+ expr = expr.peel_blocks();
+
+ while let hir::ExprKind::Path(ref qpath) = expr.kind
+ && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
+ Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id),
+ _ => None,
+ }
+ && let Some(init) = match parent_node {
+ hir::Node::Expr(expr) => Some(expr),
+ hir::Node::Local(hir::Local { init, .. }) => *init,
+ _ => None
+ }
+ {
+ expr = init.peel_blocks();
+ }
+ expr
+ }
+
+ /// If the given expression is a local binding, find the initializer expression.
+ /// If that initializer expression is another local or **outside** (`const`/`static`)
+ /// binding, find its initializer again.
+ ///
+ /// This process repeats as long as possible (but usually no more than once).
+ /// Type-check adjustments are not taken in account in this function.
+ ///
+ /// Examples:
+ /// ```
+ /// const ABC: i32 = 1;
+ /// // ^ output
+ /// let def = ABC;
+ /// dbg!(def);
+ /// // ^^^ input
+ ///
+ /// // or...
+ /// let abc = 1;
+ /// let def = abc + 2;
+ /// // ^^^^^^^ output
+ /// dbg!(def);
+ /// // ^^^ input
+ /// ```
+ pub fn expr_or_init_with_outside_body<'a>(
+ &self,
+ mut expr: &'a hir::Expr<'tcx>,
+ ) -> &'a hir::Expr<'tcx> {
+ expr = expr.peel_blocks();
+
+ while let hir::ExprKind::Path(ref qpath) = expr.kind
+ && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
+ Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id),
+ Res::Def(_, def_id) => self.tcx.hir().get_if_local(def_id),
+ _ => None,
+ }
+ && let Some(init) = match parent_node {
+ hir::Node::Expr(expr) => Some(expr),
+ hir::Node::Local(hir::Local { init, .. }) => *init,
+ hir::Node::Item(item) => match item.kind {
+ hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
+ Some(self.tcx.hir().body(body_id).value)
+ }
+ _ => None
+ }
+ _ => None
+ }
+ {
+ expr = init.peel_blocks();
+ }
+ expr
+ }
}
impl<'tcx> abi::HasDataLayout for LateContext<'tcx> {
@@ -1392,14 +1431,3 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LateContext<'tcx> {
err
}
}
-
-pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
- match lint_name.split_once("::") {
- Some((tool_name, lint_name)) => {
- let tool_name = Symbol::intern(tool_name);
-
- (Some(tool_name), lint_name)
- }
- None => (None, lint_name),
- }
-}