mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Make expand_abstract_consts
infallible
This commit is contained in:
parent
4085e94ece
commit
2ac5d91d63
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user