Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler/rustc_ast_lowering/src/delegation/generics.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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()
}

Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/delegation/ice-fn-delegation-complex-generics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![feature(fn_delegation)]
#![allow(incomplete_features)]

fn main() {
trait Foo {}
fn foo<const N: dyn for<'a> 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
}
31 changes: 31 additions & 0 deletions tests/ui/delegation/ice-fn-delegation-complex-generics.stderr
Original file line number Diff line number Diff line change
@@ -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<const N: dyn for<'a> 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<const N: dyn for<'a> 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<const N: dyn for<'a> 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`.
Loading