Skip to content

Commit 00eca69

Browse files
committed
Properly reject non-const arguments
1 parent 69cde44 commit 00eca69

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

compiler/rustc_resolve/src/late.rs

+50-2
Original file line numberDiff line numberDiff line change
@@ -2326,8 +2326,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
23262326

23272327
ExprKind::Call(ref callee, ref arguments) => {
23282328
self.resolve_expr(callee, Some(expr));
2329-
for argument in arguments {
2330-
self.resolve_expr(argument, None);
2329+
let const_args = self.legacy_const_generic_args(callee).unwrap_or(Vec::new());
2330+
for (idx, argument) in arguments.iter().enumerate() {
2331+
if const_args.contains(&idx) {
2332+
self.with_constant_rib(
2333+
IsRepeatExpr::No,
2334+
argument.is_potential_trivial_const_param(),
2335+
None,
2336+
|this| {
2337+
this.resolve_expr(argument, None);
2338+
},
2339+
);
2340+
} else {
2341+
self.resolve_expr(argument, None);
2342+
}
23312343
}
23322344
}
23332345
ExprKind::Type(ref type_expr, ref ty) => {
@@ -2406,6 +2418,42 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
24062418
Some((ident.name, ns)),
24072419
)
24082420
}
2421+
2422+
/// Checks if an expression refers to a function marked with
2423+
/// `#[rustc_legacy_const_generics]` and returns the argument index list
2424+
/// from the attribute.
2425+
fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> {
2426+
if let ExprKind::Path(None, path) = &expr.kind {
2427+
if path.segments.last().unwrap().args.is_some() {
2428+
return None;
2429+
}
2430+
if let Some(partial_res) = self.r.get_partial_res(expr.id) {
2431+
if partial_res.unresolved_segments() != 0 {
2432+
return None;
2433+
}
2434+
if let Res::Def(def::DefKind::Fn, def_id) = partial_res.base_res() {
2435+
if def_id.is_local() {
2436+
return None;
2437+
}
2438+
let attrs = self.r.cstore().item_attrs(def_id, self.r.session);
2439+
let attr = attrs
2440+
.iter()
2441+
.find(|a| self.r.session.check_name(a, sym::rustc_legacy_const_generics))?;
2442+
let mut ret = vec![];
2443+
for meta in attr.meta_item_list()? {
2444+
match meta.literal()?.kind {
2445+
LitKind::Int(a, _) => {
2446+
ret.push(a as usize);
2447+
}
2448+
_ => panic!("invalid arg index"),
2449+
}
2450+
}
2451+
return Some(ret);
2452+
}
2453+
}
2454+
}
2455+
None
2456+
}
24092457
}
24102458

24112459
impl<'a> Resolver<'a> {
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// aux-build:legacy-const-generics.rs
2+
3+
extern crate legacy_const_generics;
4+
5+
fn foo<const N: usize>() {
6+
let a = 1;
7+
legacy_const_generics::foo(0, a, 2);
8+
//~^ ERROR attempt to use a non-constant value in a constant
9+
10+
legacy_const_generics::foo(0, N, 2);
11+
12+
legacy_const_generics::foo(0, N + 1, 2);
13+
//~^ ERROR generic parameters may not be used in const operations
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0435]: attempt to use a non-constant value in a constant
2+
--> $DIR/legacy-const-generics-bad.rs:7:35
3+
|
4+
LL | let a = 1;
5+
| ----- help: consider using `const` instead of `let`: `const a`
6+
LL | legacy_const_generics::foo(0, a, 2);
7+
| ^ non-constant value
8+
9+
error: generic parameters may not be used in const operations
10+
--> $DIR/legacy-const-generics-bad.rs:12:35
11+
|
12+
LL | legacy_const_generics::foo(0, N + 1, 2);
13+
| ^ cannot perform const operation using `N`
14+
|
15+
= help: const parameters may only be used as standalone arguments, i.e. `N`
16+
= help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0435`.

0 commit comments

Comments
 (0)