Skip to content

Commit f7cd97f

Browse files
varkoryodaldevoid
andcommitted
Add ast_const_to_const
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
1 parent f761c41 commit f7cd97f

File tree

1 file changed

+74
-11
lines changed

1 file changed

+74
-11
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! instance of `AstConv`.
44
55
use errors::{Applicability, DiagnosticId};
6-
use crate::hir::{self, GenericArg, GenericArgs};
6+
use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
77
use crate::hir::def::Def;
88
use crate::hir::def_id::DefId;
99
use crate::hir::HirVec;
@@ -16,6 +16,7 @@ use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
1616
use rustc::ty::{GenericParamDef, GenericParamDefKind};
1717
use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
1818
use rustc::ty::wf::object_region_bounds;
19+
use rustc::mir::interpret::ConstValue;
1920
use rustc_data_structures::sync::Lrc;
2021
use rustc_target::spec::abi;
2122
use crate::require_c_abi_if_c_variadic;
@@ -273,6 +274,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
273274
let param_counts = def.own_counts();
274275
let arg_counts = args.own_counts();
275276
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
277+
let infer_consts = position != GenericArgPosition::Type && arg_counts.consts == 0;
276278

277279
let mut defaults: ty::GenericParamCount = Default::default();
278280
for param in &def.params {
@@ -281,6 +283,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
281283
GenericParamDefKind::Type { has_default, .. } => {
282284
defaults.types += has_default as usize
283285
}
286+
GenericParamDefKind::Const => {
287+
// FIXME(const_generics:defaults)
288+
}
284289
};
285290
}
286291

@@ -311,11 +316,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
311316
}
312317
}
313318

314-
let check_kind_count = |kind,
315-
required,
316-
permitted,
317-
provided,
318-
offset| {
319+
let check_kind_count = |kind, required, permitted, provided, offset| {
320+
debug!(
321+
"check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
322+
kind,
323+
required,
324+
permitted,
325+
provided,
326+
offset
327+
);
319328
// We enforce the following: `required` <= `provided` <= `permitted`.
320329
// For kinds without defaults (i.e., lifetimes), `required == permitted`.
321330
// 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 {
384393
0,
385394
);
386395
}
396+
// FIXME(const_generics:defaults)
397+
if !infer_consts || arg_counts.consts > param_counts.consts {
398+
check_kind_count(
399+
"const",
400+
param_counts.consts,
401+
param_counts.consts,
402+
arg_counts.consts,
403+
arg_counts.lifetimes + arg_counts.types,
404+
);
405+
}
406+
// Note that type errors are currently be emitted *after* const errors.
387407
if !infer_types
388408
|| arg_counts.types > param_counts.types - defaults.types - has_self as usize {
389409
check_kind_count(
@@ -495,7 +515,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
495515
(Some(&arg), Some(&param)) => {
496516
match (arg, &param.kind) {
497517
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
498-
| (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => {
518+
| (GenericArg::Type(_), GenericParamDefKind::Type { .. })
519+
| (GenericArg::Const(_), GenericParamDefKind::Const) => {
499520
substs.push(provided_kind(param, arg));
500521
args.next();
501522
params.next();
@@ -606,6 +627,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
606627
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
607628
self.ast_ty_to_ty(&ty).into()
608629
}
630+
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
631+
self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into()
632+
}
609633
_ => unreachable!(),
610634
}
611635
},
@@ -654,6 +678,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
654678
tcx.types.err.into()
655679
}
656680
}
681+
GenericParamDefKind::Const => {
682+
// FIXME(const_generics:defaults)
683+
// We've already errored above about the mismatch.
684+
tcx.types.err.into()
685+
}
657686
}
658687
},
659688
);
@@ -1609,6 +1638,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
16091638
// Case 3. Reference to a top-level value.
16101639
Def::Fn(def_id) |
16111640
Def::Const(def_id) |
1641+
Def::ConstParam(def_id) |
16121642
Def::Static(def_id, _) => {
16131643
path_segs.push(PathSeg(def_id, last));
16141644
}
@@ -1797,10 +1827,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
17971827
self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, def, segment, false).0
17981828
}
17991829
hir::TyKind::Array(ref ty, ref length) => {
1800-
let length_def_id = tcx.hir().local_def_id_from_hir_id(length.hir_id);
1801-
let substs = InternalSubsts::identity_for_item(tcx, length_def_id);
1802-
let length = ty::LazyConst::Unevaluated(length_def_id, substs);
1803-
let length = tcx.mk_lazy_const(length);
1830+
let length = self.ast_const_to_const(length, tcx.types.usize);
18041831
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
18051832
self.normalize_ty(ast_ty.span, array_ty)
18061833
}
@@ -1837,6 +1864,42 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
18371864
result_ty
18381865
}
18391866

1867+
pub fn ast_const_to_const(
1868+
&self,
1869+
ast_const: &hir::AnonConst,
1870+
ty: Ty<'tcx>
1871+
) -> &'tcx ty::LazyConst<'tcx> {
1872+
debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.id, ast_const);
1873+
1874+
let tcx = self.tcx();
1875+
let def_id = tcx.hir().local_def_id(ast_const.id);
1876+
1877+
let mut lazy_const = ty::LazyConst::Unevaluated(
1878+
def_id,
1879+
Substs::identity_for_item(tcx, def_id)
1880+
);
1881+
1882+
let expr = &tcx.hir().body(ast_const.body).value;
1883+
if let ExprKind::Path(ref qpath) = expr.node {
1884+
if let hir::QPath::Resolved(_, ref path) = qpath {
1885+
if let Def::ConstParam(def_id) = path.def {
1886+
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
1887+
let item_id = tcx.hir().get_parent_node(node_id);
1888+
let item_def_id = tcx.hir().local_def_id(item_id);
1889+
let generics = tcx.generics_of(item_def_id);
1890+
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
1891+
let name = tcx.hir().name(node_id).as_interned_str();
1892+
lazy_const = ty::LazyConst::Evaluated(ty::Const {
1893+
val: ConstValue::Param(ty::ParamConst::new(index, name)),
1894+
ty,
1895+
})
1896+
}
1897+
}
1898+
};
1899+
1900+
tcx.mk_lazy_const(lazy_const)
1901+
}
1902+
18401903
pub fn impl_trait_ty_to_ty(
18411904
&self,
18421905
def_id: DefId,

0 commit comments

Comments
 (0)