Add ast_const_to_const

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
varkor 2019-02-20 01:16:42 +00:00
parent f761c414b1
commit f7cd97f786

View file

@ -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,