From 47b4b8e8c5189228015ee645dfc65e9b73d2c19c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 Mar 2024 09:06:08 +1100 Subject: [PATCH] Allow multiple `impl Into<{D,Subd}iagMessage>` parameters in a function. The internal diagnostic lint currently only allows one, because that was all that occurred in practice. But rust-lang/rust-clippy/pull/12453 wants to introduce functions with more than one, and this limitation is getting in the way. --- compiler/rustc_lint/src/internal.rs | 17 +++++------------ tests/ui-fulldeps/internal-lints/diagnostics.rs | 10 ++++++++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 0872a8a20959f..153d91ce28cb0 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -409,9 +409,8 @@ impl LateLintPass<'_> for Diagnostics { } }; - // Does the callee have a `impl Into<{D,Subd}iagMessage>` parameter? (There should be at - // most one.) - let mut impl_into_diagnostic_message_param = None; + // Does the callee have one or more `impl Into<{D,Subd}iagMessage>` parameters? + let mut impl_into_diagnostic_message_params = vec![]; let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates; for (i, ¶m_ty) in fn_sig.inputs().iter().enumerate() { @@ -425,20 +424,14 @@ impl LateLintPass<'_> for Diagnostics { && let ty1 = trait_ref.args.type_at(1) && is_diag_message(ty1) { - if impl_into_diagnostic_message_param.is_some() { - cx.tcx.dcx().span_bug( - span, - "can't handle multiple `impl Into<{D,Sub}iagMessage>` params", - ); - } - impl_into_diagnostic_message_param = Some((i, p.name)); + impl_into_diagnostic_message_params.push((i, p.name)); } } } } // Is the callee interesting? - if !has_attr && impl_into_diagnostic_message_param.is_none() { + if !has_attr && impl_into_diagnostic_message_params.is_empty() { return; } @@ -481,7 +474,7 @@ impl LateLintPass<'_> for Diagnostics { // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an // `UNTRANSLATABLE_DIAGNOSTIC` lint. - if let Some((param_i, param_i_p_name)) = impl_into_diagnostic_message_param { + for (param_i, param_i_p_name) in impl_into_diagnostic_message_params { // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`? let arg_ty = call_tys[param_i]; let is_translatable = is_diag_message(arg_ty) diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index d443681d5db08..1d7417be58cc3 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -15,7 +15,7 @@ extern crate rustc_span; use rustc_errors::{ Diag, DiagCtxt, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level, LintDiagnostic, - SubdiagMessageOp, Subdiagnostic, + SubdiagMessageOp, SubdiagMessage, Subdiagnostic, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -114,9 +114,15 @@ pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) { // Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted for // `diagnostic_outside_of_impl`. - #[rustc_lint_diagnostics] pub fn skipped_because_of_annotation<'a>(dcx: &'a DiagCtxt) { #[allow(rustc::untranslatable_diagnostic)] let _diag = dcx.struct_err("untranslatable diagnostic"); // okay! } + +// Check that multiple translatable params are allowed in a single function (at one point they +// weren't). +fn f(_x: impl Into, _y: impl Into) {} +fn g() { + f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example); +}