rustc_middle/ty/
abstract_const.rs

1//! A subset of a mir body used for const evaluability checking.
2
3use rustc_errors::ErrorGuaranteed;
4use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
5
6use crate::ty::{
7    self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
8    TypeVisitableExt,
9};
10
11#[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)]
12#[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)]
13pub enum CastKind {
14    /// thir::ExprKind::As
15    As,
16    /// thir::ExprKind::Use
17    Use,
18}
19
20#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
21pub enum NotConstEvaluatable {
22    Error(ErrorGuaranteed),
23    MentionsInfer,
24    MentionsParam,
25}
26
27impl From<ErrorGuaranteed> for NotConstEvaluatable {
28    fn from(e: ErrorGuaranteed) -> NotConstEvaluatable {
29        NotConstEvaluatable::Error(e)
30    }
31}
32
33pub type BoundAbstractConst<'tcx> =
34    Result<Option<EarlyBinder<'tcx, ty::Const<'tcx>>>, ErrorGuaranteed>;
35
36impl<'tcx> TyCtxt<'tcx> {
37    pub fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, ac: T) -> T {
38        struct Expander<'tcx> {
39            tcx: TyCtxt<'tcx>,
40        }
41
42        impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Expander<'tcx> {
43            fn cx(&self) -> TyCtxt<'tcx> {
44                self.tcx
45            }
46            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
47                if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
48                    ty.super_fold_with(self)
49                } else {
50                    ty
51                }
52            }
53            fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
54                let ct = match c.kind() {
55                    ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
56                        Err(e) => ty::Const::new_error(self.tcx, e),
57                        Ok(Some(bac)) => {
58                            let args = self.tcx.erase_regions(uv.args);
59                            let bac = bac.instantiate(self.tcx, args);
60                            return bac.fold_with(self);
61                        }
62                        Ok(None) => c,
63                    },
64                    _ => c,
65                };
66                ct.super_fold_with(self)
67            }
68        }
69        ac.fold_with(&mut Expander { tcx: self })
70    }
71}