From f7cd97f7863fb9ee017aacec134589c211786c88 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 20 Feb 2019 01:16:42 +0000 Subject: [PATCH] Add ast_const_to_const Co-Authored-By: Gabriel Smith --- src/librustc_typeck/astconv.rs | 85 +++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5dbcf908020b..1dec2d483b80 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(¶m)) => { match (arg, ¶m.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,