about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs24
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs68
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs8
-rw-r--r--compiler/rustc_privacy/src/lib.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs6
8 files changed, 52 insertions, 105 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 8d01afa322e..67feb83faac 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1621,20 +1621,18 @@ impl<'tcx> InferCtxt<'tcx> {
         // variables
         let tcx = self.tcx;
         if substs.has_non_region_infer() {
-            let ac = tcx.expand_unevaluated_abstract_const(unevaluated.def, unevaluated.substs);
-            match ac {
-                Ok(None) => {
-                    substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
-                    param_env = tcx.param_env(unevaluated.def.did);
+            if let Some(ct) = tcx.bound_abstract_const(unevaluated.def)? {
+                let ct = tcx.expand_abstract_consts(ct.subst(tcx, substs));
+                if let Err(e) = ct.error_reported() {
+                    return Err(ErrorHandled::Reported(e));
+                } else if ct.has_non_region_infer() || ct.has_non_region_param() {
+                    return Err(ErrorHandled::TooGeneric);
+                } else {
+                    substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
                 }
-                Ok(Some(ct)) => {
-                    if ct.has_non_region_infer() || ct.has_non_region_param() {
-                        return Err(ErrorHandled::TooGeneric);
-                    } else {
-                        substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
-                    }
-                }
-                Err(guar) => return Err(ErrorHandled::Reported(guar)),
+            } else {
+                substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
+                param_env = tcx.param_env(unevaluated.def.did);
             }
         }
 
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index e297a01e90e..5de758ad9ba 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,7 +1,7 @@
 //! A subset of a mir body used for const evaluatability checking.
 use crate::ty::{
-    self, subst::SubstsRef, Const, EarlyBinder, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable,
-    TypeSuperFoldable, TypeVisitable,
+    self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeVisitable,
 };
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
@@ -36,7 +36,10 @@ pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>,
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Returns a const without substs applied
-    fn bound_abstract_const(self, uv: ty::WithOptConstParam<DefId>) -> BoundAbstractConst<'tcx> {
+    pub fn bound_abstract_const(
+        self,
+        uv: ty::WithOptConstParam<DefId>,
+    ) -> BoundAbstractConst<'tcx> {
         let ac = if let Some((did, param_did)) = uv.as_const_arg() {
             self.thir_abstract_const_of_const_arg((did, param_did))
         } else {
@@ -45,70 +48,37 @@ impl<'tcx> TyCtxt<'tcx> {
         Ok(ac?.map(|ac| EarlyBinder(ac)))
     }
 
-    pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(
-        self,
-        ac: T,
-    ) -> Result<Option<T>, ErrorGuaranteed> {
-        self._expand_abstract_consts(ac, true)
-    }
-
-    pub fn expand_unevaluated_abstract_const(
-        self,
-        did: ty::WithOptConstParam<DefId>,
-        substs: SubstsRef<'tcx>,
-    ) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
-        let Some(ac) = self.bound_abstract_const(did)? else {
-            return Ok(None);
-        };
-        let substs = self.erase_regions(substs);
-        let ac = ac.subst(self, substs);
-        self._expand_abstract_consts(ac, false)
-    }
-
-    fn _expand_abstract_consts<T: TypeFoldable<'tcx>>(
-        self,
-        ac: T,
-        first: bool,
-    ) -> Result<Option<T>, ErrorGuaranteed> {
+    pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(self, ac: T) -> T {
         struct Expander<'tcx> {
             tcx: TyCtxt<'tcx>,
-            first: bool,
         }
 
-        impl<'tcx> FallibleTypeFolder<'tcx> for Expander<'tcx> {
-            type Error = Option<ErrorGuaranteed>;
+        impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> {
             fn tcx(&self) -> TyCtxt<'tcx> {
                 self.tcx
             }
-            fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
-                    ty.try_super_fold_with(self)
+                    ty.super_fold_with(self)
                 } else {
-                    Ok(ty)
+                    ty
                 }
             }
-            fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, Self::Error> {
+            fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
                 let ct = match c.kind() {
-                    ty::ConstKind::Unevaluated(uv) => {
-                        if let Some(bac) = self.tcx.bound_abstract_const(uv.def)? {
+                    ty::ConstKind::Unevaluated(uv) => match self.tcx.bound_abstract_const(uv.def) {
+                        Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
+                        Ok(Some(bac)) => {
                             let substs = self.tcx.erase_regions(uv.substs);
                             bac.subst(self.tcx, substs)
-                        } else if self.first {
-                            return Err(None);
-                        } else {
-                            c
                         }
-                    }
+                        Ok(None) => c,
+                    },
                     _ => c,
                 };
-                self.first = false;
-                ct.try_super_fold_with(self)
+                ct.super_fold_with(self)
             }
         }
-        match ac.try_fold_with(&mut Expander { tcx: self, first }) {
-            Ok(c) => Ok(Some(c)),
-            Err(None) => Ok(None),
-            Err(Some(e)) => Err(e),
-        }
+        ac.fold_with(&mut Expander { tcx: self })
     }
 }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index a5580fa62ac..e6340040e9c 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -632,12 +632,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     }
 
     if tcx.features().generic_const_exprs {
-        if let Ok(Some(a2)) = tcx.expand_abstract_consts(a) {
-            a = a2;
-        }
-        if let Ok(Some(b2)) = tcx.expand_abstract_consts(b) {
-            b = b2
-        }
+        a = tcx.expand_abstract_consts(a);
+        b = tcx.expand_abstract_consts(b);
     }
 
     // Currently, the values that can be unified are primitive types,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index eebff421b81..3b41b9b830e 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -284,14 +284,8 @@ where
     }
 
     fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        self.visit_ty(c.ty())?;
         let tcx = self.def_id_visitor.tcx();
-        if let ty::ConstKind::Unevaluated(uv) = c.kind()
-            && let Ok(Some(ct)) = tcx.expand_unevaluated_abstract_const(uv.def, uv.substs)
-        {
-            ct.super_visit_with(self)?;
-        }
-        ControlFlow::CONTINUE
+        tcx.expand_abstract_consts(c).super_visit_with(self)
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index b72bc42fa65..a26653b3184 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -8,6 +8,7 @@
 //! In this case we try to build an abstract representation of this constant using
 //! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
+use rustc_hir::def::DefKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::interpret::ErrorHandled;
 
@@ -42,7 +43,15 @@ pub fn is_const_evaluatable<'tcx>(
     };
 
     if tcx.features().generic_const_exprs {
-        if let Some(ct) = tcx.expand_abstract_consts(ct)? {
+        let ct = tcx.expand_abstract_consts(ct);
+
+        let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
+            tcx.def_kind(uv.def.did) == DefKind::AnonConst
+        } else {
+            false
+        };
+
+        if !is_anon_ct {
             if satisfied_from_param_env(tcx, infcx, ct, param_env)? {
                 return Ok(());
             }
@@ -52,6 +61,7 @@ pub fn is_const_evaluatable<'tcx>(
                 return Err(NotConstEvaluatable::MentionsParam);
             }
         }
+
         let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
         match concrete {
             Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error(
@@ -78,8 +88,7 @@ pub fn is_const_evaluatable<'tcx>(
             // the current crate does not enable `feature(generic_const_exprs)`, abort
             // compilation with a useful error.
             Err(_) if tcx.sess.is_nightly_build()
-                && let Ok(Some(ac)) = tcx.expand_abstract_consts(ct)
-                && let ty::ConstKind::Expr(_) = ac.kind() =>
+                && let ty::ConstKind::Expr(_) = tcx.expand_abstract_consts(ct).kind() =>
             {
                 tcx.sess
                     .struct_span_fatal(
@@ -164,8 +173,7 @@ fn satisfied_from_param_env<'tcx>(
     for pred in param_env.caller_bounds() {
         match pred.kind().skip_binder() {
             ty::PredicateKind::ConstEvaluatable(ce) => {
-                let b_ct = tcx.expand_abstract_consts(ce)?.unwrap_or(ce);
-
+                let b_ct = tcx.expand_abstract_consts(ce);
                 let mut v = Visitor { ct, infcx, param_env };
                 let result = b_ct.visit_with(&mut v);
 
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1fd0926fec9..e58881710a5 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -462,10 +462,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     //
                     // Let's just see where this breaks :shrug:
                     {
-                        let c1 =
-                            if let Ok(Some(a)) = tcx.expand_abstract_consts(c1) { a } else { c1 };
-                        let c2 =
-                            if let Ok(Some(b)) = tcx.expand_abstract_consts(c2) { b } else { c2 };
+                        let c1 = tcx.expand_abstract_consts(c1);
+                        let c2 = tcx.expand_abstract_consts(c2);
                         debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
 
                         use rustc_hir::def::DefKind;
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 0ea126fa9c9..70e4ed29266 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -837,24 +837,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
         }
 
         fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-            // Constants can only influence object safety if they reference `Self`.
+            // Constants can only influence object safety if they are generic and reference `Self`.
             // This is only possible for unevaluated constants, so we walk these here.
-            //
-            // If `AbstractConst::from_const` returned an error we already failed compilation
-            // so we don't have to emit an additional error here.
-            //
-            // We currently recurse into abstract consts here but do not recurse in
-            // `is_const_evaluatable`. This means that the object safety check is more
-            // liberal than the const eval check.
-            //
-            // This shouldn't really matter though as we can't really use any
-            // constants which are not considered const evaluatable.
-            if let ty::ConstKind::Unevaluated(_uv) = ct.kind() &&
-                let Ok(Some(ct)) = self.tcx.expand_abstract_consts(ct){
-                self.visit_const(ct)
-            } else {
-                ct.super_visit_with(self)
-            }
+            self.tcx.expand_abstract_consts(ct).super_visit_with(self)
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index daa3f2775e0..c93b3fbf61b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -664,10 +664,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     );
 
                     {
-                        let c1 =
-                            if let Ok(Some(a)) = tcx.expand_abstract_consts(c1) { a } else { c1 };
-                        let c2 =
-                            if let Ok(Some(b)) = tcx.expand_abstract_consts(c2) { b } else { c2 };
+                        let c1 = tcx.expand_abstract_consts(c1);
+                        let c2 = tcx.expand_abstract_consts(c2);
                         debug!(
                             "evalaute_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",
                             c1, c2