diff options
Diffstat (limited to 'compiler/rustc_lint/src/context.rs')
-rw-r--r-- | compiler/rustc_lint/src/context.rs | 170 |
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), - } -} |