diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 39822d1af7d..266eec08ceb 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -668,13 +668,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// canonicalizing the consts. pub fn try_unify_abstract_consts( &self, - a: ty::Unevaluated<'tcx>, - b: ty::Unevaluated<'tcx>, + a: ty::Unevaluated<'tcx, ()>, + b: ty::Unevaluated<'tcx, ()>, ) -> bool { - let canonical = self.canonicalize_query( - ((a.def, a.substs), (b.def, b.substs)), - &mut OriginalQueryValues::default(), - ); + let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default()); debug!("canonical consts: {:?}", &canonical.value); self.tcx.try_unify_abstract_consts(canonical.value) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 73bda1337b6..5dc7b219642 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -314,12 +314,11 @@ rustc_queries! { } query try_unify_abstract_consts(key: ( - (ty::WithOptConstParam, SubstsRef<'tcx>), - (ty::WithOptConstParam, SubstsRef<'tcx>) + ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()> )) -> bool { desc { |tcx| "trying to unify the generic constants {} and {}", - tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did) + tcx.def_path_str(key.0.def.did), tcx.def_path_str(key.1.def.did) } } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index f2db95d162b..8dbd2596ad8 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -12,12 +12,31 @@ use rustc_target::abi::Size; use super::ScalarInt; /// An unevaluated, potentially generic, constant. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx> { +pub struct Unevaluated<'tcx, P = Option> { pub def: ty::WithOptConstParam, pub substs: SubstsRef<'tcx>, - pub promoted: Option, + pub promoted: P, +} + +impl<'tcx> Unevaluated<'tcx> { + pub fn shrink(self) -> Unevaluated<'tcx, ()> { + debug_assert_eq!(self.promoted, None); + Unevaluated { def: self.def, substs: self.substs, promoted: () } + } +} + +impl<'tcx> Unevaluated<'tcx, ()> { + pub fn expand(self) -> Unevaluated<'tcx> { + Unevaluated { def: self.def, substs: self.substs, promoted: None } + } +} + +impl<'tcx, P: Default> Unevaluated<'tcx, P> { + pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { + Unevaluated { def, substs, promoted: Default::default() } + } } /// Represents a constant in Rust. @@ -109,7 +128,7 @@ impl<'tcx> ConstKind<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option, ErrorReported>> { - if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self { + if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` @@ -118,29 +137,32 @@ impl<'tcx> ConstKind<'tcx> { // Note that we erase regions *before* calling `with_reveal_all_normalized`, // so that we don't try to invoke this query with // any region variables. - let param_env_and_substs = tcx + let param_env_and = tcx .erase_regions(param_env) .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(substs)); + .and(tcx.erase_regions(unevaluated)); // HACK(eddyb) when the query key would contain inference variables, // attempt using identity substs and `ParamEnv` instead, that will succeed // when the expression doesn't depend on any parameters. // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and_substs = if param_env_and_substs.needs_infer() { - tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did)) + let param_env_and = if param_env_and.needs_infer() { + tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { + def: unevaluated.def, + substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), + promoted: unevaluated.promoted, + }) } else { - param_env_and_substs + param_env_and }; // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, substs) = param_env_and_substs.into_parts(); + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = param_env_and.into_parts(); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None) - { + match tcx.const_eval_resolve(param_env, unevaluated, None) { // NOTE(eddyb) `val` contains no lifetimes/types/consts, // and we use the original type, so nothing from `substs` // (which may be identity substs, see above), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index cc858771b42..b6e673983fd 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,6 +34,12 @@ impl FlagComputation { result.flags } + pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags { + let mut result = FlagComputation::new(); + result.add_unevaluated_const(uv); + result.flags + } + fn add_flags(&mut self, flags: TypeFlags) { self.flags = self.flags | flags; } @@ -246,8 +252,8 @@ impl FlagComputation { ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => { self.add_substs(substs); } - ty::PredicateKind::ConstEvaluatable(_def_id, substs) => { - self.add_substs(substs); + ty::PredicateKind::ConstEvaluatable(uv) => { + self.add_unevaluated_const(uv); } ty::PredicateKind::ConstEquate(expected, found) => { self.add_const(expected); @@ -304,7 +310,7 @@ impl FlagComputation { } } - fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) { + fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'_, P>) { self.add_substs(ct.substs); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 1288b6e1a8b..3133cdfdd7a 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -350,6 +350,10 @@ pub trait TypeVisitor<'tcx>: Sized { c.super_visit_with(self) } + fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + uv.super_visit_with(self) + } + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { p.super_visit_with(self) } @@ -1242,6 +1246,18 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { } } + #[inline] + #[instrument(level = "trace")] + fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + let flags = FlagComputation::for_unevaluated_const(uv); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + #[inline] #[instrument(level = "trace")] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8d3dab7c6b3..82700537d3a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -598,7 +598,7 @@ pub enum PredicateKind<'tcx> { Coerce(CoercePredicate<'tcx>), /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::WithOptConstParam, SubstsRef<'tcx>), + ConstEvaluatable(ty::Unevaluated<'tcx, ()>), /// Constants must be equal. The first component is the const that is expected. ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f5d3861bab4..d9167e1980f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2539,8 +2539,8 @@ define_print_and_forward_display! { print_value_path(closure_def_id, &[]), write("` implements the trait `{}`", kind)) } - ty::PredicateKind::ConstEvaluatable(def, substs) => { - p!("the constant `", print_value_path(def.did, substs), "` can be evaluated") + ty::PredicateKind::ConstEvaluatable(uv) => { + p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated") } ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 97b5d52ea38..9e381cabdfe 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -587,7 +587,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if tcx.features().generic_const_exprs => { - tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) + tcx.try_unify_abstract_consts((au.shrink(), bu.shrink())) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 1c49ceeb153..63ebbcbc5bb 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -184,8 +184,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => { write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind) } - ty::PredicateKind::ConstEvaluatable(def_id, substs) => { - write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs) + ty::PredicateKind::ConstEvaluatable(uv) => { + write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs) } ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2), ty::PredicateKind::TypeWellFormedFromEnv(ty) => { @@ -445,8 +445,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { ty::PredicateKind::ObjectSafe(trait_def_id) => { Some(ty::PredicateKind::ObjectSafe(trait_def_id)) } - ty::PredicateKind::ConstEvaluatable(def_id, substs) => { - tcx.lift(substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs)) + ty::PredicateKind::ConstEvaluatable(uv) => { + tcx.lift(uv).map(|uv| ty::PredicateKind::ConstEvaluatable(uv)) } ty::PredicateKind::ConstEquate(c1, c2) => { tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2)) @@ -1185,13 +1185,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { Ok(match self { ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?), ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?), - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - ty::ConstKind::Unevaluated(ty::Unevaluated { - def, - substs: substs.try_fold_with(folder)?, - promoted, - }) - } + ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.try_fold_with(folder)?), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) @@ -1203,7 +1197,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match *self { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), ty::ConstKind::Param(p) => p.visit_with(visitor), - ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor), + ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) @@ -1224,3 +1218,45 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { ControlFlow::CONTINUE } } + +impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ty::Unevaluated { + def: self.def, + substs: self.substs.try_fold_with(folder)?, + promoted: self.promoted, + }) + } + + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_unevaluated_const(*self) + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.substs.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ty::Unevaluated { + def: self.def, + substs: self.substs.try_fold_with(folder)?, + promoted: self.promoted, + }) + } + + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_unevaluated_const(self.expand()) + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.substs.visit_with(visitor) + } +} diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index e090ecf2114..c62de154388 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -716,11 +716,10 @@ impl<'tcx> Cx<'tcx> { // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(self.tcx(), did); let lhs = ty::Const { - val: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: ty::WithOptConstParam::unknown(did), + val: ty::ConstKind::Unevaluated(ty::Unevaluated::new( + ty::WithOptConstParam::unknown(did), substs, - promoted: None, - }), + )), ty: var_ty, }; let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs))); @@ -912,11 +911,10 @@ impl<'tcx> Cx<'tcx> { debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: ty::WithOptConstParam::unknown(def_id), + val: ty::ConstKind::Unevaluated(ty::Unevaluated::new( + ty::WithOptConstParam::unknown(def_id), substs, - promoted: None, - }), + )), ty: self.typeck_results().node_type(expr.hir_id), }), user_ty, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index aa9ccddbdc5..217d767e4ab 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -135,11 +135,11 @@ where ty.visit_with(self) } ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE, - ty::PredicateKind::ConstEvaluatable(defs, substs) + ty::PredicateKind::ConstEvaluatable(uv) if self.def_id_visitor.tcx().features().generic_const_exprs => { let tcx = self.def_id_visitor.tcx(); - if let Ok(Some(ct)) = AbstractConst::new(tcx, defs, substs) { + if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) { self.visit_abstract_const_expr(tcx, ct)?; } ControlFlow::CONTINUE diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 8ab48b838ea..581a2bce2e5 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -245,18 +245,13 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { } } -impl<'tcx> Key - for ( - (ty::WithOptConstParam, SubstsRef<'tcx>), - (ty::WithOptConstParam, SubstsRef<'tcx>), - ) -{ +impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { - (self.0).0.did.krate == LOCAL_CRATE + (self.0).def.did.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - (self.0).0.did.default_span(tcx) + (self.0).def.did.default_span(tcx) } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 7d02983569e..5a69c5d50ff 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -19,7 +19,7 @@ use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_session::lint; -use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::def_id::LocalDefId; use rustc_span::Span; use std::cmp; @@ -29,26 +29,20 @@ use std::ops::ControlFlow; /// Check if a given constant can be evaluated. pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, - def: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, + uv: ty::Unevaluated<'tcx, ()>, param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), NotConstEvaluatable> { - debug!("is_const_evaluatable({:?}, {:?})", def, substs); + debug!("is_const_evaluatable({:?})", uv); if infcx.tcx.features().generic_const_exprs { let tcx = infcx.tcx; - match AbstractConst::new(tcx, def, substs)? { + match AbstractConst::new(tcx, uv)? { // We are looking at a generic abstract constant. Some(ct) => { for pred in param_env.caller_bounds() { match pred.kind().skip_binder() { - ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => { - if b_def == def && b_substs == substs { - debug!("is_const_evaluatable: caller_bound ~~> ok"); - return Ok(()); - } - - if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? { + ty::PredicateKind::ConstEvaluatable(uv) => { + if let Some(b_ct) = AbstractConst::new(tcx, uv)? { // Try to unify with each subtree in the AbstractConst to allow for // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable` // predicate for `(N + 1) * 2` @@ -132,7 +126,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( } let future_compat_lint = || { - if let Some(local_def_id) = def.did.as_local() { + if let Some(local_def_id) = uv.def.did.as_local() { infcx.tcx.struct_span_lint_hir( lint::builtin::CONST_EVALUATABLE_UNCHECKED, infcx.tcx.hir().local_def_id_to_hir_id(local_def_id), @@ -153,16 +147,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>( // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve( - param_env, - ty::Unevaluated { def, substs, promoted: None }, - Some(span), - ); + let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span)); - if concrete.is_ok() && substs.has_param_types_or_consts() { - match infcx.tcx.def_kind(def.did) { + if concrete.is_ok() && uv.substs.has_param_types_or_consts() { + match infcx.tcx.def_kind(uv.def.did) { DefKind::AnonConst | DefKind::InlineConst => { - let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def); + let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def); if mir_body.is_polymorphic { future_compat_lint(); @@ -174,7 +164,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( debug!(?concrete, "is_const_evaluatable"); match concrete { - Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() { + Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() { true => NotConstEvaluatable::MentionsInfer, false => NotConstEvaluatable::MentionsParam, }), @@ -202,12 +192,11 @@ pub struct AbstractConst<'tcx> { impl<'tcx> AbstractConst<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - def: ty::WithOptConstParam, - substs: SubstsRef<'tcx>, + uv: ty::Unevaluated<'tcx, ()>, ) -> Result>, ErrorReported> { - let inner = tcx.thir_abstract_const_opt_const_arg(def)?; - debug!("AbstractConst::new({:?}, {:?}) = {:?}", def, substs, inner); - Ok(inner.map(|inner| AbstractConst { inner, substs })) + let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; + debug!("AbstractConst::new({:?}) = {:?}", uv, inner); + Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs })) } pub fn from_const( @@ -215,9 +204,7 @@ impl<'tcx> AbstractConst<'tcx> { ct: &ty::Const<'tcx>, ) -> Result>, ErrorReported> { match ct.val { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => { - AbstractConst::new(tcx, def, substs) - } + ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()), ty::ConstKind::Error(_) => Err(ErrorReported), _ => Ok(None), } @@ -539,14 +526,11 @@ pub(super) fn thir_abstract_const<'tcx>( pub(super) fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, - ((a, a_substs), (b, b_substs)): ( - (ty::WithOptConstParam, SubstsRef<'tcx>), - (ty::WithOptConstParam, SubstsRef<'tcx>), - ), + (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>), ) -> bool { (|| { - if let Some(a) = AbstractConst::new(tcx, a, a_substs)? { - if let Some(b) = AbstractConst::new(tcx, b, b_substs)? { + if let Some(a) = AbstractConst::new(tcx, a)? { + if let Some(b) = AbstractConst::new(tcx, b)? { return Ok(try_unify(tcx, a, b)); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 711f242333c..72878b6cb38 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -819,10 +819,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::ConstEvaluatable(def, _) => { + ty::PredicateKind::ConstEvaluatable(uv) => { let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant"); - let const_span = self.tcx.def_span(def.did); + let const_span = self.tcx.def_span(uv.def.did); match self.tcx.sess.source_map().span_to_snippet(const_span) { Ok(snippet) => err.help(&format!( "try adding a `where` bound using this expression: `where [(); {}]:`", diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index be8a64e5299..346590a2de2 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -527,11 +527,10 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } } - ty::PredicateKind::ConstEvaluatable(def_id, substs) => { + ty::PredicateKind::ConstEvaluatable(uv) => { match const_evaluatable::is_const_evaluatable( self.selcx.infcx(), - def_id, - substs, + uv, obligation.param_env, obligation.cause.span, ) { @@ -539,7 +538,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); pending_obligation.stalled_on.extend( - substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg), + uv.substs + .iter() + .filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); ProcessResult::Unchanged } @@ -563,7 +564,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - if infcx.try_unify_abstract_consts(a, b) { + if infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) { return ProcessResult::Changed(vec![]); } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 1e2c0f54655..8a1864278de 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -845,12 +845,12 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( } fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow { - if let ty::PredicateKind::ConstEvaluatable(def, substs) = pred.kind().skip_binder() { + if let ty::PredicateKind::ConstEvaluatable(uv) = pred.kind().skip_binder() { // FIXME(generic_const_exprs): We should probably deduplicate the logic for // `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to // take a `ty::Const` instead. use rustc_middle::thir::abstract_const::Node; - if let Ok(Some(ct)) = AbstractConst::new(self.tcx, def, substs) { + if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) { const_evaluatable::walk_abstract_const(self.tcx, ct, |node| { match node.root(self.tcx) { Node::Leaf(leaf) => self.visit_const(leaf), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 79f54e6aba0..20e2fc24df1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -619,11 +619,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::PredicateKind::ConstEvaluatable(def_id, substs) => { + ty::PredicateKind::ConstEvaluatable(uv) => { match const_evaluatable::is_const_evaluatable( self.infcx, - def_id, - substs, + uv, obligation.param_env, obligation.cause.span, ) { @@ -645,7 +644,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - if self.infcx.try_unify_abstract_consts(a, b) { + if self.infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) { return Ok(EvaluatedToOk); } } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 044861829f1..dcf9bdc1e1b 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -131,11 +131,11 @@ pub fn predicate_obligations<'a, 'tcx>( wf.compute(a.into()); wf.compute(b.into()); } - ty::PredicateKind::ConstEvaluatable(def, substs) => { - let obligations = wf.nominal_obligations(def.did, substs); + ty::PredicateKind::ConstEvaluatable(uv) => { + let obligations = wf.nominal_obligations(uv.def.did, uv.substs); wf.out.extend(obligations); - for arg in substs.iter() { + for arg in uv.substs.iter() { wf.compute(arg); } } @@ -441,14 +441,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { GenericArgKind::Const(constant) => { match constant.val { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert!(promoted.is_none()); + ty::ConstKind::Unevaluated(uv) => { + assert!(uv.promoted.is_none()); - let obligations = self.nominal_obligations(def.did, substs); + let obligations = self.nominal_obligations(uv.def.did, uv.substs); self.out.extend(obligations); let predicate = - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(def, substs)) + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) .to_predicate(self.tcx()); let cause = self.cause(traits::MiscObligation); self.out.push(traits::Obligation::with_depth( diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 7d728977262..3cc66aaf0d7 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -237,9 +237,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( relator.relate(predicate.rebind(a), p.rebind(b)).is_ok() } ( - ty::PredicateKind::ConstEvaluatable(a_def, a_substs), - ty::PredicateKind::ConstEvaluatable(b_def, b_substs), - ) => tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))), + ty::PredicateKind::ConstEvaluatable(a), + ty::PredicateKind::ConstEvaluatable(b), + ) => tcx.try_unify_abstract_consts((a, b)), ( ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)), ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)), diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 9f8e06adbf9..abd237f4a75 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -972,10 +972,10 @@ fn check_type_defn<'tcx, F>( fcx.register_predicate(traits::Obligation::new( cause, fcx.param_env, - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable( + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new( ty::WithOptConstParam::unknown(discr_def_id.to_def_id()), discr_substs, - )) + ))) .to_predicate(tcx), )); } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index d3142716390..cdd6ddaa9b8 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2313,7 +2313,7 @@ fn const_evaluatable_predicates_of<'tcx>( assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs)) + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) .to_predicate(self.tcx), span, ));