Auto merge of #74877 - lcnr:min_const_generics, r=oli-obk
Implement the `min_const_generics` feature gate Implements both https://github.com/rust-lang/lang-team/issues/37 and https://github.com/rust-lang/compiler-team/issues/332. Adds the new feature gate `#![feature(min_const_generics)]`. This feature gate adds the following limitations to using const generics: - generic parameters must only be used in types if they are trivial. (either `N` or `{ N }`) - generic parameters must be either integers, `bool` or `char`. We do allow arbitrary expressions in associated consts though, meaning that the following is allowed, even if `<[u8; 0] as Foo>::ASSOC` is not const evaluatable. ```rust trait Foo { const ASSOC: usize; } impl<const N: usize> Foo for [u8; N] { const ASSOC: usize = 64 / N; } ``` r? @varkor cc @eddyb @withoutboats
This commit is contained in:
commit
f9c2177ddc
@ -1052,6 +1052,30 @@ impl Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this expr either `N`, or `{ N }`.
|
||||
///
|
||||
/// If this is not the case, name resolution does not resolve `N` when using
|
||||
/// `feature(min_const_generics)` as more complex expressions are not supported.
|
||||
pub fn is_potential_trivial_const_param(&self) -> bool {
|
||||
let this = if let ExprKind::Block(ref block, None) = self.kind {
|
||||
if block.stmts.len() == 1 {
|
||||
if let StmtKind::Expr(ref expr) = block.stmts[0].kind { expr } else { self }
|
||||
} else {
|
||||
self
|
||||
}
|
||||
} else {
|
||||
self
|
||||
};
|
||||
|
||||
if let ExprKind::Path(None, ref path) = this.kind {
|
||||
if path.segments.len() == 1 && path.segments[0].args.is_none() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn to_bound(&self) -> Option<GenericBound> {
|
||||
match &self.kind {
|
||||
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
||||
|
@ -776,7 +776,13 @@ fn validate_generic_param_order<'a>(
|
||||
span,
|
||||
&format!(
|
||||
"reorder the parameters: lifetimes, then types{}",
|
||||
if sess.features_untracked().const_generics { ", then consts" } else { "" },
|
||||
if sess.features_untracked().const_generics
|
||||
|| sess.features_untracked().min_const_generics
|
||||
{
|
||||
", then consts"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
),
|
||||
ordered_params.clone(),
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -526,12 +526,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
||||
if let GenericParamKind::Const { .. } = param.kind {
|
||||
gate_feature_post!(
|
||||
gate_feature_fn!(
|
||||
&self,
|
||||
const_generics,
|
||||
|x: &Features| x.const_generics || x.min_const_generics,
|
||||
param.ident.span,
|
||||
sym::min_const_generics,
|
||||
"const generics are unstable"
|
||||
)
|
||||
);
|
||||
}
|
||||
visit::walk_generic_param(self, param)
|
||||
}
|
||||
|
@ -579,6 +579,9 @@ declare_features! (
|
||||
/// Allows calling `transmute` in const fn
|
||||
(active, const_fn_transmute, "1.46.0", Some(53605), None),
|
||||
|
||||
/// The smallest useful subset of `const_generics`.
|
||||
(active, min_const_generics, "1.46.0", Some(74878), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -1380,7 +1380,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// we still evaluate them eagerly.
|
||||
#[inline]
|
||||
pub fn lazy_normalization(self) -> bool {
|
||||
self.features().const_generics || self.features().lazy_normalization_consts
|
||||
let features = self.features();
|
||||
// Note: We do not enable lazy normalization for `features.min_const_generics`.
|
||||
features.const_generics || features.lazy_normalization_consts
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -54,7 +54,7 @@ impl<'a> Parser<'a> {
|
||||
self.expect(&token::Colon)?;
|
||||
let ty = self.parse_ty()?;
|
||||
|
||||
self.sess.gated_spans.gate(sym::const_generics, const_span.to(self.prev_token.span));
|
||||
self.sess.gated_spans.gate(sym::min_const_generics, const_span.to(self.prev_token.span));
|
||||
|
||||
Ok(GenericParam {
|
||||
ident,
|
||||
|
@ -466,6 +466,23 @@ impl<'a> Resolver<'a> {
|
||||
);
|
||||
err
|
||||
}
|
||||
ResolutionError::ParamInNonTrivialAnonConst(name) => {
|
||||
let mut err = self.session.struct_span_err(
|
||||
span,
|
||||
"generic parameters must not be used inside of non trivial constant values",
|
||||
);
|
||||
err.span_label(
|
||||
span,
|
||||
&format!(
|
||||
"non-trivial anonymous constants must not depend on the parameter `{}`",
|
||||
name
|
||||
),
|
||||
);
|
||||
err.help(
|
||||
&format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants", name)
|
||||
);
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfInTyParamDefault => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
|
@ -111,7 +111,7 @@ crate enum RibKind<'a> {
|
||||
ItemRibKind(HasGenericParams),
|
||||
|
||||
/// We're in a constant item. Can't refer to dynamic stuff.
|
||||
ConstantItemRibKind,
|
||||
ConstantItemRibKind(bool),
|
||||
|
||||
/// We passed through a module.
|
||||
ModuleRibKind(Module<'a>),
|
||||
@ -137,7 +137,7 @@ impl RibKind<'_> {
|
||||
NormalRibKind
|
||||
| ClosureOrAsyncRibKind
|
||||
| FnItemRibKind
|
||||
| ConstantItemRibKind
|
||||
| ConstantItemRibKind(_)
|
||||
| ModuleRibKind(_)
|
||||
| MacroDefinition(_)
|
||||
| ConstParamTyRibKind => false,
|
||||
@ -426,7 +426,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
}
|
||||
fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
|
||||
debug!("visit_anon_const {:?}", constant);
|
||||
self.with_constant_rib(|this| {
|
||||
self.with_constant_rib(constant.value.is_potential_trivial_const_param(), |this| {
|
||||
visit::walk_anon_const(this, constant);
|
||||
});
|
||||
}
|
||||
@ -628,7 +628,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
if !check_ns(TypeNS) && check_ns(ValueNS) {
|
||||
// This must be equivalent to `visit_anon_const`, but we cannot call it
|
||||
// directly due to visitor lifetimes so we have to copy-paste some code.
|
||||
self.with_constant_rib(|this| {
|
||||
self.with_constant_rib(true, |this| {
|
||||
this.smart_resolve_path(
|
||||
ty.id,
|
||||
qself.as_ref(),
|
||||
@ -829,7 +829,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
| ClosureOrAsyncRibKind
|
||||
| FnItemRibKind
|
||||
| ItemRibKind(..)
|
||||
| ConstantItemRibKind
|
||||
| ConstantItemRibKind(_)
|
||||
| ModuleRibKind(..)
|
||||
| ForwardTyParamBanRibKind
|
||||
| ConstParamTyRibKind => {
|
||||
@ -948,7 +948,14 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
// Only impose the restrictions of `ConstRibKind` for an
|
||||
// actual constant expression in a provided default.
|
||||
if let Some(expr) = default {
|
||||
this.with_constant_rib(|this| this.visit_expr(expr));
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.with_constant_rib(true, |this| {
|
||||
this.visit_expr(expr)
|
||||
});
|
||||
}
|
||||
}
|
||||
AssocItemKind::Fn(_, _, generics, _) => {
|
||||
@ -989,7 +996,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
self.with_item_rib(HasGenericParams::No, |this| {
|
||||
this.visit_ty(ty);
|
||||
if let Some(expr) = expr {
|
||||
this.with_constant_rib(|this| this.visit_expr(expr));
|
||||
this.with_constant_rib(expr.is_potential_trivial_const_param(), |this| {
|
||||
this.visit_expr(expr)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1086,11 +1095,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||
}
|
||||
|
||||
fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
fn with_constant_rib(&mut self, trivial: bool, f: impl FnOnce(&mut Self)) {
|
||||
debug!("with_constant_rib");
|
||||
self.with_rib(ValueNS, ConstantItemRibKind, |this| {
|
||||
this.with_rib(TypeNS, ConstantItemRibKind, |this| {
|
||||
this.with_label_rib(ConstantItemRibKind, f);
|
||||
self.with_rib(ValueNS, ConstantItemRibKind(trivial), |this| {
|
||||
this.with_rib(TypeNS, ConstantItemRibKind(trivial), |this| {
|
||||
this.with_label_rib(ConstantItemRibKind(trivial), f);
|
||||
})
|
||||
});
|
||||
}
|
||||
@ -1220,7 +1229,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
for item in impl_items {
|
||||
use crate::ResolutionError::*;
|
||||
match &item.kind {
|
||||
AssocItemKind::Const(..) => {
|
||||
AssocItemKind::Const(_default, _ty, _expr) => {
|
||||
debug!("resolve_implementation AssocItemKind::Const",);
|
||||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
@ -1231,7 +1240,12 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
|n, s| ConstNotMemberOfTrait(n, s),
|
||||
);
|
||||
|
||||
this.with_constant_rib(|this| {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.with_constant_rib(true, |this| {
|
||||
visit::walk_assoc_item(this, item, AssocCtxt::Impl)
|
||||
});
|
||||
}
|
||||
|
@ -218,6 +218,10 @@ enum ResolutionError<'a> {
|
||||
ParamInTyOfConstParam(Symbol),
|
||||
/// constant values inside of type parameter defaults must not depend on generic parameters.
|
||||
ParamInAnonConstInTyDefault(Symbol),
|
||||
/// generic parameters must not be used inside of non trivial constant values.
|
||||
///
|
||||
/// This error is only emitted when using `min_const_generics`.
|
||||
ParamInNonTrivialAnonConst(Symbol),
|
||||
/// Error E0735: type parameters with a default cannot use `Self`
|
||||
SelfInTyParamDefault,
|
||||
/// Error E0767: use of unreachable label
|
||||
@ -2507,7 +2511,7 @@ impl<'a> Resolver<'a> {
|
||||
res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
|
||||
}
|
||||
}
|
||||
ConstantItemRibKind => {
|
||||
ConstantItemRibKind(_) => {
|
||||
// Still doesn't deal with upvars
|
||||
if record_used {
|
||||
self.report_error(span, AttemptToUseNonConstantValueInConstant);
|
||||
@ -2546,7 +2550,18 @@ impl<'a> Resolver<'a> {
|
||||
in_ty_param_default = true;
|
||||
continue;
|
||||
}
|
||||
ConstantItemRibKind => {
|
||||
ConstantItemRibKind(trivial) => {
|
||||
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
|
||||
if !trivial && self.session.features_untracked().min_const_generics {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
}
|
||||
|
||||
if in_ty_param_default {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
@ -2612,7 +2627,18 @@ impl<'a> Resolver<'a> {
|
||||
in_ty_param_default = true;
|
||||
continue;
|
||||
}
|
||||
ConstantItemRibKind => {
|
||||
ConstantItemRibKind(trivial) => {
|
||||
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
|
||||
if !trivial && self.session.features_untracked().min_const_generics {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
}
|
||||
|
||||
if in_ty_param_default {
|
||||
if record_used {
|
||||
self.report_error(
|
||||
|
@ -672,6 +672,7 @@ symbols! {
|
||||
min_align_of,
|
||||
min_align_of_val,
|
||||
min_const_fn,
|
||||
min_const_generics,
|
||||
min_const_unsafe_fn,
|
||||
min_specialization,
|
||||
minnumf32,
|
||||
|
@ -1238,6 +1238,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||
// HACK(eddyb) this provides the correct generics when
|
||||
// `feature(const_generics)` is enabled, so that const expressions
|
||||
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
||||
//
|
||||
// Note that we do not supply the parent generics when using
|
||||
// `feature(min_const_generics)`.
|
||||
Some(parent_def_id.to_def_id())
|
||||
} else {
|
||||
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
|
||||
|
@ -326,21 +326,39 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
|
||||
GenericParamKind::Const { ty: ref hir_ty, .. } => {
|
||||
let ty = icx.to_ty(hir_ty);
|
||||
let err = match ty.peel_refs().kind {
|
||||
ty::FnPtr(_) => Some("function pointers"),
|
||||
ty::RawPtr(_) => Some("raw pointers"),
|
||||
_ => None,
|
||||
let err_ty_str;
|
||||
let err = if tcx.features().min_const_generics {
|
||||
match ty.kind {
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
|
||||
ty::FnPtr(_) => Some("function pointers"),
|
||||
ty::RawPtr(_) => Some("raw pointers"),
|
||||
_ => {
|
||||
err_ty_str = format!("`{}`", ty);
|
||||
Some(err_ty_str.as_str())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match ty.peel_refs().kind {
|
||||
ty::FnPtr(_) => Some("function pointers"),
|
||||
ty::RawPtr(_) => Some("raw pointers"),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
if let Some(unsupported_type) = err {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
hir_ty.span,
|
||||
&format!(
|
||||
"using {} as const generic parameters is forbidden",
|
||||
unsupported_type
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
let mut err = tcx.sess.struct_span_err(
|
||||
hir_ty.span,
|
||||
&format!(
|
||||
"using {} as const generic parameters is forbidden",
|
||||
unsupported_type
|
||||
),
|
||||
);
|
||||
|
||||
if tcx.features().min_const_generics {
|
||||
err.note("the only supported types are integers, `bool` and `char`")
|
||||
.note("more complex types are supported with `#[feature(const_generics)]`").emit()
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
};
|
||||
if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
|
||||
.is_some()
|
||||
|
@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
|
||||
LL | trait Trait<const T: ()> {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -10,8 +10,8 @@ error[E0658]: const generics are unstable
|
||||
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: type parameters with a default must be trailing
|
||||
--> $DIR/wrong-order.rs:3:10
|
||||
--> $DIR/wrong-order.rs:5:10
|
||||
|
|
||||
LL | struct A<T = u32, const N: usize> {
|
||||
| ^
|
||||
@ -7,10 +7,10 @@ LL | struct A<T = u32, const N: usize> {
|
||||
= note: using type defaults and const parameters in the same parameter list is currently not permitted
|
||||
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/wrong-order.rs:1:12
|
||||
--> $DIR/wrong-order.rs:2:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
10
src/test/ui/const-generics/defaults/wrong-order.min.stderr
Normal file
10
src/test/ui/const-generics/defaults/wrong-order.min.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: type parameters with a default must be trailing
|
||||
--> $DIR/wrong-order.rs:5:10
|
||||
|
|
||||
LL | struct A<T = u32, const N: usize> {
|
||||
| ^
|
||||
|
|
||||
= note: using type defaults and const parameters in the same parameter list is currently not permitted
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,4 +1,6 @@
|
||||
#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
struct A<T = u32, const N: usize> {
|
||||
//~^ ERROR type parameters with a default must be trailing
|
||||
|
@ -1,8 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-56445.rs:3:12
|
||||
--> $DIR/issue-56445.rs:3:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
20
src/test/ui/const-generics/issues/issue-56445.min.stderr
Normal file
20
src/test/ui/const-generics/issues/issue-56445.min.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0771]: use of non-static lifetime `'a` in const generic
|
||||
--> $DIR/issue-56445.rs:9:26
|
||||
|
|
||||
LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
|
||||
| ^^
|
||||
|
|
||||
= note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
|
||||
|
||||
error: using `&'static str` as const generic parameters is forbidden
|
||||
--> $DIR/issue-56445.rs:9:25
|
||||
|
|
||||
LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= note: more complex types are supported with `#[feature(const_generics)]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0771`.
|
@ -1,12 +1,13 @@
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995.
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN: the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
|
||||
//~^ ERROR: use of non-static lifetime `'a` in const generic
|
||||
//[min]~| ERROR: using `&'static str` as const
|
||||
|
||||
impl Bug<'_, ""> {}
|
||||
|
@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
|
||||
LL | struct B<const I: u8>;
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61336-1.rs:1:12
|
||||
--> $DIR/issue-60818-struct-constructors.rs:3:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
@ -1,7 +1,7 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
struct Generic<const V: usize>;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-60818-struct-constructors.rs:3:12
|
||||
--> $DIR/issue-61336-1.rs:3:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
@ -1,7 +1,7 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
|
||||
// build-pass
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
|
||||
[x; N]
|
||||
|
@ -1,14 +1,14 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61336-2.rs:1:12
|
||||
--> $DIR/issue-61336-2.rs:2:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-61336-2.rs:9:5
|
||||
--> $DIR/issue-61336-2.rs:10:5
|
||||
|
|
||||
LL | [x; { N }]
|
||||
| ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
15
src/test/ui/const-generics/issues/issue-61336-2.min.stderr
Normal file
15
src/test/ui/const-generics/issues/issue-61336-2.min.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-61336-2.rs:10:5
|
||||
|
|
||||
LL | [x; { N }]
|
||||
| ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= note: the `Copy` trait is required because the repeated element will be copied
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,5 +1,6 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
|
||||
[x; { N }]
|
||||
|
24
src/test/ui/const-generics/issues/issue-61336.full.stderr
Normal file
24
src/test/ui/const-generics/issues/issue-61336.full.stderr
Normal file
@ -0,0 +1,24 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61336.rs:2:27
|
||||
|
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-61336.rs:10:5
|
||||
|
|
||||
LL | [x; N]
|
||||
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= note: the `Copy` trait is required because the repeated element will be copied
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
15
src/test/ui/const-generics/issues/issue-61336.min.stderr
Normal file
15
src/test/ui/const-generics/issues/issue-61336.min.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-61336.rs:10:5
|
||||
|
|
||||
LL | [x; N]
|
||||
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= note: the `Copy` trait is required because the repeated element will be copied
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,5 +1,6 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
|
||||
[x; N]
|
||||
|
@ -1,8 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61432.rs:3:12
|
||||
--> $DIR/issue-61422.rs:3:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
@ -1,7 +1,7 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
use std::mem;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61422.rs:3:12
|
||||
--> $DIR/issue-61432.rs:3:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
@ -1,7 +1,7 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
fn promote<const N: i32>() {
|
||||
// works:
|
||||
|
@ -1,14 +1,14 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61747.rs:1:12
|
||||
--> $DIR/issue-61747.rs:2:27
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | #![cfg_attr(full, feature(const_generics))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-61747.rs:7:23
|
||||
--> $DIR/issue-61747.rs:8:23
|
||||
|
|
||||
LL | fn successor() -> Const<{C + 1}> {
|
||||
| ^^^^^^^^^^^^^^
|
10
src/test/ui/const-generics/issues/issue-61747.min.stderr
Normal file
10
src/test/ui/const-generics/issues/issue-61747.min.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: generic parameters must not be used inside of non trivial constant values
|
||||
--> $DIR/issue-61747.rs:8:30
|
||||
|
|
||||
LL | fn successor() -> Const<{C + 1}> {
|
||||
| ^ non-trivial anonymous constants must not depend on the parameter `C`
|
||||
|
|
||||
= help: it is currently only allowed to use either `C` or `{ C }` as generic constants
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,11 +1,13 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
|
||||
struct Const<const N: usize>;
|
||||
|
||||
impl<const C: usize> Const<{C}> {
|
||||
fn successor() -> Const<{C + 1}> {
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
//[full]~^ ERROR constant expression depends on a generic parameter
|
||||
//[min]~^^ ERROR generic parameters must not be used
|
||||
Const
|
||||
}
|
||||
}
|
||||
|
18
src/test/ui/const-generics/min_const_generics/assoc_const.rs
Normal file
18
src/test/ui/const-generics/min_const_generics/assoc_const.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// check-pass
|
||||
#![feature(min_const_generics)]
|
||||
|
||||
struct Foo<const N: usize>;
|
||||
|
||||
impl<const N: usize> Foo<N> {
|
||||
const VALUE: usize = N * 2;
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
impl<const N: usize> Bar for Foo<N> {
|
||||
const ASSOC: usize = N * 3;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,29 @@
|
||||
#![feature(min_const_generics)]
|
||||
|
||||
fn test<const N: usize>() {}
|
||||
|
||||
fn ok<const M: usize>() -> [u8; M] {
|
||||
[0; { M }]
|
||||
}
|
||||
|
||||
struct Break0<const N: usize>([u8; { N + 1 }]);
|
||||
//~^ ERROR generic parameters must not be used inside of non trivial constant values
|
||||
|
||||
struct Break1<const N: usize>([u8; { { N } }]);
|
||||
//~^ ERROR generic parameters must not be used inside of non trivial constant values
|
||||
|
||||
fn break2<const N: usize>() {
|
||||
let _: [u8; N + 1];
|
||||
//~^ ERROR generic parameters must not be used inside of non trivial constant values
|
||||
}
|
||||
|
||||
fn break3<const N: usize>() {
|
||||
let _ = [0; N + 1];
|
||||
//~^ ERROR generic parameters must not be used inside of non trivial constant values
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,34 @@
|
||||
error: generic parameters must not be used inside of non trivial constant values
|
||||
--> $DIR/complex-expression.rs:9:38
|
||||
|
|
||||
LL | struct Break0<const N: usize>([u8; { N + 1 }]);
|
||||
| ^ non-trivial anonymous constants must not depend on the parameter `N`
|
||||
|
|
||||
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
|
||||
|
||||
error: generic parameters must not be used inside of non trivial constant values
|
||||
--> $DIR/complex-expression.rs:12:40
|
||||
|
|
||||
LL | struct Break1<const N: usize>([u8; { { N } }]);
|
||||
| ^ non-trivial anonymous constants must not depend on the parameter `N`
|
||||
|
|
||||
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
|
||||
|
||||
error: generic parameters must not be used inside of non trivial constant values
|
||||
--> $DIR/complex-expression.rs:16:17
|
||||
|
|
||||
LL | let _: [u8; N + 1];
|
||||
| ^ non-trivial anonymous constants must not depend on the parameter `N`
|
||||
|
|
||||
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
|
||||
|
||||
error: generic parameters must not be used inside of non trivial constant values
|
||||
--> $DIR/complex-expression.rs:21:17
|
||||
|
|
||||
LL | let _ = [0; N + 1];
|
||||
| ^ non-trivial anonymous constants must not depend on the parameter `N`
|
||||
|
|
||||
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -0,0 +1,18 @@
|
||||
#![feature(min_const_generics)]
|
||||
|
||||
struct Foo<const N: [u8; 0]>;
|
||||
//~^ ERROR using `[u8; 0]` as const generic parameters is forbidden
|
||||
|
||||
struct Bar<const N: ()>;
|
||||
//~^ ERROR using `()` as const generic parameters is forbidden
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct No;
|
||||
|
||||
struct Fez<const N: No>;
|
||||
//~^ ERROR using `No` as const generic parameters is forbidden
|
||||
|
||||
struct Faz<const N: &'static u8>;
|
||||
//~^ ERROR using `&'static u8` as const generic parameters is forbidden
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,38 @@
|
||||
error: using `[u8; 0]` as const generic parameters is forbidden
|
||||
--> $DIR/complex-types.rs:3:21
|
||||
|
|
||||
LL | struct Foo<const N: [u8; 0]>;
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= note: more complex types are supported with `#[feature(const_generics)]`
|
||||
|
||||
error: using `()` as const generic parameters is forbidden
|
||||
--> $DIR/complex-types.rs:6:21
|
||||
|
|
||||
LL | struct Bar<const N: ()>;
|
||||
| ^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= note: more complex types are supported with `#[feature(const_generics)]`
|
||||
|
||||
error: using `No` as const generic parameters is forbidden
|
||||
--> $DIR/complex-types.rs:12:21
|
||||
|
|
||||
LL | struct Fez<const N: No>;
|
||||
| ^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= note: more complex types are supported with `#[feature(const_generics)]`
|
||||
|
||||
error: using `&'static u8` as const generic parameters is forbidden
|
||||
--> $DIR/complex-types.rs:15:21
|
||||
|
|
||||
LL | struct Faz<const N: &'static u8>;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= note: more complex types are supported with `#[feature(const_generics)]`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -0,0 +1,4 @@
|
||||
fn test<const N: usize>() {}
|
||||
//~^ ERROR const generics are unstable
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,12 @@
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-min_const_generics.rs:1:15
|
||||
|
|
||||
LL | fn test<const N: usize>() {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,7 +1,8 @@
|
||||
// run-pass
|
||||
#![feature(const_generics)]
|
||||
// revisions: full min
|
||||
#![cfg_attr(full, feature(const_generics))]
|
||||
#![cfg_attr(min, feature(min_const_generics))]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(const_fn)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
|
@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
|
||||
LL | struct ConstFn<const F: fn()>;
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics-ptr.rs:5:23
|
||||
@ -13,8 +13,8 @@ error[E0658]: const generics are unstable
|
||||
LL | struct ConstPtr<const P: *const u32>;
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: using function pointers as const generic parameters is forbidden
|
||||
--> $DIR/feature-gate-const_generics-ptr.rs:1:25
|
||||
|
@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
|
||||
LL | fn foo<const X: ()>() {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics.rs:3:18
|
||||
@ -13,8 +13,8 @@ error[E0658]: const generics are unstable
|
||||
LL | struct Foo<const X: usize>([(); X]);
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
= note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
|
||||
= help: add `#![feature(min_const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user