From 58af51e2435f81f2a6a2bc99556a21e047421bed Mon Sep 17 00:00:00 2001 From: mu001999 Date: Mon, 30 Mar 2026 22:59:56 +0800 Subject: [PATCH 1/2] Emit fatal on invalid const args with nested defs --- compiler/rustc_ast_lowering/src/expr.rs | 26 +++++++++---------- compiler/rustc_ast_lowering/src/lib.rs | 13 ++++++---- .../mgca/array-expr-complex.r1.stderr | 8 ++++++ .../mgca/array-expr-complex.r2.stderr | 8 ++++++ .../mgca/array-expr-complex.r3.stderr | 8 ++++++ .../const-generics/mgca/array-expr-complex.rs | 11 +++++--- .../mgca/array-expr-complex.stderr | 20 -------------- .../mgca/bad-const-arg-fn-154539.rs | 12 +++++++++ .../mgca/bad-const-arg-fn-154539.stderr | 11 ++++++++ 9 files changed, 76 insertions(+), 41 deletions(-) create mode 100644 tests/ui/const-generics/mgca/array-expr-complex.r1.stderr create mode 100644 tests/ui/const-generics/mgca/array-expr-complex.r2.stderr create mode 100644 tests/ui/const-generics/mgca/array-expr-complex.r3.stderr delete mode 100644 tests/ui/const-generics/mgca/array-expr-complex.stderr create mode 100644 tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs create mode 100644 tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b6bc122051cbc..e0ec8ba3dcb9d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -29,7 +29,7 @@ use super::{ use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure}; use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope}; -struct WillCreateDefIdsVisitor {} +pub(super) struct WillCreateDefIdsVisitor; impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor { type Result = ControlFlow; @@ -479,18 +479,18 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { DefPathData::LateAnonConst, f.span, ); - let mut visitor = WillCreateDefIdsVisitor {}; - let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { - Box::new(Expr { - id: self.next_node_id(), - kind: ExprKind::Err(invalid_expr_error(self.tcx, span)), - span: f.span, - attrs: [].into(), - tokens: None, - }) - } else { - arg - }; + let const_value = + if let ControlFlow::Break(span) = WillCreateDefIdsVisitor.visit_expr(&arg) { + Box::new(Expr { + id: self.next_node_id(), + kind: ExprKind::Err(invalid_expr_error(self.tcx, span)), + span: f.span, + attrs: [].into(), + tokens: None, + }) + } else { + arg + }; let anon_const = AnonConst { id: node_id, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6d9fe9870c42e..9e830e29be033 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -39,6 +39,7 @@ use std::mem; use std::sync::Arc; use rustc_ast::node_id::NodeMap; +use rustc_ast::visit::Visitor; use rustc_ast::{self as ast, *}; use rustc_attr_parsing::{AttributeParser, Late, OmitDoc}; use rustc_data_structures::fingerprint::Fingerprint; @@ -2563,12 +2564,14 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { let span = self.lower_span(expr.span); let overly_complex_const = |this: &mut Self| { - let e = this.dcx().struct_span_err( - expr.span, - "complex const arguments must be placed inside of a `const` block", - ); + let msg = "complex const arguments must be placed inside of a `const` block"; + let e = if expr::WillCreateDefIdsVisitor.visit_expr(expr).is_break() { + this.dcx().struct_span_fatal(expr.span, msg).emit() + } else { + this.dcx().struct_span_err(expr.span, msg).emit() + }; - ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(e.emit()), span } + ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(e), span } }; match &expr.kind { diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr new file mode 100644 index 0000000000000..0c931af8d8b1c --- /dev/null +++ b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr @@ -0,0 +1,8 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/array-expr-complex.rs:11:28 + | +LL | takes_array::<{ [1, 2, 1 + 2] }>(); + | ^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr new file mode 100644 index 0000000000000..335af9235e0c9 --- /dev/null +++ b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr @@ -0,0 +1,8 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/array-expr-complex.rs:14:21 + | +LL | takes_array::<{ [X; 3] }>(); + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr new file mode 100644 index 0000000000000..02d74c1b5d0c5 --- /dev/null +++ b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr @@ -0,0 +1,8 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/array-expr-complex.rs:17:21 + | +LL | takes_array::<{ [0; Y] }>(); + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/array-expr-complex.rs b/tests/ui/const-generics/mgca/array-expr-complex.rs index 3e8320bc94de2..26f4700b5885c 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.rs +++ b/tests/ui/const-generics/mgca/array-expr-complex.rs @@ -1,3 +1,5 @@ +//@ revisions: r1 r2 r3 + #![expect(incomplete_features)] #![feature(min_generic_const_args, adt_const_params)] @@ -5,12 +7,15 @@ fn takes_array() {} fn generic_caller() { // not supported yet + #[cfg(r1)] takes_array::<{ [1, 2, 1 + 2] }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //[r1]~^ ERROR: complex const arguments must be placed inside of a `const` block + #[cfg(r2)] takes_array::<{ [X; 3] }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //[r2]~^ ERROR: complex const arguments must be placed inside of a `const` block + #[cfg(r3)] takes_array::<{ [0; Y] }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //[r3]~^ ERROR: complex const arguments must be placed inside of a `const` block } fn main() {} diff --git a/tests/ui/const-generics/mgca/array-expr-complex.stderr b/tests/ui/const-generics/mgca/array-expr-complex.stderr deleted file mode 100644 index 544b0f05b4e44..0000000000000 --- a/tests/ui/const-generics/mgca/array-expr-complex.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:8:28 - | -LL | takes_array::<{ [1, 2, 1 + 2] }>(); - | ^^^^^ - -error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:10:21 - | -LL | takes_array::<{ [X; 3] }>(); - | ^^^^^^ - -error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:12:21 - | -LL | takes_array::<{ [0; Y] }>(); - | ^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs new file mode 100644 index 0000000000000..7c7ffd9a9bd5f --- /dev/null +++ b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs @@ -0,0 +1,12 @@ +#![feature(min_generic_const_args)] + +trait Iter< + const FN: fn() = { + || { //~ ERROR complex const arguments must be placed inside of a `const` block + use std::io::*; + write!(_, "") + } + }, +> +{ +} diff --git a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr new file mode 100644 index 0000000000000..60774c4a3efea --- /dev/null +++ b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr @@ -0,0 +1,11 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/bad-const-arg-fn-154539.rs:5:9 + | +LL | / || { +LL | | use std::io::*; +LL | | write!(_, "") +LL | | } + | |_________^ + +error: aborting due to 1 previous error + From 6f1d601ca59c3dc05a13e7006b26d4d8cd0b3f7b Mon Sep 17 00:00:00 2001 From: mu001999 Date: Tue, 14 Apr 2026 12:28:19 +0800 Subject: [PATCH 2/2] Update test with revisions --- ...ems-before-lowering-ices.ice_155125.stderr | 23 +++++ ...ems-before-lowering-ices.ice_155127.stderr | 12 +++ ...ems-before-lowering-ices.ice_155128.stderr | 24 +++++ ...ems-before-lowering-ices.ice_155164.stderr | 13 +++ ...ems-before-lowering-ices.ice_155202.stderr | 16 ++++ .../hir-crate-items-before-lowering-ices.rs | 24 +++-- ...ir-crate-items-before-lowering-ices.stderr | 89 ------------------- 7 files changed, 103 insertions(+), 98 deletions(-) create mode 100644 tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr create mode 100644 tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr create mode 100644 tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr create mode 100644 tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr create mode 100644 tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr delete mode 100644 tests/ui/delegation/hir-crate-items-before-lowering-ices.stderr diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr new file mode 100644 index 0000000000000..e8a32e340f3e5 --- /dev/null +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr @@ -0,0 +1,23 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/hir-crate-items-before-lowering-ices.rs:13:17 + | +LL | fn foo() {} + | -------- previous definition of the value `foo` here +LL | reuse foo; + | ^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this block + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/hir-crate-items-before-lowering-ices.rs:11:13 + | +LL | / { +LL | | fn foo() {} +LL | | reuse foo; +LL | | 2 +LL | | }, + | |_____________^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr new file mode 100644 index 0000000000000..132e4e3034c4e --- /dev/null +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr @@ -0,0 +1,12 @@ +error: `#[deprecated]` attribute cannot be used on delegations + --> $DIR/hir-crate-items-before-lowering-ices.rs:27:9 + | +LL | #[deprecated] + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements + = note: `#[deny(useless_deprecated)]` on by default + +error: aborting due to 1 previous error + 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 new file mode 100644 index 0000000000000..0a1b2c5a472c7 --- /dev/null +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr @@ -0,0 +1,24 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/hir-crate-items-before-lowering-ices.rs:37:11 + | +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:35: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.ice_155164.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr new file mode 100644 index 0000000000000..34d1a92ccd225 --- /dev/null +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr @@ -0,0 +1,13 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/hir-crate-items-before-lowering-ices.rs:47:13 + | +LL | / { +LL | | +LL | | struct W; +LL | | impl W { +... | +LL | | }, + | |_____________^ + +error: aborting due to 1 previous error + 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 new file mode 100644 index 0000000000000..28f045ca69442 --- /dev/null +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `async` in this scope + --> $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:66:22 + | +LL | async || {}; + | ^^ expected `bool`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. 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 1dc2f2f8a2634..6c16a1ae22d38 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs @@ -1,13 +1,16 @@ +//@ revisions: ice_155125 ice_155127 ice_155128 ice_155164 ice_155202 + #![feature(min_generic_const_args, fn_delegation)] #![allow(incomplete_features)] +#[cfg(ice_155125)] mod ice_155125 { struct S; impl S< - { //~ ERROR: complex const arguments must be placed inside of a `const` block + { //[ice_155125]~ ERROR: complex const arguments must be placed inside of a `const` block fn foo() {} - reuse foo; //~ ERROR: the name `foo` is defined multiple times + reuse foo; //[ice_155125]~ ERROR: the name `foo` is defined multiple times 2 }, > @@ -15,32 +18,34 @@ mod ice_155125 { } } +#[cfg(ice_155127)] mod ice_155127 { struct S; fn foo() {} impl S { - #[deprecated] //~ ERROR: `#[deprecated]` attribute cannot be used on delegations - //~^ WARN: this was previously accepted by the compiler but is being phased out; + #[deprecated] //[ice_155127]~ ERROR: `#[deprecated]` attribute cannot be used on delegations + //[ice_155127]~^ WARN: this was previously accepted by the compiler but is being phased out; reuse foo; } } +#[cfg(ice_155128)] mod ice_155128 { fn a() {} - reuse a as b { //~ ERROR: this function takes 0 arguments but 1 argument was supplied + reuse a as b { //[ice_155128]~ ERROR: this function takes 0 arguments but 1 argument was supplied fn foo() {}; foo } } +#[cfg(ice_155164)] mod ice_155164 { struct X { inner: std::iter::Map< { - //~^ ERROR: complex const arguments must be placed inside of a `const` block - //~| ERROR: constant provided when a type was expected + //[ice_155164]~^ ERROR: complex const arguments must be placed inside of a `const` block struct W; impl W { reuse Iterator::fold; @@ -51,14 +56,15 @@ mod ice_155164 { } } +#[cfg(ice_155202)] mod ice_155202 { trait Trait { fn bar(self); } impl Trait for () { reuse Trait::bar { - async || {}; //~ ERROR: mismatched types - //~^ ERROR: cannot find value `async` in this scope + async || {}; //[ice_155202]~ ERROR: mismatched types + //[ice_155202]~^ ERROR: cannot find value `async` in this scope } } } diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.stderr deleted file mode 100644 index 1bc4c1f7de4e5..0000000000000 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.stderr +++ /dev/null @@ -1,89 +0,0 @@ -error[E0428]: the name `foo` is defined multiple times - --> $DIR/hir-crate-items-before-lowering-ices.rs:10:17 - | -LL | fn foo() {} - | -------- previous definition of the value `foo` here -LL | reuse foo; - | ^^^^^^^^^^ `foo` redefined here - | - = note: `foo` must be defined only once in the value namespace of this block - -error[E0425]: cannot find value `async` in this scope - --> $DIR/hir-crate-items-before-lowering-ices.rs:60:13 - | -LL | async || {}; - | ^^^^^ not found in this scope - -error: complex const arguments must be placed inside of a `const` block - --> $DIR/hir-crate-items-before-lowering-ices.rs:8:13 - | -LL | / { -LL | | fn foo() {} -LL | | reuse foo; -LL | | 2 -LL | | }, - | |_____________^ - -error: complex const arguments must be placed inside of a `const` block - --> $DIR/hir-crate-items-before-lowering-ices.rs:41:13 - | -LL | / { -LL | | -LL | | -LL | | struct W; -... | -LL | | }, - | |_____________^ - -error: `#[deprecated]` attribute cannot be used on delegations - --> $DIR/hir-crate-items-before-lowering-ices.rs:23:9 - | -LL | #[deprecated] - | ^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements - = note: `#[deny(useless_deprecated)]` on by default - -error[E0747]: constant provided when a type was expected - --> $DIR/hir-crate-items-before-lowering-ices.rs:41:13 - | -LL | / { -LL | | -LL | | -LL | | struct W; -... | -LL | | }, - | |_____________^ - -error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/hir-crate-items-before-lowering-ices.rs:32:11 - | -LL | reuse a as b { - | ___________^______- -LL | | fn foo() {}; -LL | | foo -LL | | } - | |_____- unexpected argument of type `fn() {b::foo::<_>}` - | -note: function defined here - --> $DIR/hir-crate-items-before-lowering-ices.rs:30:8 - | -LL | fn a() {} - | ^ -help: remove the extra argument - | -LL - reuse a as b { -LL + reuse { - | - -error[E0308]: mismatched types - --> $DIR/hir-crate-items-before-lowering-ices.rs:60:22 - | -LL | async || {}; - | ^^ expected `bool`, found `()` - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0061, E0308, E0425, E0428, E0747. -For more information about an error, try `rustc --explain E0061`.