Skip to content

Commit 26c96e3

Browse files
committed
Auto merge of rust-lang#103227 - lcnr:bye-bye-unevaluated-const, r=oli-obk
stop using `ty::UnevaluatedConst` directly best reviewed commit by commit. simplifies rust-lang#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`
2 parents 3022afe + b93713f commit 26c96e3

30 files changed

+131
-191
lines changed

compiler/rustc_hir_analysis/src/check/dropck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
192192
(
193193
ty::PredicateKind::ConstEvaluatable(a),
194194
ty::PredicateKind::ConstEvaluatable(b),
195-
) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))),
195+
) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
196196
(
197197
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
198198
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,6 @@ fn check_type_defn<'tcx, F>(
11011101

11021102
// Explicit `enum` discriminant values must const-evaluate successfully.
11031103
if let Some(discr_def_id) = variant.explicit_discr {
1104-
let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
1105-
11061104
let cause = traits::ObligationCause::new(
11071105
tcx.def_span(discr_def_id),
11081106
wfcx.body_id,
@@ -1112,10 +1110,7 @@ fn check_type_defn<'tcx, F>(
11121110
cause,
11131111
wfcx.param_env,
11141112
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
1115-
ty::UnevaluatedConst::new(
1116-
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
1117-
discr_substs,
1118-
),
1113+
ty::Const::from_anon_const(tcx, discr_def_id),
11191114
))
11201115
.to_predicate(tcx),
11211116
));

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,10 @@ fn const_evaluatable_predicates_of<'tcx>(
318318
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
319319
let def_id = self.tcx.hir().local_def_id(c.hir_id);
320320
let ct = ty::Const::from_anon_const(self.tcx, def_id);
321-
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
321+
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
322322
let span = self.tcx.hir().span(c.hir_id);
323323
self.preds.insert((
324-
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
324+
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
325325
.to_predicate(self.tcx),
326326
span,
327327
));

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#![feature(drain_filter)]
5656
#![feature(intra_doc_pointers)]
5757
#![feature(yeet_expr)]
58+
#![feature(result_option_inspect)]
5859
#![feature(const_option)]
5960
#![recursion_limit = "512"]
6061
#![allow(rustc::potential_query_instability)]

compiler/rustc_middle/src/mir/interpret/queries.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use crate::mir;
44
use crate::ty::subst::InternalSubsts;
55
use crate::ty::visit::TypeVisitable;
66
use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
7+
use rustc_hir::def::DefKind;
78
use rustc_hir::def_id::DefId;
9+
use rustc_session::lint;
810
use rustc_span::{Span, DUMMY_SP};
911

1012
impl<'tcx> TyCtxt<'tcx> {
@@ -83,7 +85,29 @@ impl<'tcx> TyCtxt<'tcx> {
8385
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
8486
Ok(Some(instance)) => {
8587
let cid = GlobalId { instance, promoted: None };
86-
self.const_eval_global_id_for_typeck(param_env, cid, span)
88+
self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
89+
// We are emitting the lint here instead of in `is_const_evaluatable`
90+
// as we normalize obligations before checking them, and normalization
91+
// uses this function to evaluate this constant.
92+
//
93+
// @lcnr believes that successfully evaluating even though there are
94+
// used generic parameters is a bug of evaluation, so checking for it
95+
// here does feel somewhat sensible.
96+
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
97+
assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
98+
let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
99+
if mir_body.is_polymorphic {
100+
let Some(local_def_id) = ct.def.did.as_local() else { return };
101+
self.struct_span_lint_hir(
102+
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
103+
self.hir().local_def_id_to_hir_id(local_def_id),
104+
self.def_span(ct.def.did),
105+
"cannot use constants which depend on generic parameters in types",
106+
|err| err,
107+
)
108+
}
109+
}
110+
})
87111
}
88112
Ok(None) => Err(ErrorHandled::TooGeneric),
89113
Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),

compiler/rustc_middle/src/ty/consts.rs

+4
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ impl<'tcx> Const<'tcx> {
263263
self.try_eval_usize(tcx, param_env)
264264
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
265265
}
266+
267+
pub fn is_ct_infer(self) -> bool {
268+
matches!(self.kind(), ty::ConstKind::Infer(_))
269+
}
266270
}
267271

268272
pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {

compiler/rustc_middle/src/ty/consts/kind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::ScalarInt;
1515

1616
/// An unevaluated (potentially generic) constant used in the type-system.
1717
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
18-
#[derive(Hash, HashStable)]
18+
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
1919
pub struct UnevaluatedConst<'tcx> {
2020
pub def: ty::WithOptConstParam<DefId>,
2121
pub substs: SubstsRef<'tcx>,

compiler/rustc_middle/src/ty/flags.rs

+5-13
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ impl FlagComputation {
3434
result.flags
3535
}
3636

37-
pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags {
38-
let mut result = FlagComputation::new();
39-
result.add_unevaluated_const(uv);
40-
result.flags
41-
}
42-
4337
fn add_flags(&mut self, flags: TypeFlags) {
4438
self.flags = self.flags | flags;
4539
}
@@ -256,7 +250,7 @@ impl FlagComputation {
256250
self.add_substs(substs);
257251
}
258252
ty::PredicateKind::ConstEvaluatable(uv) => {
259-
self.add_unevaluated_const(uv);
253+
self.add_const(uv);
260254
}
261255
ty::PredicateKind::ConstEquate(expected, found) => {
262256
self.add_const(expected);
@@ -289,7 +283,10 @@ impl FlagComputation {
289283
fn add_const(&mut self, c: ty::Const<'_>) {
290284
self.add_ty(c.ty());
291285
match c.kind() {
292-
ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
286+
ty::ConstKind::Unevaluated(uv) => {
287+
self.add_substs(uv.substs);
288+
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
289+
}
293290
ty::ConstKind::Infer(infer) => {
294291
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
295292
match infer {
@@ -313,11 +310,6 @@ impl FlagComputation {
313310
}
314311
}
315312

316-
fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) {
317-
self.add_substs(ct.substs);
318-
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
319-
}
320-
321313
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
322314
self.add_substs(projection.substs);
323315
match projection.term.unpack() {

compiler/rustc_middle/src/ty/fold.rs

-21
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,6 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
126126
c.super_fold_with(self)
127127
}
128128

129-
fn fold_ty_unevaluated(
130-
&mut self,
131-
uv: ty::UnevaluatedConst<'tcx>,
132-
) -> ty::UnevaluatedConst<'tcx> {
133-
uv.super_fold_with(self)
134-
}
135-
136129
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
137130
p.super_fold_with(self)
138131
}
@@ -169,13 +162,6 @@ pub trait FallibleTypeFolder<'tcx>: Sized {
169162
c.try_super_fold_with(self)
170163
}
171164

172-
fn try_fold_ty_unevaluated(
173-
&mut self,
174-
c: ty::UnevaluatedConst<'tcx>,
175-
) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> {
176-
c.try_super_fold_with(self)
177-
}
178-
179165
fn try_fold_predicate(
180166
&mut self,
181167
p: ty::Predicate<'tcx>,
@@ -215,13 +201,6 @@ where
215201
Ok(self.fold_const(c))
216202
}
217203

218-
fn try_fold_ty_unevaluated(
219-
&mut self,
220-
c: ty::UnevaluatedConst<'tcx>,
221-
) -> Result<ty::UnevaluatedConst<'tcx>, !> {
222-
Ok(self.fold_ty_unevaluated(c))
223-
}
224-
225204
fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
226205
Ok(self.fold_predicate(p))
227206
}

compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ pub enum PredicateKind<'tcx> {
683683
Coerce(CoercePredicate<'tcx>),
684684

685685
/// Constant initializer must evaluate successfully.
686-
ConstEvaluatable(ty::UnevaluatedConst<'tcx>),
686+
ConstEvaluatable(ty::Const<'tcx>),
687687

688688
/// Constants must be equal. The first component is the const that is expected.
689689
ConstEquate(Const<'tcx>, Const<'tcx>),

compiler/rustc_middle/src/ty/print/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2702,8 +2702,8 @@ define_print_and_forward_display! {
27022702
print_value_path(closure_def_id, &[]),
27032703
write("` implements the trait `{}`", kind))
27042704
}
2705-
ty::PredicateKind::ConstEvaluatable(uv) => {
2706-
p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
2705+
ty::PredicateKind::ConstEvaluatable(ct) => {
2706+
p!("the constant `", print(ct), "` can be evaluated")
27072707
}
27082708
ty::PredicateKind::ConstEquate(c1, c2) => {
27092709
p!("the constant `", print(c1), "` equals `", print(c2), "`")

compiler/rustc_middle/src/ty/structural_impls.rs

+2-23
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
166166
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
167167
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
168168
}
169-
ty::PredicateKind::ConstEvaluatable(uv) => {
170-
write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
169+
ty::PredicateKind::ConstEvaluatable(ct) => {
170+
write!(f, "ConstEvaluatable({ct:?})")
171171
}
172172
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
173173
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
@@ -832,27 +832,6 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
832832
}
833833
}
834834

835-
impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
836-
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
837-
folder.try_fold_ty_unevaluated(self)
838-
}
839-
}
840-
841-
impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
842-
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
843-
visitor.visit_ty_unevaluated(*self)
844-
}
845-
}
846-
847-
impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
848-
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
849-
self,
850-
folder: &mut F,
851-
) -> Result<Self, F::Error> {
852-
Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? })
853-
}
854-
}
855-
856835
impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
857836
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
858837
self.substs.visit_with(visitor)

compiler/rustc_middle/src/ty/subst.rs

+8
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,14 @@ impl<'tcx> GenericArg<'tcx> {
188188
_ => bug!("expected a const, but found another kind"),
189189
}
190190
}
191+
192+
pub fn is_non_region_infer(self) -> bool {
193+
match self.unpack() {
194+
GenericArgKind::Lifetime(_) => false,
195+
GenericArgKind::Type(ty) => ty.is_ty_infer(),
196+
GenericArgKind::Const(ct) => ct.is_ct_infer(),
197+
}
198+
}
191199
}
192200

193201
impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {

compiler/rustc_middle/src/ty/visit.rs

-22
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,6 @@ pub trait TypeVisitor<'tcx>: Sized {
197197
c.super_visit_with(self)
198198
}
199199

200-
fn visit_ty_unevaluated(
201-
&mut self,
202-
uv: ty::UnevaluatedConst<'tcx>,
203-
) -> ControlFlow<Self::BreakTy> {
204-
uv.super_visit_with(self)
205-
}
206-
207200
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
208201
p.super_visit_with(self)
209202
}
@@ -592,21 +585,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
592585
}
593586
}
594587

595-
#[inline]
596-
#[instrument(level = "trace", ret)]
597-
fn visit_ty_unevaluated(
598-
&mut self,
599-
uv: ty::UnevaluatedConst<'tcx>,
600-
) -> ControlFlow<Self::BreakTy> {
601-
let flags = FlagComputation::for_unevaluated_const(uv);
602-
trace!(r.flags=?flags);
603-
if flags.intersects(self.flags) {
604-
ControlFlow::Break(FoundFlags)
605-
} else {
606-
ControlFlow::CONTINUE
607-
}
608-
}
609-
610588
#[inline]
611589
#[instrument(level = "trace", ret)]
612590
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {

compiler/rustc_middle/src/ty/walk.rs

+16
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,22 @@ impl<'tcx> Ty<'tcx> {
112112
}
113113
}
114114

115+
impl<'tcx> ty::Const<'tcx> {
116+
/// Iterator that walks `self` and any types reachable from
117+
/// `self`, in depth-first order. Note that just walks the types
118+
/// that appear in `self`, it does not descend into the fields of
119+
/// structs or variants. For example:
120+
///
121+
/// ```text
122+
/// isize => { isize }
123+
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
124+
/// [isize] => { [isize], isize }
125+
/// ```
126+
pub fn walk(self) -> TypeWalker<'tcx> {
127+
TypeWalker::new(self.into())
128+
}
129+
}
130+
115131
/// We push `GenericArg`s on the stack in reverse order so as to
116132
/// maintain a pre-order traversal. As of the time of this
117133
/// writing, the fact that the traversal is pre-order is not

compiler/rustc_privacy/src/lib.rs

+10-25
Original file line numberDiff line numberDiff line change
@@ -159,34 +159,12 @@ where
159159
ty.visit_with(self)
160160
}
161161
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
162-
ty::PredicateKind::ConstEvaluatable(uv)
163-
if self.def_id_visitor.tcx().features().generic_const_exprs =>
164-
{
165-
let tcx = self.def_id_visitor.tcx();
166-
if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
167-
self.visit_abstract_const_expr(tcx, ct)?;
168-
}
169-
ControlFlow::CONTINUE
170-
}
162+
ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
171163
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
172164
_ => bug!("unexpected predicate: {:?}", predicate),
173165
}
174166
}
175167

176-
fn visit_abstract_const_expr(
177-
&mut self,
178-
tcx: TyCtxt<'tcx>,
179-
ct: AbstractConst<'tcx>,
180-
) -> ControlFlow<V::BreakTy> {
181-
walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
182-
ACNode::Leaf(leaf) => self.visit_const(leaf),
183-
ACNode::Cast(_, _, ty) => self.visit_ty(ty),
184-
ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
185-
ControlFlow::CONTINUE
186-
}
187-
})
188-
}
189-
190168
fn visit_predicates(
191169
&mut self,
192170
predicates: ty::GenericPredicates<'tcx>,
@@ -309,9 +287,16 @@ where
309287
self.visit_ty(c.ty())?;
310288
let tcx = self.def_id_visitor.tcx();
311289
if let Ok(Some(ct)) = AbstractConst::from_const(tcx, c) {
312-
self.visit_abstract_const_expr(tcx, ct)?;
290+
walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
291+
ACNode::Leaf(leaf) => self.visit_const(leaf),
292+
ACNode::Cast(_, _, ty) => self.visit_ty(ty),
293+
ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
294+
ControlFlow::CONTINUE
295+
}
296+
})
297+
} else {
298+
ControlFlow::CONTINUE
313299
}
314-
ControlFlow::CONTINUE
315300
}
316301
}
317302

0 commit comments

Comments
 (0)