Auto merge of #103227 - lcnr:bye-bye-unevaluated-const, r=oli-obk
stop using `ty::UnevaluatedConst` directly best reviewed commit by commit. simplifies #99798 because we now don't have to expand `ty::UnevaluatedConst` to `ty::Const`. I also remember some other places where using `ty::UnevaluatedConst` directly was annoying and caused issues, though I don't quite remember what they were rn '^^ r? `@oli-obk` cc `@JulianKnodt`
This commit is contained in:
commit
26c96e3416
30 changed files with 131 additions and 191 deletions
|
@ -9,14 +9,12 @@
|
|||
//! `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_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::abstract_const::{
|
||||
walk_abstract_const, AbstractConst, FailureKind, Node, NotConstEvaluatable,
|
||||
};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::iter;
|
||||
|
@ -161,11 +159,20 @@ pub fn try_unify_abstract_consts<'tcx>(
|
|||
#[instrument(skip(infcx), level = "debug")]
|
||||
pub fn is_const_evaluatable<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
uv: ty::UnevaluatedConst<'tcx>,
|
||||
ct: ty::Const<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<(), NotConstEvaluatable> {
|
||||
let tcx = infcx.tcx;
|
||||
let uv = match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => uv,
|
||||
ty::ConstKind::Param(_)
|
||||
| ty::ConstKind::Bound(_, _)
|
||||
| ty::ConstKind::Placeholder(_)
|
||||
| ty::ConstKind::Value(_)
|
||||
| ty::ConstKind::Error(_) => return Ok(()),
|
||||
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
|
||||
};
|
||||
|
||||
if tcx.features().generic_const_exprs {
|
||||
if let Some(ct) = AbstractConst::new(tcx, uv)? {
|
||||
|
@ -253,25 +260,7 @@ pub fn is_const_evaluatable<'tcx>(
|
|||
Err(NotConstEvaluatable::Error(reported))
|
||||
}
|
||||
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
|
||||
Ok(_) => {
|
||||
if uv.substs.has_non_region_param() {
|
||||
assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
|
||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
|
||||
|
||||
if mir_body.is_polymorphic {
|
||||
let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
|
||||
tcx.struct_span_lint_hir(
|
||||
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
||||
tcx.hir().local_def_id_to_hir_id(local_def_id),
|
||||
span,
|
||||
"cannot use constants which depend on generic parameters in types",
|
||||
|err| err
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +274,7 @@ fn satisfied_from_param_env<'tcx>(
|
|||
for pred in param_env.caller_bounds() {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
|
||||
if let Some(b_ct) = AbstractConst::from_const(tcx, uv)? {
|
||||
let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
|
||||
|
||||
// Try to unify with each subtree in the AbstractConst to allow for
|
||||
|
|
|
@ -1304,7 +1304,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
match obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||
let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
|
||||
bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
|
||||
};
|
||||
let mut err =
|
||||
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
|
||||
let const_span = self.tcx.def_span(uv.def.did);
|
||||
|
@ -2368,7 +2371,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
if predicate.references_error() || self.is_tainted_by_errors() {
|
||||
return;
|
||||
}
|
||||
let subst = data.substs.iter().find(|g| g.has_non_region_infer());
|
||||
let subst = data.walk().find(|g| g.is_non_region_infer());
|
||||
if let Some(subst) = subst {
|
||||
let err = self.emit_inference_failure_err(
|
||||
body_id,
|
||||
|
|
|
@ -476,9 +476,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
Err(NotConstEvaluatable::MentionsInfer) => {
|
||||
pending_obligation.stalled_on.clear();
|
||||
pending_obligation.stalled_on.extend(
|
||||
uv.substs
|
||||
.iter()
|
||||
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
||||
uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
||||
);
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
|
|
|
@ -837,24 +837,14 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_ty_unevaluated(
|
||||
&mut self,
|
||||
uv: ty::UnevaluatedConst<'tcx>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// Constants can only influence object safety if they reference `Self`.
|
||||
// This is only possible for unevaluated constants, so we walk these here.
|
||||
//
|
||||
// If `AbstractConst::new` returned an error we already failed compilation
|
||||
// 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.
|
||||
use rustc_middle::ty::abstract_const::Node;
|
||||
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
|
||||
if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
|
||||
walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
|
||||
Node::Leaf(leaf) => self.visit_const(leaf),
|
||||
Node::Cast(_, _, ty) => self.visit_ty(ty),
|
||||
|
@ -863,7 +853,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
|
|||
}
|
||||
})
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
ct.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,13 +148,8 @@ pub fn predicate_obligations<'tcx>(
|
|||
wf.compute(a.into());
|
||||
wf.compute(b.into());
|
||||
}
|
||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||
let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
|
||||
wf.out.extend(obligations);
|
||||
|
||||
for arg in uv.substs.iter() {
|
||||
wf.compute(arg);
|
||||
}
|
||||
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||
wf.compute(ct.into());
|
||||
}
|
||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||
wf.compute(c1.into());
|
||||
|
@ -476,14 +471,14 @@ impl<'tcx> WfPredicates<'tcx> {
|
|||
// obligations are handled by the parent (e.g. `ty::Ref`).
|
||||
GenericArgKind::Lifetime(_) => continue,
|
||||
|
||||
GenericArgKind::Const(constant) => {
|
||||
match constant.kind() {
|
||||
GenericArgKind::Const(ct) => {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
|
||||
self.out.extend(obligations);
|
||||
|
||||
let predicate =
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
|
||||
.to_predicate(self.tcx());
|
||||
let cause = self.cause(traits::WellFormed(None));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
|
@ -500,7 +495,7 @@ impl<'tcx> WfPredicates<'tcx> {
|
|||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into()))
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
|
||||
.to_predicate(self.tcx()),
|
||||
));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue