sort generic param order in generics_of
This commit is contained in:
parent
5da2e53f47
commit
6cb584608c
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
|
||||
|
9
src/test/ui/const-generics/argument_order.rs
Normal file
9
src/test/ui/const-generics/argument_order.rs
Normal file
@ -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() { }
|
16
src/test/ui/const-generics/argument_order.stderr
Normal file
16
src/test/ui/const-generics/argument_order.stderr
Normal file
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user