Auto merge of #80547 - lqd:const_generics_defaults, r=varkor
In which we start to parse const generics defaults As discussed in this [zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/const.20generic.20defaults), this PR extracts the parsing parts from `@JulianKnodt's` PR #75384 for a better user-experience using the newly stabilized `min_const_generics` (albeit temporary) as shown in #80507: trying to use default values on const generics currently results in parse errors, as if the user didn't use the correct syntax (which is somewhat true but also misleading). This PR extracts (and slightly modifies in a couple places) `@JulianKnodt's` parsing code (with attribution if I've done everything correctly), AST and HIR changes, and feature gate setup. This feature is now marked as "incomplete" and thus will also print out the expected "const generics default values are unstable" error instead of a syntax error. Note that, as I've only extracted the parsing part, the actual feature will not work at all if enabled. There will be ICEs, and inference errors on the const generics default values themselves. Fixes #80507. Once this merges, I'll: - modify the const generics tracking issue to refer to the `const_generics_defaults` gate rather than the older temporary name it uses there. - create the GH `F-const_generics_defaults` label r? `@varkor`
This commit is contained in:
commit
a609fb45ef
@ -368,6 +368,8 @@ pub enum GenericParamKind {
|
||||
ty: P<Ty>,
|
||||
/// Span of the `const` keyword.
|
||||
kw_span: Span,
|
||||
/// Optional default value for the const generic param
|
||||
default: Option<AnonConst>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -790,8 +790,9 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
||||
GenericParamKind::Type { default } => {
|
||||
visit_opt(default, |default| vis.visit_ty(default));
|
||||
}
|
||||
GenericParamKind::Const { ty, kw_span: _ } => {
|
||||
GenericParamKind::Const { ty, kw_span: _, default } => {
|
||||
vis.visit_ty(ty);
|
||||
visit_opt(default, |default| vis.visit_anon_const(default));
|
||||
}
|
||||
}
|
||||
smallvec![param]
|
||||
|
@ -578,7 +578,12 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime => (),
|
||||
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
|
||||
GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty),
|
||||
GenericParamKind::Const { ref ty, ref default, .. } => {
|
||||
visitor.visit_ty(ty);
|
||||
if let Some(default) = default {
|
||||
visitor.visit_anon_const(default);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2242,13 +2242,14 @@ fn lower_generic_param(
|
||||
|
||||
(hir::ParamName::Plain(param.ident), kind)
|
||||
}
|
||||
GenericParamKind::Const { ref ty, kw_span: _ } => {
|
||||
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
|
||||
let ty = self
|
||||
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
|
||||
this.lower_ty(&ty, ImplTraitContext::disallowed())
|
||||
});
|
||||
let default = default.as_ref().map(|def| self.lower_anon_const(def));
|
||||
|
||||
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty })
|
||||
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default })
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -733,7 +733,7 @@ fn validate_generic_param_order(
|
||||
let (ord_kind, ident) = match ¶m.kind {
|
||||
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
|
||||
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
|
||||
GenericParamKind::Const { ref ty, kw_span: _ } => {
|
||||
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
|
||||
let ty = pprust::ty_to_string(ty);
|
||||
let unordered = sess.features_untracked().const_generics;
|
||||
(ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
|
||||
@ -774,8 +774,8 @@ fn validate_generic_param_order(
|
||||
}
|
||||
GenericParamKind::Type { default: None } => (),
|
||||
GenericParamKind::Lifetime => (),
|
||||
// FIXME(const_generics:defaults)
|
||||
GenericParamKind::Const { ty: _, kw_span: _ } => (),
|
||||
// FIXME(const_generics_defaults)
|
||||
GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
@ -619,6 +619,10 @@ macro_rules! gate_all {
|
||||
extended_key_value_attributes,
|
||||
"arbitrary expressions in key-value attributes are unstable"
|
||||
);
|
||||
gate_all!(
|
||||
const_generics_defaults,
|
||||
"default values for const generic parameters are experimental"
|
||||
);
|
||||
if sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
// Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
|
||||
// involved, so we only emit errors where there are no other parsing errors.
|
||||
|
@ -2668,13 +2668,17 @@ pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::Generic
|
||||
s.print_type(default)
|
||||
}
|
||||
}
|
||||
ast::GenericParamKind::Const { ref ty, kw_span: _ } => {
|
||||
ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
|
||||
s.word_space("const");
|
||||
s.print_ident(param.ident);
|
||||
s.s.space();
|
||||
s.word_space(":");
|
||||
s.print_type(ty);
|
||||
s.print_type_bounds(":", ¶m.bounds)
|
||||
s.print_type_bounds(":", ¶m.bounds);
|
||||
if let Some(ref _default) = default {
|
||||
// FIXME(const_generics_defaults): print the `default` value here
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -145,7 +145,8 @@ fn inject_impl_of_structural_trait(
|
||||
*default = None;
|
||||
ast::GenericArg::Type(cx.ty_ident(span, param.ident))
|
||||
}
|
||||
ast::GenericParamKind::Const { ty: _, kw_span: _ } => {
|
||||
ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
|
||||
*default = None;
|
||||
ast::GenericArg::Const(cx.const_ident(span, param.ident))
|
||||
}
|
||||
})
|
||||
|
@ -581,7 +581,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
/// Allows `if let` guard in match arms.
|
||||
(active, if_let_guard, "1.47.0", Some(51114), None),
|
||||
|
||||
/// Allows non-trivial generic constants which have to be manually propageted upwards.
|
||||
/// Allows non-trivial generic constants which have to be manually propagated upwards.
|
||||
(active, const_evaluatable_checked, "1.48.0", Some(76560), None),
|
||||
|
||||
/// Allows basic arithmetic on floating point types in a `const fn`.
|
||||
@ -623,6 +623,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
/// `:pat2018` and `:pat2021` macro matchers.
|
||||
(active, edition_macro_pats, "1.51.0", Some(54883), None),
|
||||
|
||||
/// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
|
||||
(active, const_generics_defaults, "1.51.0", Some(44580), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
@ -647,6 +650,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
sym::repr128,
|
||||
sym::unsized_locals,
|
||||
sym::capture_disjoint_fields,
|
||||
sym::const_generics_defaults,
|
||||
];
|
||||
|
||||
/// Some features are not allowed to be used together at the same time, if
|
||||
|
@ -418,6 +418,8 @@ pub enum GenericParamKind<'hir> {
|
||||
},
|
||||
Const {
|
||||
ty: &'hir Ty<'hir>,
|
||||
/// Optional default value for the const generic param
|
||||
default: Option<AnonConst>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -877,7 +877,12 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
|
||||
GenericParamKind::Const { ref ty } => visitor.visit_ty(ty),
|
||||
GenericParamKind::Const { ref ty, ref default } => {
|
||||
visitor.visit_ty(ty);
|
||||
if let Some(ref default) = default {
|
||||
visitor.visit_anon_const(default);
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_list!(visitor, visit_param_bound, param.bounds);
|
||||
}
|
||||
|
@ -2205,9 +2205,13 @@ pub fn print_generic_param(&mut self, param: &GenericParam<'_>) {
|
||||
self.print_type(&default)
|
||||
}
|
||||
}
|
||||
GenericParamKind::Const { ref ty } => {
|
||||
GenericParamKind::Const { ref ty, ref default } => {
|
||||
self.word_space(":");
|
||||
self.print_type(ty)
|
||||
self.print_type(ty);
|
||||
if let Some(ref _default) = default {
|
||||
// FIXME(const_generics_defaults): print the `default` value here
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -958,7 +958,7 @@ fn strip_generic_default_params(
|
||||
ty::GenericParamDefKind::Type { has_default, .. } => {
|
||||
Some((param.def_id, has_default))
|
||||
}
|
||||
ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
|
||||
ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults)
|
||||
})
|
||||
.peekable();
|
||||
let has_default = {
|
||||
|
@ -1834,7 +1834,7 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics<'tcx>) {
|
||||
EntryKind::ConstParam,
|
||||
true,
|
||||
);
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ fn generic_args_to_print(
|
||||
self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
|
||||
)
|
||||
}
|
||||
ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
|
||||
ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults)
|
||||
}
|
||||
})
|
||||
.count();
|
||||
|
@ -5,7 +5,7 @@
|
||||
self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
|
||||
};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
|
||||
@ -56,12 +56,26 @@ fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a,
|
||||
self.expect(&token::Colon)?;
|
||||
let ty = self.parse_ty()?;
|
||||
|
||||
// Parse optional const generics default value, taking care of feature gating the spans
|
||||
// with the unstable syntax mechanism.
|
||||
let default = if self.eat(&token::Eq) {
|
||||
// The gated span goes from the `=` to the end of the const argument that follows (and
|
||||
// which could be a block expression).
|
||||
let start = self.prev_token.span;
|
||||
let const_arg = self.parse_const_arg()?;
|
||||
let span = start.to(const_arg.value.span);
|
||||
self.sess.gated_spans.gate(sym::const_generics_defaults, span);
|
||||
Some(const_arg)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(GenericParam {
|
||||
ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: preceding_attrs.into(),
|
||||
bounds: Vec::new(),
|
||||
kind: GenericParamKind::Const { ty, kw_span: const_span },
|
||||
kind: GenericParamKind::Const { ty, kw_span: const_span, default },
|
||||
is_placeholder: false,
|
||||
})
|
||||
}
|
||||
|
@ -515,6 +515,23 @@ pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by
|
||||
/// the caller.
|
||||
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
|
||||
// Parse const argument.
|
||||
let value = if let token::OpenDelim(token::Brace) = self.token.kind {
|
||||
self.parse_block_expr(
|
||||
None,
|
||||
self.token.span,
|
||||
BlockCheckMode::Default,
|
||||
ast::AttrVec::new(),
|
||||
)?
|
||||
} else {
|
||||
self.handle_unambiguous_unbraced_const_arg()?
|
||||
};
|
||||
Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
||||
}
|
||||
|
||||
/// Parse a generic argument in a path segment.
|
||||
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
||||
fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
|
||||
@ -524,17 +541,7 @@ fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
|
||||
GenericArg::Lifetime(self.expect_lifetime())
|
||||
} else if self.check_const_arg() {
|
||||
// Parse const argument.
|
||||
let value = if let token::OpenDelim(token::Brace) = self.token.kind {
|
||||
self.parse_block_expr(
|
||||
None,
|
||||
self.token.span,
|
||||
BlockCheckMode::Default,
|
||||
ast::AttrVec::new(),
|
||||
)?
|
||||
} else {
|
||||
self.handle_unambiguous_unbraced_const_arg()?
|
||||
};
|
||||
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
||||
GenericArg::Const(self.parse_const_arg()?)
|
||||
} else if self.check_type() {
|
||||
// Parse type argument.
|
||||
match self.parse_ty() {
|
||||
|
@ -443,7 +443,7 @@ fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
|
||||
|
||||
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
|
||||
let kind = match &p.kind {
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
hir::GenericParamKind::Type { default, .. } if default.is_some() => {
|
||||
AnnotationKind::Container
|
||||
}
|
||||
|
@ -586,7 +586,8 @@ fn visit_generics(&mut self, generics: &'ast Generics) {
|
||||
// Allow all following defaults to refer to this type parameter.
|
||||
default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
|
||||
}
|
||||
GenericParamKind::Const { ref ty, kw_span: _ } => {
|
||||
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
|
||||
// FIXME(const_generics_defaults): handle `default` value here
|
||||
for bound in ¶m.bounds {
|
||||
self.visit_param_bound(bound);
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ enum ResolutionError<'a> {
|
||||
/// Error E0530: `X` bindings cannot shadow `Y`s.
|
||||
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
|
||||
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
|
||||
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
|
||||
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
|
||||
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
|
||||
ParamInTyOfConstParam(Symbol),
|
||||
/// constant values inside of type parameter defaults must not depend on generic parameters.
|
||||
|
@ -1343,9 +1343,12 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
hir::GenericParamKind::Const { ref ty } => {
|
||||
hir::GenericParamKind::Const { ref ty, ref default } => {
|
||||
self.process_bounds(param.bounds);
|
||||
self.visit_ty(ty);
|
||||
if let Some(default) = default {
|
||||
self.visit_anon_const(default);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -614,9 +614,13 @@ fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<
|
||||
start: offset + text.len(),
|
||||
end: offset + text.len() + param_text.as_str().len(),
|
||||
});
|
||||
if let hir::GenericParamKind::Const { ref ty } = param.kind {
|
||||
if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind {
|
||||
param_text.push_str(": ");
|
||||
param_text.push_str(&ty_to_string(&ty));
|
||||
if let Some(ref _default) = default {
|
||||
// FIXME(const_generics_defaults): push the `default` value here
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
if !param.bounds.is_empty() {
|
||||
param_text.push_str(": ");
|
||||
|
@ -368,6 +368,7 @@
|
||||
const_fn_transmute,
|
||||
const_fn_union,
|
||||
const_generics,
|
||||
const_generics_defaults,
|
||||
const_if_match,
|
||||
const_impl_trait,
|
||||
const_in_array_repeat_expressions,
|
||||
|
@ -387,7 +387,7 @@ pub(crate) fn check_generic_arg_count(
|
||||
defaults.types += has_default as usize
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ fn inferred_kind(
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
let ty = tcx.at(self.span).type_of(param.def_id);
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
if infer_args {
|
||||
// No const parameters were provided, we can infer all.
|
||||
self.astconv.ct_infer(ty, Some(param), self.span).into()
|
||||
|
@ -1376,7 +1376,7 @@ fn inferred_kind(
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
// No const parameters were provided, we have to infer them.
|
||||
self.fcx.var_for_def(self.span, param)
|
||||
}
|
||||
|
@ -286,9 +286,9 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
|
||||
// We currently only check wf of const params here.
|
||||
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),
|
||||
|
||||
// Const parameters are well formed if their
|
||||
// type is structural match.
|
||||
hir::GenericParamKind::Const { ty: hir_ty } => {
|
||||
// Const parameters are well formed if their type is structural match.
|
||||
// FIXME(const_generics_defaults): we also need to check that the `default` is wf.
|
||||
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
|
||||
let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
|
||||
|
||||
let err_ty_str;
|
||||
@ -785,7 +785,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
}
|
||||
|
||||
GenericParamDefKind::Const => {
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
let def_id = self.tcx.hir().local_def_id(param.hir_id);
|
||||
self.tcx.ensure().type_of(def_id);
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -607,11 +607,12 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
|
||||
synthetic,
|
||||
},
|
||||
),
|
||||
hir::GenericParamKind::Const { ref ty } => (
|
||||
hir::GenericParamKind::Const { ref ty, default: _ } => (
|
||||
self.name.ident().name,
|
||||
GenericParamDefKind::Const {
|
||||
did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
|
||||
ty: ty.clean(cx),
|
||||
// FIXME(const_generics_defaults): add `default` field here for docs
|
||||
},
|
||||
),
|
||||
};
|
||||
@ -1385,7 +1386,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type {
|
||||
if let Some(ct) = const_ {
|
||||
ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
|
||||
}
|
||||
// FIXME(const_generics:defaults)
|
||||
// FIXME(const_generics_defaults)
|
||||
indices.consts += 1;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn foo<const SIZE: usize = 5>() {}
|
||||
//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
|
||||
//~^ ERROR default values for const generic parameters are experimental
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
|
||||
error[E0658]: default values for const generic parameters are experimental
|
||||
--> $DIR/default_function_param.rs:1:26
|
||||
|
|
||||
LL | fn foo<const SIZE: usize = 5>() {}
|
||||
| ^ expected one of 7 possible tokens
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
trait Foo<const KIND: bool = true> {}
|
||||
//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
|
||||
//~^ ERROR default values for const generic parameters are experimental
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,12 @@
|
||||
error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=`
|
||||
error[E0658]: default values for const generic parameters are experimental
|
||||
--> $DIR/default_trait_param.rs:1:28
|
||||
|
|
||||
LL | trait Foo<const KIND: bool = true> {}
|
||||
| ^ expected one of 7 possible tokens
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -7,7 +7,7 @@
|
||||
//[full]~^ ERROR constant values inside of type parameter defaults
|
||||
//[min]~^^ ERROR generic parameters may not be used in const operations
|
||||
|
||||
// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults.
|
||||
// FIXME(const_generics_defaults): We still don't know how to deal with type defaults.
|
||||
struct Bar<T = [u8; N], const N: usize>(T);
|
||||
//~^ ERROR constant values inside of type parameter defaults
|
||||
//~| ERROR type parameters with a default
|
||||
|
@ -0,0 +1,9 @@
|
||||
#[cfg(FALSE)]
|
||||
struct A<const N: usize = 3>;
|
||||
//~^ ERROR default values for const generic parameters are experimental
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn foo<const B: bool = false>() {}
|
||||
//~^ ERROR default values for const generic parameters are experimental
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,21 @@
|
||||
error[E0658]: default values for const generic parameters are experimental
|
||||
--> $DIR/feature-gate-const_generics_defaults.rs:2:25
|
||||
|
|
||||
LL | struct A<const N: usize = 3>;
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: default values for const generic parameters are experimental
|
||||
--> $DIR/feature-gate-const_generics_defaults.rs:6:22
|
||||
|
|
||||
LL | fn foo<const B: bool = false>() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
= help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -407,6 +407,10 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
|
||||
eq_expr(&l.value, &r.value)
|
||||
}
|
||||
|
||||
pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool {
|
||||
matches!(
|
||||
(l, r),
|
||||
@ -497,7 +501,8 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool {
|
||||
&& match (&l.kind, &r.kind) {
|
||||
(Lifetime, Lifetime) => true,
|
||||
(Type { default: l }, Type { default: r }) => both(l, r, |l, r| eq_ty(l, r)),
|
||||
(Const { ty: l, kw_span: _ }, Const { ty: r, kw_span: _ }) => eq_ty(l, r),
|
||||
(Const { ty: lt, kw_span: _ , default: ld}, Const { ty: rt, kw_span: _, default: rd }) =>
|
||||
eq_ty(lt, rt) && both(ld, rd, |ld, rd| eq_anon_const(ld, rd)),
|
||||
_ => false,
|
||||
}
|
||||
&& over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r))
|
||||
|
Loading…
Reference in New Issue
Block a user