init impl
This commit is contained in:
parent
8d670b93d4
commit
05afcb6d26
24 changed files with 537 additions and 28 deletions
|
|
@ -2396,6 +2396,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
|
||||
match &expr.kind {
|
||||
ExprKind::Call(func, args) if let ExprKind::Path(qself, path) = &func.kind => {
|
||||
let qpath = self.lower_qpath(
|
||||
func.id,
|
||||
qself,
|
||||
path,
|
||||
ParamMode::Explicit,
|
||||
AllowReturnTypeNotation::No,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
let lowered_args = self.arena.alloc_from_iter(args.iter().map(|arg| {
|
||||
let const_arg = if let ExprKind::ConstBlock(anon_const) = &arg.kind {
|
||||
let def_id = self.local_def_id(anon_const.id);
|
||||
let def_kind = self.tcx.def_kind(def_id);
|
||||
assert_eq!(DefKind::AnonConst, def_kind);
|
||||
self.lower_anon_const_to_const_arg_direct(anon_const)
|
||||
} else {
|
||||
self.lower_expr_to_const_arg_direct(arg)
|
||||
};
|
||||
|
||||
&*self.arena.alloc(const_arg)
|
||||
}));
|
||||
|
||||
ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::TupleCall(qpath, lowered_args),
|
||||
}
|
||||
}
|
||||
ExprKind::Path(qself, path) => {
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
|
|
@ -2460,7 +2489,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&& let StmtKind::Expr(expr) = &stmt.kind
|
||||
&& matches!(
|
||||
expr.kind,
|
||||
ExprKind::Block(..) | ExprKind::Path(..) | ExprKind::Struct(..)
|
||||
ExprKind::Block(..)
|
||||
| ExprKind::Path(..)
|
||||
| ExprKind::Struct(..)
|
||||
| ExprKind::Call(..)
|
||||
)
|
||||
{
|
||||
return self.lower_expr_to_const_arg_direct(expr);
|
||||
|
|
|
|||
|
|
@ -499,6 +499,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {
|
|||
match self.kind {
|
||||
ConstArgKind::Struct(path, _) => path.span(),
|
||||
ConstArgKind::Path(path) => path.span(),
|
||||
ConstArgKind::TupleCall(path, _) => path.span(),
|
||||
ConstArgKind::Anon(anon) => anon.span,
|
||||
ConstArgKind::Error(span, _) => span,
|
||||
ConstArgKind::Infer(span, _) => span,
|
||||
|
|
@ -519,6 +520,8 @@ pub enum ConstArgKind<'hir, Unambig = ()> {
|
|||
Anon(&'hir AnonConst),
|
||||
/// Represents construction of struct/struct variants
|
||||
Struct(QPath<'hir>, &'hir [&'hir ConstArgExprField<'hir>]),
|
||||
/// Tuple constructor variant
|
||||
TupleCall(QPath<'hir>, &'hir [&'hir ConstArg<'hir>]),
|
||||
/// Error const
|
||||
Error(Span, ErrorGuaranteed),
|
||||
/// This variant is not always used to represent inference consts, sometimes
|
||||
|
|
|
|||
|
|
@ -1090,6 +1090,13 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
|
|||
|
||||
V::Result::output()
|
||||
}
|
||||
ConstArgKind::TupleCall(qpath, args) => {
|
||||
try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span()));
|
||||
for arg in *args {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -314,6 +314,7 @@ pub enum PermitVariants {
|
|||
enum TypeRelativePath<'tcx> {
|
||||
AssocItem(DefId, GenericArgsRef<'tcx>),
|
||||
Variant { adt: Ty<'tcx>, variant_did: DefId },
|
||||
Ctor { ctor_def_id: DefId, args: GenericArgsRef<'tcx> },
|
||||
}
|
||||
|
||||
/// New-typed boolean indicating whether explicit late-bound lifetimes
|
||||
|
|
@ -1261,6 +1262,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
TypeRelativePath::Variant { adt, variant_did } => {
|
||||
Ok((adt, DefKind::Variant, variant_did))
|
||||
}
|
||||
TypeRelativePath::Ctor { .. } => {
|
||||
let e = tcx.dcx().span_err(span, "expected type, found tuple constructor");
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1294,6 +1299,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
(def_id, args)
|
||||
}
|
||||
TypeRelativePath::Ctor { ctor_def_id, args } => {
|
||||
return Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)));
|
||||
}
|
||||
// FIXME(mgca): implement support for this once ready to support all adt ctor expressions,
|
||||
// not just const ctors
|
||||
TypeRelativePath::Variant { .. } => {
|
||||
|
|
@ -1326,6 +1334,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.iter()
|
||||
.find(|vd| tcx.hygienic_eq(segment.ident, vd.ident(tcx), adt_def.did()));
|
||||
if let Some(variant_def) = variant_def {
|
||||
// FIXME(mgca): do we want constructor resolutions to take priority over
|
||||
// other possible resolutions?
|
||||
if matches!(mode, LowerTypeRelativePathMode::Const)
|
||||
&& let Some((CtorKind::Fn, ctor_def_id)) = variant_def.ctor
|
||||
{
|
||||
tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
slice::from_ref(segment).iter(),
|
||||
GenericsArgsErrExtend::EnumVariant {
|
||||
qself: hir_self_ty,
|
||||
assoc_segment: segment,
|
||||
adt_def,
|
||||
},
|
||||
);
|
||||
let ty::Adt(_, enum_args) = self_ty.kind() else { unreachable!() };
|
||||
return Ok(TypeRelativePath::Ctor { ctor_def_id, args: enum_args });
|
||||
}
|
||||
if let PermitVariants::Yes = mode.permit_variants() {
|
||||
tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
|
|
@ -2266,12 +2291,106 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
hir::ConstArgKind::Struct(qpath, inits) => {
|
||||
self.lower_const_arg_struct(hir_id, qpath, inits, const_arg.span())
|
||||
}
|
||||
hir::ConstArgKind::TupleCall(qpath, args) => {
|
||||
self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span())
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon),
|
||||
hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span),
|
||||
hir::ConstArgKind::Error(_, e) => ty::Const::new_error(tcx, e),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_const_arg_tuple_call(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
qpath: hir::QPath<'tcx>,
|
||||
args: &'tcx [&'tcx hir::ConstArg<'tcx>],
|
||||
span: Span,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let non_adt_or_variant_res = || {
|
||||
let e = tcx.dcx().span_err(span, "tuple constructor with invalid base path");
|
||||
ty::Const::new_error(tcx, e)
|
||||
};
|
||||
|
||||
let ctor_const = match qpath {
|
||||
hir::QPath::Resolved(maybe_qself, path) => {
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
||||
self.lower_resolved_const_path(opt_self_ty, path, hir_id)
|
||||
}
|
||||
hir::QPath::TypeRelative(hir_self_ty, segment) => {
|
||||
let self_ty = self.lower_ty(hir_self_ty);
|
||||
match self.lower_type_relative_const_path(
|
||||
self_ty,
|
||||
hir_self_ty,
|
||||
segment,
|
||||
hir_id,
|
||||
span,
|
||||
) {
|
||||
Ok(c) => c,
|
||||
Err(_) => return non_adt_or_variant_res(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let Some(value) = ctor_const.try_to_value() else {
|
||||
return non_adt_or_variant_res();
|
||||
};
|
||||
|
||||
let (adt_def, adt_args, variant_did) = match value.ty.kind() {
|
||||
ty::FnDef(def_id, fn_args)
|
||||
if let DefKind::Ctor(CtorOf::Variant, _) = tcx.def_kind(*def_id) =>
|
||||
{
|
||||
let parent_did = tcx.parent(*def_id);
|
||||
let enum_did = tcx.parent(parent_did);
|
||||
(tcx.adt_def(enum_did), fn_args, parent_did)
|
||||
}
|
||||
ty::FnDef(def_id, fn_args)
|
||||
if let DefKind::Ctor(CtorOf::Struct, _) = tcx.def_kind(*def_id) =>
|
||||
{
|
||||
let parent_did = tcx.parent(*def_id);
|
||||
(tcx.adt_def(parent_did), fn_args, parent_did)
|
||||
}
|
||||
_ => return non_adt_or_variant_res(),
|
||||
};
|
||||
|
||||
let variant_def = adt_def.variant_with_id(variant_did);
|
||||
let variant_idx = adt_def.variant_index_with_id(variant_did).as_u32();
|
||||
|
||||
if args.len() != variant_def.fields.len() {
|
||||
let e = tcx.dcx().span_err(
|
||||
span,
|
||||
format!(
|
||||
"tuple constructor has {} arguments but {} were provided",
|
||||
variant_def.fields.len(),
|
||||
args.len()
|
||||
),
|
||||
);
|
||||
return ty::Const::new_error(tcx, e);
|
||||
}
|
||||
|
||||
let fields = variant_def
|
||||
.fields
|
||||
.iter()
|
||||
.zip(args)
|
||||
.map(|(field_def, arg)| {
|
||||
self.lower_const_arg(arg, FeedConstTy::Param(field_def.did, adt_args))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let opt_discr_const = if adt_def.is_enum() {
|
||||
let valtree = ty::ValTree::from_scalar_int(tcx, variant_idx.into());
|
||||
Some(ty::Const::new_value(tcx, valtree, tcx.types.u32))
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
|
||||
fn lower_const_arg_struct(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
|
|
@ -2403,6 +2522,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let args = self.lower_generic_args_of_path_segment(span, did, segment);
|
||||
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
|
||||
}
|
||||
Res::Def(DefKind::Ctor(_, CtorKind::Fn), did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self
|
||||
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
let parent_did = tcx.parent(did);
|
||||
let generics_did = if let DefKind::Ctor(CtorOf::Variant, _) = tcx.def_kind(did) {
|
||||
tcx.parent(parent_did)
|
||||
} else {
|
||||
parent_did
|
||||
};
|
||||
let args = self.lower_generic_args_of_path_segment(span, generics_did, segment);
|
||||
ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
|
||||
}
|
||||
Res::Def(DefKind::AssocConst, did) => {
|
||||
let trait_segment = if let [modules @ .., trait_, _item] = path.segments {
|
||||
let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None);
|
||||
|
|
@ -2438,9 +2571,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
DefKind::Mod
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Ctor(CtorOf::Variant, CtorKind::Fn)
|
||||
| DefKind::Struct
|
||||
| DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::TyAlias
|
||||
| DefKind::TraitAlias
|
||||
|
|
|
|||
|
|
@ -1139,6 +1139,7 @@ impl<'a> State<'a> {
|
|||
match &const_arg.kind {
|
||||
// FIXME(mgca): proper printing for struct exprs
|
||||
ConstArgKind::Struct(..) => self.word("/* STRUCT EXPR */"),
|
||||
ConstArgKind::TupleCall(..) => self.word("/* TUPLE CALL */"),
|
||||
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
|
||||
ConstArgKind::Anon(anon) => self.print_anon_const(anon),
|
||||
ConstArgKind::Error(_, _) => self.word("/*ERROR*/"),
|
||||
|
|
|
|||
|
|
@ -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::TupleCall(..)
|
||||
| hir::ConstArgKind::Path(..)
|
||||
| hir::ConstArgKind::Infer(..) => true,
|
||||
hir::ConstArgKind::Anon(..) => false,
|
||||
|
|
|
|||
|
|
@ -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(_) => return visit::walk_expr(self, expr),
|
||||
ExprKind::Struct(_) | ExprKind::Call(..) => return visit::walk_expr(self, expr),
|
||||
// FIXME(mgca): we may want to handle block labels in some manner
|
||||
ExprKind::Block(block, _) if let [stmt] = block.stmts.as_slice() => match stmt.kind {
|
||||
// FIXME(mgca): this probably means that mac calls that expand
|
||||
|
|
|
|||
|
|
@ -323,6 +323,9 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind
|
|||
// FIXME(mgca): proper printing :3
|
||||
ConstantKind::Path { path: "/* STRUCT EXPR */".to_string().into() }
|
||||
}
|
||||
hir::ConstArgKind::TupleCall(..) => {
|
||||
ConstantKind::Path { path: "/* TUPLE CALL */".to_string().into() }
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
|
||||
hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer,
|
||||
}
|
||||
|
|
@ -1804,7 +1807,9 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||
let ct = cx.tcx.normalize_erasing_regions(typing_env, ct);
|
||||
print_const(cx, ct)
|
||||
}
|
||||
hir::ConstArgKind::Struct(..) | hir::ConstArgKind::Path(..) => {
|
||||
hir::ConstArgKind::Struct(..)
|
||||
| hir::ConstArgKind::Path(..)
|
||||
| hir::ConstArgKind::TupleCall(..) => {
|
||||
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
|
||||
print_const(cx, ct)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
self.body(field!(anon_const.body));
|
||||
},
|
||||
ConstArgKind::Struct(..) => chain!(self, "let ConstArgKind::Struct(..) = {const_arg}.kind"),
|
||||
ConstArgKind::TupleCall(..) => chain!(self, "let ConstArgKind::TupleCall(..) = {const_arg}.kind"),
|
||||
ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"),
|
||||
ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1140,7 +1140,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx
|
|||
ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value),
|
||||
ConstItemRhs::TypeConst(const_arg) => match const_arg.kind {
|
||||
ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value),
|
||||
ConstArgKind::Struct(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => {
|
||||
ConstArgKind::Struct(..) | ConstArgKind::TupleCall(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => {
|
||||
None
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -671,11 +671,19 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
.iter()
|
||||
.zip(*inits_b)
|
||||
.all(|(init_a, init_b)| self.eq_const_arg(init_a.expr, init_b.expr))
|
||||
},
|
||||
}
|
||||
(ConstArgKind::TupleCall(path_a, args_a), ConstArgKind::TupleCall(path_b, args_b)) => {
|
||||
self.eq_qpath(path_a, path_b)
|
||||
&& args_a
|
||||
.iter()
|
||||
.zip(*args_b)
|
||||
.all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b))
|
||||
}
|
||||
// Use explicit match for now since ConstArg is undergoing flux.
|
||||
(
|
||||
ConstArgKind::Path(..)
|
||||
| ConstArgKind::Anon(..)
|
||||
| ConstArgKind::TupleCall(..)
|
||||
| ConstArgKind::Infer(..)
|
||||
| ConstArgKind::Struct(..)
|
||||
| ConstArgKind::Error(..),
|
||||
|
|
@ -1546,6 +1554,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
self.hash_const_arg(init.expr);
|
||||
}
|
||||
},
|
||||
ConstArgKind::TupleCall(path, args) => {
|
||||
self.hash_qpath(path);
|
||||
for arg in *args {
|
||||
self.hash_const_arg(arg);
|
||||
}
|
||||
},
|
||||
ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
//@ known-bug: #136379
|
||||
#![feature(min_generic_const_args)]
|
||||
pub struct S();
|
||||
|
||||
impl S {
|
||||
pub fn f() -> [u8; S] {
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
//@ known-bug: #138132
|
||||
#![feature(min_generic_const_args)]
|
||||
struct b(Box<[u8; c]>);
|
||||
impl b {
|
||||
fn d(self) {
|
||||
self.0.e()
|
||||
}
|
||||
}
|
||||
struct c<'a>(&'a u8);
|
||||
fn main() {}
|
||||
52
tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs
Normal file
52
tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//@ run-pass
|
||||
#![feature(min_generic_const_args, adt_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ConstParamTy)]
|
||||
struct Point(u32, u32);
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ConstParamTy)]
|
||||
enum MyEnum<T> {
|
||||
Variant(T),
|
||||
Other,
|
||||
}
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: u32;
|
||||
}
|
||||
|
||||
fn with_point<const P: Point>() -> Point {
|
||||
P
|
||||
}
|
||||
|
||||
fn with_enum<const E: MyEnum<u32>>() -> MyEnum<u32> {
|
||||
E
|
||||
}
|
||||
|
||||
fn test<T: Trait, const N: u32>() {
|
||||
with_point::<{ Point(<T as Trait>::ASSOC, N) }>();
|
||||
}
|
||||
|
||||
fn test_basic<const N: u32>() {
|
||||
with_point::<{ Point(N, N) }>();
|
||||
with_point::<{ Point(const { 5 }, const { 10 }) }>();
|
||||
|
||||
with_enum::<{ MyEnum::Variant::<u32>(N) }>();
|
||||
with_enum::<{ MyEnum::Variant::<u32>(const { 42 }) }>();
|
||||
|
||||
with_enum::<{ <MyEnum<u32>>::Variant(N) }>();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_basic::<5>();
|
||||
|
||||
let p = with_point::<{ Point(const { 1 }, const { 2 }) }>();
|
||||
assert_eq!(p, Point(1, 2));
|
||||
|
||||
let e = with_enum::<{ MyEnum::Variant::<u32>(const { 10 }) }>();
|
||||
assert_eq!(e, MyEnum::Variant(10));
|
||||
}
|
||||
19
tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs
Normal file
19
tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#![feature(min_generic_const_args, adt_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||
struct Point(u32, u32);
|
||||
|
||||
fn with_point<const P: Point>() {}
|
||||
|
||||
fn test<const N: u32>() {
|
||||
with_point::<{ Point(N + 1, N) }>();
|
||||
//~^ ERROR complex const arguments must be placed inside of a `const` block
|
||||
|
||||
with_point::<{ Point(const { N + 1 }, N) }>();
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
14
tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr
Normal file
14
tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/tuple_ctor_complex_args.rs:12:26
|
||||
|
|
||||
LL | with_point::<{ Point(N + 1, N) }>();
|
||||
| ^^^^^
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/tuple_ctor_complex_args.rs:15:34
|
||||
|
|
||||
LL | with_point::<{ Point(const { N + 1 }, N) }>();
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
46
tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs
Normal file
46
tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#![feature(min_generic_const_args, adt_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||
struct Point(u32, u32);
|
||||
|
||||
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||
enum MyEnum<T> {
|
||||
Variant(T),
|
||||
Unit,
|
||||
}
|
||||
|
||||
const CONST_ITEM: u32 = 42;
|
||||
|
||||
fn accepts_point<const P: Point>() {}
|
||||
fn accepts_enum<const E: MyEnum<u32>>() {}
|
||||
|
||||
fn non_ctor() {}
|
||||
|
||||
fn test_errors<const N: usize>() {
|
||||
accepts_point::<{ Point(N) }>();
|
||||
//~^ ERROR tuple constructor has 2 arguments but 1 were provided
|
||||
|
||||
accepts_point::<{ Point(N, N, N) }>();
|
||||
//~^ ERROR tuple constructor has 2 arguments but 3 were provided
|
||||
|
||||
accepts_point::<{ UnresolvedIdent(N, N) }>();
|
||||
//~^ ERROR cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope
|
||||
//~| ERROR tuple constructor with invalid base path
|
||||
|
||||
accepts_point::<{ non_ctor(N, N) }>();
|
||||
//~^ ERROR tuple constructor with invalid base path
|
||||
|
||||
accepts_point::<{ CONST_ITEM(N, N) }>();
|
||||
//~^ ERROR tuple constructor with invalid base path
|
||||
|
||||
accepts_point::<{ Point }>();
|
||||
//~^ ERROR the constant `Point` is not of type `Point`
|
||||
|
||||
accepts_enum::<{ MyEnum::Variant::<u32> }>();
|
||||
//~^ ERROR the constant `MyEnum::<u32>::Variant` is not of type `MyEnum<u32>`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
68
tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr
Normal file
68
tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope
|
||||
--> $DIR/tuple_ctor_erroneous.rs:29:23
|
||||
|
|
||||
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^^ not found in this scope
|
||||
|
|
||||
help: you might be missing a const parameter
|
||||
|
|
||||
LL | fn test_errors<const N: usize, const UnresolvedIdent: /* Type */>() {
|
||||
| +++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: tuple constructor has 2 arguments but 1 were provided
|
||||
--> $DIR/tuple_ctor_erroneous.rs:23:23
|
||||
|
|
||||
LL | accepts_point::<{ Point(N) }>();
|
||||
| ^^^^^
|
||||
|
||||
error: tuple constructor has 2 arguments but 3 were provided
|
||||
--> $DIR/tuple_ctor_erroneous.rs:26:23
|
||||
|
|
||||
LL | accepts_point::<{ Point(N, N, N) }>();
|
||||
| ^^^^^
|
||||
|
||||
error: tuple constructor with invalid base path
|
||||
--> $DIR/tuple_ctor_erroneous.rs:29:23
|
||||
|
|
||||
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: tuple constructor with invalid base path
|
||||
--> $DIR/tuple_ctor_erroneous.rs:33:23
|
||||
|
|
||||
LL | accepts_point::<{ non_ctor(N, N) }>();
|
||||
| ^^^^^^^^
|
||||
|
||||
error: tuple constructor with invalid base path
|
||||
--> $DIR/tuple_ctor_erroneous.rs:36:23
|
||||
|
|
||||
LL | accepts_point::<{ CONST_ITEM(N, N) }>();
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: the constant `Point` is not of type `Point`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:39:23
|
||||
|
|
||||
LL | accepts_point::<{ Point }>();
|
||||
| ^^^^^ expected `Point`, found struct constructor
|
||||
|
|
||||
note: required by a const generic parameter in `accepts_point`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:17:18
|
||||
|
|
||||
LL | fn accepts_point<const P: Point>() {}
|
||||
| ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point`
|
||||
|
||||
error: the constant `MyEnum::<u32>::Variant` is not of type `MyEnum<u32>`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:42:22
|
||||
|
|
||||
LL | accepts_enum::<{ MyEnum::Variant::<u32> }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum<u32>`, found enum constructor
|
||||
|
|
||||
note: required by a const generic parameter in `accepts_enum`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:18:17
|
||||
|
|
||||
LL | fn accepts_enum<const E: MyEnum<u32>>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
16
tests/ui/const-generics/mgca/tuple_ctor_in_array_len.rs
Normal file
16
tests/ui/const-generics/mgca/tuple_ctor_in_array_len.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! Regression test for <https://github.com/rust-lang/rust/issues/136379>
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
pub struct S();
|
||||
|
||||
impl S {
|
||||
pub fn f() -> [u8; S] {
|
||||
//~^ ERROR the constant `S` is not of type `usize`
|
||||
[]
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
23
tests/ui/const-generics/mgca/tuple_ctor_in_array_len.stderr
Normal file
23
tests/ui/const-generics/mgca/tuple_ctor_in_array_len.stderr
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
error: the constant `S` is not of type `usize`
|
||||
--> $DIR/tuple_ctor_in_array_len.rs:9:19
|
||||
|
|
||||
LL | pub fn f() -> [u8; S] {
|
||||
| ^^^^^^^ expected `usize`, found struct constructor
|
||||
|
|
||||
= note: the length of array `[u8; S]` must be type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/tuple_ctor_in_array_len.rs:11:9
|
||||
|
|
||||
LL | pub fn f() -> [u8; S] {
|
||||
| ------- expected `[u8; S]` because of return type
|
||||
LL |
|
||||
LL | []
|
||||
| ^^ expected an array with a size of S, found one with a size of 0
|
||||
|
|
||||
= note: expected array `[u8; S]`
|
||||
found array `[_; 0]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
38
tests/ui/const-generics/mgca/tuple_ctor_nested.rs
Normal file
38
tests/ui/const-generics/mgca/tuple_ctor_nested.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//@ run-pass
|
||||
#![feature(min_generic_const_args, adt_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ConstParamTy)]
|
||||
struct Inner(u32);
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ConstParamTy)]
|
||||
struct Outer(Inner);
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ConstParamTy)]
|
||||
enum Container<T> {
|
||||
Wrap(T),
|
||||
}
|
||||
|
||||
fn with_outer<const O: Outer>() -> Outer {
|
||||
O
|
||||
}
|
||||
|
||||
fn with_container<const C: Container<Inner>>() -> Container<Inner> {
|
||||
C
|
||||
}
|
||||
|
||||
fn test<const N: u32>() {
|
||||
with_outer::<{ Outer(Inner(N)) }>();
|
||||
with_outer::<{ Outer(Inner(const { 42 })) }>();
|
||||
|
||||
with_container::<{ Container::Wrap::<Inner>(Inner(N)) }>();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test::<5>();
|
||||
|
||||
let o = with_outer::<{ Outer(Inner(const { 10 })) }>();
|
||||
assert_eq!(o, Outer(Inner(10)));
|
||||
}
|
||||
26
tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs
Normal file
26
tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//@ run-pass
|
||||
#![feature(min_generic_const_args, adt_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ConstParamTy)]
|
||||
enum Option<T> {
|
||||
Some(T),
|
||||
}
|
||||
|
||||
fn with_option<const O: Option<u32>>() -> Option<u32> {
|
||||
O
|
||||
}
|
||||
|
||||
fn test<const N: u32>() {
|
||||
with_option::<{ <Option<u32>>::Some(N) }>();
|
||||
with_option::<{ <Option<u32>>::Some(const { 42 }) }>();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test::<5>();
|
||||
|
||||
let o = with_option::<{ <Option<u32>>::Some(const { 10 }) }>();
|
||||
assert_eq!(o, Option::Some(10));
|
||||
}
|
||||
14
tests/ui/const-generics/mgca/type_as_const_in_array_len.rs
Normal file
14
tests/ui/const-generics/mgca/type_as_const_in_array_len.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
//! Regression test for <https://github.com/rust-lang/rust/issues/138132>
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
struct B(Box<[u8; C]>);
|
||||
//~^ ERROR missing generics for struct `C`
|
||||
impl B {
|
||||
fn d(self) {
|
||||
self.0.e()
|
||||
}
|
||||
}
|
||||
struct C<'a>(&'a u8);
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
error[E0107]: missing generics for struct `C`
|
||||
--> $DIR/type_as_const_in_array_len.rs:6:19
|
||||
|
|
||||
LL | struct B(Box<[u8; C]>);
|
||||
| ^ expected 1 lifetime argument
|
||||
|
|
||||
note: struct defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/type_as_const_in_array_len.rs:13:8
|
||||
|
|
||||
LL | struct C<'a>(&'a u8);
|
||||
| ^ --
|
||||
help: add missing lifetime argument
|
||||
|
|
||||
LL | struct B(Box<[u8; C<'a>]>);
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue