diff options
| author | Ellen <supbscripter@gmail.com> | 2022-01-12 23:29:10 +0000 |
|---|---|---|
| committer | Ellen <supbscripter@gmail.com> | 2022-01-15 01:16:55 +0000 |
| commit | dec8ed438c530a3b722a5ee881c9fef180cc97b1 (patch) | |
| tree | 5f5257bfa426a4f266de1db6b6e513f531d0f4c6 /compiler/rustc_trait_selection/src | |
| parent | 71bbb603f4108bc1f0bc8c8395ec725bb66e7802 (diff) | |
attempt to re-add `ty::Unevaluated` visitor and friends
Diffstat (limited to 'compiler/rustc_trait_selection/src')
6 files changed, 41 insertions, 57 deletions
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<DefId>, - 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), - ); - - if concrete.is_ok() && substs.has_param_types_or_consts() { - match infcx.tcx.def_kind(def.did) { + let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span)); + + 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<DefId>, - substs: SubstsRef<'tcx>, + uv: ty::Unevaluated<'tcx, ()>, ) -> Result<Option<AbstractConst<'tcx>>, 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<Option<AbstractConst<'tcx>>, 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<DefId>, SubstsRef<'tcx>), - (ty::WithOptConstParam<DefId>, 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<Self::BreakTy> { - 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( |
