Skip to content

Commit

Permalink
sort generic param order in generics_of
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Mar 19, 2020
1 parent 5da2e53 commit 6cb5846
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 37 deletions.
2 changes: 2 additions & 0 deletions src/librustc_ast_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
94 changes: 57 additions & 37 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/const-generics/argument_order.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 16 additions & 0 deletions src/test/ui/const-generics/argument_order.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 6cb5846

Please sign in to comment.