Early error for mixing order of const and type parameters
This commit is contained in:
parent
47f373128a
commit
3e6787cb4c
3 changed files with 28 additions and 14 deletions
|
@ -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> {
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue