Skip to content

Commit 2ac5d91

Browse files
BoxyUwUJulianKnodt
authored andcommitted
Make expand_abstract_consts infallible
1 parent 4085e94 commit 2ac5d91

File tree

8 files changed

+52
-105
lines changed

8 files changed

+52
-105
lines changed

compiler/rustc_infer/src/infer/mod.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -1621,20 +1621,18 @@ impl<'tcx> InferCtxt<'tcx> {
16211621
// variables
16221622
let tcx = self.tcx;
16231623
if substs.has_non_region_infer() {
1624-
let ac = tcx.expand_unevaluated_abstract_const(unevaluated.def, unevaluated.substs);
1625-
match ac {
1626-
Ok(None) => {
1627-
substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
1628-
param_env = tcx.param_env(unevaluated.def.did);
1624+
if let Some(ct) = tcx.bound_abstract_const(unevaluated.def)? {
1625+
let ct = tcx.expand_abstract_consts(ct.subst(tcx, substs));
1626+
if let Err(e) = ct.error_reported() {
1627+
return Err(ErrorHandled::Reported(e));
1628+
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
1629+
return Err(ErrorHandled::TooGeneric);
1630+
} else {
1631+
substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
16291632
}
1630-
Ok(Some(ct)) => {
1631-
if ct.has_non_region_infer() || ct.has_non_region_param() {
1632-
return Err(ErrorHandled::TooGeneric);
1633-
} else {
1634-
substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
1635-
}
1636-
}
1637-
Err(guar) => return Err(ErrorHandled::Reported(guar)),
1633+
} else {
1634+
substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
1635+
param_env = tcx.param_env(unevaluated.def.did);
16381636
}
16391637
}
16401638

+19-49
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! A subset of a mir body used for const evaluatability checking.
22
use crate::ty::{
3-
self, subst::SubstsRef, Const, EarlyBinder, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable,
4-
TypeSuperFoldable, TypeVisitable,
3+
self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
4+
TypeVisitable,
55
};
66
use rustc_errors::ErrorGuaranteed;
77
use rustc_hir::def_id::DefId;
@@ -36,7 +36,10 @@ pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>,
3636

3737
impl<'tcx> TyCtxt<'tcx> {
3838
/// Returns a const without substs applied
39-
fn bound_abstract_const(self, uv: ty::WithOptConstParam<DefId>) -> BoundAbstractConst<'tcx> {
39+
pub fn bound_abstract_const(
40+
self,
41+
uv: ty::WithOptConstParam<DefId>,
42+
) -> BoundAbstractConst<'tcx> {
4043
let ac = if let Some((did, param_did)) = uv.as_const_arg() {
4144
self.thir_abstract_const_of_const_arg((did, param_did))
4245
} else {
@@ -45,70 +48,37 @@ impl<'tcx> TyCtxt<'tcx> {
4548
Ok(ac?.map(|ac| EarlyBinder(ac)))
4649
}
4750

48-
pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(
49-
self,
50-
ac: T,
51-
) -> Result<Option<T>, ErrorGuaranteed> {
52-
self._expand_abstract_consts(ac, true)
53-
}
54-
55-
pub fn expand_unevaluated_abstract_const(
56-
self,
57-
did: ty::WithOptConstParam<DefId>,
58-
substs: SubstsRef<'tcx>,
59-
) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
60-
let Some(ac) = self.bound_abstract_const(did)? else {
61-
return Ok(None);
62-
};
63-
let substs = self.erase_regions(substs);
64-
let ac = ac.subst(self, substs);
65-
self._expand_abstract_consts(ac, false)
66-
}
67-
68-
fn _expand_abstract_consts<T: TypeFoldable<'tcx>>(
69-
self,
70-
ac: T,
71-
first: bool,
72-
) -> Result<Option<T>, ErrorGuaranteed> {
51+
pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(self, ac: T) -> T {
7352
struct Expander<'tcx> {
7453
tcx: TyCtxt<'tcx>,
75-
first: bool,
7654
}
7755

78-
impl<'tcx> FallibleTypeFolder<'tcx> for Expander<'tcx> {
79-
type Error = Option<ErrorGuaranteed>;
56+
impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> {
8057
fn tcx(&self) -> TyCtxt<'tcx> {
8158
self.tcx
8259
}
83-
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
60+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
8461
if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
85-
ty.try_super_fold_with(self)
62+
ty.super_fold_with(self)
8663
} else {
87-
Ok(ty)
64+
ty
8865
}
8966
}
90-
fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, Self::Error> {
67+
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
9168
let ct = match c.kind() {
92-
ty::ConstKind::Unevaluated(uv) => {
93-
if let Some(bac) = self.tcx.bound_abstract_const(uv.def)? {
69+
ty::ConstKind::Unevaluated(uv) => match self.tcx.bound_abstract_const(uv.def) {
70+
Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
71+
Ok(Some(bac)) => {
9472
let substs = self.tcx.erase_regions(uv.substs);
9573
bac.subst(self.tcx, substs)
96-
} else if self.first {
97-
return Err(None);
98-
} else {
99-
c
10074
}
101-
}
75+
Ok(None) => c,
76+
},
10277
_ => c,
10378
};
104-
self.first = false;
105-
ct.try_super_fold_with(self)
79+
ct.super_fold_with(self)
10680
}
10781
}
108-
match ac.try_fold_with(&mut Expander { tcx: self, first }) {
109-
Ok(c) => Ok(Some(c)),
110-
Err(None) => Ok(None),
111-
Err(Some(e)) => Err(e),
112-
}
82+
ac.fold_with(&mut Expander { tcx: self })
11383
}
11484
}

compiler/rustc_middle/src/ty/relate.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -632,12 +632,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
632632
}
633633

634634
if tcx.features().generic_const_exprs {
635-
if let Ok(Some(a2)) = tcx.expand_abstract_consts(a) {
636-
a = a2;
637-
}
638-
if let Ok(Some(b2)) = tcx.expand_abstract_consts(b) {
639-
b = b2
640-
}
635+
a = tcx.expand_abstract_consts(a);
636+
b = tcx.expand_abstract_consts(b);
641637
}
642638

643639
// Currently, the values that can be unified are primitive types,

compiler/rustc_privacy/src/lib.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,8 @@ where
284284
}
285285

286286
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
287-
self.visit_ty(c.ty())?;
288287
let tcx = self.def_id_visitor.tcx();
289-
if let ty::ConstKind::Unevaluated(uv) = c.kind()
290-
&& let Ok(Some(ct)) = tcx.expand_unevaluated_abstract_const(uv.def, uv.substs)
291-
{
292-
ct.super_visit_with(self)?;
293-
}
294-
ControlFlow::CONTINUE
288+
tcx.expand_abstract_consts(c).super_visit_with(self)
295289
}
296290
}
297291

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! In this case we try to build an abstract representation of this constant using
99
//! `thir_abstract_const` which can then be checked for structural equality with other
1010
//! generic constants mentioned in the `caller_bounds` of the current environment.
11+
use rustc_hir::def::DefKind;
1112
use rustc_infer::infer::InferCtxt;
1213
use rustc_middle::mir::interpret::ErrorHandled;
1314

@@ -42,7 +43,15 @@ pub fn is_const_evaluatable<'tcx>(
4243
};
4344

4445
if tcx.features().generic_const_exprs {
45-
if let Some(ct) = tcx.expand_abstract_consts(ct)? {
46+
let ct = tcx.expand_abstract_consts(ct);
47+
48+
let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
49+
tcx.def_kind(uv.def.did) == DefKind::AnonConst
50+
} else {
51+
false
52+
};
53+
54+
if !is_anon_ct {
4655
if satisfied_from_param_env(tcx, infcx, ct, param_env)? {
4756
return Ok(());
4857
}
@@ -52,6 +61,7 @@ pub fn is_const_evaluatable<'tcx>(
5261
return Err(NotConstEvaluatable::MentionsParam);
5362
}
5463
}
64+
5565
let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
5666
match concrete {
5767
Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error(
@@ -78,8 +88,7 @@ pub fn is_const_evaluatable<'tcx>(
7888
// the current crate does not enable `feature(generic_const_exprs)`, abort
7989
// compilation with a useful error.
8090
Err(_) if tcx.sess.is_nightly_build()
81-
&& let Ok(Some(ac)) = tcx.expand_abstract_consts(ct)
82-
&& let ty::ConstKind::Expr(_) = ac.kind() =>
91+
&& let ty::ConstKind::Expr(_) = tcx.expand_abstract_consts(ct).kind() =>
8392
{
8493
tcx.sess
8594
.struct_span_fatal(
@@ -164,8 +173,7 @@ fn satisfied_from_param_env<'tcx>(
164173
for pred in param_env.caller_bounds() {
165174
match pred.kind().skip_binder() {
166175
ty::PredicateKind::ConstEvaluatable(ce) => {
167-
let b_ct = tcx.expand_abstract_consts(ce)?.unwrap_or(ce);
168-
176+
let b_ct = tcx.expand_abstract_consts(ce);
169177
let mut v = Visitor { ct, infcx, param_env };
170178
let result = b_ct.visit_with(&mut v);
171179

compiler/rustc_trait_selection/src/traits/fulfill.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
462462
//
463463
// Let's just see where this breaks :shrug:
464464
{
465-
let c1 =
466-
if let Ok(Some(a)) = tcx.expand_abstract_consts(c1) { a } else { c1 };
467-
let c2 =
468-
if let Ok(Some(b)) = tcx.expand_abstract_consts(c2) { b } else { c2 };
465+
let c1 = tcx.expand_abstract_consts(c1);
466+
let c2 = tcx.expand_abstract_consts(c2);
469467
debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
470468

471469
use rustc_hir::def::DefKind;

compiler/rustc_trait_selection/src/traits/object_safety.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -837,24 +837,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
837837
}
838838

839839
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
840-
// Constants can only influence object safety if they reference `Self`.
840+
// Constants can only influence object safety if they are generic and reference `Self`.
841841
// This is only possible for unevaluated constants, so we walk these here.
842-
//
843-
// If `AbstractConst::from_const` returned an error we already failed compilation
844-
// so we don't have to emit an additional error here.
845-
//
846-
// We currently recurse into abstract consts here but do not recurse in
847-
// `is_const_evaluatable`. This means that the object safety check is more
848-
// liberal than the const eval check.
849-
//
850-
// This shouldn't really matter though as we can't really use any
851-
// constants which are not considered const evaluatable.
852-
if let ty::ConstKind::Unevaluated(_uv) = ct.kind() &&
853-
let Ok(Some(ct)) = self.tcx.expand_abstract_consts(ct){
854-
self.visit_const(ct)
855-
} else {
856-
ct.super_visit_with(self)
857-
}
842+
self.tcx.expand_abstract_consts(ct).super_visit_with(self)
858843
}
859844
}
860845

compiler/rustc_trait_selection/src/traits/select/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -664,10 +664,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
664664
);
665665

666666
{
667-
let c1 =
668-
if let Ok(Some(a)) = tcx.expand_abstract_consts(c1) { a } else { c1 };
669-
let c2 =
670-
if let Ok(Some(b)) = tcx.expand_abstract_consts(c2) { b } else { c2 };
667+
let c1 = tcx.expand_abstract_consts(c1);
668+
let c2 = tcx.expand_abstract_consts(c2);
671669
debug!(
672670
"evalaute_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",
673671
c1, c2

0 commit comments

Comments
 (0)