Skip to content

Commit 3e6787c

Browse files
committed
Early error for mixing order of const and type parameters
1 parent 47f3731 commit 3e6787c

File tree

3 files changed

+27
-13
lines changed

3 files changed

+27
-13
lines changed

src/librustc_passes/ast_validation.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use syntax::visit::{self, Visitor};
2121
use syntax::{span_err, struct_span_err, walk_list};
2222
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
2323
use syntax_pos::{Span, MultiSpan};
24-
use errors::Applicability;
24+
use errors::{Applicability, FatalError};
2525
use log::debug;
2626

2727
#[derive(Copy, Clone, Debug)]
@@ -368,6 +368,8 @@ fn validate_generics_order<'a>(
368368
let mut max_param: Option<ParamKindOrd> = None;
369369
let mut out_of_order = FxHashMap::default();
370370
let mut param_idents = vec![];
371+
let mut found_type = false;
372+
let mut found_const = false;
371373

372374
for (kind, bounds, span, ident) in generics {
373375
if let Some(ident) = ident {
@@ -381,6 +383,11 @@ fn validate_generics_order<'a>(
381383
}
382384
Some(_) | None => *max_param = Some(kind),
383385
};
386+
match kind {
387+
ParamKindOrd::Type => found_type = true,
388+
ParamKindOrd::Const => found_const = true,
389+
_ => {}
390+
}
384391
}
385392

386393
let mut ordered_params = "<".to_string();
@@ -408,8 +415,8 @@ fn validate_generics_order<'a>(
408415
GenericPosition::Arg => "argument",
409416
};
410417

411-
for (param_ord, (max_param, spans)) in out_of_order {
412-
let mut err = handler.struct_span_err(spans,
418+
for (param_ord, (max_param, spans)) in &out_of_order {
419+
let mut err = handler.struct_span_err(spans.clone(),
413420
&format!(
414421
"{} {pos}s must be declared prior to {} {pos}s",
415422
param_ord,
@@ -430,6 +437,13 @@ fn validate_generics_order<'a>(
430437
}
431438
err.emit();
432439
}
440+
441+
// FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
442+
// if we don't. Const parameters and type parameters can currently conflict if they
443+
// are out-of-order.
444+
if !out_of_order.is_empty() && found_type && found_const {
445+
FatalError.raise();
446+
}
433447
}
434448

435449
impl<'a> Visitor<'a> for AstValidator<'a> {
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#![feature(const_generics)]
22
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
33

4-
fn foo<const X: (), T>(_: &T) {
5-
//~^ ERROR type parameters must be declared prior to const parameters
6-
}
7-
84
fn bar<const X: (), 'a>(_: &'a ()) {
95
//~^ ERROR lifetime parameters must be declared prior to const parameters
106
}
117

8+
fn foo<const X: (), T>(_: &T) {
9+
//~^ ERROR type parameters must be declared prior to const parameters
10+
}
11+
1212
fn main() {}

src/test/ui/const-generics/const-param-before-other-params.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t
44
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66

7-
error: type parameters must be declared prior to const parameters
7+
error: lifetime parameters must be declared prior to const parameters
88
--> $DIR/const-param-before-other-params.rs:4:21
99
|
10-
LL | fn foo<const X: (), T>(_: &T) {
11-
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
10+
LL | fn bar<const X: (), 'a>(_: &'a ()) {
11+
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
1212

13-
error: lifetime parameters must be declared prior to const parameters
13+
error: type parameters must be declared prior to const parameters
1414
--> $DIR/const-param-before-other-params.rs:8:21
1515
|
16-
LL | fn bar<const X: (), 'a>(_: &'a ()) {
17-
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
16+
LL | fn foo<const X: (), T>(_: &T) {
17+
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
1818

1919
error: aborting due to 2 previous errors
2020

0 commit comments

Comments
 (0)