Introduce feature(generic_const_parameter_types)

This commit is contained in:
Boxy 2025-02-25 00:06:38 +00:00
parent 60493b8973
commit df5b279ca9
56 changed files with 419 additions and 154 deletions

View File

@ -508,6 +508,8 @@ declare_features! (
(incomplete, generic_const_exprs, "1.56.0", Some(76560)),
/// Allows generic parameters and where-clauses on free & associated const items.
(incomplete, generic_const_items, "1.73.0", Some(113521)),
/// Allows the type of const generics to depend on generic parameters
(incomplete, generic_const_parameter_types, "CURRENT_RUSTC_VERSION", Some(137626)),
/// Allows any generic constants being used as pattern type range ends
(incomplete, generic_pattern_types, "1.86.0", Some(136574)),
/// Allows registering static items globally, possibly across crates, to iterate over at runtime.

View File

@ -966,7 +966,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
let ty = tcx.type_of(param.def_id).instantiate_identity();
if tcx.features().unsized_const_params() {
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
wfcx.register_bound(
ObligationCause::new(
hir_ty.span,
@ -980,7 +980,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
Ok(())
})
} else if tcx.features().adt_const_params() {
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
wfcx.register_bound(
ObligationCause::new(
hir_ty.span,

View File

@ -1822,6 +1822,9 @@ fn const_param_default<'tcx>(
),
};
let icx = ItemCtxt::new(tcx, def_id);
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id()));
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let ct = icx
.lowerer()
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
ty::EarlyBinder::bind(ct)
}

View File

@ -223,10 +223,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
hir::GenericParamKind::Const { .. } => {
let param_def_id = param.def_id.to_def_id();
let ct_ty = tcx
.type_of(param_def_id)
.no_bound_vars()
.expect("const parameters cannot be generic");
let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
predicates
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));

View File

@ -273,7 +273,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
// We lower to an infer even when the feature gate is not enabled
// as it is useful for diagnostics to be able to see a `ConstKind::Infer`
args.push(ctx.provided_kind(param, arg));
args.push(ctx.provided_kind(&args, param, arg));
args_iter.next();
params.next();
}

View File

@ -232,12 +232,15 @@ impl AssocItemQSelf {
/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
/// desired behavior.
#[derive(Debug, Clone, Copy)]
pub enum FeedConstTy {
pub enum FeedConstTy<'a, 'tcx> {
/// Feed the type.
///
/// The `DefId` belongs to the const param that we are supplying
/// this (anon) const arg to.
Param(DefId),
///
/// The list of generic args is used to instantiate the parameters
/// used by the type of the const param specified by `DefId`.
Param(DefId, &'a [ty::GenericArg<'tcx>]),
/// Don't feed the type.
No,
}
@ -298,6 +301,7 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
fn provided_kind(
&mut self,
preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx>;
@ -481,6 +485,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
fn provided_kind(
&mut self,
preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
@ -526,7 +531,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
.lowerer
// Ambig portions of `ConstArg` are handled in the match arm below
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
.lower_const_arg(
ct.as_unambig_ct(),
FeedConstTy::Param(param.def_id, preceding_args),
)
.into(),
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.lowerer.ct_infer(Some(param), inf.span).into()
@ -582,8 +590,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let ty = tcx
.at(self.span)
.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
.instantiate(tcx, preceding_args);
if let Err(guar) = ty.error_reported() {
return ty::Const::new_error(tcx, guar).into();
}
@ -2107,14 +2114,50 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
pub fn lower_const_arg(
&self,
const_arg: &hir::ConstArg<'tcx>,
feed: FeedConstTy,
feed: FeedConstTy<'_, 'tcx>,
) -> Const<'tcx> {
let tcx = self.tcx();
if let FeedConstTy::Param(param_def_id) = feed
if let FeedConstTy::Param(param_def_id, args) = feed
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
{
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
// We must error if the instantiated type has any inference variables as we will
// use this type to feed the `type_of` and query results must not contain inference
// variables otherwise we will ICE.
//
// We also error if the type contains any regions as effectively any region will wind
// up as a region variable in mir borrowck. It would also be somewhat concerning if
// hir typeck was using equality but mir borrowck wound up using subtyping as that could
// result in a non-infer in hir typeck but a region variable in borrowck.
//
// FIXME(generic_const_parameter_types): Ideally we remove these errors one day when
// we have the ability to intermix typeck of anon const const args with the parent
// bodies typeck.
if tcx.features().generic_const_parameter_types()
&& (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions())
{
let e = tcx.dcx().span_err(
const_arg.span(),
"anonymous constants with lifetimes in their type are not yet supported",
);
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
return ty::Const::new_error(tcx, e);
}
if anon_const_type.has_non_region_infer() {
let e = tcx.dcx().span_err(
const_arg.span(),
"anonymous constants with inferred types are not yet supported",
);
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
return ty::Const::new_error(tcx, e);
}
tcx.feed_anon_const_type(
anon.def_id,
ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)),
);
}
let hir_id = const_arg.hir_id;
@ -2230,10 +2273,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let expr = &tcx.hir_body(anon.body).value;
debug!(?expr);
let ty = tcx
.type_of(anon.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
// FIXME(generic_const_parameter_types): We should use the proper generic args
// here. It's only used as a hint for literals so doesn't matter too much to use the right
// generic arguments, just weaker type inference.
let ty = tcx.type_of(anon.def_id).instantiate_identity();
match self.try_lower_anon_const_lit(ty, expr) {
Some(v) => v,

View File

@ -260,7 +260,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
pub fn lower_const_arg_for_rustdoc<'tcx>(
tcx: TyCtxt<'tcx>,
hir_ct: &hir::ConstArg<'tcx>,
feed: FeedConstTy,
feed: FeedConstTy<'_, 'tcx>,
) -> Const<'tcx> {
let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)

View File

@ -519,7 +519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn lower_const_arg(
&self,
const_arg: &'tcx hir::ConstArg<'tcx>,
feed: FeedConstTy,
feed: FeedConstTy<'_, 'tcx>,
) -> ty::Const<'tcx> {
let ct = self.lowerer().lower_const_arg(const_arg, feed);
self.register_wf_obligation(
@ -1135,7 +1135,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.last()
.is_some_and(|GenericPathSegment(def_id, _)| tcx.generics_of(*def_id).has_self);
let (res, self_ctor_args) = if let Res::SelfCtor(impl_def_id) = res {
let (res, implicit_args) = if let Res::Def(DefKind::ConstParam, def) = res {
// types of const parameters are somewhat special as they are part of
// the same environment as the const parameter itself. this means that
// unlike most paths `type-of(N)` can return a type naming parameters
// introduced by the containing item, rather than provided through `N`.
//
// for example given `<T, const M: usize, const N: [T; M]>` and some
// `let a = N;` expression. The path to `N` would wind up with no args
// (as it has no args), but instantiating the early binder on `typeof(N)`
// requires providing generic arguments for `[T, M, N]`.
(res, Some(ty::GenericArgs::identity_for_item(tcx, tcx.parent(def))))
} else if let Res::SelfCtor(impl_def_id) = res {
let ty = LoweredTy::from_raw(
self,
span,
@ -1261,6 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn provided_kind(
&mut self,
preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
@ -1280,7 +1292,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
.fcx
// Ambiguous parts of `ConstArg` are handled in the match arms below
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
.lower_const_arg(
ct.as_unambig_ct(),
FeedConstTy::Param(param.def_id, preceding_args),
)
.into(),
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.fcx.ct_infer(Some(param), inf.span).into()
@ -1320,7 +1335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let args_raw = self_ctor_args.unwrap_or_else(|| {
let args_raw = implicit_args.unwrap_or_else(|| {
lower_generic_args(
self,
def_id,

View File

@ -426,6 +426,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
fn provided_kind(
&mut self,
preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
@ -446,7 +447,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
.cfcx
// We handle the ambig portions of `ConstArg` in the match arms below
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
.lower_const_arg(
ct.as_unambig_ct(),
FeedConstTy::Param(param.def_id, preceding_args),
)
.into(),
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.cfcx.ct_infer(Some(param), inf.span).into()

View File

@ -342,6 +342,7 @@ impl ParamConst {
ParamConst::new(def.index, def.name)
}
#[instrument(level = "debug")]
pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
// `ConstArgHasType` are never desugared to be higher ranked.

View File

@ -125,9 +125,6 @@ resolve_const_param_in_enum_discriminant =
resolve_const_param_in_non_trivial_anon_const =
const parameters may only be used as standalone arguments, i.e. `{$name}`
resolve_const_param_in_ty_of_const_param =
const parameters may not be used in the type of const parameters
resolve_constructor_private_if_any_field_private =
a constructor is private if any of the fields is private
@ -250,9 +247,6 @@ resolve_lifetime_param_in_enum_discriminant =
resolve_lifetime_param_in_non_trivial_anon_const =
lifetime parameters may not be used in const expressions
resolve_lifetime_param_in_ty_of_const_param =
lifetime parameters may not be used in the type of const parameters
resolve_lowercase_self =
attempt to use a non-constant value in a constant
.suggestion = try using `Self`
@ -437,9 +431,6 @@ resolve_type_param_in_enum_discriminant =
resolve_type_param_in_non_trivial_anon_const =
type parameters may not be used in const expressions
resolve_type_param_in_ty_of_const_param =
type parameters may not be used in the type of const parameters
resolve_undeclared_label =
use of undeclared label `{$name}`
.label = undeclared label `{$name}`

View File

@ -890,9 +890,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ResolutionError::ForwardDeclaredGenericParam => {
self.dcx().create_err(errs::ForwardDeclaredGenericParam { span })
}
ResolutionError::ParamInTyOfConstParam { name, param_kind: is_type } => self
.dcx()
.create_err(errs::ParamInTyOfConstParam { span, name, param_kind: is_type }),
ResolutionError::ParamInTyOfConstParam { name } => {
self.dcx().create_err(errs::ParamInTyOfConstParam { span, name })
}
ResolutionError::ParamInNonTrivialAnonConst { name, param_kind: is_type } => {
self.dcx().create_err(errs::ParamInNonTrivialAnonConst {
span,

View File

@ -347,19 +347,6 @@ pub(crate) struct ParamInTyOfConstParam {
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) param_kind: Option<ParamKindInTyOfConstParam>,
}
#[derive(Debug)]
#[derive(Subdiagnostic)]
pub(crate) enum ParamKindInTyOfConstParam {
#[note(resolve_type_param_in_ty_of_const_param)]
Type,
#[note(resolve_const_param_in_ty_of_const_param)]
Const,
#[note(resolve_lifetime_param_in_ty_of_const_param)]
Lifetime,
}
#[derive(Diagnostic)]

View File

@ -1131,6 +1131,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return Res::Err;
}
if let RibKind::ConstParamTy = all_ribs[rib_index].kind {
if let Some(span) = finalize {
self.report_error(
span,
ResolutionError::ParamInTyOfConstParam { name: rib_ident.name },
);
}
assert_eq!(res, Res::Err);
return Res::Err;
}
match res {
Res::Local(_) => {
use ResolutionError::*;
@ -1209,10 +1220,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if let Some(span) = finalize {
self.report_error(
span,
ParamInTyOfConstParam {
name: rib_ident.name,
param_kind: None,
},
ParamInTyOfConstParam { name: rib_ident.name },
);
}
return Res::Err;
@ -1239,6 +1247,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
| RibKind::MacroDefinition(..)
| RibKind::InlineAsmSym
| RibKind::AssocItem
| RibKind::ConstParamTy
| RibKind::ForwardGenericParamBan => {
// Nothing to do. Continue.
continue;
@ -1292,18 +1301,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
RibKind::Item(has_generic_params, def_kind) => {
(has_generic_params, def_kind)
}
RibKind::ConstParamTy => {
if let Some(span) = finalize {
self.report_error(
span,
ResolutionError::ParamInTyOfConstParam {
name: rib_ident.name,
param_kind: Some(errors::ParamKindInTyOfConstParam::Type),
},
);
}
return Res::Err;
}
};
if let Some(span) = finalize {
@ -1328,6 +1325,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
| RibKind::MacroDefinition(..)
| RibKind::InlineAsmSym
| RibKind::AssocItem
| RibKind::ConstParamTy
| RibKind::ForwardGenericParamBan => continue,
RibKind::ConstantItem(trivial, _) => {
@ -1361,18 +1359,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
RibKind::Item(has_generic_params, def_kind) => {
(has_generic_params, def_kind)
}
RibKind::ConstParamTy => {
if let Some(span) = finalize {
self.report_error(
span,
ResolutionError::ParamInTyOfConstParam {
name: rib_ident.name,
param_kind: Some(errors::ParamKindInTyOfConstParam::Const),
},
);
}
return Res::Err;
}
};
// This was an attempt to use a const parameter outside its scope.

View File

@ -227,9 +227,11 @@ impl RibKind<'_> {
| RibKind::ConstantItem(..)
| RibKind::Module(_)
| RibKind::MacroDefinition(_)
| RibKind::ConstParamTy
| RibKind::InlineAsmSym => false,
RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true,
RibKind::ConstParamTy
| RibKind::AssocItem
| RibKind::Item(..)
| RibKind::ForwardGenericParamBan => true,
}
}
@ -1570,6 +1572,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
}
let mut forward_ty_ban_rib_const_param_ty = Rib {
bindings: forward_ty_ban_rib.bindings.clone(),
patterns_with_skipped_bindings: FxHashMap::default(),
kind: RibKind::ConstParamTy,
};
let mut forward_const_ban_rib_const_param_ty = Rib {
bindings: forward_const_ban_rib.bindings.clone(),
patterns_with_skipped_bindings: FxHashMap::default(),
kind: RibKind::ConstParamTy,
};
self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
for param in params {
match param.kind {
@ -1592,21 +1605,27 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
// Allow all following defaults to refer to this type parameter.
forward_ty_ban_rib
.bindings
.remove(&Ident::with_dummy_span(param.ident.name));
let i = &Ident::with_dummy_span(param.ident.name);
forward_ty_ban_rib.bindings.remove(i);
if this.r.tcx.features().generic_const_parameter_types() {
forward_ty_ban_rib_const_param_ty.bindings.remove(i);
}
}
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
// Const parameters can't have param bounds.
assert!(param.bounds.is_empty());
this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
this.ribs[TypeNS].push(forward_ty_ban_rib_const_param_ty);
this.ribs[ValueNS].push(forward_const_ban_rib_const_param_ty);
if this.r.tcx.features().generic_const_parameter_types() {
this.visit_ty(ty)
});
this.ribs[TypeNS].pop().unwrap();
this.ribs[ValueNS].pop().unwrap();
} else {
this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
this.visit_ty(ty)
});
}
forward_const_ban_rib_const_param_ty = this.ribs[ValueNS].pop().unwrap();
forward_ty_ban_rib_const_param_ty = this.ribs[TypeNS].pop().unwrap();
if let Some(expr) = default {
this.ribs[TypeNS].push(forward_ty_ban_rib);
@ -1620,9 +1639,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
// Allow all following defaults to refer to this const parameter.
forward_const_ban_rib
.bindings
.remove(&Ident::with_dummy_span(param.ident.name));
let i = &Ident::with_dummy_span(param.ident.name);
forward_const_ban_rib.bindings.remove(i);
if this.r.tcx.features().generic_const_parameter_types() {
forward_const_ban_rib_const_param_ty.bindings.remove(i);
}
}
}
}

View File

@ -3052,7 +3052,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
.create_err(errors::ParamInTyOfConstParam {
span: lifetime_ref.ident.span,
name: lifetime_ref.ident.name,
param_kind: Some(errors::ParamKindInTyOfConstParam::Lifetime),
})
.emit();
}

View File

@ -30,9 +30,7 @@ use std::sync::Arc;
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use effective_visibilities::EffectiveVisibilitiesVisitor;
use errors::{
ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam,
};
use errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use imports::{Import, ImportData, ImportKind, NameResolution};
use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
@ -276,8 +274,10 @@ enum ResolutionError<'ra> {
},
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
ForwardDeclaredGenericParam,
// FIXME(generic_const_parameter_types): This should give custom output specifying it's only
// problematic to use *forward declared* parameters when the feature is enabled.
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
ParamInTyOfConstParam { name: Symbol, param_kind: Option<ParamKindInTyOfConstParam> },
ParamInTyOfConstParam { name: Symbol },
/// generic parameters must not be used inside const evaluations.
///
/// This error is only emitted when using `min_const_generics`.

View File

@ -1037,6 +1037,7 @@ symbols! {
generic_associated_types_extended,
generic_const_exprs,
generic_const_items,
generic_const_parameter_types,
generic_param_attrs,
generic_pattern_types,
get_context,

View File

@ -1189,9 +1189,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let span = obligation.cause.span;
let mut diag = match ty.kind() {
_ if ty.has_param() => {
span_bug!(span, "const param tys cannot mention other generic parameters");
}
ty::Float(_) => {
struct_span_code_err!(
self.dcx(),

View File

@ -3,16 +3,12 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
| ^ the type must not depend on the parameter `N`
|
= note: const parameters may not be used in the type of const parameters
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/const-param-type-depends-on-const-param.rs:15:40
|
LL | pub struct SelfDependent<const N: [u8; N]>;
| ^ the type must not depend on the parameter `N`
|
= note: const parameters may not be used in the type of const parameters
error: aborting due to 2 previous errors

View File

@ -3,16 +3,12 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
| ^ the type must not depend on the parameter `N`
|
= note: const parameters may not be used in the type of const parameters
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/const-param-type-depends-on-const-param.rs:15:40
|
LL | pub struct SelfDependent<const N: [u8; N]>;
| ^ the type must not depend on the parameter `N`
|
= note: const parameters may not be used in the type of const parameters
error: `[u8; N]` is forbidden as the type of a const generic parameter
--> $DIR/const-param-type-depends-on-const-param.rs:11:47

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub struct Dependent<T, const X: T>([(); X]);
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error[E0392]: type parameter `T` is never used
--> $DIR/const-param-type-depends-on-type-param.rs:11:22

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub struct Dependent<T, const X: T>([(); X]);
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error[E0392]: type parameter `T` is never used
--> $DIR/const-param-type-depends-on-type-param.rs:11:22

View File

@ -0,0 +1,23 @@
#![feature(
adt_const_params,
unsized_const_params,
generic_const_parameter_types,
generic_arg_infer
)]
#![allow(incomplete_features)]
use std::marker::ConstParamTy_;
fn foo<T: ConstParamTy_, const N: usize, const M: [T; N]>() -> [T; N] {
loop {}
}
fn main() {
// Requires inferring `T`/`N` from `12_u8` and `2` respectively.
let a = foo::<_, _, { [12_u8; 2] }>();
//~^ ERROR: anonymous constants with inferred types are not yet supported
// Requires inferring `T`/`N`/`12_?i`/`_` from `[u8; 2]`
let b: [u8; 2] = foo::<_, _, { [12; _] }>();
//~^ ERROR: anonymous constants with inferred types are not yet supported
}

View File

@ -0,0 +1,14 @@
error: anonymous constants with inferred types are not yet supported
--> $DIR/bad_inference.rs:17:25
|
LL | let a = foo::<_, _, { [12_u8; 2] }>();
| ^^^^^^^^^^^^^^
error: anonymous constants with inferred types are not yet supported
--> $DIR/bad_inference.rs:21:34
|
LL | let b: [u8; 2] = foo::<_, _, { [12; _] }>();
| ^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -0,0 +1,19 @@
//@ check-pass
#![feature(
adt_const_params,
unsized_const_params,
generic_const_parameter_types,
generic_arg_infer
)]
#![allow(incomplete_features)]
use std::marker::ConstParamTy_;
fn foo<T: ConstParamTy_, const N: usize, const M: [T; N]>() -> [T; N] {
M
}
fn main() {
let a: [u8; 2] = foo::<u8, 2, { [12; _] }>();
}

View File

@ -0,0 +1,11 @@
#![feature(adt_const_params, generic_const_parameter_types)]
#![expect(incomplete_features)]
use std::marker::PhantomData;
struct UsesConst<const N: [u8; M], const M: usize>;
//~^ ERROR: the type of const parameters must not depend on other generic parameters
struct UsesType<const N: [T; 2], T>(PhantomData<T>);
//~^ ERROR: the type of const parameters must not depend on other generic parameters
fn main() {}

View File

@ -0,0 +1,15 @@
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/forward_declared_type.rs:6:32
|
LL | struct UsesConst<const N: [u8; M], const M: usize>;
| ^ the type must not depend on the parameter `M`
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/forward_declared_type.rs:8:27
|
LL | struct UsesType<const N: [T; 2], T>(PhantomData<T>);
| ^ the type must not depend on the parameter `T`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0770`.

View File

@ -0,0 +1,13 @@
//@ check-pass
#![feature(adt_const_params, generic_arg_infer, generic_const_parameter_types)]
#![expect(incomplete_features)]
struct Bar<const N: usize, const M: [u8; N]>;
fn foo<const N: usize, const M: [u8; N]>(_: Bar<N, M>) {}
fn main() {
foo(Bar::<2, { [1; 2] }>);
foo::<_, _>(Bar::<2, { [1; 2] }>);
}

View File

@ -0,0 +1,20 @@
#![feature(generic_const_parameter_types, adt_const_params, unsized_const_params)]
#![expect(incomplete_features)]
fn foo<'a, const N: &'a u32>() {}
fn bar() {
foo::<'static, { &1_u32 }>();
//~^ ERROR: anonymous constants with lifetimes in their type are not yet supported
foo::<'_, { &1_u32 }>();
//~^ ERROR: anonymous constants with lifetimes in their type are not yet supported
}
fn borrowck<'a, const N: &'static u32, const M: &'a u32>() {
foo::<'a, M>();
foo::<'static, M>();
//~^ ERROR: lifetime may not live long enough
foo::<'static, N>();
}
fn main() {}

View File

@ -0,0 +1,23 @@
error: anonymous constants with lifetimes in their type are not yet supported
--> $DIR/lifetime_dependent_const_param.rs:7:20
|
LL | foo::<'static, { &1_u32 }>();
| ^^^^^^^^^^
error: anonymous constants with lifetimes in their type are not yet supported
--> $DIR/lifetime_dependent_const_param.rs:9:15
|
LL | foo::<'_, { &1_u32 }>();
| ^^^^^^^^^^
error: lifetime may not live long enough
--> $DIR/lifetime_dependent_const_param.rs:15:5
|
LL | fn borrowck<'a, const N: &'static u32, const M: &'a u32>() {
| -- lifetime `'a` defined here
LL | foo::<'a, M>();
LL | foo::<'static, M>();
| ^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: aborting due to 3 previous errors

View File

@ -0,0 +1,15 @@
#![feature(adt_const_params, unsized_const_params, generic_const_parameter_types)]
#![allow(incomplete_features)]
use std::marker::ConstParamTy_;
fn foo<const N: usize, const M: [u8; N]>() {}
fn bar<T: ConstParamTy_, const M: [T; 2]>() {}
fn main() {
foo::<3, { [1; 2] }>();
//~^ ERROR: mismatched type
bar::<u8, { [2_u16; 2] }>();
//~^ ERROR: mismatched type
}

View File

@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/mismatched_args_with_value.rs:10:16
|
LL | foo::<3, { [1; 2] }>();
| ^^^^^^ expected an array with a size of 3, found one with a size of 2
error[E0308]: mismatched types
--> $DIR/mismatched_args_with_value.rs:13:18
|
LL | bar::<u8, { [2_u16; 2] }>();
| ^^^^^ expected `u8`, found `u16`
|
help: change the type of the numeric literal from `u16` to `u8`
|
LL - bar::<u8, { [2_u16; 2] }>();
LL + bar::<u8, { [2_u8; 2] }>();
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,9 @@
#![feature(adt_const_params, unsized_const_params, generic_const_parameter_types)]
#![expect(incomplete_features)]
use std::marker::{ConstParamTy_, PhantomData};
struct UsesType<T, const N: usize, const M: [T; N]>(PhantomData<T>);
//~^ ERROR: `[T; N]` can't be used as a const parameter type
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0741]: `[T; N]` can't be used as a const parameter type
--> $DIR/no_const_param_ty_bound.rs:6:45
|
LL | struct UsesType<T, const N: usize, const M: [T; N]>(PhantomData<T>);
| ^^^^^^
|
= note: `T` must implement `UnsizedConstParamTy`, but it does not
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0741`.

View File

@ -0,0 +1,21 @@
//@ check-pass
#![feature(
adt_const_params,
unsized_const_params,
generic_const_parameter_types,
generic_arg_infer
)]
#![allow(incomplete_features)]
use std::marker::ConstParamTy_;
fn foo<U, T: ConstParamTy_, const N: usize, const M: [T; N]>(_: U) -> [T; N] {
loop {}
}
fn main() {
// Check that `_` doesnt cause a "Type of const argument is uninferred" error
// as it is not actually used by the type of `M`.
let a = foo::<_, u8, 2, { [12; _] }>(true);
}

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
| ^^ the type must not depend on the parameter `'a`
|
= note: lifetime parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
| ^^ the type must not depend on the parameter `'a`
|
= note: lifetime parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn foo<const N: usize, const A: [u8; N]>() {}
| ^ the type must not depend on the parameter `N`
|
= note: const parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn foo<const N: usize, const A: [u8; N]>() {}
| ^ the type must not depend on the parameter `N`
|
= note: const parameters may not be used in the type of const parameters
error: `[u8; N]` is forbidden as the type of a const generic parameter
--> $DIR/issue-62878.rs:5:33

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
| ^^^ the type must not depend on the parameter `LEN`
|
= note: const parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
| ^^^ the type must not depend on the parameter `LEN`
|
= note: const parameters may not be used in the type of const parameters
error: `[u8; LEN]` is forbidden as the type of a const generic parameter
--> $DIR/issue-71169.rs:5:38

View File

@ -3,16 +3,12 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
| ^^^^ the type must not depend on the parameter `Args`
|
= note: type parameters may not be used in the type of const parameters
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/issue-71381.rs:23:40
|
LL | const FN: unsafe extern "C" fn(Args),
| ^^^^ the type must not depend on the parameter `Args`
|
= note: type parameters may not be used in the type of const parameters
error: aborting due to 2 previous errors

View File

@ -3,16 +3,12 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
| ^^^^ the type must not depend on the parameter `Args`
|
= note: type parameters may not be used in the type of const parameters
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/issue-71381.rs:23:40
|
LL | const FN: unsafe extern "C" fn(Args),
| ^^^^ the type must not depend on the parameter `Args`
|
= note: type parameters may not be used in the type of const parameters
error: using function pointers as const generic parameters is forbidden
--> $DIR/issue-71381.rs:14:61

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
| ^ the type must not depend on the parameter `A`
|
= note: type parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
| ^ the type must not depend on the parameter `A`
|
= note: type parameters may not be used in the type of const parameters
error: using function pointers as const generic parameters is forbidden
--> $DIR/issue-71611.rs:5:21

View File

@ -3,16 +3,12 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T)
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/issue-88997.rs:8:54
|
LL | struct Range<T: PartialOrd, const MIN: T, const MAX: T>(T)
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error: aborting due to 2 previous errors

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | pub struct Foo<T, const H: T>(T)
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | fn function_with_str<'a, const STRING: &'a str>() {}
| ^^ the type must not depend on the parameter `'a`
|
= note: lifetime parameters may not be used in the type of const parameters
warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/E0771.rs:1:30

View File

@ -0,0 +1,21 @@
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/feature-gate-generic-const-parameter-types.rs:7:50
|
LL | struct MyADT<const LEN: usize, const ARRAY: [u8; LEN]>;
| ^^^ the type must not depend on the parameter `LEN`
error: `[u8; LEN]` is forbidden as the type of a const generic parameter
--> $DIR/feature-gate-generic-const-parameter-types.rs:7:45
|
LL | struct MyADT<const LEN: usize, const ARRAY: [u8; LEN]>;
| ^^^^^^^^^
|
= note: the only supported types are integers, `bool`, and `char`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0770`.

View File

@ -0,0 +1,11 @@
//@ [feature] check-pass
//@ revisions: normal feature
#![cfg_attr(feature, feature(adt_const_params, generic_const_parameter_types))]
#![cfg_attr(feature, expect(incomplete_features))]
struct MyADT<const LEN: usize, const ARRAY: [u8; LEN]>;
//[normal]~^ ERROR: the type of const parameters must not depend on other generic parameters
//[normal]~| ERROR: `[u8; LEN]` is forbidden as the type of a const generic parameter
fn main() {}

View File

@ -3,8 +3,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | struct G<T, const N: Vec<T>>(T);
| ^ the type must not depend on the parameter `T`
|
= note: type parameters may not be used in the type of const parameters
error: aborting due to 1 previous error

View File

@ -9,8 +9,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
| ^^ the type must not depend on the parameter `'a`
|
= note: lifetime parameters may not be used in the type of const parameters
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/unusual-rib-combinations.rs:11:15

View File

@ -3,6 +3,7 @@ trait Foo<const N: Bar<2>> {
//~^ WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
//~| ERROR cycle detected when computing type of `Foo::N`
//~| ERROR cycle detected when computing type of `Foo::N`
fn func() {}
}

View File

@ -13,7 +13,7 @@ LL | trait Foo<const N: dyn Bar<2>> {
| +++
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:20
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:20
|
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^
@ -32,7 +32,7 @@ LL | trait Foo<const N: Bar<2>> {
| ^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Bar::M`...
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:11
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:11
|
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^^^^^^^^^^
@ -44,6 +44,26 @@ LL | trait Foo<const N: Bar<2>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error; 2 warnings emitted
error[E0391]: cycle detected when computing type of `Foo::N`
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11
|
LL | trait Foo<const N: Bar<2>> {
| ^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Bar::M`...
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:11
|
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `Foo::N`, completing the cycle
note: cycle used when computing explicit predicates of trait `Foo`
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1
|
LL | trait Foo<const N: Bar<2>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 2 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0391`.