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:
commit
415b207b7f
56 changed files with 419 additions and 154 deletions
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue