about summary refs log tree commit diff
path: root/compiler/rustc_lint
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-26 06:09:32 +0000
committerbors <bors@rust-lang.org>2023-08-26 06:09:32 +0000
commitadb16d5ebd576188e5a4d49f3597e32acbf90e00 (patch)
tree55a62521a94bc3399a3d755f55435826392439d1 /compiler/rustc_lint
parent0154f6c8108156d4835823d123d394abbf2ea741 (diff)
parentec91a2361ba0de6aa90f92fe620d49ef84b177ef (diff)
Auto merge of #3038 - rust-lang:rustup-2023-08-26, r=RalfJung
Automatic sync from rustc
Diffstat (limited to 'compiler/rustc_lint')
-rw-r--r--compiler/rustc_lint/messages.ftl13
-rw-r--r--compiler/rustc_lint/src/context.rs50
-rw-r--r--compiler/rustc_lint/src/errors.rs42
-rw-r--r--compiler/rustc_lint/src/levels.rs54
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/lints.rs20
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs64
7 files changed, 163 insertions, 82 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index c4a7f717840..7f7f36ca170 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -158,13 +158,15 @@ lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
 
 lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
 
+lint_check_name_removed = lint `{$lint_name}` has been removed: {$reason}
+
+lint_check_name_renamed = lint `{$lint_name}` has been renamed to `{$replace}`
+
 lint_check_name_unknown = unknown lint: `{$lint_name}`
     .help = did you mean: `{$suggestion}`
 
 lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
 
-lint_check_name_warning = {$msg}
-
 lint_command_line_source = `forbid` lint level was set on command line
 
 lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike
@@ -323,6 +325,8 @@ lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined be
 lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
     .label = casting happend here
 
+lint_invalid_reference_casting_note_book = for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
+
 lint_lintpass_by_hand = implementing `LintPass` by hand
     .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
@@ -482,8 +486,11 @@ lint_redundant_semicolons =
         *[false] this semicolon
     }
 
-lint_renamed_or_removed_lint = {$msg}
+lint_removed_lint = lint `{$name}` has been removed: {$reason}
+
+lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
     .suggestion = use the new name
+    .help = use the new name `{$replace}`
 
 lint_requested_level = requested on the command line with `{$level} {$lint_name}`
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index f73797415bc..9dfde84b552 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -17,8 +17,8 @@
 use self::TargetLint::*;
 
 use crate::errors::{
-    CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel,
-    UnsupportedGroup,
+    CheckNameDeprecated, CheckNameRemoved, CheckNameRenamed, CheckNameUnknown,
+    CheckNameUnknownTool, RequestedLevel, UnsupportedGroup,
 };
 use crate::levels::LintLevelsBuilder;
 use crate::passes::{EarlyLintPassObject, LateLintPassObject};
@@ -124,9 +124,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
@@ -342,25 +343,32 @@ impl LintStore {
             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,
+            CheckLintNameResult::Renamed(replace) => {
+                sess.emit_warning(CheckNameRenamed {
+                    lint_name,
+                    replace: &replace,
+                    sub: RequestedLevel { level, lint_name },
+                });
+            }
+            CheckLintNameResult::Removed(reason) => {
+                sess.emit_warning(CheckNameRemoved {
+                    lint_name,
+                    reason: &reason,
                     sub: RequestedLevel { level, lint_name },
                 });
             }
             CheckLintNameResult::NoLint(suggestion) => {
                 sess.emit_err(CheckNameUnknown {
-                    lint_name: lint_name.clone(),
+                    lint_name,
                     suggestion,
                     sub: RequestedLevel { level, lint_name },
                 });
             }
             CheckLintNameResult::Tool(Err((Some(_), new_name))) => {
                 sess.emit_warning(CheckNameDeprecated {
-                    lint_name: lint_name.clone(),
-                    new_name,
+                    lint_name,
+                    new_name: &new_name,
                     sub: RequestedLevel { level, lint_name },
                 });
             }
@@ -445,14 +453,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 +968,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)
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 68167487a1b..607875b3faa 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -91,9 +91,9 @@ pub struct BuiltinEllipsisInclusiveRangePatterns {
 
 #[derive(Subdiagnostic)]
 #[note(lint_requested_level)]
-pub struct RequestedLevel {
+pub struct RequestedLevel<'a> {
     pub level: Level,
-    pub lint_name: String,
+    pub lint_name: &'a str,
 }
 
 #[derive(Diagnostic)]
@@ -102,13 +102,13 @@ pub struct UnsupportedGroup {
     pub lint_group: String,
 }
 
-pub struct CheckNameUnknown {
-    pub lint_name: String,
+pub struct CheckNameUnknown<'a> {
+    pub lint_name: &'a str,
     pub suggestion: Option<Symbol>,
-    pub sub: RequestedLevel,
+    pub sub: RequestedLevel<'a>,
 }
 
-impl IntoDiagnostic<'_> for CheckNameUnknown {
+impl IntoDiagnostic<'_> for CheckNameUnknown<'_> {
     fn into_diagnostic(
         self,
         handler: &Handler,
@@ -127,25 +127,35 @@ impl IntoDiagnostic<'_> for CheckNameUnknown {
 
 #[derive(Diagnostic)]
 #[diag(lint_check_name_unknown_tool, code = "E0602")]
-pub struct CheckNameUnknownTool {
+pub struct CheckNameUnknownTool<'a> {
     pub tool_name: Symbol,
     #[subdiagnostic]
-    pub sub: RequestedLevel,
+    pub sub: RequestedLevel<'a>,
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_check_name_warning)]
-pub struct CheckNameWarning {
-    pub msg: String,
+#[diag(lint_check_name_renamed)]
+pub struct CheckNameRenamed<'a> {
+    pub lint_name: &'a str,
+    pub replace: &'a str,
     #[subdiagnostic]
-    pub sub: RequestedLevel,
+    pub sub: RequestedLevel<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(lint_check_name_removed)]
+pub struct CheckNameRemoved<'a> {
+    pub lint_name: &'a str,
+    pub reason: &'a str,
+    #[subdiagnostic]
+    pub sub: RequestedLevel<'a>,
 }
 
 #[derive(Diagnostic)]
 #[diag(lint_check_name_deprecated)]
-pub struct CheckNameDeprecated {
-    pub lint_name: String,
-    pub new_name: String,
+pub struct CheckNameDeprecated<'a> {
+    pub lint_name: &'a str,
+    pub new_name: &'a str,
     #[subdiagnostic]
-    pub sub: RequestedLevel,
+    pub sub: RequestedLevel<'a>,
 }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 1f4e5fa4d3b..f58782c0f22 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -4,15 +4,15 @@ use crate::{
     fluent_generated as fluent,
     late::unerased_lint_store,
     lints::{
-        DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint,
-        RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
+        DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, RemovedLint,
+        RenamedLint, RenamedLintSuggestion, UnknownLint, UnknownLintSuggestion,
     },
 };
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
-use rustc_feature::Features;
+use rustc_feature::{Features, GateIssue};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::HirId;
@@ -24,12 +24,14 @@ use rustc_middle::lint::{
 };
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{RegisteredTools, TyCtxt};
-use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES};
 use rustc_session::lint::{
-    builtin::{self, FORBIDDEN_LINT_GROUPS, SINGLE_USE_LIFETIMES, UNFULFILLED_LINT_EXPECTATIONS},
+    builtin::{
+        self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES,
+        UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES,
+    },
     Level, Lint, LintExpectationId, LintId,
 };
-use rustc_session::parse::{add_feature_diagnostics, feature_err};
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -566,7 +568,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     continue;
                 }
 
-                if self.check_gated_lint(id, DUMMY_SP) {
+                if self.check_gated_lint(id, DUMMY_SP, true) {
                     let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
                     self.insert(id, (level, src));
                 }
@@ -837,7 +839,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             reason,
                         };
                         for &id in *ids {
-                            if self.check_gated_lint(id, attr.span) {
+                            if self.check_gated_lint(id, attr.span, false) {
                                 self.insert_spec(id, (level, src));
                             }
                         }
@@ -854,7 +856,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                                     reason,
                                 };
                                 for &id in ids {
-                                    if self.check_gated_lint(id, attr.span) {
+                                    if self.check_gated_lint(id, attr.span, false) {
                                         self.insert_spec(id, (level, src));
                                     }
                                 }
@@ -913,18 +915,26 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
 
                     _ if !self.warn_about_weird_lints => {}
 
-                    CheckLintNameResult::Warning(msg, renamed) => {
+                    CheckLintNameResult::Renamed(new_name) => {
                         let suggestion =
-                            renamed.as_ref().map(|replace| RenamedOrRemovedLintSuggestion {
-                                suggestion: sp,
-                                replace: replace.as_str(),
-                            });
+                            RenamedLintSuggestion { suggestion: sp, replace: new_name.as_str() };
+                        let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
+                        self.emit_spanned_lint(
+                            RENAMED_AND_REMOVED_LINTS,
+                            sp.into(),
+                            RenamedLint { name: name.as_str(), suggestion },
+                        );
+                    }
+
+                    CheckLintNameResult::Removed(reason) => {
+                        let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
                         self.emit_spanned_lint(
                             RENAMED_AND_REMOVED_LINTS,
                             sp.into(),
-                            RenamedOrRemovedLint { msg, suggestion },
+                            RemovedLint { name: name.as_str(), reason: reason.as_str() },
                         );
                     }
+
                     CheckLintNameResult::NoLint(suggestion) => {
                         let name = if let Some(tool_ident) = tool_ident {
                             format!("{}::{}", tool_ident.name, name)
@@ -943,7 +953,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                 // If this lint was renamed, apply the new lint instead of ignoring the attribute.
                 // This happens outside of the match because the new lint should be applied even if
                 // we don't warn about the name change.
-                if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result {
+                if let CheckLintNameResult::Renamed(new_name) = lint_result {
                     // Ignore any errors or warnings that happen because the new name is inaccurate
                     // NOTE: `new_name` already includes the tool name, so we don't have to add it again.
                     if let CheckLintNameResult::Ok(ids) =
@@ -955,7 +965,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             reason,
                         };
                         for &id in ids {
-                            if self.check_gated_lint(id, attr.span) {
+                            if self.check_gated_lint(id, attr.span, false) {
                                 self.insert_spec(id, (level, src));
                             }
                         }
@@ -1000,7 +1010,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     // FIXME only emit this once for each attribute, instead of repeating it 4 times for
     // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`.
     #[track_caller]
-    fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
+    fn check_gated_lint(&self, lint_id: LintId, span: Span, lint_from_cli: bool) -> bool {
         if let Some(feature) = lint_id.lint.feature_gate {
             if !self.features.enabled(feature) {
                 let lint = builtin::UNKNOWN_LINTS;
@@ -1015,7 +1025,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     |lint| {
                         lint.set_arg("name", lint_id.lint.name_lower());
                         lint.note(fluent::lint_note);
-                        add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
+                        rustc_session::parse::add_feature_diagnostics_for_issue(
+                            lint,
+                            &self.sess.parse_sess,
+                            feature,
+                            GateIssue::Language,
+                            lint_from_cli,
+                        );
                         lint
                     },
                 );
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 585b10e79e4..e578f09b58f 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -40,7 +40,7 @@
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![allow(internal_features)]
 
 #[macro_use]
 extern crate rustc_middle;
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 25982a45853..0e942d774a7 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -764,11 +764,13 @@ pub enum InvalidFromUtf8Diag {
 #[derive(LintDiagnostic)]
 pub enum InvalidReferenceCastingDiag {
     #[diag(lint_invalid_reference_casting_borrow_as_mut)]
+    #[note(lint_invalid_reference_casting_note_book)]
     BorrowAsMut {
         #[label]
         orig_cast: Option<Span>,
     },
     #[diag(lint_invalid_reference_casting_assign_to_ref)]
+    #[note(lint_invalid_reference_casting_note_book)]
     AssignToRef {
         #[label]
         orig_cast: Option<Span>,
@@ -1010,24 +1012,30 @@ pub struct DeprecatedLintName<'a> {
     pub replace: &'a str,
 }
 
-// FIXME: Non-translatable msg
 #[derive(LintDiagnostic)]
-#[diag(lint_renamed_or_removed_lint)]
-pub struct RenamedOrRemovedLint<'a> {
-    pub msg: &'a str,
+#[diag(lint_renamed_lint)]
+pub struct RenamedLint<'a> {
+    pub name: &'a str,
     #[subdiagnostic]
-    pub suggestion: Option<RenamedOrRemovedLintSuggestion<'a>>,
+    pub suggestion: RenamedLintSuggestion<'a>,
 }
 
 #[derive(Subdiagnostic)]
 #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
-pub struct RenamedOrRemovedLintSuggestion<'a> {
+pub struct RenamedLintSuggestion<'a> {
     #[primary_span]
     pub suggestion: Span,
     pub replace: &'a str,
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_removed_lint)]
+pub struct RemovedLint<'a> {
+    pub name: &'a str,
+    pub reason: &'a str,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_unknown_lint)]
 pub struct UnknownLint {
     pub name: String,
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 2577cabb3f0..883f6242b56 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -56,20 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        // &mut <expr>
-        let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
-            expr
-        // <expr> = ...
-        } else if let ExprKind::Assign(expr, _, _) = expr.kind {
-            expr
-        // <expr> += ...
-        } else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
-            expr
-        } else {
-            return;
-        };
-
-        let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else {
+        let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else {
             return;
         };
 
@@ -86,15 +73,58 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
         cx.emit_spanned_lint(
             INVALID_REFERENCE_CASTING,
             expr.span,
-            if matches!(expr.kind, ExprKind::AddrOf(..)) {
-                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
-            } else {
+            if is_assignment {
                 InvalidReferenceCastingDiag::AssignToRef { orig_cast }
+            } else {
+                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
             },
         );
     }
 }
 
+fn is_operation_we_care_about<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx Expr<'tcx>,
+) -> Option<(bool, &'tcx Expr<'tcx>)> {
+    fn deref_assign_or_addr_of<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(bool, &'tcx Expr<'tcx>)> {
+        // &mut <expr>
+        let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
+            expr
+        // <expr> = ...
+        } else if let ExprKind::Assign(expr, _, _) = expr.kind {
+            expr
+        // <expr> += ...
+        } else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
+            expr
+        } else {
+            return None;
+        };
+
+        if let ExprKind::Unary(UnOp::Deref, e) = &inner.kind {
+            Some((!matches!(expr.kind, ExprKind::AddrOf(..)), e))
+        } else {
+            None
+        }
+    }
+
+    fn ptr_write<'tcx>(
+        cx: &LateContext<'tcx>,
+        e: &'tcx Expr<'tcx>,
+    ) -> Option<(bool, &'tcx Expr<'tcx>)> {
+        if let ExprKind::Call(path, [arg_ptr, _arg_val]) = e.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_write | sym::ptr_write_volatile | sym::ptr_write_unaligned))
+        {
+            Some((true, arg_ptr))
+        } else {
+            None
+        }
+    }
+
+    deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
+}
+
 fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
     let e = e.peel_blocks();