1 use rustc_middle
::mir
::interpret
::InterpResult
;
2 use rustc_middle
::ty
::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}
;
3 use std
::ops
::ControlFlow
;
5 /// Checks whether a type contains generic parameters which require substitution.
7 /// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization
8 /// types may be "concrete enough" even though they still contain generic parameters in
9 /// case these parameters are unused.
10 pub(crate) fn ensure_monomorphic_enough
<'tcx
, T
>(tcx
: TyCtxt
<'tcx
>, ty
: T
) -> InterpResult
<'tcx
>
12 T
: TypeVisitable
<'tcx
>,
14 debug
!("ensure_monomorphic_enough: ty={:?}", ty
);
15 if !ty
.needs_subst() {
20 struct UsedParamsNeedSubstVisitor
<'tcx
> {
24 impl<'tcx
> TypeVisitor
<'tcx
> for UsedParamsNeedSubstVisitor
<'tcx
> {
25 type BreakTy
= FoundParam
;
27 fn visit_ty(&mut self, ty
: Ty
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
28 if !ty
.needs_subst() {
29 return ControlFlow
::Continue(());
33 ty
::Param(_
) => ControlFlow
::Break(FoundParam
),
34 ty
::Closure(def_id
, substs
)
35 | ty
::Generator(def_id
, substs
, ..)
36 | ty
::FnDef(def_id
, substs
) => {
37 let instance
= ty
::InstanceDef
::Item(ty
::WithOptConstParam
::unknown(def_id
));
38 let unused_params
= self.tcx
.unused_generic_params(instance
);
39 for (index
, subst
) in substs
.into_iter().enumerate() {
42 .expect("more generic parameters than can fit into a `u32`");
43 // Only recurse when generic parameters in fns, closures and generators
44 // are used and require substitution.
45 // Just in case there are closures or generators within this subst,
47 if unused_params
.is_used(index
) && subst
.needs_subst() {
48 return subst
.visit_with(self);
51 ControlFlow
::Continue(())
53 _
=> ty
.super_visit_with(self),
57 fn visit_const(&mut self, c
: ty
::Const
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
59 ty
::ConstKind
::Param(..) => ControlFlow
::Break(FoundParam
),
60 _
=> c
.super_visit_with(self),
65 let mut vis
= UsedParamsNeedSubstVisitor { tcx }
;
66 if matches
!(ty
.visit_with(&mut vis
), ControlFlow
::Break(FoundParam
)) {
67 throw_inval
!(TooGeneric
);