From 87539a3c0b33360b1468df727a5569e973b8eb3e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 18 Mar 2026 16:49:58 +0300 Subject: [PATCH 1/3] ast: Preserve the star symbol span in glob delegation items --- compiler/rustc_ast/src/ast.rs | 9 +++++++-- compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state/item.rs | 10 ++++++++-- compiler/rustc_expand/src/expand.rs | 8 ++++---- compiler/rustc_parse/src/parser/item.rs | 13 +++++++++---- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 74cc1ec17e6f0..5f0b33d5243c9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3878,12 +3878,17 @@ pub struct Delegation { pub from_glob: bool, } +#[derive(Clone, Encodable, Decodable, Debug, Walkable)] +pub enum DelegationSuffixes { + List(ThinVec<(Ident, Option)>), + Glob(Span), +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct DelegationMac { pub qself: Option>, pub prefix: Path, - // Some for list delegation, and None for glob delegation. - pub suffixes: Option)>>, + pub suffixes: DelegationSuffixes, pub body: Option>, } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index bdf290f9a9e63..858f0a6bd8ffe 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -430,6 +430,7 @@ macro_rules! common_visitor_and_walkers { Defaultness, Delegation, DelegationMac, + DelegationSuffixes, DelimArgs, DelimSpan, EnumDef, diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 3407feb3dcc3a..2bc39ccfd1dcb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -435,7 +435,10 @@ impl<'a> State<'a> { &item.vis, &deleg.qself, &deleg.prefix, - deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)), + match &deleg.suffixes { + ast::DelegationSuffixes::List(s) => DelegationKind::List(s), + ast::DelegationSuffixes::Glob(_) => DelegationKind::Glob, + }, &deleg.body, ), } @@ -641,7 +644,10 @@ impl<'a> State<'a> { vis, &deleg.qself, &deleg.prefix, - deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)), + match &deleg.suffixes { + ast::DelegationSuffixes::List(s) => DelegationKind::List(s), + ast::DelegationSuffixes::Glob(_) => DelegationKind::Glob, + }, &deleg.body, ), } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 76a9a6f9d03d9..4d0963eb72c4a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -8,9 +8,9 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list}; use rustc_ast::{ self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrItemKind, AttrStyle, AttrVec, - DUMMY_NODE_ID, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, - ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind, - TyKind, token, + DUMMY_NODE_ID, DelegationSuffixes, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs, + HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId, + PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; use rustc_attr_parsing::{ @@ -2294,7 +2294,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { res } None if let Some((deleg, item)) = node.delegation() => { - let Some(suffixes) = &deleg.suffixes else { + let DelegationSuffixes::List(suffixes) = &deleg.suffixes else { let traitless_qself = matches!(&deleg.qself, Some(qself) if qself.position == 0); let (item, of_trait) = match node.to_annotatable() { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0f4927432f6fa..6e1505a4cb25f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -833,7 +833,7 @@ impl<'a> Parser<'a> { kind: AssocItemKind::DelegationMac(Box::new(DelegationMac { qself: None, prefix: of_trait.trait_ref.path.clone(), - suffixes: None, + suffixes: DelegationSuffixes::Glob(whole_reuse_span), body, })), })); @@ -855,10 +855,12 @@ impl<'a> Parser<'a> { Ok(if self.eat_path_sep() { let suffixes = if self.eat(exp!(Star)) { - None + DelegationSuffixes::Glob(self.prev_token.span) } else { let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?)); - Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0) + DelegationSuffixes::List( + self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0, + ) }; ItemKind::DelegationMac(Box::new(DelegationMac { @@ -1492,7 +1494,10 @@ impl<'a> Parser<'a> { let span = self.psess.source_map().guess_head_span(span); let descr = kind.descr(); let help = match kind { - ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => false, + ItemKind::DelegationMac(box DelegationMac { + suffixes: DelegationSuffixes::Glob(_), + .. + }) => false, _ => true, }; self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help }); From abf79cf69ba5e0413ba0810381f29f0b80458547 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 18 Mar 2026 17:30:57 +0300 Subject: [PATCH 2/3] expand: More precise location for glob delegation The span location of the last segment in the desugared path is inherited from the star symbol's span --- compiler/rustc_expand/src/base.rs | 11 +++++++-- compiler/rustc_resolve/src/macros.rs | 23 ++++++++++++------- .../delegation/impl-reuse-negative-traits.rs | 2 +- .../impl-reuse-negative-traits.stderr | 6 ++--- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 225906dfba2de..580e0823a3d2f 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1018,18 +1018,24 @@ impl SyntaxExtension { pub fn glob_delegation( trait_def_id: DefId, impl_def_id: LocalDefId, + star_span: Span, edition: Edition, ) -> SyntaxExtension { struct GlobDelegationExpanderImpl { trait_def_id: DefId, impl_def_id: LocalDefId, + star_span: Span, } impl GlobDelegationExpander for GlobDelegationExpanderImpl { fn expand( &self, ecx: &mut ExtCtxt<'_>, ) -> ExpandResult)>, ()> { - match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) { + match ecx.resolver.glob_delegation_suffixes( + self.trait_def_id, + self.impl_def_id, + self.star_span, + ) { Ok(suffixes) => ExpandResult::Ready(suffixes), Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()), Err(Indeterminate) => ExpandResult::Retry(()), @@ -1037,7 +1043,7 @@ impl SyntaxExtension { } } - let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id }; + let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id, star_span }; SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition) } @@ -1169,6 +1175,7 @@ pub trait ResolverExpand { &self, trait_def_id: DefId, impl_def_id: LocalDefId, + star_span: Span, ) -> Result)>, Indeterminate>; /// Record the name of an opaque `Ty::ImplTrait` pre-expansion so that it can be used diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d6c708f7a12e1..505a61662e63c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -4,7 +4,7 @@ use std::mem; use std::sync::Arc; -use rustc_ast::{self as ast, Crate, DUMMY_NODE_ID, NodeId}; +use rustc_ast::{self as ast, Crate, DUMMY_NODE_ID, DelegationSuffixes, NodeId}; use rustc_ast_pretty::pprust; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, DiagCtxtHandle, StashKey}; @@ -286,7 +286,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive), InvocationKind::GlobDelegation { ref item, .. } => { let ast::AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() }; - deleg_impl = Some(self.invocation_parent(invoc_id)); + let DelegationSuffixes::Glob(star_span) = deleg.suffixes else { unreachable!() }; + deleg_impl = Some((self.invocation_parent(invoc_id), star_span)); // It is sufficient to consider glob delegation a bang macro for now. (&deleg.prefix, MacroKind::Bang) } @@ -530,6 +531,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { &self, trait_def_id: DefId, impl_def_id: LocalDefId, + star_span: Span, ) -> Result)>, Indeterminate> { let target_trait = self.expect_module(trait_def_id); if !target_trait.unexpanded_invocations.borrow().is_empty() { @@ -549,13 +551,13 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { let mut idents = Vec::new(); target_trait.for_each_child(self, |this, ident, orig_ident_span, ns, _binding| { - // FIXME: Adjust hygiene for idents from globs, like for glob imports. if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id) && overriding_keys.contains(&BindingKey::new(ident, ns)) { // The name is overridden, do not produce it from the glob delegation. } else { - idents.push((ident.orig(orig_ident_span), None)); + // FIXME: Adjust hygiene for idents from globs, like for glob imports. + idents.push((ident.orig(star_span.with_ctxt(orig_ident_span.ctxt())), None)); } }); Ok(idents) @@ -579,7 +581,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope: &ParentScope<'ra>, node_id: NodeId, force: bool, - deleg_impl: Option, + deleg_impl: Option<(LocalDefId, Span)>, invoc_in_mod_inert_attr: Option, suggestion_span: Option, ) -> Result<(Arc, Res), Indeterminate> { @@ -755,7 +757,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { kind: MacroKind, parent_scope: &ParentScope<'ra>, force: bool, - deleg_impl: Option, + deleg_impl: Option<(LocalDefId, Span)>, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, ignore_import: Option>, suggestion_span: Option, @@ -840,10 +842,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let res = res?; let ext = match deleg_impl { - Some(impl_def_id) => match res { + Some((impl_def_id, star_span)) => match res { def::Res::Def(DefKind::Trait, def_id) => { let edition = self.tcx.sess.edition(); - Some(Arc::new(SyntaxExtension::glob_delegation(def_id, impl_def_id, edition))) + Some(Arc::new(SyntaxExtension::glob_delegation( + def_id, + impl_def_id, + star_span, + edition, + ))) } _ => None, }, diff --git a/tests/ui/delegation/impl-reuse-negative-traits.rs b/tests/ui/delegation/impl-reuse-negative-traits.rs index 7bcbc82f03db8..8bc2b72708599 100644 --- a/tests/ui/delegation/impl-reuse-negative-traits.rs +++ b/tests/ui/delegation/impl-reuse-negative-traits.rs @@ -4,7 +4,6 @@ trait Trait { fn foo(&self); - //~^ ERROR negative impls cannot have any items [E0749] } struct S; @@ -15,5 +14,6 @@ impl Trait for S { struct F(S); reuse impl !Trait for F { &self.0 } +//~^ ERROR negative impls cannot have any items fn main() {} diff --git a/tests/ui/delegation/impl-reuse-negative-traits.stderr b/tests/ui/delegation/impl-reuse-negative-traits.stderr index 1be6ef715920d..7510fdd89d7c6 100644 --- a/tests/ui/delegation/impl-reuse-negative-traits.stderr +++ b/tests/ui/delegation/impl-reuse-negative-traits.stderr @@ -1,8 +1,8 @@ error[E0749]: negative impls cannot have any items - --> $DIR/impl-reuse-negative-traits.rs:6:8 + --> $DIR/impl-reuse-negative-traits.rs:16:1 | -LL | fn foo(&self); - | ^^^ +LL | reuse impl !Trait for F { &self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error From 6f66e768cf4d92daa1da8d3065ee7eb43bde5260 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 18 Mar 2026 19:05:12 +0300 Subject: [PATCH 3/3] delegation: Give declaration of `self` syntax context of the whole item Instead of the last segment of the delegation path. `self` is something that introduced by the whole delegation item, not some specific part of it, and the last segment may need to have a different context for path resolution purposes. --- compiler/rustc_resolve/src/late.rs | 26 +++++-- tests/ui/delegation/impl-reuse-pass.rs | 25 ------- .../ui/delegation/impl-reuse-self-hygiene.rs | 39 +++++++++++ .../delegation/impl-reuse-self-hygiene.stderr | 68 +++++++++++++++++++ 4 files changed, 128 insertions(+), 30 deletions(-) create mode 100644 tests/ui/delegation/impl-reuse-self-hygiene.rs create mode 100644 tests/ui/delegation/impl-reuse-self-hygiene.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 453fe9d7a8e0e..c8f371042f64a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2989,7 +2989,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { item.id, LifetimeBinderKind::Function, span, - |this| this.resolve_delegation(delegation, item.id, false, &item.attrs), + |this| { + this.resolve_delegation(delegation, item.id, false, &item.attrs, item.span) + }, ); } @@ -3335,7 +3337,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { item.id, LifetimeBinderKind::Function, delegation.path.segments.last().unwrap().ident.span, - |this| this.resolve_delegation(delegation, item.id, false, &item.attrs), + |this| { + this.resolve_delegation( + delegation, + item.id, + false, + &item.attrs, + item.span, + ) + }, ); } AssocItemKind::Type(box TyAlias { generics, .. }) => self @@ -3649,7 +3659,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Here we don't use `trait_id`, as we can process unresolved trait, however // in this case we are still in a trait impl, https://github.com/rust-lang/rust/issues/150152 - this.resolve_delegation(delegation, item.id, is_in_trait_impl, &item.attrs); + this.resolve_delegation( + delegation, + item.id, + is_in_trait_impl, + &item.attrs, + item.span, + ); }, ); } @@ -3805,6 +3821,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { item_id: NodeId, is_in_trait_impl: bool, attrs: &[Attribute], + item_span: Span, ) { self.smart_resolve_path( delegation.id, @@ -3829,8 +3846,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let Some(body) = &delegation.body else { return }; self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| { - let span = delegation.path.segments.last().unwrap().ident.span; - let ident = Ident::new(kw::SelfLower, span.normalize_to_macro_rules()); + let ident = Ident::new(kw::SelfLower, item_span.normalize_to_macro_rules()); let res = Res::Local(delegation.id); this.innermost_rib_bindings(ValueNS).insert(ident, res); diff --git a/tests/ui/delegation/impl-reuse-pass.rs b/tests/ui/delegation/impl-reuse-pass.rs index 90060b03f9efd..578e8c08e7038 100644 --- a/tests/ui/delegation/impl-reuse-pass.rs +++ b/tests/ui/delegation/impl-reuse-pass.rs @@ -173,19 +173,6 @@ mod macros { macro_rules! m { () => { M } } reuse impl Trait for m!() { self_0_ref!(self) } - struct S1(u8); - macro_rules! one_line_reuse { ($self:ident) => { reuse impl Trait for S1 { $self.0 } } } - one_line_reuse!(self); - - struct S2(u8); - macro_rules! one_line_reuse_expr { ($x:expr) => { reuse impl Trait for S2 { $x } } } - one_line_reuse_expr!(self.0); - - struct S3(u8); - macro_rules! s3 { () => { S3 } } - macro_rules! one_line_reuse_expr2 { ($x:expr) => { reuse impl Trait for s3!() { $x } } } - one_line_reuse_expr2!(self.0); - fn f() { let s = S(1); s.foo(); @@ -194,18 +181,6 @@ mod macros { let m = M(41); m.foo(); m.bar(); - - let s1 = S1(2); - s1.foo(); - s1.bar(); - - let s2 = S2(4); - s2.foo(); - s2.bar(); - - let s3 = S3(5); - s3.foo(); - s3.bar(); } } diff --git a/tests/ui/delegation/impl-reuse-self-hygiene.rs b/tests/ui/delegation/impl-reuse-self-hygiene.rs new file mode 100644 index 0000000000000..75df8d4143c48 --- /dev/null +++ b/tests/ui/delegation/impl-reuse-self-hygiene.rs @@ -0,0 +1,39 @@ +#![allow(incomplete_features)] +#![feature(fn_delegation)] + +trait Trait { + fn foo(&self) -> u8 { 0 } + fn bar(&self) -> u8 { 1 } +} + +// impl Trait for u8 {} +// struct S(u8); + +// macro_rules! self_0_ref { ($self:ident) => { &$self.0 } } + +// reuse impl Trait for S { self_0_ref!(self) } + +// struct M(u8); +// macro_rules! m { () => { M } } +// reuse impl Trait for m!() { self_0_ref!(self) } + +struct S1(u8); +macro_rules! one_line_reuse { ($self:ident) => { reuse impl Trait for S1 { $self.0 } } } +//~^ ERROR expected value, found module `self` +//~| ERROR expected value, found module `self` +one_line_reuse!(self); + +struct S2(u8); +macro_rules! one_line_reuse_expr { ($x:expr) => { reuse impl Trait for S2 { $x } } } +one_line_reuse_expr!(self.0); +//~^ ERROR expected value, found module `self` +//~| ERROR expected value, found module `self` + +struct S3(u8); +macro_rules! s3 { () => { S3 } } +macro_rules! one_line_reuse_expr2 { ($x:expr) => { reuse impl Trait for s3!() { $x } } } +one_line_reuse_expr2!(self.0); +//~^ ERROR expected value, found module `self` +//~| ERROR expected value, found module `self` + +fn main() {} diff --git a/tests/ui/delegation/impl-reuse-self-hygiene.stderr b/tests/ui/delegation/impl-reuse-self-hygiene.stderr new file mode 100644 index 0000000000000..b1684963e6147 --- /dev/null +++ b/tests/ui/delegation/impl-reuse-self-hygiene.stderr @@ -0,0 +1,68 @@ +error[E0424]: expected value, found module `self` + --> $DIR/impl-reuse-self-hygiene.rs:21:76 + | +LL | macro_rules! one_line_reuse { ($self:ident) => { reuse impl Trait for S1 { $self.0 } } } + | --------------------------^^^^^---- + | | | + | | `self` value is a keyword only available in methods with a `self` parameter + | `self` not allowed in an implementation +... +LL | one_line_reuse!(self); + | --------------------- in this macro invocation + | + = note: this error originates in the macro `one_line_reuse` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0424]: expected value, found module `self` + --> $DIR/impl-reuse-self-hygiene.rs:21:76 + | +LL | macro_rules! one_line_reuse { ($self:ident) => { reuse impl Trait for S1 { $self.0 } } } + | --------------------------^^^^^---- + | | | + | | `self` value is a keyword only available in methods with a `self` parameter + | `self` not allowed in an implementation +... +LL | one_line_reuse!(self); + | --------------------- in this macro invocation + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: this error originates in the macro `one_line_reuse` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0424]: expected value, found module `self` + --> $DIR/impl-reuse-self-hygiene.rs:28:22 + | +LL | macro_rules! one_line_reuse_expr { ($x:expr) => { reuse impl Trait for S2 { $x } } } + | ------------------------------ `self` not allowed in an implementation +LL | one_line_reuse_expr!(self.0); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + +error[E0424]: expected value, found module `self` + --> $DIR/impl-reuse-self-hygiene.rs:28:22 + | +LL | macro_rules! one_line_reuse_expr { ($x:expr) => { reuse impl Trait for S2 { $x } } } + | ------------------------------ `self` not allowed in an implementation +LL | one_line_reuse_expr!(self.0); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0424]: expected value, found module `self` + --> $DIR/impl-reuse-self-hygiene.rs:35:23 + | +LL | macro_rules! one_line_reuse_expr2 { ($x:expr) => { reuse impl Trait for s3!() { $x } } } + | --------------------------------- `self` not allowed in an implementation +LL | one_line_reuse_expr2!(self.0); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + +error[E0424]: expected value, found module `self` + --> $DIR/impl-reuse-self-hygiene.rs:35:23 + | +LL | macro_rules! one_line_reuse_expr2 { ($x:expr) => { reuse impl Trait for s3!() { $x } } } + | --------------------------------- `self` not allowed in an implementation +LL | one_line_reuse_expr2!(self.0); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0424`.