Skip to content

Commit 6cb5846

Browse files
committed
sort generic param order in generics_of
1 parent 5da2e53 commit 6cb5846

File tree

4 files changed

+84
-37
lines changed

4 files changed

+84
-37
lines changed

src/librustc_ast_passes/ast_validation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@ impl<'a> AstValidator<'a> {
645645
}
646646
}
647647

648+
/// Checks that generic parameters are in the correct order,
649+
/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
648650
fn validate_generic_param_order<'a>(
649651
sess: &Session,
650652
handler: &rustc_errors::Handler,

src/librustc_typeck/collect.rs

+57-37
Original file line numberDiff line numberDiff line change
@@ -1291,47 +1291,67 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
12911291
// Now create the real type and const parameters.
12921292
let type_start = own_start - has_self as u32 + params.len() as u32;
12931293
let mut i = 0;
1294-
params.extend(ast_generics.params.iter().filter_map(|param| {
1295-
let kind = match param.kind {
1296-
GenericParamKind::Type { ref default, synthetic, .. } => {
1297-
if !allow_defaults && default.is_some() {
1298-
if !tcx.features().default_type_parameter_fallback {
1299-
tcx.struct_span_lint_hir(
1300-
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
1301-
param.hir_id,
1302-
param.span,
1303-
|lint| {
1304-
lint.build(
1305-
"defaults for type parameters are only allowed in \
1306-
`struct`, `enum`, `type`, or `trait` definitions.",
1307-
)
1308-
.emit();
1309-
},
1310-
);
1311-
}
1312-
}
13131294

1314-
ty::GenericParamDefKind::Type {
1315-
has_default: default.is_some(),
1316-
object_lifetime_default: object_lifetime_defaults
1317-
.as_ref()
1318-
.map_or(rl::Set1::Empty, |o| o[i]),
1319-
synthetic,
1295+
// FIXME(const_generics): a few places in the compiler expect generic params
1296+
// to be in the order lifetimes, then type params, then const params.
1297+
//
1298+
// To prevent internal errors in case a const params are supplied in front of
1299+
// type parameters we first add all type params, then all const params.
1300+
params.extend(ast_generics.params.iter().filter_map(|param| {
1301+
if let GenericParamKind::Type { ref default, synthetic, .. } = param.kind {
1302+
if !allow_defaults && default.is_some() {
1303+
if !tcx.features().default_type_parameter_fallback {
1304+
tcx.struct_span_lint_hir(
1305+
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
1306+
param.hir_id,
1307+
param.span,
1308+
|lint| {
1309+
lint.build(
1310+
"defaults for type parameters are only allowed in \
1311+
`struct`, `enum`, `type`, or `trait` definitions.",
1312+
)
1313+
.emit();
1314+
},
1315+
);
13201316
}
13211317
}
1322-
GenericParamKind::Const { .. } => ty::GenericParamDefKind::Const,
1323-
_ => return None,
1324-
};
13251318

1326-
let param_def = ty::GenericParamDef {
1327-
index: type_start + i as u32,
1328-
name: param.name.ident().name,
1329-
def_id: tcx.hir().local_def_id(param.hir_id),
1330-
pure_wrt_drop: param.pure_wrt_drop,
1331-
kind,
1332-
};
1333-
i += 1;
1334-
Some(param_def)
1319+
let kind = ty::GenericParamDefKind::Type {
1320+
has_default: default.is_some(),
1321+
object_lifetime_default: object_lifetime_defaults
1322+
.as_ref()
1323+
.map_or(rl::Set1::Empty, |o| o[i]),
1324+
synthetic,
1325+
};
1326+
1327+
let param_def = ty::GenericParamDef {
1328+
index: type_start + i as u32,
1329+
name: param.name.ident().name,
1330+
def_id: tcx.hir().local_def_id(param.hir_id),
1331+
pure_wrt_drop: param.pure_wrt_drop,
1332+
kind,
1333+
};
1334+
i += 1;
1335+
Some(param_def)
1336+
} else {
1337+
None
1338+
}
1339+
}));
1340+
1341+
params.extend(ast_generics.params.iter().filter_map(|param| {
1342+
if let GenericParamKind::Const { .. } = param.kind {
1343+
let param_def = ty::GenericParamDef {
1344+
index: type_start + i as u32,
1345+
name: param.name.ident().name,
1346+
def_id: tcx.hir().local_def_id(param.hir_id),
1347+
pure_wrt_drop: param.pure_wrt_drop,
1348+
kind: ty::GenericParamDefKind::Const,
1349+
};
1350+
i += 1;
1351+
Some(param_def)
1352+
} else {
1353+
None
1354+
}
13351355
}));
13361356

13371357
// provide junk type parameter defs - the only place that
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
struct Bad<const N: usize, T> { //~ ERROR type parameters must be declared prior
5+
arr: [u8; { N }],
6+
another: T,
7+
}
8+
9+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: type parameters must be declared prior to const parameters
2+
--> $DIR/argument_order.rs:4:28
3+
|
4+
LL | struct Bad<const N: usize, T> {
5+
| -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
6+
7+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
8+
--> $DIR/argument_order.rs:1:12
9+
|
10+
LL | #![feature(const_generics)]
11+
| ^^^^^^^^^^^^^^
12+
|
13+
= note: `#[warn(incomplete_features)]` on by default
14+
15+
error: aborting due to previous error
16+

0 commit comments

Comments
 (0)