From 11a338deb6884f72f3d3558d810e9b025de23167 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 25 Mar 2026 12:08:31 +0300 Subject: [PATCH] Fix nested zero-args delegation ICE --- compiler/rustc_ast_lowering/src/delegation.rs | 11 +++++ tests/ui/delegation/explicit-paths-pass.rs | 4 -- tests/ui/delegation/inner-attr.rs | 1 + tests/ui/delegation/inner-attr.stderr | 22 +++++++++- .../zero-args-delegations-ice-154332.rs | 30 +++++++++++++ .../zero-args-delegations-ice-154332.stderr | 43 +++++++++++++++++++ 6 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 tests/ui/delegation/zero-args-delegations-ice-154332.rs create mode 100644 tests/ui/delegation/zero-args-delegations-ice-154332.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 03acf40ef5fe..022f9e3c83f1 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -432,6 +432,17 @@ fn lower_delegation_body( 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. + if param_count == 0 + && let Some(block) = block + { + args.push(this.lower_target_expr(&block)); + } + let final_expr = this.finalize_body_lowering(delegation, args, generics, span); (this.arena.alloc_from_iter(parameters), final_expr) diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs index dd0ee2c732f5..7efbb3795185 100644 --- a/tests/ui/delegation/explicit-paths-pass.rs +++ b/tests/ui/delegation/explicit-paths-pass.rs @@ -17,11 +17,8 @@ impl Trait for F {} mod to_reuse { pub fn foo(x: i32) -> i32 { x + 1 } - pub fn zero_args() -> i32 { 15 } } -reuse to_reuse::zero_args { self } - struct S(F); impl Trait for S { reuse Trait::bar { self.0 } @@ -49,5 +46,4 @@ fn main() { #[inline] reuse to_reuse::foo; assert_eq!(43, foo(42)); - assert_eq!(15, zero_args()); } diff --git a/tests/ui/delegation/inner-attr.rs b/tests/ui/delegation/inner-attr.rs index 6c996807d6ba..501118713d12 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: 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 257ab760ffc1..226a48ecf9a4 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -3,11 +3,29 @@ error: an inner attribute is not permitted in this context | LL | reuse a as b { #![rustc_dummy] self } | ^^^^^^^^^^^^^^^ -LL | +... LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -error: aborting due to 1 previous error +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/inner-attr.rs:6:7 + | +LL | reuse a as b { #![rustc_dummy] self } + | ^ ---- unexpected argument + | +note: function defined here + --> $DIR/inner-attr.rs:4: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 new file mode 100644 index 000000000000..c684803014ad --- /dev/null +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.rs @@ -0,0 +1,30 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod test_ice { + fn a() {} + + reuse a as b { //~ 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) {} + + reuse foo:: as bar; + bar(&"".to_string(), &"".to_string()); + }; + + closure(); + } +} + +mod test_2 { + mod to_reuse { + pub fn zero_args() -> i32 { + 15 + } + } + + reuse to_reuse::zero_args { self } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied +} + +fn main() {} diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr new file mode 100644 index 000000000000..dcac56e0b2ba --- /dev/null +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr @@ -0,0 +1,43 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/zero-args-delegations-ice-154332.rs:7:11 + | +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:5: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: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0061`.