about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2019-02-20 01:16:42 +0000
committervarkor <github@varkor.com>2019-03-05 22:13:10 +0000
commitf7cd97f7863fb9ee017aacec134589c211786c88 (patch)
tree824f8601a85cdedb032edd93f95725ac768088ea
parentf761c414b12f3851ddef7b5849bb8fdcf8d75d44 (diff)
downloadrust-f7cd97f7863fb9ee017aacec134589c211786c88.tar.gz
rust-f7cd97f7863fb9ee017aacec134589c211786c88.zip
Add ast_const_to_const
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
-rw-r--r--src/librustc_typeck/astconv.rs85
1 files changed, 74 insertions, 11 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5dbcf908020..1dec2d483b8 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -3,7 +3,7 @@
 //! instance of `AstConv`.
 
 use errors::{Applicability, DiagnosticId};
-use crate::hir::{self, GenericArg, GenericArgs};
+use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
 use crate::hir::def::Def;
 use crate::hir::def_id::DefId;
 use crate::hir::HirVec;
@@ -16,6 +16,7 @@ use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
 use rustc::ty::wf::object_region_bounds;
+use rustc::mir::interpret::ConstValue;
 use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::abi;
 use crate::require_c_abi_if_c_variadic;
@@ -273,6 +274,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         let param_counts = def.own_counts();
         let arg_counts = args.own_counts();
         let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+        let infer_consts = position != GenericArgPosition::Type && arg_counts.consts == 0;
 
         let mut defaults: ty::GenericParamCount = Default::default();
         for param in &def.params {
@@ -281,6 +283,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 GenericParamDefKind::Type { has_default, .. } => {
                     defaults.types += has_default as usize
                 }
+                GenericParamDefKind::Const => {
+                    // FIXME(const_generics:defaults)
+                }
             };
         }
 
@@ -311,11 +316,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             }
         }
 
-        let check_kind_count = |kind,
-                                required,
-                                permitted,
-                                provided,
-                                offset| {
+        let check_kind_count = |kind, required, permitted, provided, offset| {
+            debug!(
+                "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
+                kind,
+                required,
+                permitted,
+                provided,
+                offset
+            );
             // We enforce the following: `required` <= `provided` <= `permitted`.
             // For kinds without defaults (i.e., lifetimes), `required == permitted`.
             // For other kinds (i.e., types), `permitted` may be greater than `required`.
@@ -384,6 +393,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 0,
             );
         }
+        // FIXME(const_generics:defaults)
+        if !infer_consts || arg_counts.consts > param_counts.consts {
+            check_kind_count(
+                "const",
+                param_counts.consts,
+                param_counts.consts,
+                arg_counts.consts,
+                arg_counts.lifetimes + arg_counts.types,
+            );
+        }
+        // Note that type errors are currently be emitted *after* const errors.
         if !infer_types
             || arg_counts.types > param_counts.types - defaults.types - has_self as usize {
             check_kind_count(
@@ -495,7 +515,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     (Some(&arg), Some(&param)) => {
                         match (arg, &param.kind) {
                             (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
-                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => {
+                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. })
+                            | (GenericArg::Const(_), GenericParamDefKind::Const) => {
                                 substs.push(provided_kind(param, arg));
                                 args.next();
                                 params.next();
@@ -606,6 +627,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
                         self.ast_ty_to_ty(&ty).into()
                     }
+                    (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+                        self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into()
+                    }
                     _ => unreachable!(),
                 }
             },
@@ -654,6 +678,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                             tcx.types.err.into()
                         }
                     }
+                    GenericParamDefKind::Const => {
+                        // FIXME(const_generics:defaults)
+                        // We've already errored above about the mismatch.
+                        tcx.types.err.into()
+                    }
                 }
             },
         );
@@ -1609,6 +1638,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             // Case 3. Reference to a top-level value.
             Def::Fn(def_id) |
             Def::Const(def_id) |
+            Def::ConstParam(def_id) |
             Def::Static(def_id, _) => {
                 path_segs.push(PathSeg(def_id, last));
             }
@@ -1797,10 +1827,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, def, segment, false).0
             }
             hir::TyKind::Array(ref ty, ref length) => {
-                let length_def_id = tcx.hir().local_def_id_from_hir_id(length.hir_id);
-                let substs = InternalSubsts::identity_for_item(tcx, length_def_id);
-                let length = ty::LazyConst::Unevaluated(length_def_id, substs);
-                let length = tcx.mk_lazy_const(length);
+                let length = self.ast_const_to_const(length, tcx.types.usize);
                 let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
                 self.normalize_ty(ast_ty.span, array_ty)
             }
@@ -1837,6 +1864,42 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         result_ty
     }
 
+    pub fn ast_const_to_const(
+        &self,
+        ast_const: &hir::AnonConst,
+        ty: Ty<'tcx>
+    ) -> &'tcx ty::LazyConst<'tcx> {
+        debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.id, ast_const);
+
+        let tcx = self.tcx();
+        let def_id = tcx.hir().local_def_id(ast_const.id);
+
+        let mut lazy_const = ty::LazyConst::Unevaluated(
+            def_id,
+            Substs::identity_for_item(tcx, def_id)
+        );
+
+        let expr = &tcx.hir().body(ast_const.body).value;
+        if let ExprKind::Path(ref qpath) = expr.node {
+            if let hir::QPath::Resolved(_, ref path) = qpath {
+                if let Def::ConstParam(def_id) = path.def {
+                    let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+                    let item_id = tcx.hir().get_parent_node(node_id);
+                    let item_def_id = tcx.hir().local_def_id(item_id);
+                    let generics = tcx.generics_of(item_def_id);
+                    let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
+                    let name = tcx.hir().name(node_id).as_interned_str();
+                    lazy_const = ty::LazyConst::Evaluated(ty::Const {
+                        val: ConstValue::Param(ty::ParamConst::new(index, name)),
+                        ty,
+                    })
+                }
+            }
+        };
+
+        tcx.mk_lazy_const(lazy_const)
+    }
+
     pub fn impl_trait_ty_to_ty(
         &self,
         def_id: DefId,