sort generic param order in generics_of

This commit is contained in:
Bastian Kauschke 2020-03-19 20:20:09 +01:00
parent 5da2e53f47
commit 6cb584608c
4 changed files with 84 additions and 37 deletions
src
librustc_ast_passes
librustc_typeck
test/ui/const-generics

@ -645,6 +645,8 @@ 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<'a>(
sess: &Session,
handler: &rustc_errors::Handler,

@ -1291,47 +1291,67 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0;
params.extend(ast_generics.params.iter().filter_map(|param| {
let kind = match param.kind {
GenericParamKind::Type { ref default, synthetic, .. } => {
if !allow_defaults && default.is_some() {
if !tcx.features().default_type_parameter_fallback {
tcx.struct_span_lint_hir(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
|lint| {
lint.build(
"defaults for type parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions.",
)
.emit();
},
);
}
}
ty::GenericParamDefKind::Type {
has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults
.as_ref()
.map_or(rl::Set1::Empty, |o| o[i]),
synthetic,
// FIXME(const_generics): a few places in the compiler expect generic params
// to be in the order lifetimes, then type params, then const params.
//
// To prevent internal errors in case a const params are supplied in front of
// type parameters we first add all type params, then all const params.
params.extend(ast_generics.params.iter().filter_map(|param| {
if let GenericParamKind::Type { ref default, synthetic, .. } = param.kind {
if !allow_defaults && default.is_some() {
if !tcx.features().default_type_parameter_fallback {
tcx.struct_span_lint_hir(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
|lint| {
lint.build(
"defaults for type parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions.",
)
.emit();
},
);
}
}
GenericParamKind::Const { .. } => ty::GenericParamDefKind::Const,
_ => return None,
};
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
name: param.name.ident().name,
def_id: tcx.hir().local_def_id(param.hir_id),
pure_wrt_drop: param.pure_wrt_drop,
kind,
};
i += 1;
Some(param_def)
let kind = ty::GenericParamDefKind::Type {
has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults
.as_ref()
.map_or(rl::Set1::Empty, |o| o[i]),
synthetic,
};
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
name: param.name.ident().name,
def_id: tcx.hir().local_def_id(param.hir_id),
pure_wrt_drop: param.pure_wrt_drop,
kind,
};
i += 1;
Some(param_def)
} else {
None
}
}));
params.extend(ast_generics.params.iter().filter_map(|param| {
if let GenericParamKind::Const { .. } = param.kind {
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
name: param.name.ident().name,
def_id: tcx.hir().local_def_id(param.hir_id),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Const,
};
i += 1;
Some(param_def)
} else {
None
}
}));
// provide junk type parameter defs - the only place that

@ -0,0 +1,9 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
struct Bad<const N: usize, T> { //~ ERROR type parameters must be declared prior
arr: [u8; { N }],
another: T,
}
fn main() { }

@ -0,0 +1,16 @@
error: type parameters must be declared prior to const parameters
--> $DIR/argument_order.rs:4:28
|
LL | struct Bad<const N: usize, T> {
| -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/argument_order.rs:1:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error: aborting due to previous error