Properly reject non-const arguments
This commit is contained in:
parent
69cde44390
commit
00eca69bff
3 changed files with 86 additions and 2 deletions
|
@ -2326,8 +2326,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
|
|
||||||
ExprKind::Call(ref callee, ref arguments) => {
|
ExprKind::Call(ref callee, ref arguments) => {
|
||||||
self.resolve_expr(callee, Some(expr));
|
self.resolve_expr(callee, Some(expr));
|
||||||
for argument in arguments {
|
let const_args = self.legacy_const_generic_args(callee).unwrap_or(Vec::new());
|
||||||
self.resolve_expr(argument, None);
|
for (idx, argument) in arguments.iter().enumerate() {
|
||||||
|
if const_args.contains(&idx) {
|
||||||
|
self.with_constant_rib(
|
||||||
|
IsRepeatExpr::No,
|
||||||
|
argument.is_potential_trivial_const_param(),
|
||||||
|
None,
|
||||||
|
|this| {
|
||||||
|
this.resolve_expr(argument, None);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.resolve_expr(argument, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Type(ref type_expr, ref ty) => {
|
ExprKind::Type(ref type_expr, ref ty) => {
|
||||||
|
@ -2406,6 +2418,42 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
Some((ident.name, ns)),
|
Some((ident.name, ns)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if an expression refers to a function marked with
|
||||||
|
/// `#[rustc_legacy_const_generics]` and returns the argument index list
|
||||||
|
/// from the attribute.
|
||||||
|
fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> {
|
||||||
|
if let ExprKind::Path(None, path) = &expr.kind {
|
||||||
|
if path.segments.last().unwrap().args.is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if let Some(partial_res) = self.r.get_partial_res(expr.id) {
|
||||||
|
if partial_res.unresolved_segments() != 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if let Res::Def(def::DefKind::Fn, def_id) = partial_res.base_res() {
|
||||||
|
if def_id.is_local() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let attrs = self.r.cstore().item_attrs(def_id, self.r.session);
|
||||||
|
let attr = attrs
|
||||||
|
.iter()
|
||||||
|
.find(|a| self.r.session.check_name(a, sym::rustc_legacy_const_generics))?;
|
||||||
|
let mut ret = vec![];
|
||||||
|
for meta in attr.meta_item_list()? {
|
||||||
|
match meta.literal()?.kind {
|
||||||
|
LitKind::Int(a, _) => {
|
||||||
|
ret.push(a as usize);
|
||||||
|
}
|
||||||
|
_ => panic!("invalid arg index"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Some(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Resolver<'a> {
|
impl<'a> Resolver<'a> {
|
||||||
|
|
16
src/test/ui/legacy-const-generics-bad.rs
Normal file
16
src/test/ui/legacy-const-generics-bad.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// aux-build:legacy-const-generics.rs
|
||||||
|
|
||||||
|
extern crate legacy_const_generics;
|
||||||
|
|
||||||
|
fn foo<const N: usize>() {
|
||||||
|
let a = 1;
|
||||||
|
legacy_const_generics::foo(0, a, 2);
|
||||||
|
//~^ ERROR attempt to use a non-constant value in a constant
|
||||||
|
|
||||||
|
legacy_const_generics::foo(0, N, 2);
|
||||||
|
|
||||||
|
legacy_const_generics::foo(0, N + 1, 2);
|
||||||
|
//~^ ERROR generic parameters may not be used in const operations
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
20
src/test/ui/legacy-const-generics-bad.stderr
Normal file
20
src/test/ui/legacy-const-generics-bad.stderr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0435]: attempt to use a non-constant value in a constant
|
||||||
|
--> $DIR/legacy-const-generics-bad.rs:7:35
|
||||||
|
|
|
||||||
|
LL | let a = 1;
|
||||||
|
| ----- help: consider using `const` instead of `let`: `const a`
|
||||||
|
LL | legacy_const_generics::foo(0, a, 2);
|
||||||
|
| ^ non-constant value
|
||||||
|
|
||||||
|
error: generic parameters may not be used in const operations
|
||||||
|
--> $DIR/legacy-const-generics-bad.rs:12:35
|
||||||
|
|
|
||||||
|
LL | legacy_const_generics::foo(0, N + 1, 2);
|
||||||
|
| ^ cannot perform const operation using `N`
|
||||||
|
|
|
||||||
|
= help: const parameters may only be used as standalone arguments, i.e. `N`
|
||||||
|
= help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0435`.
|
Loading…
Add table
Add a link
Reference in a new issue