From bc2abcefd8d4bbdc2c36d7b9198adf35e6b5e190 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 22 May 2026 10:14:32 +0300 Subject: [PATCH 1/5] Do not always generate first delegation argument --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/delegation.rs | 43 +++-- compiler/rustc_ast_lowering/src/errors.rs | 7 + compiler/rustc_ast_lowering/src/lib.rs | 69 +++++++- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_parse/src/parser/item.rs | 2 +- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 52 ++++-- compiler/rustc_resolve/src/lib.rs | 5 + tests/ui/delegation/delegation-first-arg.rs | 83 +++++++++ .../ui/delegation/delegation-first-arg.stderr | 157 ++++++++++++++++++ ...ems-before-lowering-ices.ice_155128.stderr | 20 +-- .../hir-crate-items-before-lowering-ices.rs | 2 +- tests/ui/delegation/inner-attr.rs | 2 +- tests/ui/delegation/inner-attr.stderr | 18 +- .../zero-args-delegations-ice-154332.rs | 4 +- .../zero-args-delegations-ice-154332.stderr | 37 +---- .../zero-args-delegations-ice-154427.rs | 22 +++ .../zero-args-delegations-ice-154427.stderr | 25 +++ 21 files changed, 448 insertions(+), 109 deletions(-) create mode 100644 tests/ui/delegation/delegation-first-arg.rs create mode 100644 tests/ui/delegation/delegation-first-arg.stderr create mode 100644 tests/ui/delegation/zero-args-delegations-ice-154427.rs create mode 100644 tests/ui/delegation/zero-args-delegations-ice-154427.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 682ba78cddc5f..f31f940c766f8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3918,7 +3918,7 @@ pub struct Delegation { pub rename: Option, pub body: Option>, /// The item was expanded from a glob delegation item. - pub from_glob: bool, + pub from_glob_or_list: bool, } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1e96d1d52f7eb..7689e3453cd68 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -428,7 +428,6 @@ macro_rules! common_visitor_and_walkers { ConstItem, ConstItemRhsKind, Defaultness, - Delegation, DelegationMac, DelegationSuffixes, DelimArgs, @@ -573,6 +572,7 @@ macro_rules! common_visitor_and_walkers { fn visit_fn_decl(FnDecl); fn visit_fn_header(FnHeader); fn visit_fn_ret_ty(FnRetTy); + fn visit_delegation(Delegation); //fn visit_foreign_item(ForeignItem); fn visit_foreign_mod(ForeignMod); fn visit_format_args(FormatArgs); diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 8accaa8c3125c..fbe9e06a95fb8 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -50,13 +50,16 @@ use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, FnDeclFlags}; use rustc_middle::span_bug; -use rustc_middle::ty::Asyncness; +use rustc_middle::ty::{Asyncness, TyCtxt}; use rustc_span::symbol::kw; use rustc_span::{Ident, Span, Symbol}; use smallvec::SmallVec; use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults}; -use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee}; +use crate::errors::{ + CycleInDelegationSignatureResolution, DelegationBlockSpecifiedWhenNoParams, + UnresolvedDelegationCallee, +}; use crate::{ AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, ResolverAstLoweringExt, @@ -105,6 +108,12 @@ static ATTRS_ADDITIONS: &[AttrAdditionInfo] = &[ }, ]; +// Function parameter count, including C variadic `...` if present. +pub(crate) fn param_count(tcx: TyCtxt<'_>, def_id: DefId) -> (usize, bool /*c_variadic*/) { + let sig = tcx.fn_sig(def_id).skip_binder().skip_binder(); + (sig.inputs().len() + usize::from(sig.c_variadic()), sig.c_variadic()) +} + impl<'hir> LoweringContext<'_, 'hir> { fn is_method(&self, def_id: DefId, span: Span) -> bool { match self.tcx.def_kind(def_id) { @@ -140,13 +149,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let is_method = self.is_method(sig_id, span); - let (param_count, c_variadic) = self.param_count(sig_id); + let (param_count, c_variadic) = param_count(self.tcx, sig_id); let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); let (body_id, call_expr_id) = self.lower_delegation_body( delegation, - is_method, + sig_id, param_count, &mut generics, span, @@ -274,12 +283,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()) } - // Function parameter count, including C variadic `...` if present. - fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/) { - let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder(); - (sig.inputs().len() + usize::from(sig.c_variadic()), sig.c_variadic()) - } - fn lower_delegation_decl( &mut self, sig_id: DefId, @@ -407,7 +410,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_body( &mut self, delegation: &Delegation, - is_method: bool, + sig_id: DefId, param_count: usize, generics: &mut GenericsGenerationResults<'hir>, span: Span, @@ -419,12 +422,20 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut parameters: Vec> = Vec::with_capacity(param_count); let mut args: Vec> = Vec::with_capacity(param_count); + let is_method = this.is_method(sig_id, span); + + // Should be in sync with conditions in `lower_delayed_owner::is_dead_code`. + let generate_block = is_method + || matches!(this.tcx.def_kind(sig_id), DefKind::Fn) + || !delegation.from_glob_or_list; + for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(is_method, idx, span); parameters.push(param); let arg = if let Some(block) = block && idx == 0 + && generate_block { let mut self_resolver = SelfResolver { ctxt: this, @@ -441,15 +452,13 @@ impl<'hir> LoweringContext<'_, 'hir> { args.push(arg); } - // If we have no params in signature function but user still wrote some code in - // delegation body, then add this code as first arg, eventually an error will be shown, - // also nested delegations may need to access information about this code (#154332), - // so it is better to leave this code as opposed to bodies of extern functions, - // which are completely erased from existence. + // Report an error if user has explicitly specified delegation's block + // in a single delegation when reused function has no params. if param_count == 0 + && !delegation.from_glob_or_list && let Some(block) = block { - args.push(this.lower_target_expr(&block)); + this.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span }); } let (final_expr, hir_id) = diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index a1c1d1e11d694..dc30d966e7593 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -535,3 +535,10 @@ pub(crate) struct CycleInDelegationSignatureResolution { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag("delegation block is specified for function with no params")] +pub(crate) struct DelegationBlockSpecifiedWhenNoParams { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a916ee1f143bd..badc9b8c14c59 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -555,13 +555,21 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { let mut delayed_ids: FxIndexSet = Default::default(); for def_id in ast_index.indices() { - match &ast_index[def_id] { + // Check if this def is inside delegation (or it is delegation itself), if so, + // we should lower it in delayed mode, as we need to resolve delegation in order + // to understand whether to generate block as first arg or not. + let def_inside_delegation = resolver.defs_in_delegations_blocks.contains_key(&def_id); + let is_delegation = matches!( + ast_index[def_id], AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. }) - | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) => { - delayed_ids.insert(def_id); - } - _ => lowerer.lower_node(def_id), - }; + | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) + ); + + if def_inside_delegation || is_delegation { + delayed_ids.insert(def_id); + } else { + lowerer.lower_node(def_id); + } } // Don't hash unless necessary, because it's expensive. @@ -590,10 +598,53 @@ pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) { owners: Owners::Map(&mut map), }; - lowerer.lower_node(def_id); + let is_dead_code = || -> bool { + // Try to find enclosing delegation (delegation in which block this `def_id` is placed). + let Some(&parent_del) = resolver.defs_in_delegations_blocks.get(&def_id) else { + return false; + }; + + let from_glob_or_list = match &ast_index[parent_del] { + AstOwner::Item(Item { kind: ItemKind::Delegation(d), .. }) + | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation(d), .. }, _) => { + d.from_glob_or_list + } + _ => unreachable!(), + }; - for (child_def_id, owner) in map { - tcx.feed_delayed_owner(child_def_id, owner); + let is_method_or_free = if let Some(info) = resolver.delegation_infos.get(&parent_del) + && let Some(sig_id) = resolver + .partial_res_map + .get(&info.resolution_node) + .and_then(|r| r.expect_full_res().opt_def_id()) + { + tcx.opt_associated_item(sig_id).is_some_and(|a| a.is_method()) + || matches!(tcx.def_kind(sig_id), DefKind::Fn) + } else { + // If delegation is unresolved for some reason we will generate an error delegation + // and some errors will be certainly emitted, so no delayed bugs should happen. + return false; + }; + + let (param_count, _) = delegation::param_count(tcx, parent_del.to_def_id()); + + // Should be in sync with conditions in `lower_delegation_body`. + (!is_method_or_free && from_glob_or_list) || param_count == 0 + }; + + if !is_dead_code() { + lowerer.lower_node(def_id); + + for (child_def_id, owner) in map { + // We can encounter `NonOwner` which will result in a phantom being written + // to the map, however this `NonOwner` could be inserted from lowering of + // other owner (for example use trees), so we do not feed delayed_owner + // with Phantom as (1) it is Phantom by default, (2) we want to avoid + // consistency assert during query feeding. + if !matches!(owner, hir::MaybeOwner::Phantom) { + tcx.feed_delayed_owner(child_def_id, owner); + } + } } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 741c34e0304af..66e816fb57302 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2066,7 +2066,7 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( ident: rename.unwrap_or(ident), rename, body: deleg.body.clone(), - from_glob, + from_glob_or_list: true, })), tokens: None, } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 74f9e75fb48c0..75de9b8c40aaa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -247,6 +247,7 @@ pub struct ResolverAstLowering<'tcx> { // Information about delegations which is used when handling recursive delegations pub delegation_infos: LocalDefIdMap, + pub defs_in_delegations_blocks: LocalDefIdMap, pub disambiguators: LocalDefIdMap>, } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3f6429c6a60f0..8bfaa3acad392 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -909,7 +909,7 @@ impl<'a> Parser<'a> { ident, rename, body: self.parse_delegation_body()?, - from_glob: false, + from_glob_or_list: false, })) }) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 43443e0ac3052..5990f85e30571 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1462,7 +1462,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); - } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) + } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob_or_list) && ident.name != kw::Underscore { // Don't add underscore names, they cannot be looked up anyway. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index cdc2df5bf2945..fc3b3ca845b8f 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -50,21 +50,39 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { name: Option, def_kind: DefKind, span: Span, + ) -> TyCtxtFeed<'tcx, LocalDefId> { + self.create_feed(node_id, name, def_kind, span, false) + } + + fn create_feed( + &mut self, + node_id: NodeId, + name: Option, + def_kind: DefKind, + span: Span, + is_owner: bool, ) -> TyCtxtFeed<'tcx, LocalDefId> { let parent_def = self.invocation_parent.parent_def; debug!( "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", node_id, def_kind, parent_def ); - self.r.create_def( + + let feed = self.r.create_def( parent_def, node_id, name, def_kind, self.parent_scope.expansion.to_expn_id(), span.with_parent(None), - false, - ) + is_owner, + ); + + if let Some(last_delegation) = self.invocation_parent.last_delegation { + self.r.defs_in_delegations_blocks.insert(feed.def_id(), last_delegation); + } + + feed } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { @@ -86,16 +104,8 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { // We only get here if the owner didn't exist yet. After the owner has been created, // future invocations of `collect_definitions` will get the owner out of the `owners` // table. - let parent_def = self.invocation_parent.parent_def; - let feed = self.r.create_def( - parent_def, - owner, - name, - def_kind, - self.parent_scope.expansion.to_expn_id(), - span.with_parent(None), - true, - ); + + let feed = self.create_feed(owner, name, def_kind, span, true); let tables = PerOwnerResolverData::new(owner, feed.key()); let orig_invoc_owner = mem::replace(&mut self.invocation_parent.owner, owner); @@ -240,6 +250,22 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ); } + fn visit_delegation(&mut self, node: &'a Delegation) { + // Do not map defs in path (i.e., consts with blocks), consider only + // delegation's block which is its first argument. + visit::walk_path(self, &node.path); + node.qself.as_ref().inspect(|qself| visit::walk_qself(self, qself)); + + let orig_last_delegation = mem::replace( + &mut self.invocation_parent.last_delegation, + Some(self.invocation_parent.parent_def), + ); + + node.body.as_ref().inspect(|block| self.brg_visit_block(block)); + + self.invocation_parent.last_delegation = orig_last_delegation; + } + fn visit_block(&mut self, block: &'a Block) { self.brg_visit_block(block); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f5f4c9e6e2580..b645b2a8844e3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -189,6 +189,7 @@ struct InvocationParent { in_attr: bool, const_arg_context: ConstArgContext, owner: NodeId, + last_delegation: Option, } impl InvocationParent { @@ -198,6 +199,7 @@ impl InvocationParent { in_attr: false, const_arg_context: ConstArgContext::NonDirect, owner: CRATE_NODE_ID, + last_delegation: None, }; } @@ -1524,8 +1526,10 @@ pub struct Resolver<'ra, 'tcx> { item_generics_num_lifetimes: FxHashMap = default::fx_hash_map(), /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), + delegation_fn_sigs: LocalDefIdMap = Default::default(), delegation_infos: LocalDefIdMap = Default::default(), + defs_in_delegations_blocks: LocalDefIdMap = Default::default(), main_def: Option = None, trait_impls: FxIndexMap>, @@ -2026,6 +2030,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), delegation_infos: self.delegation_infos, + defs_in_delegations_blocks: self.defs_in_delegations_blocks, disambiguators, }; ResolverOutputs { global_ctxt, ast_lowering } diff --git a/tests/ui/delegation/delegation-first-arg.rs b/tests/ui/delegation/delegation-first-arg.rs new file mode 100644 index 0000000000000..9d7175945da8b --- /dev/null +++ b/tests/ui/delegation/delegation-first-arg.rs @@ -0,0 +1,83 @@ +#![feature(fn_delegation)] + +trait Trait: Sized { + fn value(self) {} + fn r#ref(&self) {} + fn mut_ref(&mut self) {} + + fn static_empty() {} + fn static_one_param(x: usize) {} +} + +struct S; +impl Trait for S {} + +struct F(S); +// In glob delegations silently remove first arg if no params or generate default +// first arg (`arg0`) if it is a static function. +reuse impl Trait for F { self.0 } +//~^ ERROR: type annotations needed +//~| ERROR: type annotations needed + +struct F1(S); +impl F1 { + reuse Trait::{value, r#ref, mut_ref} { self.0 } + + // Error is reported as user has explicitly specified block when no params. + reuse ::static_empty { self.0 } + //~^ ERROR: delegation block is specified for function with no params + + reuse ::static_one_param { self.0 } + //~^ ERROR: `usize` is a primitive type and therefore doesn't have fields +} + +struct F2(S); +impl F2 { + // In list delegations silently remove first arg if it is not a method. + reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + //~^ ERROR: mismatched types + //~| ERROR: mismatched types +} + +mod trait_to_reuse { + use super::Trait; + + pub fn value(_: impl Trait) {} + pub fn r#ref(_: &impl Trait) {} + pub fn mut_ref(_: &mut impl Trait) {} + + pub fn static_empty() {} + pub fn static_one_param(x: usize) {} +} + +struct F3(S); +impl Trait for F3 { + reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + //~^ ERROR: mismatched types + //~| ERROR: mismatched types +} + +struct F4(S); +impl F4 { + reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + //~^ ERROR: no field `0` on type `impl Trait` + //~| ERROR: no field `0` on type `&impl Trait` + //~| ERROR: no field `0` on type `&mut impl Trait` + //~| ERROR: `usize` is a primitive type and therefore doesn't have fields +} + +mod to_reuse { + pub fn empty() {} + pub fn one_param(x: usize) {} +} + +// Error is reported as user has explicitly specified block when no params. +reuse to_reuse::empty { self + 1 } +//~^ ERROR: delegation block is specified for function with no params + +reuse to_reuse::one_param { self + 1 } + +// In list delegations silently remove first arg if there are no params. +reuse to_reuse::{empty as empty1, one_param as one_param1} { self + 1 } + +fn main() {} diff --git a/tests/ui/delegation/delegation-first-arg.stderr b/tests/ui/delegation/delegation-first-arg.stderr new file mode 100644 index 0000000000000..b9c86e5ea8cd3 --- /dev/null +++ b/tests/ui/delegation/delegation-first-arg.stderr @@ -0,0 +1,157 @@ +error: delegation block is specified for function with no params + --> $DIR/delegation-first-arg.rs:27:38 + | +LL | reuse ::static_empty { self.0 } + | ^^^^^^^^^^ + +error: delegation block is specified for function with no params + --> $DIR/delegation-first-arg.rs:75:23 + | +LL | reuse to_reuse::empty { self + 1 } + | ^^^^^^^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/delegation-first-arg.rs:18:1 + | +LL | reuse impl Trait for F { self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: the type must implement `Trait` +help: the following types implement trait `Trait` + --> $DIR/delegation-first-arg.rs:13:1 + | +LL | impl Trait for S {} + | ^^^^^^^^^^^^^^^^ `S` +... +LL | reuse impl Trait for F { self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^ `F` +... +LL | impl Trait for F3 { + | ^^^^^^^^^^^^^^^^^ `F3` + +error[E0283]: type annotations needed + --> $DIR/delegation-first-arg.rs:18:1 + | +LL | reuse impl Trait for F { self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: the type must implement `Trait` +help: the following types implement trait `Trait` + --> $DIR/delegation-first-arg.rs:13:1 + | +LL | impl Trait for S {} + | ^^^^^^^^^^^^^^^^ `S` +... +LL | reuse impl Trait for F { self.0 } + | ^^^^^^^^^^^^^^^^^^^^^^ `F` +... +LL | impl Trait for F3 { + | ^^^^^^^^^^^^^^^^^ `F3` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0610]: `usize` is a primitive type and therefore doesn't have fields + --> $DIR/delegation-first-arg.rs:30:49 + | +LL | reuse ::static_one_param { self.0 } + | ^ + +error[E0308]: mismatched types + --> $DIR/delegation-first-arg.rs:37:83 + | +LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ----- arguments to this function are incorrect ^^^^^^ expected `&S`, found `S` + | +note: method defined here + --> $DIR/delegation-first-arg.rs:5:8 + | +LL | fn r#ref(&self) {} + | ^^^^^ ----- +help: consider borrowing here + | +LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { &self.0 } + | + + +error[E0308]: mismatched types + --> $DIR/delegation-first-arg.rs:37:83 + | +LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ------- ^^^^^^ expected `&mut S`, found `S` + | | + | arguments to this function are incorrect + | +note: method defined here + --> $DIR/delegation-first-arg.rs:6:8 + | +LL | fn mut_ref(&mut self) {} + | ^^^^^^^ --------- +help: consider mutably borrowing here + | +LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { &mut self.0 } + | ++++ + +error[E0308]: mismatched types + --> $DIR/delegation-first-arg.rs:55:85 + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ----- arguments to this function are incorrect ^^^^^^ expected `&_`, found `S` + | + = note: expected reference `&_` + found struct `S` +note: function defined here + --> $DIR/delegation-first-arg.rs:46:12 + | +LL | pub fn r#ref(_: &impl Trait) {} + | ^^^^^ -------------- +help: consider borrowing here + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { &self.0 } + | + + +error[E0308]: mismatched types + --> $DIR/delegation-first-arg.rs:55:85 + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ------- ^^^^^^ expected `&mut _`, found `S` + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut _` + found struct `S` +note: function defined here + --> $DIR/delegation-first-arg.rs:47:12 + | +LL | pub fn mut_ref(_: &mut impl Trait) {} + | ^^^^^^^ ------------------ +help: consider mutably borrowing here + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { &mut self.0 } + | ++++ + +error[E0609]: no field `0` on type `impl Trait` + --> $DIR/delegation-first-arg.rs:62:90 + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ^ unknown field + +error[E0609]: no field `0` on type `&impl Trait` + --> $DIR/delegation-first-arg.rs:62:90 + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ^ unknown field + +error[E0609]: no field `0` on type `&mut impl Trait` + --> $DIR/delegation-first-arg.rs:62:90 + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ^ unknown field + +error[E0610]: `usize` is a primitive type and therefore doesn't have fields + --> $DIR/delegation-first-arg.rs:62:90 + | +LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } + | ^ + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0283, E0308, E0609, E0610. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr index 833b0869002e2..ebfc526b62cf9 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr @@ -1,24 +1,12 @@ -error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/hir-crate-items-before-lowering-ices.rs:36:11 +error: delegation block is specified for function with no params + --> $DIR/hir-crate-items-before-lowering-ices.rs:36:18 | LL | reuse a as b { - | ___________^______- + | __________________^ LL | | fn foo() {}; LL | | foo LL | | } - | |_____- unexpected argument of type `fn() {foo::<_>}` - | -note: function defined here - --> $DIR/hir-crate-items-before-lowering-ices.rs:34:8 - | -LL | fn a() {} - | ^ -help: remove the extra argument - | -LL - reuse a as b { -LL + reuse { - | + | |_____^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs index c223d5d4a5adc..28523fb91582c 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs @@ -33,7 +33,7 @@ mod ice_155127 { mod ice_155128 { fn a() {} - reuse a as b { //[ice_155128]~ ERROR: this function takes 0 arguments but 1 argument was supplied + reuse a as b { //[ice_155128]~ ERROR: delegation block is specified for function with no params fn foo() {}; foo } diff --git a/tests/ui/delegation/inner-attr.rs b/tests/ui/delegation/inner-attr.rs index 6bd2892095fc0..452b3b3b73d5b 100644 --- a/tests/ui/delegation/inner-attr.rs +++ b/tests/ui/delegation/inner-attr.rs @@ -3,6 +3,6 @@ fn a() {} reuse a as b { #![rustc_dummy] self } //~ ERROR an inner attribute is not permitted in this context -//~^ ERROR: this function takes 0 arguments but 1 argument was supplied +//~^ ERROR: delegation block is specified for function with no params fn main() {} diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr index 307586ccef93d..d6f8cc752902d 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -9,23 +9,11 @@ LL | fn main() {} | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/inner-attr.rs:5:7 +error: delegation block is specified for function with no params + --> $DIR/inner-attr.rs:5:14 | LL | reuse a as b { #![rustc_dummy] self } - | ^ ---- unexpected argument - | -note: function defined here - --> $DIR/inner-attr.rs:3:4 - | -LL | fn a() {} - | ^ -help: remove the extra argument - | -LL - reuse a as b { #![rustc_dummy] self } -LL + reuse self } - | + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.rs b/tests/ui/delegation/zero-args-delegations-ice-154332.rs index a9d7876db5e87..b1810af36d450 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.rs +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.rs @@ -3,7 +3,7 @@ mod test_ice { fn a() {} - reuse a as b { //~ ERROR: this function takes 0 arguments but 1 argument was supplied + reuse a as b { //~ ERROR: delegation block is specified for function with no params let closure = || { fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} @@ -23,7 +23,7 @@ mod test_2 { } reuse to_reuse::zero_args { self } - //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~^ ERROR: delegation block is specified for function with no params } fn main() {} diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr index 517a01dac6f0e..423b32511acf9 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr @@ -1,43 +1,20 @@ -error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/zero-args-delegations-ice-154332.rs:6:11 +error: delegation block is specified for function with no params + --> $DIR/zero-args-delegations-ice-154332.rs:6:18 | LL | reuse a as b { - | ___________^______- + | __________________^ LL | | let closure = || { LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} ... | LL | | closure(); LL | | } - | |_____- unexpected argument of type `()` - | -note: function defined here - --> $DIR/zero-args-delegations-ice-154332.rs:4:8 - | -LL | fn a() {} - | ^ -help: remove the extra argument - | -LL - reuse a as b { -LL + reuse { - | + | |_____^ -error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/zero-args-delegations-ice-154332.rs:25:21 +error: delegation block is specified for function with no params + --> $DIR/zero-args-delegations-ice-154332.rs:25:31 | LL | reuse to_reuse::zero_args { self } - | ^^^^^^^^^ ---- unexpected argument - | -note: function defined here - --> $DIR/zero-args-delegations-ice-154332.rs:20:16 - | -LL | pub fn zero_args() -> i32 { - | ^^^^^^^^^ -help: remove the extra argument - | -LL - reuse to_reuse::zero_args { self } -LL + reuse to_reuse::zero_argself } - | + | ^^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/zero-args-delegations-ice-154427.rs b/tests/ui/delegation/zero-args-delegations-ice-154427.rs new file mode 100644 index 0000000000000..b50066b057638 --- /dev/null +++ b/tests/ui/delegation/zero-args-delegations-ice-154427.rs @@ -0,0 +1,22 @@ +#![feature(fn_delegation)] + +mod ice_154427 { + trait Trait { + fn foo(); + } + struct F; + struct S; + mod to_reuse { + use super::F; + pub fn foo(_: F) {} + } + impl Trait for S { + reuse to_reuse::foo { self } + //~^ ERROR: this function takes 1 argument but 0 arguments were supplied + //~| ERROR: delegation block is specified for function with no params + } + + fn main() {} +} + +fn main() {} diff --git a/tests/ui/delegation/zero-args-delegations-ice-154427.stderr b/tests/ui/delegation/zero-args-delegations-ice-154427.stderr new file mode 100644 index 0000000000000..b73976fedda74 --- /dev/null +++ b/tests/ui/delegation/zero-args-delegations-ice-154427.stderr @@ -0,0 +1,25 @@ +error: delegation block is specified for function with no params + --> $DIR/zero-args-delegations-ice-154427.rs:14:29 + | +LL | reuse to_reuse::foo { self } + | ^^^^^^^^ + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/zero-args-delegations-ice-154427.rs:14:25 + | +LL | reuse to_reuse::foo { self } + | ^^^ argument #1 of type `F` is missing + | +note: function defined here + --> $DIR/zero-args-delegations-ice-154427.rs:11:16 + | +LL | pub fn foo(_: F) {} + | ^^^ ---- +help: provide the argument + | +LL | reuse to_reuse::foo(/* F */) { self } + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0061`. From c6dd82d5d5166e6bf0b982e6595c22d352cb21a2 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 25 May 2026 09:44:26 +0300 Subject: [PATCH 2/5] Check if the delegation itself is a dead code --- compiler/rustc_ast_lowering/src/lib.rs | 18 +++++++++++---- .../zero-args-delegations-ice-154332.rs | 22 +++++++++++++++++++ .../zero-args-delegations-ice-154332.stderr | 15 ++++++++++++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index badc9b8c14c59..094888c714271 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -581,7 +581,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { } /// Lowers an AST owner corresponding to `def_id`, now only delegations are lowered this way. -pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) { +pub fn lower_delayed_owner<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { let krate = tcx.hir_crate(()); let (resolver, krate) = &*krate.delayed_resolver.borrow(); @@ -598,12 +598,22 @@ pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) { owners: Owners::Map(&mut map), }; - let is_dead_code = || -> bool { + fn is_dead_code<'tcx>( + tcx: TyCtxt<'tcx>, + resolver: &ResolverAstLowering<'tcx>, + ast_index: &IndexVec>, + def_id: LocalDefId, + ) -> bool { // Try to find enclosing delegation (delegation in which block this `def_id` is placed). let Some(&parent_del) = resolver.defs_in_delegations_blocks.get(&def_id) else { return false; }; + // Check if the delegation itself is a dead-code (recursively up to topmost delegation). + if is_dead_code(tcx, resolver, ast_index, parent_del) { + return true; + } + let from_glob_or_list = match &ast_index[parent_del] { AstOwner::Item(Item { kind: ItemKind::Delegation(d), .. }) | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation(d), .. }, _) => { @@ -630,9 +640,9 @@ pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) { // Should be in sync with conditions in `lower_delegation_body`. (!is_method_or_free && from_glob_or_list) || param_count == 0 - }; + } - if !is_dead_code() { + if !is_dead_code(tcx, resolver, &ast_index, def_id) { lowerer.lower_node(def_id); for (child_def_id, owner) in map { diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.rs b/tests/ui/delegation/zero-args-delegations-ice-154332.rs index b1810af36d450..10d8def4c8c76 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.rs +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.rs @@ -26,4 +26,26 @@ mod test_2 { //~^ ERROR: delegation block is specified for function with no params } +mod nested_delegations { + fn a() {} + + reuse a as b { //~ ERROR: delegation block is specified for function with no params + let closure = || { + reuse a as b { + fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} + + reuse foo:: as bar; + bar(&"".to_string(), &"".to_string()); + + reuse a as b { + reuse foo:: as bar; + bar(&"".to_string(), &"".to_string()); + } + } + }; + + closure(); + } +} + fn main() {} diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr index 423b32511acf9..fd2f34eedabb7 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr @@ -16,5 +16,18 @@ error: delegation block is specified for function with no params LL | reuse to_reuse::zero_args { self } | ^^^^^^^^ -error: aborting due to 2 previous errors +error: delegation block is specified for function with no params + --> $DIR/zero-args-delegations-ice-154332.rs:32:18 + | +LL | reuse a as b { + | __________________^ +LL | | let closure = || { +LL | | reuse a as b { +LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} +... | +LL | | closure(); +LL | | } + | |_____^ + +error: aborting due to 3 previous errors From cea0e2d82e41756ea81b8036726aab1411615b7a Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 25 May 2026 09:54:12 +0300 Subject: [PATCH 3/5] `from_glob_or_list` -> `DelegationSource` --- compiler/rustc_ast/src/ast.rs | 9 ++++++++- compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_lowering/src/delegation.rs | 5 +++-- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_expand/src/expand.rs | 6 +++++- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_resolve/src/build_reduced_graph.rs | 8 ++++---- 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f31f940c766f8..bb4b1828a29fc 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3908,6 +3908,13 @@ pub struct EiiImpl { pub is_default: bool, } +#[derive(Clone, Encodable, Decodable, Debug, Walkable)] +pub enum DelegationSource { + Single, + List, + Glob, +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct Delegation { /// Path resolution id. @@ -3918,7 +3925,7 @@ pub struct Delegation { pub rename: Option, pub body: Option>, /// The item was expanded from a glob delegation item. - pub from_glob_or_list: bool, + pub source: DelegationSource, } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7689e3453cd68..e5db9e1cb19a3 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, DelegationMac, DelegationSuffixes, + DelegationSource, DelimArgs, DelimSpan, EnumDef, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index fbe9e06a95fb8..2f9cbf0c59421 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -423,11 +423,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut args: Vec> = Vec::with_capacity(param_count); let is_method = this.is_method(sig_id, span); + let is_single_delegation = matches!(delegation.source, DelegationSource::Single); // Should be in sync with conditions in `lower_delayed_owner::is_dead_code`. let generate_block = is_method || matches!(this.tcx.def_kind(sig_id), DefKind::Fn) - || !delegation.from_glob_or_list; + || is_single_delegation; for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(is_method, idx, span); @@ -455,7 +456,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Report an error if user has explicitly specified delegation's block // in a single delegation when reused function has no params. if param_count == 0 - && !delegation.from_glob_or_list + && is_single_delegation && let Some(block) = block { this.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span }); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 094888c714271..06c81f8ed1cb0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -617,7 +617,7 @@ pub fn lower_delayed_owner<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { let from_glob_or_list = match &ast_index[parent_del] { AstOwner::Item(Item { kind: ItemKind::Delegation(d), .. }) | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation(d), .. }, _) => { - d.from_glob_or_list + !matches!(d.source, DelegationSource::Single) } _ => unreachable!(), }; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 66e816fb57302..ac16dbc2fa387 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2066,7 +2066,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( ident: rename.unwrap_or(ident), rename, body: deleg.body.clone(), - from_glob_or_list: true, + source: if from_glob { + ast::DelegationSource::Glob + } else { + ast::DelegationSource::List + }, })), tokens: None, } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8bfaa3acad392..7b9527a6730ae 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -909,7 +909,7 @@ impl<'a> Parser<'a> { ident, rename, body: self.parse_delegation_body()?, - from_glob_or_list: false, + source: DelegationSource::Single, })) }) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 5990f85e30571..6a42fb4925fff 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,9 +9,9 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, Fn, - ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, - TyAlias, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, + DelegationSource, Fn, ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, + StmtKind, TraitAlias, TyAlias, }; use rustc_attr_parsing::AttributeParser; use rustc_expand::base::{ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; @@ -1462,7 +1462,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); - } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob_or_list) + } else if !matches!(&item.kind, AssocItemKind::Delegation(d) if matches!(d.source, DelegationSource::Glob)) && ident.name != kw::Underscore { // Don't add underscore names, they cannot be looked up anyway. From ee1c893ad39e29832a83cb3a4e20c139d20398e0 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 29 May 2026 14:24:00 +0300 Subject: [PATCH 4/5] Simplifying delegation's block deletion logic --- compiler/rustc_ast_lowering/src/delegation.rs | 77 +++++-- compiler/rustc_ast_lowering/src/errors.rs | 7 + compiler/rustc_ast_lowering/src/lib.rs | 79 +------ compiler/rustc_middle/src/ty/mod.rs | 6 +- compiler/rustc_resolve/src/def_collector.rs | 2 +- compiler/rustc_resolve/src/late.rs | 12 +- compiler/rustc_resolve/src/lib.rs | 2 - tests/ui/delegation/delegation-first-arg.rs | 4 +- .../ui/delegation/delegation-first-arg.stderr | 86 +++---- ...ems-before-lowering-ices.ice_155128.stderr | 26 ++- ...ems-before-lowering-ices.ice_155164.stderr | 2 +- ...ems-before-lowering-ices.ice_155202.stderr | 4 +- .../hir-crate-items-before-lowering-ices.rs | 1 + tests/ui/delegation/inner-attr.rs | 1 + tests/ui/delegation/inner-attr.stderr | 20 +- .../delegation/self-coercion-static-free.rs | 10 +- .../self-coercion-static-free.stderr | 112 ++++++--- .../target-expr-removal-defs-inside.rs | 35 +++ .../target-expr-removal-defs-inside.stderr | 218 ++++++++++++++++++ .../target-expression-removal-pass.rs | 39 ++++ .../zero-args-delegations-ice-154332.rs | 10 +- .../zero-args-delegations-ice-154332.stderr | 158 ++++++++++++- .../zero-args-delegations-ice-154427.rs | 3 +- .../zero-args-delegations-ice-154427.stderr | 19 +- 24 files changed, 720 insertions(+), 213 deletions(-) create mode 100644 tests/ui/delegation/target-expr-removal-defs-inside.rs create mode 100644 tests/ui/delegation/target-expr-removal-defs-inside.stderr create mode 100644 tests/ui/delegation/target-expression-removal-pass.rs diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 2f9cbf0c59421..88b1d69755ed0 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -57,8 +57,8 @@ use smallvec::SmallVec; use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults}; use crate::errors::{ - CycleInDelegationSignatureResolution, DelegationBlockSpecifiedWhenNoParams, - UnresolvedDelegationCallee, + CycleInDelegationSignatureResolution, DelegationAttemptedBlockWithDefsDeletion, + DelegationBlockSpecifiedWhenNoParams, UnresolvedDelegationCallee, }; use crate::{ AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, @@ -131,9 +131,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span); // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356) - let sig_id = if let Some(delegation_info) = self.resolver.delegation_info(self.owner.def_id) + let sig_id = if let Some(resolution_node) = + self.resolver.delegation_info(self.owner.def_id).and_then(|i| i.resolution_node) { - self.get_sig_id(delegation_info.resolution_node, span) + self.get_sig_id(resolution_node, span) } else { self.dcx().span_delayed_bug( span, @@ -151,6 +152,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let (param_count, c_variadic) = param_count(self.tcx, sig_id); + if !self.check_block_soundness(delegation, sig_id, is_method, param_count) { + return self.generate_delegation_error(span, delegation); + } + let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); let (body_id, call_expr_id) = self.lower_delegation_body( @@ -188,6 +193,48 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn check_block_soundness( + &self, + delegation: &Delegation, + sig_id: DefId, + is_method: bool, + param_count: usize, + ) -> bool { + let mut result = true; + + // Report an error if user has explicitly specified delegation's block + // in a single delegation when reused function has no params. + if let Some(block) = delegation.body.as_ref() { + if param_count == 0 && matches!(delegation.source, DelegationSource::Single) { + self.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span }); + result = false; + } + + if !self.should_generate_block(delegation, sig_id, is_method) + && self + .resolver + .delegation_info(self.owner.def_id) + .is_some_and(|i| i.block_contains_defs) + { + self.dcx().emit_err(DelegationAttemptedBlockWithDefsDeletion { span: block.span }); + result = false; + } + } + + result + } + + fn should_generate_block( + &self, + delegation: &Delegation, + sig_id: DefId, + is_method: bool, + ) -> bool { + is_method + || matches!(self.tcx.def_kind(sig_id), DefKind::Fn) + || matches!(delegation.source, DelegationSource::Single) + } + fn add_attrs_if_needed(&mut self, span: Span, sig_id: DefId) { let new_attrs = self.create_new_attrs(ATTRS_ADDITIONS, span, sig_id, self.attrs.get(&PARENT_ID)); @@ -262,9 +309,10 @@ impl<'hir> LoweringContext<'_, 'hir> { // it means that we refer to another delegation as a callee, so in order to obtain // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it. if let Some(local_id) = def_id.as_local() - && let Some(delegation_info) = self.resolver.delegation_info(local_id) + && let Some(resolution_node) = + self.resolver.delegation_info(local_id).and_then(|i| i.resolution_node) { - node_id = delegation_info.resolution_node; + node_id = resolution_node; if visited.contains(&node_id) { // We encountered a cycle in the resolution, or delegation callee refers to non-existent // entity, in this case emit an error. @@ -423,12 +471,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut args: Vec> = Vec::with_capacity(param_count); let is_method = this.is_method(sig_id, span); - let is_single_delegation = matches!(delegation.source, DelegationSource::Single); - - // Should be in sync with conditions in `lower_delayed_owner::is_dead_code`. - let generate_block = is_method - || matches!(this.tcx.def_kind(sig_id), DefKind::Fn) - || is_single_delegation; for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(is_method, idx, span); @@ -436,7 +478,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let arg = if let Some(block) = block && idx == 0 - && generate_block + && this.should_generate_block(delegation, sig_id, is_method) { let mut self_resolver = SelfResolver { ctxt: this, @@ -453,15 +495,6 @@ impl<'hir> LoweringContext<'_, 'hir> { args.push(arg); } - // Report an error if user has explicitly specified delegation's block - // in a single delegation when reused function has no params. - if param_count == 0 - && is_single_delegation - && let Some(block) = block - { - this.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span }); - } - let (final_expr, hir_id) = this.finalize_body_lowering(delegation, args, generics, span); diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index dc30d966e7593..392a5c5934ea1 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -542,3 +542,10 @@ pub(crate) struct DelegationBlockSpecifiedWhenNoParams { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag("attempted to delete delegation's block that contains definitions inside")] +pub(crate) struct DelegationAttemptedBlockWithDefsDeletion { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 06c81f8ed1cb0..e2ad4620cc5f0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -555,20 +555,14 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { let mut delayed_ids: FxIndexSet = Default::default(); for def_id in ast_index.indices() { - // Check if this def is inside delegation (or it is delegation itself), if so, - // we should lower it in delayed mode, as we need to resolve delegation in order - // to understand whether to generate block as first arg or not. - let def_inside_delegation = resolver.defs_in_delegations_blocks.contains_key(&def_id); - let is_delegation = matches!( - ast_index[def_id], + match ast_index[def_id] { AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. }) - | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) - ); - - if def_inside_delegation || is_delegation { - delayed_ids.insert(def_id); - } else { - lowerer.lower_node(def_id); + | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) => { + delayed_ids.insert(def_id); + } + _ => { + lowerer.lower_node(def_id); + } } } @@ -598,63 +592,10 @@ pub fn lower_delayed_owner<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { owners: Owners::Map(&mut map), }; - fn is_dead_code<'tcx>( - tcx: TyCtxt<'tcx>, - resolver: &ResolverAstLowering<'tcx>, - ast_index: &IndexVec>, - def_id: LocalDefId, - ) -> bool { - // Try to find enclosing delegation (delegation in which block this `def_id` is placed). - let Some(&parent_del) = resolver.defs_in_delegations_blocks.get(&def_id) else { - return false; - }; - - // Check if the delegation itself is a dead-code (recursively up to topmost delegation). - if is_dead_code(tcx, resolver, ast_index, parent_del) { - return true; - } - - let from_glob_or_list = match &ast_index[parent_del] { - AstOwner::Item(Item { kind: ItemKind::Delegation(d), .. }) - | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation(d), .. }, _) => { - !matches!(d.source, DelegationSource::Single) - } - _ => unreachable!(), - }; - - let is_method_or_free = if let Some(info) = resolver.delegation_infos.get(&parent_del) - && let Some(sig_id) = resolver - .partial_res_map - .get(&info.resolution_node) - .and_then(|r| r.expect_full_res().opt_def_id()) - { - tcx.opt_associated_item(sig_id).is_some_and(|a| a.is_method()) - || matches!(tcx.def_kind(sig_id), DefKind::Fn) - } else { - // If delegation is unresolved for some reason we will generate an error delegation - // and some errors will be certainly emitted, so no delayed bugs should happen. - return false; - }; - - let (param_count, _) = delegation::param_count(tcx, parent_del.to_def_id()); + lowerer.lower_node(def_id); - // Should be in sync with conditions in `lower_delegation_body`. - (!is_method_or_free && from_glob_or_list) || param_count == 0 - } - - if !is_dead_code(tcx, resolver, &ast_index, def_id) { - lowerer.lower_node(def_id); - - for (child_def_id, owner) in map { - // We can encounter `NonOwner` which will result in a phantom being written - // to the map, however this `NonOwner` could be inserted from lowering of - // other owner (for example use trees), so we do not feed delayed_owner - // with Phantom as (1) it is Phantom by default, (2) we want to avoid - // consistency assert during query feeding. - if !matches!(owner, hir::MaybeOwner::Phantom) { - tcx.feed_delayed_owner(child_def_id, owner); - } - } + for (child_def_id, owner) in map { + tcx.feed_delayed_owner(child_def_id, owner); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 75de9b8c40aaa..45a6906179209 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -247,16 +247,16 @@ pub struct ResolverAstLowering<'tcx> { // Information about delegations which is used when handling recursive delegations pub delegation_infos: LocalDefIdMap, - pub defs_in_delegations_blocks: LocalDefIdMap, pub disambiguators: LocalDefIdMap>, } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct DelegationInfo { // NodeId (either delegation.id or item_id in case of a trait impl) for signature resolution, // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 - pub resolution_node: ast::NodeId, + pub resolution_node: Option, + pub block_contains_defs: bool, } #[derive(Clone, Copy, Debug, StableHash)] diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index fc3b3ca845b8f..d241ba5281e88 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -79,7 +79,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { ); if let Some(last_delegation) = self.invocation_parent.last_delegation { - self.r.defs_in_delegations_blocks.insert(feed.def_id(), last_delegation); + self.r.delegation_infos.entry(last_delegation).or_default().block_contains_defs = true; } feed diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fb8de90d28aca..bd2736fbd6698 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRe use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate}; use rustc_middle::middle::resolve_bound_vars::Set1; -use rustc_middle::ty::{AssocTag, DelegationInfo, Visibility}; +use rustc_middle::ty::{AssocTag, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; use rustc_session::errors::feature_err; @@ -3923,12 +3923,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.visit_path(&delegation.path); }); - self.r.delegation_infos.insert( - self.r.current_owner.def_id, - DelegationInfo { - resolution_node: if is_in_trait_impl { item_id } else { delegation.id }, - }, - ); + let info = self.r.delegation_infos.entry(self.r.current_owner.def_id).or_default(); + let resolution_node = if is_in_trait_impl { item_id } else { delegation.id }; + + info.resolution_node = Some(resolution_node); let Some(body) = &delegation.body else { return }; self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b645b2a8844e3..e9eba4afc43b2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1529,7 +1529,6 @@ pub struct Resolver<'ra, 'tcx> { delegation_fn_sigs: LocalDefIdMap = Default::default(), delegation_infos: LocalDefIdMap = Default::default(), - defs_in_delegations_blocks: LocalDefIdMap = Default::default(), main_def: Option = None, trait_impls: FxIndexMap>, @@ -2030,7 +2029,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), delegation_infos: self.delegation_infos, - defs_in_delegations_blocks: self.defs_in_delegations_blocks, disambiguators, }; ResolverOutputs { global_ctxt, ast_lowering } diff --git a/tests/ui/delegation/delegation-first-arg.rs b/tests/ui/delegation/delegation-first-arg.rs index 9d7175945da8b..005a5910b69c0 100644 --- a/tests/ui/delegation/delegation-first-arg.rs +++ b/tests/ui/delegation/delegation-first-arg.rs @@ -26,6 +26,7 @@ impl F1 { // Error is reported as user has explicitly specified block when no params. reuse ::static_empty { self.0 } //~^ ERROR: delegation block is specified for function with no params + //~| ERROR: this function takes 0 arguments but 1 argument was supplied reuse ::static_one_param { self.0 } //~^ ERROR: `usize` is a primitive type and therefore doesn't have fields @@ -35,8 +36,6 @@ struct F2(S); impl F2 { // In list delegations silently remove first arg if it is not a method. reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } - //~^ ERROR: mismatched types - //~| ERROR: mismatched types } mod trait_to_reuse { @@ -74,6 +73,7 @@ mod to_reuse { // Error is reported as user has explicitly specified block when no params. reuse to_reuse::empty { self + 1 } //~^ ERROR: delegation block is specified for function with no params +//~| ERROR: this function takes 0 arguments but 1 argument was supplied reuse to_reuse::one_param { self + 1 } diff --git a/tests/ui/delegation/delegation-first-arg.stderr b/tests/ui/delegation/delegation-first-arg.stderr index b9c86e5ea8cd3..601fee336296a 100644 --- a/tests/ui/delegation/delegation-first-arg.stderr +++ b/tests/ui/delegation/delegation-first-arg.stderr @@ -5,7 +5,7 @@ LL | reuse ::static_empty { self.0 } | ^^^^^^^^^^ error: delegation block is specified for function with no params - --> $DIR/delegation-first-arg.rs:75:23 + --> $DIR/delegation-first-arg.rs:74:23 | LL | reuse to_reuse::empty { self + 1 } | ^^^^^^^^^^^^ @@ -49,48 +49,31 @@ LL | impl Trait for F3 { | ^^^^^^^^^^^^^^^^^ `F3` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0610]: `usize` is a primitive type and therefore doesn't have fields - --> $DIR/delegation-first-arg.rs:30:49 +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/delegation-first-arg.rs:27:25 | -LL | reuse ::static_one_param { self.0 } - | ^ - -error[E0308]: mismatched types - --> $DIR/delegation-first-arg.rs:37:83 +LL | reuse ::static_empty { self.0 } + | ^^^^^^^^^^^^ ------ unexpected argument | -LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } - | ----- arguments to this function are incorrect ^^^^^^ expected `&S`, found `S` +note: associated function defined here + --> $DIR/delegation-first-arg.rs:8:8 | -note: method defined here - --> $DIR/delegation-first-arg.rs:5:8 +LL | fn static_empty() {} + | ^^^^^^^^^^^^ +help: remove the extra argument | -LL | fn r#ref(&self) {} - | ^^^^^ ----- -help: consider borrowing here +LL - reuse ::static_empty { self.0 } +LL + reuse ::static_emptself.0 } | -LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { &self.0 } - | + -error[E0308]: mismatched types - --> $DIR/delegation-first-arg.rs:37:83 - | -LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } - | ------- ^^^^^^ expected `&mut S`, found `S` - | | - | arguments to this function are incorrect - | -note: method defined here - --> $DIR/delegation-first-arg.rs:6:8 - | -LL | fn mut_ref(&mut self) {} - | ^^^^^^^ --------- -help: consider mutably borrowing here +error[E0610]: `usize` is a primitive type and therefore doesn't have fields + --> $DIR/delegation-first-arg.rs:31:49 | -LL | reuse ::{value, r#ref, mut_ref, static_empty, static_one_param} { &mut self.0 } - | ++++ +LL | reuse ::static_one_param { self.0 } + | ^ error[E0308]: mismatched types - --> $DIR/delegation-first-arg.rs:55:85 + --> $DIR/delegation-first-arg.rs:54:85 | LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } | ----- arguments to this function are incorrect ^^^^^^ expected `&_`, found `S` @@ -98,7 +81,7 @@ LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_ = note: expected reference `&_` found struct `S` note: function defined here - --> $DIR/delegation-first-arg.rs:46:12 + --> $DIR/delegation-first-arg.rs:45:12 | LL | pub fn r#ref(_: &impl Trait) {} | ^^^^^ -------------- @@ -108,7 +91,7 @@ LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_ | + error[E0308]: mismatched types - --> $DIR/delegation-first-arg.rs:55:85 + --> $DIR/delegation-first-arg.rs:54:85 | LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } | ------- ^^^^^^ expected `&mut _`, found `S` @@ -118,7 +101,7 @@ LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_ = note: expected mutable reference `&mut _` found struct `S` note: function defined here - --> $DIR/delegation-first-arg.rs:47:12 + --> $DIR/delegation-first-arg.rs:46:12 | LL | pub fn mut_ref(_: &mut impl Trait) {} | ^^^^^^^ ------------------ @@ -128,30 +111,47 @@ LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_ | ++++ error[E0609]: no field `0` on type `impl Trait` - --> $DIR/delegation-first-arg.rs:62:90 + --> $DIR/delegation-first-arg.rs:61:90 | LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } | ^ unknown field error[E0609]: no field `0` on type `&impl Trait` - --> $DIR/delegation-first-arg.rs:62:90 + --> $DIR/delegation-first-arg.rs:61:90 | LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } | ^ unknown field error[E0609]: no field `0` on type `&mut impl Trait` - --> $DIR/delegation-first-arg.rs:62:90 + --> $DIR/delegation-first-arg.rs:61:90 | LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } | ^ unknown field error[E0610]: `usize` is a primitive type and therefore doesn't have fields - --> $DIR/delegation-first-arg.rs:62:90 + --> $DIR/delegation-first-arg.rs:61:90 | LL | reuse trait_to_reuse::{value, r#ref, mut_ref, static_empty, static_one_param} { self.0 } | ^ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/delegation-first-arg.rs:74:17 + | +LL | reuse to_reuse::empty { self + 1 } + | ^^^^^ -------- unexpected argument + | +note: function defined here + --> $DIR/delegation-first-arg.rs:69:12 + | +LL | pub fn empty() {} + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::empty { self + 1 } +LL + reuse to_reuse::emptself + 1 } + | + error: aborting due to 13 previous errors -Some errors have detailed explanations: E0283, E0308, E0609, E0610. -For more information about an error, try `rustc --explain E0283`. +Some errors have detailed explanations: E0061, E0283, E0308, E0609, E0610. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr index ebfc526b62cf9..c9c59bb56aba9 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr @@ -3,10 +3,34 @@ error: delegation block is specified for function with no params | LL | reuse a as b { | __________________^ +LL | | LL | | fn foo() {}; LL | | foo LL | | } | |_____^ -error: aborting due to 1 previous error +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/hir-crate-items-before-lowering-ices.rs:36:11 + | +LL | reuse a as b { + | ___________^______- +LL | | +LL | | fn foo() {}; +LL | | foo +LL | | } + | |_____- unexpected argument of type `fn() {foo::<_>}` + | +note: function defined here + --> $DIR/hir-crate-items-before-lowering-ices.rs:34:8 + | +LL | fn a() {} + | ^ +help: remove the extra argument + | +LL - reuse a as b { +LL + reuse { + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr index 8590881e67836..34d1a92ccd225 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/hir-crate-items-before-lowering-ices.rs:46:13 + --> $DIR/hir-crate-items-before-lowering-ices.rs:47:13 | LL | / { LL | | diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr index abe70cb82f3b3..28f045ca69442 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find value `async` in this scope - --> $DIR/hir-crate-items-before-lowering-ices.rs:65:13 + --> $DIR/hir-crate-items-before-lowering-ices.rs:66:13 | LL | async || {}; | ^^^^^ not found in this scope error[E0308]: mismatched types - --> $DIR/hir-crate-items-before-lowering-ices.rs:65:22 + --> $DIR/hir-crate-items-before-lowering-ices.rs:66:22 | LL | async || {}; | ^^ expected `bool`, found `()` diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs index 28523fb91582c..e8fba33bcab17 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs @@ -34,6 +34,7 @@ mod ice_155128 { fn a() {} reuse a as b { //[ice_155128]~ ERROR: delegation block is specified for function with no params + //[ice_155128]~^ ERROR: this function takes 0 arguments but 1 argument was supplied fn foo() {}; foo } diff --git a/tests/ui/delegation/inner-attr.rs b/tests/ui/delegation/inner-attr.rs index 452b3b3b73d5b..4a1e7cde5185f 100644 --- a/tests/ui/delegation/inner-attr.rs +++ b/tests/ui/delegation/inner-attr.rs @@ -4,5 +4,6 @@ fn a() {} reuse a as b { #![rustc_dummy] self } //~ ERROR an inner attribute is not permitted in this context //~^ ERROR: delegation block is specified for function with no params +//~| ERROR: this function takes 0 arguments but 1 argument was supplied fn main() {} diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr index d6f8cc752902d..f47f92fb4e28b 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -15,5 +15,23 @@ error: delegation block is specified for function with no params LL | reuse a as b { #![rustc_dummy] self } | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/inner-attr.rs:5:7 + | +LL | reuse a as b { #![rustc_dummy] self } + | ^ ---- unexpected argument + | +note: function defined here + --> $DIR/inner-attr.rs:3:4 + | +LL | fn a() {} + | ^ +help: remove the extra argument + | +LL - reuse a as b { #![rustc_dummy] self } +LL + reuse self } + | + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/self-coercion-static-free.rs b/tests/ui/delegation/self-coercion-static-free.rs index f61d4247a1d94..2aeb5bd404991 100644 --- a/tests/ui/delegation/self-coercion-static-free.rs +++ b/tests/ui/delegation/self-coercion-static-free.rs @@ -20,10 +20,11 @@ struct S(F); impl Trait for S { reuse ::{static_value, static_mut_ref, static_ref} { - let _ = self; - S::static_self() //~^ ERROR: mismatched types //~| ERROR: mismatched types + //~| ERROR: mismatched types + let _ = self; + S::static_self() } } @@ -31,10 +32,11 @@ struct S1(Box>>>>>); impl Trait for S1 { reuse ::{static_value, static_mut_ref, static_ref} { - let _ = self; - S1::static_self() //~^ ERROR: mismatched types //~| ERROR: mismatched types + //~| ERROR: mismatched types + let _ = self; + S1::static_self() } } diff --git a/tests/ui/delegation/self-coercion-static-free.stderr b/tests/ui/delegation/self-coercion-static-free.stderr index 5f78272815aa5..b61ec58ee715c 100644 --- a/tests/ui/delegation/self-coercion-static-free.stderr +++ b/tests/ui/delegation/self-coercion-static-free.stderr @@ -1,49 +1,103 @@ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:24:9 + --> $DIR/self-coercion-static-free.rs:22:26 | -LL | S::static_self() - | ^^^^^^^^^^^^^^^^ expected `&mut F`, found `F` +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^ + | | + | expected `F`, found `S` + | arguments to this function are incorrect | -help: consider mutably borrowing here +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:10:8 | -LL | &mut S::static_self() - | ++++ +LL | fn static_value(_: Self) -> i32 { 1 } + | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:24:9 + --> $DIR/self-coercion-static-free.rs:22:40 | -LL | S::static_self() - | ^^^^^^^^^^^^^^^^ expected `&F`, found `F` +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^^^ + | | + | expected `&mut F`, found `&mut S` + | arguments to this function are incorrect | -help: consider borrowing here + = note: expected mutable reference `&mut F` + found mutable reference `&mut S` +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:11:8 | -LL | &S::static_self() - | + +LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } + | ^^^^^^^^^^^^^^ ------------ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:35:9 + --> $DIR/self-coercion-static-free.rs:22:56 | -LL | S1::static_self() - | ^^^^^^^^^^^^^^^^^ expected `&mut F`, found `F` +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^ + | | + | expected `&F`, found `&S` + | arguments to this function are incorrect | -help: consider mutably borrowing here + = note: expected reference `&F` + found reference `&S` +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:12:8 | -LL | &mut S1::static_self() - | ++++ +LL | fn static_ref(_: &Self) -> i32 { 3 } + | ^^^^^^^^^^ -------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:35:9 + --> $DIR/self-coercion-static-free.rs:34:26 | -LL | S1::static_self() - | ^^^^^^^^^^^^^^^^^ expected `&F`, found `F` +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^ + | | + | expected `F`, found `S1` + | arguments to this function are incorrect | -help: consider borrowing here +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:10:8 + | +LL | fn static_value(_: Self) -> i32 { 1 } + | ^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/self-coercion-static-free.rs:34:40 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^^^ + | | + | expected `&mut F`, found `&mut S1` + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut F` + found mutable reference `&mut S1` +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:11:8 + | +LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } + | ^^^^^^^^^^^^^^ ------------ + +error[E0308]: mismatched types + --> $DIR/self-coercion-static-free.rs:34:56 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^ + | | + | expected `&F`, found `&S1` + | arguments to this function are incorrect + | + = note: expected reference `&F` + found reference `&S1` +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:12:8 | -LL | &S1::static_self() - | + +LL | fn static_ref(_: &Self) -> i32 { 3 } + | ^^^^^^^^^^ -------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:48:43 + --> $DIR/self-coercion-static-free.rs:50:43 | LL | reuse to_reuse::{value, mut_ref, r#ref} { F } | ------- ^ expected `&mut _`, found `F` @@ -53,7 +107,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { F } = note: expected mutable reference `&mut _` found struct `F` note: function defined here - --> $DIR/self-coercion-static-free.rs:44:12 + --> $DIR/self-coercion-static-free.rs:46:12 | LL | pub fn mut_ref(_: &mut impl Trait) -> i32 { 2 } | ^^^^^^^ ------------------ @@ -63,7 +117,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { &mut F } | ++++ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:48:43 + --> $DIR/self-coercion-static-free.rs:50:43 | LL | reuse to_reuse::{value, mut_ref, r#ref} { F } | ----- ^ expected `&_`, found `F` @@ -73,7 +127,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { F } = note: expected reference `&_` found struct `F` note: function defined here - --> $DIR/self-coercion-static-free.rs:45:12 + --> $DIR/self-coercion-static-free.rs:47:12 | LL | pub fn r#ref(_: &impl Trait) -> i32 { 3 } | ^^^^^ -------------- @@ -82,6 +136,6 @@ help: consider borrowing here LL | reuse to_reuse::{value, mut_ref, r#ref} { &F } | + -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/delegation/target-expr-removal-defs-inside.rs b/tests/ui/delegation/target-expr-removal-defs-inside.rs new file mode 100644 index 0000000000000..f36030549defb --- /dev/null +++ b/tests/ui/delegation/target-expr-removal-defs-inside.rs @@ -0,0 +1,35 @@ +#![feature(fn_delegation)] + +pub trait Trait: Sized { + fn static_self() -> F { F } + + fn static_value(_: Self) -> i32 { 1 } + fn static_mut_ref(_: &mut Self) -> i32 { 2 } + fn static_ref(_: &Self) -> i32 { 3 } +} + +struct F; +impl Trait for F {} + +struct S(F); + +reuse impl Trait for S { + //~^ ERROR: attempted to delete delegation's block that contains definitions inside + //~| ERROR: attempted to delete delegation's block that contains definitions inside + //~| ERROR: attempted to delete delegation's block that contains definitions inside + //~| ERROR: attempted to delete delegation's block that contains definitions inside + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: method `static_self` has an incompatible type for trait + //~| ERROR: method `static_value` has 0 parameters but the declaration in trait `Trait::static_value` has 1 + //~| ERROR: method `static_mut_ref` has 0 parameters but the declaration in trait `Trait::static_mut_ref` has 1 + //~| ERROR: method `static_ref` has 0 parameters but the declaration in trait `Trait::static_ref` has 1 + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + struct Def {} + + self +} + +fn main() {} diff --git a/tests/ui/delegation/target-expr-removal-defs-inside.stderr b/tests/ui/delegation/target-expr-removal-defs-inside.stderr new file mode 100644 index 0000000000000..79bff70e1406a --- /dev/null +++ b/tests/ui/delegation/target-expr-removal-defs-inside.stderr @@ -0,0 +1,218 @@ +error: attempted to delete delegation's block that contains definitions inside + --> $DIR/target-expr-removal-defs-inside.rs:16:24 + | +LL | reuse impl Trait for S { + | ________________________^ +... | +LL | | self +LL | | } + | |_^ + +error: attempted to delete delegation's block that contains definitions inside + --> $DIR/target-expr-removal-defs-inside.rs:16:24 + | +LL | reuse impl Trait for S { + | ________________________^ +... | +LL | | self +LL | | } + | |_^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: attempted to delete delegation's block that contains definitions inside + --> $DIR/target-expr-removal-defs-inside.rs:16:24 + | +LL | reuse impl Trait for S { + | ________________________^ +... | +LL | | self +LL | | } + | |_^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: attempted to delete delegation's block that contains definitions inside + --> $DIR/target-expr-removal-defs-inside.rs:16:24 + | +LL | reuse impl Trait for S { + | ________________________^ +... | +LL | | self +LL | | } + | |_^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0053]: method `static_self` has an incompatible type for trait + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | |_^ expected `F`, found `()` + | +note: type in trait + --> $DIR/target-expr-removal-defs-inside.rs:4:25 + | +LL | fn static_self() -> F { F } + | ^ + = note: expected signature `fn() -> F` + found signature `fn() -> ()` +help: change the output type to match the trait + | +LL - reuse impl Trait for S { +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - struct Def {} +LL - +LL - self +LL - } +LL + -> F + | + +error[E0050]: method `static_value` has 0 parameters but the declaration in trait `Trait::static_value` has 1 + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | fn static_value(_: Self) -> i32 { 1 } + | ---- trait requires 1 parameter +... +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | |_^ expected 1 parameter, found 0 + +error[E0050]: method `static_mut_ref` has 0 parameters but the declaration in trait `Trait::static_mut_ref` has 1 + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } + | --------- trait requires 1 parameter +... +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | |_^ expected 1 parameter, found 0 + +error[E0050]: method `static_ref` has 0 parameters but the declaration in trait `Trait::static_ref` has 1 + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | fn static_ref(_: &Self) -> i32 { 3 } + | ----- trait requires 1 parameter +... +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | |_^ expected 1 parameter, found 0 + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | reuse impl Trait for S { + | _^ - + | |________________________| +... || +LL | || self +LL | || } + | ||_^ unexpected argument + | |_| + | + | +note: associated function defined here + --> $DIR/target-expr-removal-defs-inside.rs:4:8 + | +LL | fn static_self() -> F { F } + | ^^^^^^^^^^^ +help: remove the extra argument + | +LL - reuse impl Trait for S { +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - +LL - struct Def {} +LL - +LL - self +LL - } +LL + reuse impl Trait for S } + | + +error[E0308]: mismatched types + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | | ^- help: consider using a semicolon here: `;` + | | | + | |_expected `()`, found `F` + | expected `()` because of default return type + +error[E0308]: mismatched types + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | | ^- help: consider using a semicolon here: `;` + | | | + | |_expected `()`, found `i32` + | expected `()` because of default return type + +error[E0308]: mismatched types + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | | ^- help: consider using a semicolon here: `;` + | | | + | |_expected `()`, found `i32` + | expected `()` because of default return type + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/target-expr-removal-defs-inside.rs:16:1 + | +LL | / reuse impl Trait for S { +... | +LL | | self +LL | | } + | | ^- help: consider using a semicolon here: `;` + | | | + | |_expected `()`, found `i32` + | expected `()` because of default return type + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0050, E0053, E0061, E0308. +For more information about an error, try `rustc --explain E0050`. diff --git a/tests/ui/delegation/target-expression-removal-pass.rs b/tests/ui/delegation/target-expression-removal-pass.rs new file mode 100644 index 0000000000000..14bf5a66c6efe --- /dev/null +++ b/tests/ui/delegation/target-expression-removal-pass.rs @@ -0,0 +1,39 @@ +//@ run-pass + +#![feature(fn_delegation)] + +trait Trait: Sized { + fn by_value(self) -> i32 { 1 } + fn by_mut_ref(&mut self) -> i32 { 2 } + fn by_ref(&self) -> i32 { 3 } + + fn static_self() -> F { F } + + fn static_value(_: F) -> i32 { 1 } + fn static_mut_ref(_: &mut F) -> i32 { 2 } + fn static_ref(_: &F) -> i32 { 3 } +} + +#[derive(Default, Eq, PartialEq, Debug)] +struct F; +impl Trait for F {} + +struct S(F); + +impl Trait for S { + // Delegation's expression is removed from static functions. + reuse ::* { self.0 } +} + +fn main() { + let mut s = S(F); + assert_eq!(s.by_mut_ref(), 2); + assert_eq!(s.by_ref(), 3); + assert_eq!(s.by_value(), 1); + + assert_eq!(S::static_self(), F); + + assert_eq!(S::static_value(F), 1); + assert_eq!(S::static_mut_ref(&mut F), 2); + assert_eq!(S::static_ref(&F), 3); +} diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.rs b/tests/ui/delegation/zero-args-delegations-ice-154332.rs index 10d8def4c8c76..133b6f93b40e6 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.rs +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.rs @@ -4,6 +4,7 @@ mod test_ice { fn a() {} reuse a as b { //~ ERROR: delegation block is specified for function with no params + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied let closure = || { fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} @@ -24,20 +25,25 @@ mod test_2 { reuse to_reuse::zero_args { self } //~^ ERROR: delegation block is specified for function with no params + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types } mod nested_delegations { fn a() {} reuse a as b { //~ ERROR: delegation block is specified for function with no params + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied let closure = || { - reuse a as b { + reuse a as b { //~ ERROR: delegation block is specified for function with no params + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} reuse foo:: as bar; bar(&"".to_string(), &"".to_string()); - reuse a as b { + reuse a as b { //~ ERROR: delegation block is specified for function with no params + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied reuse foo:: as bar; bar(&"".to_string(), &"".to_string()); } diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr index fd2f34eedabb7..3dd8f238f98ea 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr @@ -3,6 +3,7 @@ error: delegation block is specified for function with no params | LL | reuse a as b { | __________________^ +LL | | LL | | let closure = || { LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} ... | @@ -11,23 +12,172 @@ LL | | } | |_____^ error: delegation block is specified for function with no params - --> $DIR/zero-args-delegations-ice-154332.rs:25:31 + --> $DIR/zero-args-delegations-ice-154332.rs:26:31 | LL | reuse to_reuse::zero_args { self } | ^^^^^^^^ error: delegation block is specified for function with no params - --> $DIR/zero-args-delegations-ice-154332.rs:32:18 + --> $DIR/zero-args-delegations-ice-154332.rs:35:18 | LL | reuse a as b { | __________________^ +LL | | LL | | let closure = || { LL | | reuse a as b { -LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} ... | LL | | closure(); LL | | } | |_____^ -error: aborting due to 3 previous errors +error: delegation block is specified for function with no params + --> $DIR/zero-args-delegations-ice-154332.rs:38:26 + | +LL | reuse a as b { + | __________________________^ +LL | | +LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} +... | +LL | | } + | |_____________^ + +error: delegation block is specified for function with no params + --> $DIR/zero-args-delegations-ice-154332.rs:45:30 + | +LL | reuse a as b { + | ______________________________^ +LL | | +LL | | reuse foo:: as bar; +LL | | bar(&"".to_string(), &"".to_string()); +LL | | } + | |_________________^ + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/zero-args-delegations-ice-154332.rs:6:11 + | +LL | reuse a as b { + | ___________^______- +LL | | +LL | | let closure = || { +LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} +... | +LL | | closure(); +LL | | } + | |_____- unexpected argument of type `()` + | +note: function defined here + --> $DIR/zero-args-delegations-ice-154332.rs:4:8 + | +LL | fn a() {} + | ^ +help: remove the extra argument + | +LL - reuse a as b { +LL + reuse { + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/zero-args-delegations-ice-154332.rs:26:21 + | +LL | reuse to_reuse::zero_args { self } + | ^^^^^^^^^ ---- unexpected argument + | +note: function defined here + --> $DIR/zero-args-delegations-ice-154332.rs:21:16 + | +LL | pub fn zero_args() -> i32 { + | ^^^^^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::zero_args { self } +LL + reuse to_reuse::zero_argself } + | + +error[E0308]: mismatched types + --> $DIR/zero-args-delegations-ice-154332.rs:26:21 + | +LL | reuse to_reuse::zero_args { self } + | ^^^^^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::zero_args; { self } + | + +help: try adding a return type + | +LL - reuse to_reuse::zero_args { self } +LL + reuse to_reuse:: -> i32 { self } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/zero-args-delegations-ice-154332.rs:35:11 + | +LL | reuse a as b { + | ___________^______- +LL | | +LL | | let closure = || { +LL | | reuse a as b { +... | +LL | | closure(); +LL | | } + | |_____- unexpected argument of type `()` + | +note: function defined here + --> $DIR/zero-args-delegations-ice-154332.rs:33:8 + | +LL | fn a() {} + | ^ +help: remove the extra argument + | +LL - reuse a as b { +LL + reuse { + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/zero-args-delegations-ice-154332.rs:38:19 + | +LL | reuse a as b { + | ___________________^______- +LL | | +LL | | fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {} +... | +LL | | } + | |_____________- unexpected argument of type `()` + | +note: function defined here + --> $DIR/zero-args-delegations-ice-154332.rs:33:8 + | +LL | fn a() {} + | ^ +help: remove the extra argument + | +LL - reuse a as b { +LL + reuse { + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/zero-args-delegations-ice-154332.rs:45:23 + | +LL | reuse a as b { + | _______________________^______- +LL | | +LL | | reuse foo:: as bar; +LL | | bar(&"".to_string(), &"".to_string()); +LL | | } + | |_________________- unexpected argument of type `()` + | +note: function defined here + --> $DIR/zero-args-delegations-ice-154332.rs:33:8 + | +LL | fn a() {} + | ^ +help: remove the extra argument + | +LL - reuse a as b { +LL + reuse { + | + +error: aborting due to 11 previous errors +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/zero-args-delegations-ice-154427.rs b/tests/ui/delegation/zero-args-delegations-ice-154427.rs index b50066b057638..b0e00947a041f 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154427.rs +++ b/tests/ui/delegation/zero-args-delegations-ice-154427.rs @@ -12,8 +12,7 @@ mod ice_154427 { } impl Trait for S { reuse to_reuse::foo { self } - //~^ ERROR: this function takes 1 argument but 0 arguments were supplied - //~| ERROR: delegation block is specified for function with no params + //~^ ERROR: delegation block is specified for function with no params } fn main() {} diff --git a/tests/ui/delegation/zero-args-delegations-ice-154427.stderr b/tests/ui/delegation/zero-args-delegations-ice-154427.stderr index b73976fedda74..7aca43d1b3e64 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154427.stderr +++ b/tests/ui/delegation/zero-args-delegations-ice-154427.stderr @@ -4,22 +4,5 @@ error: delegation block is specified for function with no params LL | reuse to_reuse::foo { self } | ^^^^^^^^ -error[E0061]: this function takes 1 argument but 0 arguments were supplied - --> $DIR/zero-args-delegations-ice-154427.rs:14:25 - | -LL | reuse to_reuse::foo { self } - | ^^^ argument #1 of type `F` is missing - | -note: function defined here - --> $DIR/zero-args-delegations-ice-154427.rs:11:16 - | -LL | pub fn foo(_: F) {} - | ^^^ ---- -help: provide the argument - | -LL | reuse to_reuse::foo(/* F */) { self } - | +++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0061`. From da21a60f2012951c200e225e9a6be0995bc430f9 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 29 May 2026 15:21:23 +0300 Subject: [PATCH 5/5] Cleanups --- compiler/rustc_ast_lowering/src/delegation.rs | 16 ++++++++-------- compiler/rustc_ast_lowering/src/lib.rs | 8 +++----- compiler/rustc_resolve/src/lib.rs | 1 - 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 88b1d69755ed0..b1d0a0888c62e 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -50,7 +50,7 @@ use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, FnDeclFlags}; use rustc_middle::span_bug; -use rustc_middle::ty::{Asyncness, TyCtxt}; +use rustc_middle::ty::Asyncness; use rustc_span::symbol::kw; use rustc_span::{Ident, Span, Symbol}; use smallvec::SmallVec; @@ -108,12 +108,6 @@ static ATTRS_ADDITIONS: &[AttrAdditionInfo] = &[ }, ]; -// Function parameter count, including C variadic `...` if present. -pub(crate) fn param_count(tcx: TyCtxt<'_>, def_id: DefId) -> (usize, bool /*c_variadic*/) { - let sig = tcx.fn_sig(def_id).skip_binder().skip_binder(); - (sig.inputs().len() + usize::from(sig.c_variadic()), sig.c_variadic()) -} - impl<'hir> LoweringContext<'_, 'hir> { fn is_method(&self, def_id: DefId, span: Span) -> bool { match self.tcx.def_kind(def_id) { @@ -150,7 +144,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let is_method = self.is_method(sig_id, span); - let (param_count, c_variadic) = param_count(self.tcx, sig_id); + let (param_count, c_variadic) = self.param_count(sig_id); if !self.check_block_soundness(delegation, sig_id, is_method, param_count) { return self.generate_delegation_error(span, delegation); @@ -331,6 +325,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()) } + // Function parameter count, including C variadic `...` if present. + fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/) { + let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder(); + (sig.inputs().len() + usize::from(sig.c_variadic()), sig.c_variadic()) + } + fn lower_delegation_decl( &mut self, sig_id: DefId, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e2ad4620cc5f0..20eac0ab1e79a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -555,14 +555,12 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { let mut delayed_ids: FxIndexSet = Default::default(); for def_id in ast_index.indices() { - match ast_index[def_id] { + match &ast_index[def_id] { AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. }) | AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) => { delayed_ids.insert(def_id); } - _ => { - lowerer.lower_node(def_id); - } + _ => lowerer.lower_node(def_id), } } @@ -575,7 +573,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { } /// Lowers an AST owner corresponding to `def_id`, now only delegations are lowered this way. -pub fn lower_delayed_owner<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { +pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) { let krate = tcx.hir_crate(()); let (resolver, krate) = &*krate.delayed_resolver.borrow(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e9eba4afc43b2..7f16fdfb7c5f0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1526,7 +1526,6 @@ pub struct Resolver<'ra, 'tcx> { item_generics_num_lifetimes: FxHashMap = default::fx_hash_map(), /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), - delegation_fn_sigs: LocalDefIdMap = Default::default(), delegation_infos: LocalDefIdMap = Default::default(),