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>>, impl<'tcx> TyCtxt<'tcx> { /// Returns a const without substs applied - fn bound_abstract_const(self, uv: ty::WithOptConstParam) -> BoundAbstractConst<'tcx> { + pub fn bound_abstract_const( + self, + uv: ty::WithOptConstParam, + ) -> 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>( - self, - ac: T, - ) -> Result, ErrorGuaranteed> { - self._expand_abstract_consts(ac, true) - } - - pub fn expand_unevaluated_abstract_const( - self, - did: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, - ) -> Result>, 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>( - self, - ac: T, - first: bool, - ) -> Result, ErrorGuaranteed> { + pub fn expand_abstract_consts>(self, ac: T) -> T { struct Expander<'tcx> { tcx: TyCtxt<'tcx>, - first: bool, } - impl<'tcx> FallibleTypeFolder<'tcx> for Expander<'tcx> { - type Error = Option; + impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, 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, 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.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 { - // 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