Properly reject non-const arguments

This commit is contained in:
Amanieu d'Antras 2021-02-24 06:46:30 +00:00
parent 69cde44390
commit 00eca69bff
3 changed files with 86 additions and 2 deletions

View file

@ -2326,8 +2326,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Call(ref callee, ref arguments) => {
self.resolve_expr(callee, Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
let const_args = self.legacy_const_generic_args(callee).unwrap_or(Vec::new());
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) => {
@ -2406,6 +2418,42 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
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> {