Skip to content

Commit

Permalink
Auto merge of #90207 - BoxyUwU:stabilise_cg_defaults, r=lcnr
Browse files Browse the repository at this point in the history
Stabilise `feature(const_generics_defaults)`

`feature(const_generics_defaults)` is complete implementation wise and has a pretty extensive test suite so I think is ready for stabilisation.

needs stabilisation report and maybe an RFC 😅

r? `@lcnr`
cc `@rust-lang/project-const-generics`
  • Loading branch information
bors committed Dec 12, 2021
2 parents 4c9bdf4 + 1e896df commit 753e569
Show file tree
Hide file tree
Showing 94 changed files with 101 additions and 380 deletions.
11 changes: 2 additions & 9 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,7 @@ pub type GenericBounds = Vec<GenericBound>;
pub enum ParamKindOrd {
Lifetime,
Type,
// `unordered` is only `true` if `sess.unordered_const_ty_params()`
// returns true. Specifically, if it's only `min_const_generics`, it will still require
// ordering consts after types.
Const { unordered: bool },
Const,
// `Infer` is not actually constructed directly from the AST, but is implicitly constructed
// during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last.
Infer,
Expand All @@ -346,11 +343,7 @@ impl Ord for ParamKindOrd {
use ParamKindOrd::*;
let to_int = |v| match v {
Lifetime => 0,
Infer | Type | Const { unordered: true } => 1,
// technically both consts should be ordered equally,
// but only one is ever encountered at a time, so this is
// fine.
Const { unordered: false } => 2,
Infer | Type | Const => 1,
};

to_int(*self).cmp(&to_int(*other))
Expand Down
28 changes: 3 additions & 25 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,6 @@ impl<'a> AstValidator<'a> {
/// Checks that generic parameters are in the correct order,
/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
fn validate_generic_param_order(
sess: &Session,
handler: &rustc_errors::Handler,
generics: &[GenericParam],
span: Span,
Expand All @@ -911,8 +910,7 @@ fn validate_generic_param_order(
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()),
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
let ty = pprust::ty_to_string(ty);
let unordered = sess.features_untracked().unordered_const_ty_params();
(ParamKindOrd::Const { unordered }, format!("const {}: {}", ident, ty))
(ParamKindOrd::Const, format!("const {}: {}", ident, ty))
}
};
param_idents.push((kind, ord_kind, bounds, idx, ident));
Expand Down Expand Up @@ -968,14 +966,7 @@ fn validate_generic_param_order(
);
err.span_suggestion(
span,
&format!(
"reorder the parameters: lifetimes, {}",
if sess.features_untracked().unordered_const_ty_params() {
"then consts and types"
} else {
"then types, then consts"
}
),
"reorder the parameters: lifetimes, then consts and types",
ordered_params.clone(),
Applicability::MachineApplicable,
);
Expand Down Expand Up @@ -1342,8 +1333,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}

fn visit_generics(&mut self, generics: &'a Generics) {
let cg_defaults = self.session.features_untracked().unordered_const_ty_params();

let mut prev_param_default = None;
for param in &generics.params {
match param.kind {
Expand All @@ -1358,25 +1347,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
span,
"generic parameters with a default must be trailing",
);
if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults {
err.note(
"using type defaults and const parameters \
in the same parameter list is currently not permitted",
);
}
err.emit();
break;
}
}
}
}

validate_generic_param_order(
self.session,
self.err_handler(),
&generics.params,
generics.span,
);
validate_generic_param_order(self.err_handler(), &generics.params, generics.span);

for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,10 +724,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
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.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ declare_features! (
(accepted, const_fn_union, "1.56.0", Some(51909), None),
/// Allows unsizing coercions in `const fn`.
(accepted, const_fn_unsize, "1.54.0", Some(64992), None),
/// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
(accepted, const_generics_defaults, "1.59.0", Some(44580), None),
/// Allows the use of `if` and `match` in constants.
(accepted, const_if_match, "1.46.0", Some(49146), None),
/// Allows indexing into constant arrays.
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ macro_rules! declare_features {
}
}

pub fn unordered_const_ty_params(&self) -> bool {
self.const_generics_defaults || self.generic_const_exprs || self.adt_const_params
}

/// Some features are known to be incomplete and using them is likely to have
/// unanticipated results, such as compiler crashes. We warn the user about these
/// to alert them.
Expand Down Expand Up @@ -334,8 +330,6 @@ declare_features! (
(active, const_fn_trait_bound, "1.53.0", Some(57563), None),
/// Allows `for _ in _` loops in const contexts.
(active, const_for, "1.56.0", Some(87575), 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),
/// Allows argument and return position `impl Trait` in a `const fn`.
(active, const_impl_trait, "1.48.0", Some(77463), None),
/// Allows using `&mut` in constant functions.
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,11 @@ impl GenericArg<'_> {
}
}

pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd {
pub fn to_ord(&self) -> ast::ParamKindOrd {
match self {
GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
GenericArg::Type(_) => ast::ParamKindOrd::Type,
GenericArg::Const(_) => {
ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
}
GenericArg::Const(_) => ast::ParamKindOrd::Const,
GenericArg::Infer(_) => ast::ParamKindOrd::Infer,
}
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ impl GenericParamDefKind {
GenericParamDefKind::Const { .. } => "constant",
}
}
pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd {
pub fn to_ord(&self) -> ast::ParamKindOrd {
match self {
GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
GenericParamDefKind::Const { .. } => {
ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() }
}
GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const,
}
}
}
Expand Down
17 changes: 3 additions & 14 deletions compiler/rustc_parse/src/parser/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_ast::{
self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
};
use rustc_errors::PResult;
use rustc_span::symbol::{kw, sym};
use rustc_span::symbol::kw;

impl<'a> Parser<'a> {
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
Expand Down Expand Up @@ -59,19 +59,8 @@ impl<'a> Parser<'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
};
// Parse optional const generics default value.
let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None };

Ok(GenericParam {
ident,
Expand Down
36 changes: 4 additions & 32 deletions compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
_ => {}
}

let kind_ord = param.kind.to_ord(tcx);
let arg_ord = arg.to_ord(tcx.features());
let kind_ord = param.kind.to_ord();
let arg_ord = arg.to_ord();

// This note is only true when generic parameters are strictly ordered by their kind.
if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
Expand Down Expand Up @@ -298,26 +298,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.params
.clone()
.into_iter()
.map(|param| {
(
match param.kind {
GenericParamDefKind::Lifetime => {
ParamKindOrd::Lifetime
}
GenericParamDefKind::Type { .. } => {
ParamKindOrd::Type
}
GenericParamDefKind::Const { .. } => {
ParamKindOrd::Const {
unordered: tcx
.features()
.unordered_const_ty_params(),
}
}
},
param,
)
})
.map(|param| (param.kind.to_ord(), param))
.collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
param_types_present.sort_by_key(|(ord, _)| *ord);
let (mut param_types_present, ordered_params): (
Expand All @@ -330,16 +311,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx,
arg,
param,
!args_iter.clone().is_sorted_by_key(|arg| match arg {
GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
GenericArg::Type(_) => ParamKindOrd::Type,
GenericArg::Const(_) => ParamKindOrd::Const {
unordered: tcx
.features()
.unordered_const_ty_params(),
},
GenericArg::Infer(_) => ParamKindOrd::Infer,
}),
!args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
Some(&format!(
"reorder the arguments: {}: `<{}>`",
param_types_present
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),

// 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));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// revisions: cfail
#![feature(generic_const_exprs, adt_const_params, const_generics_defaults)]
#![feature(generic_const_exprs, adt_const_params)]
#![allow(incomplete_features)]
// regression test for #77650
struct C<T, const N: core::num::NonZeroUsize>([T; N.get()])
Expand Down
1 change: 0 additions & 1 deletion src/test/rustdoc/const-generics/const-generic-defaults.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![crate_name = "foo"]
#![feature(const_generics_defaults)]

// @has foo/struct.Foo.html '//pre[@class="rust struct"]' \
// 'pub struct Foo<const M: usize = 10_usize, const N: usize = M, T = i32>(_);'
Expand Down
30 changes: 0 additions & 30 deletions src/test/ui/const-generics/argument_order.min.stderr

This file was deleted.

5 changes: 0 additions & 5 deletions src/test/ui/const-generics/argument_order.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
// revisions: full min
#![cfg_attr(full, feature(const_generics_defaults))]

struct Bad<const N: usize, T> {
//[min]~^ ERROR type parameters must be declared prior to const parameters
arr: [u8; { N }],
another: T,
}

struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
//~^ ERROR lifetime parameters must be declared prior
//[min]~^^ ERROR type parameters must be declared prior to const parameters
a: &'a T,
b: &'b U,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: lifetime parameters must be declared prior to const parameters
--> $DIR/argument_order.rs:10:32
--> $DIR/argument_order.rs:6:32
|
LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
| -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>`

error[E0747]: lifetime provided when a type was expected
--> $DIR/argument_order.rs:18:23
--> $DIR/argument_order.rs:13:23
|
LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>;
| ^^^^^^^
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ error[E0747]: constant provided when a type was expected
|
LL | fn foo<const N: usize>() -> Array<N, ()> {
| ^
|
= note: type arguments must be provided before constant arguments
= help: reorder the arguments: types, then consts: `<T, N>`

error: aborting due to previous error

Expand Down

This file was deleted.

5 changes: 0 additions & 5 deletions src/test/ui/const-generics/const-param-before-other-params.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
// revisions: full min
#![cfg_attr(full, feature(const_generics_defaults))]
#![cfg_attr(full, allow(incomplete_features))]

fn bar<const X: u8, 'a>(_: &'a ()) {
//~^ ERROR lifetime parameters must be declared prior to const parameters
}

fn foo<const X: u8, T>(_: &T) {}
//[min]~^ ERROR type parameters must be declared prior to const parameters

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: lifetime parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:5:21
--> $DIR/const-param-before-other-params.rs:1:21
|
LL | fn bar<const X: u8, 'a>(_: &'a ()) {
| --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: u8>`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(const_generics_defaults)]

pub struct Defaulted<const N: usize=3>;
impl Defaulted {
pub fn new() -> Self {
Expand Down
Loading

0 comments on commit 753e569

Please sign in to comment.