Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 26c96e3

Browse files
committedOct 22, 2022
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`
2 parents 3022afe + b93713f commit 26c96e3

File tree

30 files changed

+131
-191
lines changed

30 files changed

+131
-191
lines changed
 

‎compiler/rustc_hir_analysis/src/check/dropck.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 6 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 25 additions & 1 deletion
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 5 additions & 13 deletions
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

Lines changed: 0 additions & 21 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 23 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 0 additions & 22 deletions
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

Lines changed: 16 additions & 0 deletions
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

Lines changed: 10 additions & 25 deletions
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

‎compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@
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.
1111
use rustc_errors::ErrorGuaranteed;
12-
use rustc_hir::def::DefKind;
1312
use rustc_infer::infer::InferCtxt;
1413
use rustc_middle::mir::interpret::ErrorHandled;
1514
use rustc_middle::ty::abstract_const::{
1615
walk_abstract_const, AbstractConst, FailureKind, Node, NotConstEvaluatable,
1716
};
1817
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
19-
use rustc_session::lint;
2018
use rustc_span::Span;
2119

2220
use std::iter;
@@ -161,11 +159,20 @@ pub fn try_unify_abstract_consts<'tcx>(
161159
#[instrument(skip(infcx), level = "debug")]
162160
pub fn is_const_evaluatable<'tcx>(
163161
infcx: &InferCtxt<'tcx>,
164-
uv: ty::UnevaluatedConst<'tcx>,
162+
ct: ty::Const<'tcx>,
165163
param_env: ty::ParamEnv<'tcx>,
166164
span: Span,
167165
) -> Result<(), NotConstEvaluatable> {
168166
let tcx = infcx.tcx;
167+
let uv = match ct.kind() {
168+
ty::ConstKind::Unevaluated(uv) => uv,
169+
ty::ConstKind::Param(_)
170+
| ty::ConstKind::Bound(_, _)
171+
| ty::ConstKind::Placeholder(_)
172+
| ty::ConstKind::Value(_)
173+
| ty::ConstKind::Error(_) => return Ok(()),
174+
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
175+
};
169176

170177
if tcx.features().generic_const_exprs {
171178
if let Some(ct) = AbstractConst::new(tcx, uv)? {
@@ -253,25 +260,7 @@ pub fn is_const_evaluatable<'tcx>(
253260
Err(NotConstEvaluatable::Error(reported))
254261
}
255262
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
256-
Ok(_) => {
257-
if uv.substs.has_non_region_param() {
258-
assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
259-
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
260-
261-
if mir_body.is_polymorphic {
262-
let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
263-
tcx.struct_span_lint_hir(
264-
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
265-
tcx.hir().local_def_id_to_hir_id(local_def_id),
266-
span,
267-
"cannot use constants which depend on generic parameters in types",
268-
|err| err
269-
)
270-
}
271-
}
272-
273-
Ok(())
274-
},
263+
Ok(_) => Ok(()),
275264
}
276265
}
277266
}
@@ -285,7 +274,7 @@ fn satisfied_from_param_env<'tcx>(
285274
for pred in param_env.caller_bounds() {
286275
match pred.kind().skip_binder() {
287276
ty::PredicateKind::ConstEvaluatable(uv) => {
288-
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
277+
if let Some(b_ct) = AbstractConst::from_const(tcx, uv)? {
289278
let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
290279

291280
// Try to unify with each subtree in the AbstractConst to allow for

‎compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13041304
}
13051305

13061306
match obligation.predicate.kind().skip_binder() {
1307-
ty::PredicateKind::ConstEvaluatable(uv) => {
1307+
ty::PredicateKind::ConstEvaluatable(ct) => {
1308+
let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
1309+
bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
1310+
};
13081311
let mut err =
13091312
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
13101313
let const_span = self.tcx.def_span(uv.def.did);
@@ -2368,7 +2371,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23682371
if predicate.references_error() || self.is_tainted_by_errors() {
23692372
return;
23702373
}
2371-
let subst = data.substs.iter().find(|g| g.has_non_region_infer());
2374+
let subst = data.walk().find(|g| g.is_non_region_infer());
23722375
if let Some(subst) = subst {
23732376
let err = self.emit_inference_failure_err(
23742377
body_id,

‎compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -476,9 +476,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
476476
Err(NotConstEvaluatable::MentionsInfer) => {
477477
pending_obligation.stalled_on.clear();
478478
pending_obligation.stalled_on.extend(
479-
uv.substs
480-
.iter()
481-
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
479+
uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
482480
);
483481
ProcessResult::Unchanged
484482
}

‎compiler/rustc_trait_selection/src/traits/object_safety.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -837,24 +837,14 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
837837
}
838838
}
839839

840-
fn visit_ty_unevaluated(
841-
&mut self,
842-
uv: ty::UnevaluatedConst<'tcx>,
843-
) -> ControlFlow<Self::BreakTy> {
840+
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
844841
// Constants can only influence object safety if they reference `Self`.
845842
// This is only possible for unevaluated constants, so we walk these here.
846843
//
847-
// If `AbstractConst::new` returned an error we already failed compilation
844+
// If `AbstractConst::from_const` returned an error we already failed compilation
848845
// so we don't have to emit an additional error here.
849-
//
850-
// We currently recurse into abstract consts here but do not recurse in
851-
// `is_const_evaluatable`. This means that the object safety check is more
852-
// liberal than the const eval check.
853-
//
854-
// This shouldn't really matter though as we can't really use any
855-
// constants which are not considered const evaluatable.
856846
use rustc_middle::ty::abstract_const::Node;
857-
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
847+
if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
858848
walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
859849
Node::Leaf(leaf) => self.visit_const(leaf),
860850
Node::Cast(_, _, ty) => self.visit_ty(ty),
@@ -863,7 +853,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
863853
}
864854
})
865855
} else {
866-
ControlFlow::CONTINUE
856+
ct.super_visit_with(self)
867857
}
868858
}
869859
}

‎compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,8 @@ pub fn predicate_obligations<'tcx>(
148148
wf.compute(a.into());
149149
wf.compute(b.into());
150150
}
151-
ty::PredicateKind::ConstEvaluatable(uv) => {
152-
let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
153-
wf.out.extend(obligations);
154-
155-
for arg in uv.substs.iter() {
156-
wf.compute(arg);
157-
}
151+
ty::PredicateKind::ConstEvaluatable(ct) => {
152+
wf.compute(ct.into());
158153
}
159154
ty::PredicateKind::ConstEquate(c1, c2) => {
160155
wf.compute(c1.into());
@@ -476,14 +471,14 @@ impl<'tcx> WfPredicates<'tcx> {
476471
// obligations are handled by the parent (e.g. `ty::Ref`).
477472
GenericArgKind::Lifetime(_) => continue,
478473

479-
GenericArgKind::Const(constant) => {
480-
match constant.kind() {
474+
GenericArgKind::Const(ct) => {
475+
match ct.kind() {
481476
ty::ConstKind::Unevaluated(uv) => {
482477
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
483478
self.out.extend(obligations);
484479

485480
let predicate =
486-
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
481+
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
487482
.to_predicate(self.tcx());
488483
let cause = self.cause(traits::WellFormed(None));
489484
self.out.push(traits::Obligation::with_depth(
@@ -500,7 +495,7 @@ impl<'tcx> WfPredicates<'tcx> {
500495
cause,
501496
self.recursion_depth,
502497
self.param_env,
503-
ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into()))
498+
ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
504499
.to_predicate(self.tcx()),
505500
));
506501
}

‎src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: generic parameters may not be used in const operations
2-
--> $DIR/dependence_lint.rs:13:32
2+
--> $DIR/dependence_lint.rs:14:32
33
|
44
LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
55
| ^ cannot perform const operation using `T`
@@ -8,7 +8,7 @@ LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
88
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
99

1010
error: generic parameters may not be used in const operations
11-
--> $DIR/dependence_lint.rs:20:37
11+
--> $DIR/dependence_lint.rs:21:37
1212
|
1313
LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
1414
| ^ cannot perform const operation using `T`
@@ -17,7 +17,7 @@ LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable,
1717
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
1818

1919
warning: cannot use constants which depend on generic parameters in types
20-
--> $DIR/dependence_lint.rs:9:9
20+
--> $DIR/dependence_lint.rs:10:9
2121
|
2222
LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
2323
| ^^^^^^^^^^^^^^^^^^^
@@ -27,7 +27,7 @@ LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_
2727
= note: `#[warn(const_evaluatable_unchecked)]` on by default
2828

2929
warning: cannot use constants which depend on generic parameters in types
30-
--> $DIR/dependence_lint.rs:16:9
30+
--> $DIR/dependence_lint.rs:17:9
3131
|
3232
LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
3333
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

‎src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
error: overly complex generic constant
2-
--> $DIR/dependence_lint.rs:16:9
2+
--> $DIR/dependence_lint.rs:17:9
33
|
44
LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
66
|
77
= help: consider moving this anonymous constant into a `const` function
88

99
error: overly complex generic constant
10-
--> $DIR/dependence_lint.rs:20:17
10+
--> $DIR/dependence_lint.rs:21:17
1111
|
1212
LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
1414
|
1515
= help: consider moving this anonymous constant into a `const` function
1616

1717
error: unconstrained generic constant
18-
--> $DIR/dependence_lint.rs:13:12
18+
--> $DIR/dependence_lint.rs:14:12
1919
|
2020
LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^
2222
|
2323
= help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:`
2424

2525
error: unconstrained generic constant
26-
--> $DIR/dependence_lint.rs:9:9
26+
--> $DIR/dependence_lint.rs:10:9
2727
|
2828
LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
2929
| ^^^^^^^^^^^^^^^^^^^

‎src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// revisions: full gce
2+
// compile-flags: -Zdeduplicate-diagnostics=yes
23

34
#![cfg_attr(gce, feature(generic_const_exprs))]
45
#![allow(incomplete_features)]

‎src/test/ui/const-generics/generic_const_exprs/function-call.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// check-pass
2+
// compile-flags: -Zdeduplicate-diagnostics=yes
23

34
const fn foo<T>() -> usize {
45
// We might instead branch on `std::mem::size_of::<*mut T>() < 8` here,

‎src/test/ui/const-generics/generic_const_exprs/function-call.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: cannot use constants which depend on generic parameters in types
2-
--> $DIR/function-call.rs:14:17
2+
--> $DIR/function-call.rs:15:17
33
|
44
LL | let _ = [0; foo::<T>()];
55
| ^^^^^^^^^^

‎src/test/ui/const-generics/min_const_generics/complex-expression.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// compile-flags: -Zdeduplicate-diagnostics=yes
12
use std::mem::size_of;
23

34
fn test<const N: usize>() {}

‎src/test/ui/const-generics/min_const_generics/complex-expression.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: generic parameters may not be used in const operations
2-
--> $DIR/complex-expression.rs:9:38
2+
--> $DIR/complex-expression.rs:10:38
33
|
44
LL | struct Break0<const N: usize>([u8; { N + 1 }]);
55
| ^ cannot perform const operation using `N`
@@ -8,7 +8,7 @@ LL | struct Break0<const N: usize>([u8; { N + 1 }]);
88
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
99

1010
error: generic parameters may not be used in const operations
11-
--> $DIR/complex-expression.rs:12:40
11+
--> $DIR/complex-expression.rs:13:40
1212
|
1313
LL | struct Break1<const N: usize>([u8; { { N } }]);
1414
| ^ cannot perform const operation using `N`
@@ -17,7 +17,7 @@ LL | struct Break1<const N: usize>([u8; { { N } }]);
1717
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
1818

1919
error: generic parameters may not be used in const operations
20-
--> $DIR/complex-expression.rs:16:17
20+
--> $DIR/complex-expression.rs:17:17
2121
|
2222
LL | let _: [u8; N + 1];
2323
| ^ cannot perform const operation using `N`
@@ -26,7 +26,7 @@ LL | let _: [u8; N + 1];
2626
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
2727

2828
error: generic parameters may not be used in const operations
29-
--> $DIR/complex-expression.rs:21:17
29+
--> $DIR/complex-expression.rs:22:17
3030
|
3131
LL | let _ = [0; N + 1];
3232
| ^ cannot perform const operation using `N`
@@ -35,7 +35,7 @@ LL | let _ = [0; N + 1];
3535
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
3636

3737
error: generic parameters may not be used in const operations
38-
--> $DIR/complex-expression.rs:25:45
38+
--> $DIR/complex-expression.rs:26:45
3939
|
4040
LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
4141
| ^ cannot perform const operation using `T`
@@ -44,7 +44,7 @@ LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
4444
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
4545

4646
error: generic parameters may not be used in const operations
47-
--> $DIR/complex-expression.rs:28:47
47+
--> $DIR/complex-expression.rs:29:47
4848
|
4949
LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
5050
| ^ cannot perform const operation using `T`
@@ -53,7 +53,7 @@ LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
5353
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
5454

5555
error: generic parameters may not be used in const operations
56-
--> $DIR/complex-expression.rs:32:32
56+
--> $DIR/complex-expression.rs:33:32
5757
|
5858
LL | let _: [u8; size_of::<*mut T>() + 1];
5959
| ^ cannot perform const operation using `T`
@@ -62,7 +62,7 @@ LL | let _: [u8; size_of::<*mut T>() + 1];
6262
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
6363

6464
warning: cannot use constants which depend on generic parameters in types
65-
--> $DIR/complex-expression.rs:37:17
65+
--> $DIR/complex-expression.rs:38:17
6666
|
6767
LL | let _ = [0; size_of::<*mut T>() + 1];
6868
| ^^^^^^^^^^^^^^^^^^^^^^^

‎src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// check-pass
2+
// compile-flags: -Zdeduplicate-diagnostics=yes
23
#![allow(dead_code)]
34

45
fn foo<T>() {

‎src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: cannot use constants which depend on generic parameters in types
2-
--> $DIR/const-evaluatable-unchecked.rs:5:9
2+
--> $DIR/const-evaluatable-unchecked.rs:6:9
33
|
44
LL | [0; std::mem::size_of::<*mut T>()];
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | [0; std::mem::size_of::<*mut T>()];
99
= note: `#[warn(const_evaluatable_unchecked)]` on by default
1010

1111
warning: cannot use constants which depend on generic parameters in types
12-
--> $DIR/const-evaluatable-unchecked.rs:16:21
12+
--> $DIR/const-evaluatable-unchecked.rs:17:21
1313
|
1414
LL | let _ = [0; Self::ASSOC];
1515
| ^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | let _ = [0; Self::ASSOC];
1818
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
1919

2020
warning: cannot use constants which depend on generic parameters in types
21-
--> $DIR/const-evaluatable-unchecked.rs:28:21
21+
--> $DIR/const-evaluatable-unchecked.rs:29:21
2222
|
2323
LL | let _ = [0; Self::ASSOC];
2424
| ^^^^^^^^^^^

0 commit comments

Comments
 (0)
Please sign in to comment.