]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/abstract_const.rs
Auto merge of #105323 - cjgillot:simplify-const-prop, r=davidtwco
[rust.git] / compiler / rustc_middle / src / ty / abstract_const.rs
1 //! A subset of a mir body used for const evaluatability checking.
2 use crate::ty::{
3     self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
4     TypeVisitable,
5 };
6 use rustc_errors::ErrorGuaranteed;
7 use rustc_hir::def_id::DefId;
8
9 #[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)]
10 #[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)]
11 pub enum CastKind {
12     /// thir::ExprKind::As
13     As,
14     /// thir::ExprKind::Use
15     Use,
16 }
17
18 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
19 pub enum NotConstEvaluatable {
20     Error(ErrorGuaranteed),
21     MentionsInfer,
22     MentionsParam,
23 }
24
25 impl From<ErrorGuaranteed> for NotConstEvaluatable {
26     fn from(e: ErrorGuaranteed) -> NotConstEvaluatable {
27         NotConstEvaluatable::Error(e)
28     }
29 }
30
31 TrivialTypeTraversalAndLiftImpls! {
32     NotConstEvaluatable,
33 }
34
35 pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>, ErrorGuaranteed>;
36
37 impl<'tcx> TyCtxt<'tcx> {
38     /// Returns a const without substs applied
39     pub fn bound_abstract_const(
40         self,
41         uv: ty::WithOptConstParam<DefId>,
42     ) -> BoundAbstractConst<'tcx> {
43         let ac = if let Some((did, param_did)) = uv.as_const_arg() {
44             self.thir_abstract_const_of_const_arg((did, param_did))
45         } else {
46             self.thir_abstract_const(uv.did)
47         };
48         Ok(ac?.map(|ac| EarlyBinder(ac)))
49     }
50
51     pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(self, ac: T) -> T {
52         struct Expander<'tcx> {
53             tcx: TyCtxt<'tcx>,
54         }
55
56         impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> {
57             fn tcx(&self) -> TyCtxt<'tcx> {
58                 self.tcx
59             }
60             fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
61                 if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
62                     ty.super_fold_with(self)
63                 } else {
64                     ty
65                 }
66             }
67             fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
68                 let ct = match c.kind() {
69                     ty::ConstKind::Unevaluated(uv) => match self.tcx.bound_abstract_const(uv.def) {
70                         Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
71                         Ok(Some(bac)) => {
72                             let substs = self.tcx.erase_regions(uv.substs);
73                             bac.subst(self.tcx, substs)
74                         }
75                         Ok(None) => c,
76                     },
77                     _ => c,
78                 };
79                 ct.super_fold_with(self)
80             }
81         }
82         ac.fold_with(&mut Expander { tcx: self })
83     }
84 }