Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2517,6 +2517,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
}
}
ExprKind::Array(elements) => {
let lowered_elems = self.arena.alloc_from_iter(elements.iter().map(|element| {
let const_arg = if let ExprKind::ConstBlock(anon_const) = &element.kind {
let def_id = self.local_def_id(anon_const.id);
assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id));
self.lower_anon_const_to_const_arg(anon_const)
} else {
self.lower_expr_to_const_arg_direct(element)
};
&*self.arena.alloc(const_arg)
}));
let array_expr = self.arena.alloc(hir::ConstArgArrayExpr {
span: self.lower_span(expr.span),
elems: lowered_elems,
});

ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Array(array_expr),
span,
}
}
ExprKind::Underscore => ConstArg {
hir_id: self.lower_node_id(expr.id),
kind: hir::ConstArgKind::Infer(()),
Expand All @@ -2532,6 +2554,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
| ExprKind::Struct(..)
| ExprKind::Call(..)
| ExprKind::Tup(..)
| ExprKind::Array(..)
)
{
return self.lower_expr_to_const_arg_direct(expr);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ pub enum ConstArgKind<'hir, Unambig = ()> {
Struct(QPath<'hir>, &'hir [&'hir ConstArgExprField<'hir>]),
/// Tuple constructor variant
TupleCall(QPath<'hir>, &'hir [&'hir ConstArg<'hir>]),
/// Array literal argument
Array(&'hir ConstArgArrayExpr<'hir>),
/// Error const
Error(ErrorGuaranteed),
/// This variant is not always used to represent inference consts, sometimes
Expand All @@ -529,6 +531,12 @@ pub struct ConstArgExprField<'hir> {
pub expr: &'hir ConstArg<'hir>,
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct ConstArgArrayExpr<'hir> {
pub span: Span,
pub elems: &'hir [&'hir ConstArg<'hir>],
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct InferArg {
#[stable_hasher(ignore)]
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,12 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
}
V::Result::output()
}
ConstArgKind::Array(array_expr) => {
for arg in array_expr.elems {
try_visit!(visitor.visit_const_arg_unambig(*arg));
}
V::Result::output()
}
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
ConstArgKind::Error(_) => V::Result::output(), // errors and spans are not important
Expand Down
31 changes: 31 additions & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2389,6 +2389,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::ConstArgKind::TupleCall(qpath, args) => {
self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span)
}
hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, feed),
hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon),
hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span),
hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e),
Expand All @@ -2402,6 +2403,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

fn lower_const_arg_array(
&self,
array_expr: &'tcx hir::ConstArgArrayExpr<'tcx>,
feed: FeedConstTy<'tcx>,
) -> Const<'tcx> {
let tcx = self.tcx();

let FeedConstTy::WithTy(ty) = feed else {
return Const::new_error_with_message(tcx, array_expr.span, "unsupported const array");
};

let ty::Array(elem_ty, _) = ty.kind() else {
return Const::new_error_with_message(
tcx,
array_expr.span,
"const array must have an array type",
);
};

let elems = array_expr
.elems
.iter()
.map(|elem| self.lower_const_arg(elem, FeedConstTy::WithTy(*elem_ty)))
.collect::<Vec<_>>();

let valtree = ty::ValTree::from_branches(tcx, elems);

ty::Const::new_value(tcx, valtree, ty)
}

fn lower_const_arg_tuple_call(
&self,
hir_id: HirId,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,7 @@ impl<'a> State<'a> {
}
ConstArgKind::Struct(qpath, fields) => self.print_const_struct(qpath, fields),
ConstArgKind::TupleCall(qpath, args) => self.print_const_ctor(qpath, args),
ConstArgKind::Array(..) => self.word("/* ARRAY EXPR */"),
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
ConstArgKind::Anon(anon) => self.print_anon_const(anon),
ConstArgKind::Error(_) => self.word("/*ERROR*/"),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// Skip encoding defs for these as they should not have had a `DefId` created
hir::ConstArgKind::Error(..)
| hir::ConstArgKind::Struct(..)
| hir::ConstArgKind::Array(..)
| hir::ConstArgKind::TupleCall(..)
| hir::ConstArgKind::Tup(..)
| hir::ConstArgKind::Path(..)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {

// Avoid overwriting `const_arg_context` as we may want to treat const blocks
// as being anon consts if we are inside a const argument.
ExprKind::Struct(_) | ExprKind::Call(..) | ExprKind::Tup(..) => {
ExprKind::Struct(_) | ExprKind::Call(..) | ExprKind::Tup(..) | ExprKind::Array(..) => {
return visit::walk_expr(self, expr);
}
// FIXME(mgca): we may want to handle block labels in some manner
Expand Down
4 changes: 4 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind
// FIXME(mgca): proper printing :3
ConstantKind::Path { path: "/* TUPLE EXPR */".to_string().into() }
}
hir::ConstArgKind::Array(..) => {
ConstantKind::Path { path: "/* ARRAY EXPR */".to_string().into() }
}
hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer,
hir::ConstArgKind::Literal(..) => {
Expand Down Expand Up @@ -1818,6 +1821,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
| hir::ConstArgKind::Path(..)
| hir::ConstArgKind::TupleCall(..)
| hir::ConstArgKind::Tup(..)
| hir::ConstArgKind::Array(..)
| hir::ConstArgKind::Literal(..) => {
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
print_const(cx, ct)
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/utils/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
},
ConstArgKind::Struct(..) => chain!(self, "let ConstArgKind::Struct(..) = {const_arg}.kind"),
ConstArgKind::TupleCall(..) => chain!(self, "let ConstArgKind::TupleCall(..) = {const_arg}.kind"),
ConstArgKind::Array(..) => chain!(self, "let ConstArgKind::Array(..) = {const_arg}.kind"),
ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"),
ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"),
ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"),
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx
| ConstArgKind::Tup(..)
| ConstArgKind::Literal(..)
| ConstArgKind::TupleCall(..)
| ConstArgKind::Array(..)
| ConstArgKind::Path(_)
| ConstArgKind::Error(..)
| ConstArgKind::Infer(..) => None,
Expand Down
11 changes: 11 additions & 0 deletions src/tools/clippy/clippy_utils/src/hir_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,11 @@ impl HirEqInterExpr<'_, '_, '_> {
.all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b))
},
(ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r,
(ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => {
l_arr.elems.len() == r_arr.elems.len()
&& l_arr.elems.iter().zip(r_arr.elems.iter())
.all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem))
}
// Use explicit match for now since ConstArg is undergoing flux.
(
ConstArgKind::Path(..)
Expand All @@ -696,6 +701,7 @@ impl HirEqInterExpr<'_, '_, '_> {
| ConstArgKind::Infer(..)
| ConstArgKind::Struct(..)
| ConstArgKind::Literal(..)
| ConstArgKind::Array(..)
| ConstArgKind::Error(..),
_,
) => false,
Expand Down Expand Up @@ -1575,6 +1581,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_const_arg(arg);
}
},
ConstArgKind::Array(array_expr) => {
for elem in array_expr.elems {
self.hash_const_arg(elem);
}
},
ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {},
ConstArgKind::Literal(lit) => lit.hash(&mut self.s),
}
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-complex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![expect(incomplete_features)]
#![feature(min_generic_const_args, adt_const_params)]

fn takes_array<const A: [u32; 3]>() {}

fn generic_caller<const X: u32, const Y: usize>() {
// not supported yet
takes_array::<{ [1, 2, 1 + 2] }>();
//~^ ERROR: complex const arguments must be placed inside of a `const` block
takes_array::<{ [X; 3] }>();
//~^ ERROR: complex const arguments must be placed inside of a `const` block
takes_array::<{ [0; Y] }>();
//~^ ERROR: complex const arguments must be placed inside of a `const` block
}

fn main() {}
20 changes: 20 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-complex.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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:19
|
LL | takes_array::<{ [X; 3] }>();
| ^^^^^^^^^^

error: complex const arguments must be placed inside of a `const` block
--> $DIR/array-expr-complex.rs:12:19
|
LL | takes_array::<{ [0; Y] }>();
| ^^^^^^^^^^

error: aborting due to 3 previous errors

9 changes: 9 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![expect(incomplete_features)]
#![feature(min_generic_const_args)]

fn takes_empty_array<const A: []>() {}
//~^ ERROR: expected type, found `]`

fn main() {
takes_empty_array::<{ [] }>();
}
8 changes: 8 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-empty.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: expected type, found `]`
--> $DIR/array-expr-empty.rs:4:32
|
LL | fn takes_empty_array<const A: []>() {}
| ^ expected type

error: aborting due to 1 previous error

25 changes: 25 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//@ run-pass
#![expect(incomplete_features)]
#![feature(min_generic_const_args, adt_const_params)]
#![allow(dead_code)]

fn takes_array_u32<const A: [u32; 3]>() {}
fn takes_array_bool<const A: [bool; 2]>() {}
fn takes_nested_array<const A: [[u32; 2]; 2]>() {}
fn takes_empty_array<const A: [u32; 0]>() {}

fn generic_caller<const X: u32, const Y: u32>() {
takes_array_u32::<{ [X, Y, X] }>();
takes_array_u32::<{ [X, Y, const { 1 }] }>();
takes_array_u32::<{ [X, Y, const { 1 + 1 }] }>();
takes_array_u32::<{ [2_002, 2u32, 1_u32] }>();

takes_array_bool::<{ [true, false] }>();

takes_nested_array::<{ [[X, Y], [3, 4]] }>();
takes_nested_array::<{ [[1u32, 2_u32], [const { 3 }, 4]] }>();

takes_empty_array::<{ [] }>();
}

fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ run-pass
#![expect(incomplete_features)]
#![feature(min_generic_const_args, adt_const_params)]
#![allow(dead_code)]

fn takes_array<const A: [u32; 3]>() {}

trait Trait {
#[type_const]
const ASSOC: u32;
}

fn generic_caller<T: Trait, const N: u32>() {
takes_array::<{ [T::ASSOC, N, T::ASSOC] }>();
takes_array::<{ [1_u32, T::ASSOC, 2] }>();
}

fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-with-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ run-pass
#![expect(incomplete_features)]
#![feature(min_generic_const_args, adt_const_params)]
#![allow(dead_code)]

macro_rules! make_array {
($n:expr, $m:expr, $p:expr) => {
[N, $m, $p]
};
}

fn takes_array<const A: [u32; 3]>() {}

fn generic_caller<const N: u32>() {
takes_array::<{ make_array!(N, 2, 3) }>();
}

fn main() {}
20 changes: 20 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-with-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//@ run-pass
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
#![allow(dead_code)]

use std::marker::ConstParamTy;

#[derive(PartialEq, Eq, ConstParamTy)]
struct Container {
values: [u32; 3],
}

fn takes_container<const C: Container>() {}

fn generic_caller<const N: u32, const M: u32>() {
takes_container::<{ Container { values: [N, M, 1] } }>();
takes_container::<{ Container { values: [1, 2, 3] } }>();
}

fn main() {}
13 changes: 13 additions & 0 deletions tests/ui/const-generics/mgca/array-expr-with-tuple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//@ run-pass
#![feature(min_generic_const_args, adt_const_params, unsized_const_params)]
#![expect(incomplete_features)]
#![allow(dead_code)]

fn takes_tuple<const T: ([u32; 2], u32, [u32; 2])>() {}

fn generic_caller<const N: u32, const M: u32>() {
takes_tuple::<{ ([N, M], 5, [M, N]) }>();
takes_tuple::<{ ([1, 2], 3, [4, 5]) }>();
}

fn main() {}
Loading