From 262a68ff5966bd74d951fa5636a421d142ffccb6 Mon Sep 17 00:00:00 2001 From: lapla Date: Wed, 24 Jun 2026 16:48:08 +0900 Subject: [PATCH] Propagate errors in const-to-valtree lowering --- .../src/hir_ty_lowering/mod.rs | 18 ++++++------- compiler/rustc_middle/src/ty/consts.rs | 18 ++++++++++++- .../mgca/type_const-adt-expr-missing-field.rs | 13 ++++++++++ .../type_const-adt-expr-missing-field.stderr | 26 +++++++++++++++++++ ...ype_const-tuple-call-expr-missing-field.rs | 17 ++++++++++++ ...const-tuple-call-expr-missing-field.stderr | 26 +++++++++++++++++++ 6 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs create mode 100644 tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr create mode 100644 tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.rs create mode 100644 tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 87f88a16b2c42..f29b6902886b6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2409,9 +2409,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|elem| self.lower_const_arg(elem, *elem_ty)) .collect::>(); - let valtree = ty::ValTree::from_branches(tcx, elems); - - ty::Const::new_value(tcx, valtree, ty) + ty::Const::new_value_from_branches(tcx, elems, ty) } fn lower_const_arg_tuple_call( @@ -2509,9 +2507,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None }; - let valtree = ty::ValTree::from_branches(tcx, opt_discr_const.into_iter().chain(fields)); - let adt_ty = Ty::new_adt(tcx, adt_def, adt_args); - ty::Const::new_value(tcx, valtree, adt_ty) + ty::Const::new_value_from_branches( + tcx, + opt_discr_const.into_iter().chain(fields), + Ty::new_adt(tcx, adt_def, adt_args), + ) } fn lower_const_arg_tup( @@ -2537,8 +2537,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|(expr, ty)| self.lower_const_arg(expr, ty)) .collect::>(); - let valtree = ty::ValTree::from_branches(tcx, exprs); - ty::Const::new_value(tcx, valtree, ty) + ty::Const::new_value_from_branches(tcx, exprs, ty) } fn lower_const_arg_struct( @@ -2680,8 +2679,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None }; - let valtree = ty::ValTree::from_branches(tcx, opt_discr_const.into_iter().chain(fields)); - ty::Const::new_value(tcx, valtree, ty) + ty::Const::new_value_from_branches(tcx, opt_discr_const.into_iter().chain(fields), ty) } pub fn lower_path_for_struct_expr( diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 30d9a9fb1650c..0864ed12e4409 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -4,7 +4,7 @@ use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; use rustc_macros::StableHash; use rustc_type_ir::walk::TypeWalker; -use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; +use rustc_type_ir::{self as ir, TypeFlags, TypeVisitableExt, WithCachedTypeInfo}; use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; @@ -116,6 +116,22 @@ impl<'tcx> Const<'tcx> { Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree })) } + pub fn new_value_from_branches( + tcx: TyCtxt<'tcx>, + branches: impl IntoIterator>, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + let branches: Vec<_> = branches.into_iter().collect(); + if let Some(e) = branches.iter().find_map(|c| c.error_reported().err()) { + return Const::new_error(tcx, e); + } + if let Err(e) = ty.error_reported() { + return Const::new_error(tcx, e); + } + + Const::new_value(tcx, ty::ValTree::from_branches(tcx, branches), ty) + } + #[inline] pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Expr(expr)) diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs new file mode 100644 index 0000000000000..f26e69e2a1e41 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs @@ -0,0 +1,13 @@ +// Regression test for https://github.com/rust-lang/rust/issues/154632 + +#![feature(generic_const_exprs)] +#![feature(min_generic_const_args)] +#![feature(generic_const_items)] + +type const ADD1 : usize = const { N + 1 }; +//~^ ERROR: unconstrained generic constant +type const AliasFnUnused: ADD1 = ADD1::<{ Some:: {} }>; +//~^ ERROR: expected type, found constant `ADD1` [E0573] +//~| ERROR: struct expression with missing field initialiser for `0` + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr new file mode 100644 index 0000000000000..b77af0971d544 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr @@ -0,0 +1,26 @@ +error[E0573]: expected type, found constant `ADD1` + --> $DIR/type_const-adt-expr-missing-field.rs:9:27 + | +LL | type const AliasFnUnused: ADD1 = ADD1::<{ Some:: {} }>; + | ^^^^ not a type + +error: unconstrained generic constant + --> $DIR/type_const-adt-expr-missing-field.rs:7:1 + | +LL | type const ADD1 : usize = const { N + 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try adding a `where` bound + | +LL | type const ADD1 : usize where [(); const { N + 1 }]: = const { N + 1 }; + | ++++++++++++++++++++++++++++ + +error: struct expression with missing field initialiser for `0` + --> $DIR/type_const-adt-expr-missing-field.rs:9:43 + | +LL | type const AliasFnUnused: ADD1 = ADD1::<{ Some:: {} }>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.rs new file mode 100644 index 0000000000000..37bc00122f5ba --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![feature(min_generic_const_args)] +#![feature(adt_const_params)] +#![feature(generic_const_items)] + +use std::marker::ConstParamTy; + +#[derive(Eq, PartialEq, ConstParamTy)] +struct Wrap(usize); + +type const ADD1: usize = const { N + 1 }; +//~^ ERROR: unconstrained generic constant +type const AliasFnUnused: ADD1 = ADD1::<{ Wrap(Some:: {}) }>; +//~^ ERROR: expected type, found constant `ADD1` [E0573] +//~| ERROR: struct expression with missing field initialiser for `0` + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.stderr b/tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.stderr new file mode 100644 index 0000000000000..95c19d14eb42c --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-tuple-call-expr-missing-field.stderr @@ -0,0 +1,26 @@ +error[E0573]: expected type, found constant `ADD1` + --> $DIR/type_const-tuple-call-expr-missing-field.rs:13:27 + | +LL | type const AliasFnUnused: ADD1 = ADD1::<{ Wrap(Some:: {}) }>; + | ^^^^ not a type + +error: unconstrained generic constant + --> $DIR/type_const-tuple-call-expr-missing-field.rs:11:1 + | +LL | type const ADD1: usize = const { N + 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try adding a `where` bound + | +LL | type const ADD1: usize where [(); const { N + 1 }]: = const { N + 1 }; + | ++++++++++++++++++++++++++++ + +error: struct expression with missing field initialiser for `0` + --> $DIR/type_const-tuple-call-expr-missing-field.rs:13:48 + | +LL | type const AliasFnUnused: ADD1 = ADD1::<{ Wrap(Some:: {}) }>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0573`.