Add ast_const_to_const
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
parent
f761c414b1
commit
f7cd97f786
1 changed files with 74 additions and 11 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue