Early error for mixing order of const and type parameters

This commit is contained in:
varkor 2019-05-04 14:38:10 +01:00
parent 47f373128a
commit 3e6787cb4c
3 changed files with 28 additions and 14 deletions

View file

@ -21,7 +21,7 @@ use syntax::visit::{self, Visitor};
use syntax::{span_err, struct_span_err, walk_list}; use syntax::{span_err, struct_span_err, walk_list};
use syntax_ext::proc_macro_decls::is_proc_macro_attr; use syntax_ext::proc_macro_decls::is_proc_macro_attr;
use syntax_pos::{Span, MultiSpan}; use syntax_pos::{Span, MultiSpan};
use errors::Applicability; use errors::{Applicability, FatalError};
use log::debug; use log::debug;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -368,6 +368,8 @@ fn validate_generics_order<'a>(
let mut max_param: Option<ParamKindOrd> = None; let mut max_param: Option<ParamKindOrd> = None;
let mut out_of_order = FxHashMap::default(); let mut out_of_order = FxHashMap::default();
let mut param_idents = vec![]; let mut param_idents = vec![];
let mut found_type = false;
let mut found_const = false;
for (kind, bounds, span, ident) in generics { for (kind, bounds, span, ident) in generics {
if let Some(ident) = ident { if let Some(ident) = ident {
@ -381,6 +383,11 @@ fn validate_generics_order<'a>(
} }
Some(_) | None => *max_param = Some(kind), Some(_) | None => *max_param = Some(kind),
}; };
match kind {
ParamKindOrd::Type => found_type = true,
ParamKindOrd::Const => found_const = true,
_ => {}
}
} }
let mut ordered_params = "<".to_string(); let mut ordered_params = "<".to_string();
@ -408,8 +415,8 @@ fn validate_generics_order<'a>(
GenericPosition::Arg => "argument", GenericPosition::Arg => "argument",
}; };
for (param_ord, (max_param, spans)) in out_of_order { for (param_ord, (max_param, spans)) in &out_of_order {
let mut err = handler.struct_span_err(spans, let mut err = handler.struct_span_err(spans.clone(),
&format!( &format!(
"{} {pos}s must be declared prior to {} {pos}s", "{} {pos}s must be declared prior to {} {pos}s",
param_ord, param_ord,
@ -430,6 +437,13 @@ fn validate_generics_order<'a>(
} }
err.emit(); err.emit();
} }
// FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
// if we don't. Const parameters and type parameters can currently conflict if they
// are out-of-order.
if !out_of_order.is_empty() && found_type && found_const {
FatalError.raise();
}
} }
impl<'a> Visitor<'a> for AstValidator<'a> { impl<'a> Visitor<'a> for AstValidator<'a> {

View file

@ -1,12 +1,12 @@
#![feature(const_generics)] #![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn foo<const X: (), T>(_: &T) {
//~^ ERROR type parameters must be declared prior to const parameters
}
fn bar<const X: (), 'a>(_: &'a ()) { fn bar<const X: (), 'a>(_: &'a ()) {
//~^ ERROR lifetime parameters must be declared prior to const parameters //~^ ERROR lifetime parameters must be declared prior to const parameters
} }
fn foo<const X: (), T>(_: &T) {
//~^ ERROR type parameters must be declared prior to const parameters
}
fn main() {} fn main() {}

View file

@ -4,17 +4,17 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t
LL | #![feature(const_generics)] LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: type parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:4:21
|
LL | fn foo<const X: (), T>(_: &T) {
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
error: lifetime parameters must be declared prior to const parameters error: lifetime parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:8:21 --> $DIR/const-param-before-other-params.rs:4:21
| |
LL | fn bar<const X: (), 'a>(_: &'a ()) { LL | fn bar<const X: (), 'a>(_: &'a ()) {
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
error: type parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:8:21
|
LL | fn foo<const X: (), T>(_: &T) {
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors