From 9750d22c17092fa747e088ae24bb749077edefa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jan 2026 21:13:48 +0000 Subject: [PATCH] Silence unused type param and inference errors on struct parse error --- compiler/rustc_hir/src/hir.rs | 20 +++++++++++++++ .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +++++- .../error_reporting/infer/need_type_info.rs | 25 ++++++++++++++++++- .../structs/parse-error-with-type-param.fixed | 14 +++++++++++ .../ui/structs/parse-error-with-type-param.rs | 14 +++++++++++ .../parse-error-with-type-param.stderr | 18 +++++++++++++ 6 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 tests/ui/structs/parse-error-with-type-param.fixed create mode 100644 tests/ui/structs/parse-error-with-type-param.rs create mode 100644 tests/ui/structs/parse-error-with-type-param.stderr diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index dac4c7e3965a..b296522749f0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4525,6 +4525,26 @@ impl ItemKind<'_> { _ => return None, }) } + + pub fn recovered(&self) -> bool { + match self { + ItemKind::Struct( + _, + _, + VariantData::Struct { recovered: ast::Recovered::Yes(_), .. }, + ) => true, + ItemKind::Union( + _, + _, + VariantData::Struct { recovered: ast::Recovered::Yes(_), .. }, + ) => true, + ItemKind::Enum(_, _, def) => def.variants.iter().any(|v| match v.data { + VariantData::Struct { recovered: ast::Recovered::Yes(_), .. } => true, + _ => false, + }), + _ => false, + } + } } // The bodies for items are stored "out of line", in a separate diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index cfc7e57cc14e..8b50eceb26e4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2160,7 +2160,12 @@ fn report_bivariance<'tcx>( const_param_help, }); diag.code(E0392); - diag.emit() + if item.kind.recovered() { + // Silence potentially redundant error, as the item had a parse error. + diag.delay_as_bug() + } else { + diag.emit() + } } /// Detects cases where an ADT/LTA is trivially cyclical -- we want to detect this so diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 0a2442b71e78..e3c8bfe4a452 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -488,7 +488,30 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let Some(InferSource { span, kind }) = local_visitor.infer_source else { - return self.bad_inference_failure_err(failure_span, arg_data, error_code); + let silence = if let DefKind::AssocFn = self.tcx.def_kind(body_def_id) + && let parent = self.tcx.parent(body_def_id.into()) + && self.tcx.is_automatically_derived(parent) + && let Some(parent) = parent.as_local() + && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(parent) + && let hir::ItemKind::Impl(imp) = item.kind + && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = imp.self_ty.kind + && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, def_id) = path.res + && let Some(def_id) = def_id.as_local() + && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(def_id) + { + // We have encountered an inference error within an automatically derived `impl`, + // from a `#[derive(..)]` on an item that had a parse error. Because the parse + // error might have caused the expanded code to be malformed, we silence the + // inference error. + item.kind.recovered() + } else { + false + }; + let mut err = self.bad_inference_failure_err(failure_span, arg_data, error_code); + if silence { + err.downgrade_to_delayed_bug(); + } + return err; }; let (source_kind, name, long_ty_path) = kind.ty_localized_msg(self); diff --git a/tests/ui/structs/parse-error-with-type-param.fixed b/tests/ui/structs/parse-error-with-type-param.fixed new file mode 100644 index 000000000000..46d1c2722843 --- /dev/null +++ b/tests/ui/structs/parse-error-with-type-param.fixed @@ -0,0 +1,14 @@ +//@ run-rustfix +// #141403 +#![allow(dead_code)] + +#[derive(Clone)] +struct B { + a: A<(T, u32)>, // <- note, comma is missing here + /// asdf + //~^ ERROR found a documentation comment that doesn't document anything + b: u32, +} +#[derive(Clone)] +struct A(T); +fn main() {} diff --git a/tests/ui/structs/parse-error-with-type-param.rs b/tests/ui/structs/parse-error-with-type-param.rs new file mode 100644 index 000000000000..27a9fc854f57 --- /dev/null +++ b/tests/ui/structs/parse-error-with-type-param.rs @@ -0,0 +1,14 @@ +//@ run-rustfix +// #141403 +#![allow(dead_code)] + +#[derive(Clone)] +struct B { + a: A<(T, u32)> // <- note, comma is missing here + /// asdf + //~^ ERROR found a documentation comment that doesn't document anything + b: u32, +} +#[derive(Clone)] +struct A(T); +fn main() {} diff --git a/tests/ui/structs/parse-error-with-type-param.stderr b/tests/ui/structs/parse-error-with-type-param.stderr new file mode 100644 index 000000000000..d01eae193b14 --- /dev/null +++ b/tests/ui/structs/parse-error-with-type-param.stderr @@ -0,0 +1,18 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/parse-error-with-type-param.rs:8:5 + | +LL | struct B { + | - while parsing this struct +LL | a: A<(T, u32)> // <- note, comma is missing here +LL | /// asdf + | ^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` +help: missing comma here + | +LL | a: A<(T, u32)>, // <- note, comma is missing here + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0585`.