1
Fork 0

Rollup merge of #137617 - BoxyUwU:generic_const_parameter_types, r=lcnr

Introduce `feature(generic_const_parameter_types)`

Allows to define const generic parameters whose type depends on other generic parameters, e.g. `Foo<const N: usize, const ARR: [u8; N]>;`

Wasn't going to implement for this for a while until we could implement it with `bad_inference.rs` resolved but apparently the project simd folks would like to be able to use this for some intrinsics and the inference issue isn't really a huge problem there aiui. (cc ``@workingjubilee`` )
This commit is contained in:
Matthias Krüger 2025-03-01 11:33:58 +01:00 committed by GitHub
commit 415b207b7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 419 additions and 154 deletions

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`.