about summary refs log tree commit diff
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
authorAmanieu d'Antras <amanieu@gmail.com>2021-02-24 06:46:30 +0000
committerAmanieu d'Antras <amanieu@gmail.com>2021-02-24 06:46:30 +0000
commit00eca69bffcb4ef95ba1dd6013b840bf12a85804 (patch)
treea0f9e23cfc467a9b8859909622450a5fb2a413db /compiler/rustc_resolve
parent69cde44390de43748904bceb808e2e1b097e62a8 (diff)
Properly reject non-const arguments
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/src/late.rs52
1 files changed, 50 insertions, 2 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 701d48a982d..877633820be 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -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> {