From 694054ba9a0935308c29c165f0ad7201398a637b Mon Sep 17 00:00:00 2001 From: delta17920 Date: Thu, 5 Mar 2026 13:56:48 +0000 Subject: [PATCH] ast_lowering: fix ICE in fn_delegation with complex generics --- .../src/delegation/generics.rs | 6 ++++ compiler/rustc_ast_lowering/src/item.rs | 10 +++--- .../ice-fn-delegation-complex-generics.rs | 11 +++++++ .../ice-fn-delegation-complex-generics.stderr | 31 +++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 tests/ui/delegation/ice-fn-delegation-complex-generics.rs create mode 100644 tests/ui/delegation/ice-fn-delegation-complex-generics.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index 9e7ec04d38fb7..1c916b8a79fd8 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -1,6 +1,7 @@ use hir::HirId; use hir::def::{DefKind, Res}; use rustc_ast::*; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::GenericParamDefKind; @@ -165,12 +166,17 @@ impl<'hir> GenericsGenerationResults<'hir> { // then parent and child types and consts. // `generics_of` in `rustc_hir_analysis` will order them anyway, // however we want the order to be consistent in HIR too. + // Deduplicate by parameter name/ident to handle cases where + // parent and child create separate copies of the same logical param + let mut seen = FxHashSet::default(); + parent .iter() .filter(|p| p.is_lifetime()) .chain(child.iter().filter(|p| p.is_lifetime())) .chain(parent.iter().filter(|p| !p.is_lifetime())) .chain(child.iter().filter(|p| !p.is_lifetime())) + .filter(move |p| seen.insert(p.def_id)) .copied() } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c17eb7c633d1b..8b9548328d815 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -62,10 +62,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { for (def_id, info) in lctx.children { let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - assert!( - matches!(owner, hir::MaybeOwner::Phantom), - "duplicate copy of {def_id:?} in lctx.children" - ); + // Skip duplicates instead of panicking - can happen with complex generic bounds + // in delegation items. The duplicate doesn't matter because both are the same DefId + // and later type checking will catch the actual errors (E0428, etc.) + if !matches!(owner, hir::MaybeOwner::Phantom) { + continue; + } *owner = info; } } diff --git a/tests/ui/delegation/ice-fn-delegation-complex-generics.rs b/tests/ui/delegation/ice-fn-delegation-complex-generics.rs new file mode 100644 index 0000000000000..71bb2ea54c04d --- /dev/null +++ b/tests/ui/delegation/ice-fn-delegation-complex-generics.rs @@ -0,0 +1,11 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +fn main() { + trait Foo {} + fn foo Foo>() {} + //~^ ERROR `(dyn Foo + 'static)` is forbidden as the type of a const generic parameter + //~| ERROR `(dyn Foo + 'static)` is forbidden as the type of a const generic parameter + reuse foo; + //~^ ERROR the name `foo` is defined multiple times +} diff --git a/tests/ui/delegation/ice-fn-delegation-complex-generics.stderr b/tests/ui/delegation/ice-fn-delegation-complex-generics.stderr new file mode 100644 index 0000000000000..47dfeea2b006d --- /dev/null +++ b/tests/ui/delegation/ice-fn-delegation-complex-generics.stderr @@ -0,0 +1,31 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/ice-fn-delegation-complex-generics.rs:9:5 + | +LL | fn foo Foo>() {} + | ---------------------------------- previous definition of the value `foo` here +... +LL | reuse foo; + | ^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this block + +error: `(dyn Foo + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/ice-fn-delegation-complex-generics.rs:6:21 + | +LL | fn foo Foo>() {} + | ^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error: `(dyn Foo + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/ice-fn-delegation-complex-generics.rs:6:21 + | +LL | fn foo Foo>() {} + | ^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0428`.