1 use rustc_middle
::mir
::interpret
::InterpResult
;
2 use rustc_middle
::ty
::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}
;
3 use std
::convert
::TryInto
;
5 /// Returns `true` if a used generic parameter requires substitution.
6 crate fn ensure_monomorphic_enough
<'tcx
, T
>(tcx
: TyCtxt
<'tcx
>, ty
: T
) -> InterpResult
<'tcx
>
10 debug
!("ensure_monomorphic_enough: ty={:?}", ty
);
11 if !ty
.needs_subst() {
15 struct UsedParamsNeedSubstVisitor
<'tcx
> {
19 impl<'tcx
> TypeVisitor
<'tcx
> for UsedParamsNeedSubstVisitor
<'tcx
> {
20 fn visit_const(&mut self, c
: &'tcx ty
::Const
<'tcx
>) -> bool
{
26 ty
::ConstKind
::Param(..) => true,
27 _
=> c
.super_visit_with(self),
31 fn visit_ty(&mut self, ty
: Ty
<'tcx
>) -> bool
{
32 if !ty
.needs_subst() {
38 ty
::Closure(def_id
, substs
)
39 | ty
::Generator(def_id
, substs
, ..)
40 | ty
::FnDef(def_id
, substs
) => {
41 let unused_params
= self.tcx
.unused_generic_params(def_id
);
42 for (index
, subst
) in substs
.into_iter().enumerate() {
45 .expect("more generic parameters than can fit into a `u32`");
47 unused_params
.contains(index
).map(|unused
| !unused
).unwrap_or(true);
48 // Only recurse when generic parameters in fns, closures and generators
49 // are used and require substitution.
50 match (is_used
, subst
.needs_subst()) {
51 // Just in case there are closures or generators within this subst,
53 (true, true) if subst
.super_visit_with(self) => {
54 // Only return when we find a parameter so the remaining substs
58 // Confirm that polymorphization replaced the parameter with
59 // `ty::Param`/`ty::ConstKind::Param`.
60 (false, true) if cfg
!(debug_assertions
) => match subst
.unpack() {
61 ty
::subst
::GenericArgKind
::Type(ty
) => {
62 assert
!(matches
!(ty
.kind
, ty
::Param(_
)))
64 ty
::subst
::GenericArgKind
::Const(ct
) => {
65 assert
!(matches
!(ct
.val
, ty
::ConstKind
::Param(_
)))
67 ty
::subst
::GenericArgKind
::Lifetime(..) => (),
74 _
=> ty
.super_visit_with(self),
79 let mut vis
= UsedParamsNeedSubstVisitor { tcx }
;
80 if ty
.visit_with(&mut vis
) {
81 throw_inval
!(TooGeneric
);