Skip to content

Commit

Permalink
Allow multiple impl Into<{D,Subd}iagMessage> parameters in a function.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nnethercote committed Mar 11, 2024
1 parent c69fda7 commit 47b4b8e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 14 deletions.
17 changes: 5 additions & 12 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, &param_ty) in fn_sig.inputs().iter().enumerate() {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down
10 changes: 8 additions & 2 deletions tests/ui-fulldeps/internal-lints/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<DiagMessage>, _y: impl Into<SubdiagMessage>) {}
fn g() {
f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example);
}

0 comments on commit 47b4b8e

Please sign in to comment.