Skip to content

Commit dec8ed4

Browse files
committed
attempt to re-add ty::Unevaluated visitor and friends
1 parent 71bbb60 commit dec8ed4

File tree

21 files changed

+175
-122
lines changed

21 files changed

+175
-122
lines changed

compiler/rustc_infer/src/infer/mod.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -668,13 +668,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
668668
/// canonicalizing the consts.
669669
pub fn try_unify_abstract_consts(
670670
&self,
671-
a: ty::Unevaluated<'tcx>,
672-
b: ty::Unevaluated<'tcx>,
671+
a: ty::Unevaluated<'tcx, ()>,
672+
b: ty::Unevaluated<'tcx, ()>,
673673
) -> bool {
674-
let canonical = self.canonicalize_query(
675-
((a.def, a.substs), (b.def, b.substs)),
676-
&mut OriginalQueryValues::default(),
677-
);
674+
let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default());
678675
debug!("canonical consts: {:?}", &canonical.value);
679676

680677
self.tcx.try_unify_abstract_consts(canonical.value)

compiler/rustc_middle/src/query/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,11 @@ rustc_queries! {
314314
}
315315

316316
query try_unify_abstract_consts(key: (
317-
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
318-
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)
317+
ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
319318
)) -> bool {
320319
desc {
321320
|tcx| "trying to unify the generic constants {} and {}",
322-
tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did)
321+
tcx.def_path_str(key.0.def.did), tcx.def_path_str(key.1.def.did)
323322
}
324323
}
325324

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

+35-13
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,31 @@ use rustc_target::abi::Size;
1212

1313
use super::ScalarInt;
1414
/// An unevaluated, potentially generic, constant.
15-
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
15+
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
1616
#[derive(Hash, HashStable)]
17-
pub struct Unevaluated<'tcx> {
17+
pub struct Unevaluated<'tcx, P = Option<Promoted>> {
1818
pub def: ty::WithOptConstParam<DefId>,
1919
pub substs: SubstsRef<'tcx>,
20-
pub promoted: Option<Promoted>,
20+
pub promoted: P,
21+
}
22+
23+
impl<'tcx> Unevaluated<'tcx> {
24+
pub fn shrink(self) -> Unevaluated<'tcx, ()> {
25+
debug_assert_eq!(self.promoted, None);
26+
Unevaluated { def: self.def, substs: self.substs, promoted: () }
27+
}
28+
}
29+
30+
impl<'tcx> Unevaluated<'tcx, ()> {
31+
pub fn expand(self) -> Unevaluated<'tcx> {
32+
Unevaluated { def: self.def, substs: self.substs, promoted: None }
33+
}
34+
}
35+
36+
impl<'tcx, P: Default> Unevaluated<'tcx, P> {
37+
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
38+
Unevaluated { def, substs, promoted: Default::default() }
39+
}
2140
}
2241

2342
/// Represents a constant in Rust.
@@ -109,7 +128,7 @@ impl<'tcx> ConstKind<'tcx> {
109128
tcx: TyCtxt<'tcx>,
110129
param_env: ParamEnv<'tcx>,
111130
) -> Option<Result<ConstValue<'tcx>, ErrorReported>> {
112-
if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self {
131+
if let ConstKind::Unevaluated(unevaluated) = self {
113132
use crate::mir::interpret::ErrorHandled;
114133

115134
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
@@ -118,29 +137,32 @@ impl<'tcx> ConstKind<'tcx> {
118137
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
119138
// so that we don't try to invoke this query with
120139
// any region variables.
121-
let param_env_and_substs = tcx
140+
let param_env_and = tcx
122141
.erase_regions(param_env)
123142
.with_reveal_all_normalized(tcx)
124-
.and(tcx.erase_regions(substs));
143+
.and(tcx.erase_regions(unevaluated));
125144

126145
// HACK(eddyb) when the query key would contain inference variables,
127146
// attempt using identity substs and `ParamEnv` instead, that will succeed
128147
// when the expression doesn't depend on any parameters.
129148
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
130149
// we can call `infcx.const_eval_resolve` which handles inference variables.
131-
let param_env_and_substs = if param_env_and_substs.needs_infer() {
132-
tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
150+
let param_env_and = if param_env_and.needs_infer() {
151+
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
152+
def: unevaluated.def,
153+
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
154+
promoted: unevaluated.promoted,
155+
})
133156
} else {
134-
param_env_and_substs
157+
param_env_and
135158
};
136159

137160
// FIXME(eddyb) maybe the `const_eval_*` methods should take
138-
// `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
139-
let (param_env, substs) = param_env_and_substs.into_parts();
161+
// `ty::ParamEnvAnd` instead of having them separate.
162+
let (param_env, unevaluated) = param_env_and.into_parts();
140163
// try to resolve e.g. associated constants to their definition on an impl, and then
141164
// evaluate the const.
142-
match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None)
143-
{
165+
match tcx.const_eval_resolve(param_env, unevaluated, None) {
144166
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
145167
// and we use the original type, so nothing from `substs`
146168
// (which may be identity substs, see above),

compiler/rustc_middle/src/ty/flags.rs

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

37+
pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
38+
let mut result = FlagComputation::new();
39+
result.add_unevaluated_const(uv);
40+
result.flags
41+
}
42+
3743
fn add_flags(&mut self, flags: TypeFlags) {
3844
self.flags = self.flags | flags;
3945
}
@@ -246,8 +252,8 @@ impl FlagComputation {
246252
ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
247253
self.add_substs(substs);
248254
}
249-
ty::PredicateKind::ConstEvaluatable(_def_id, substs) => {
250-
self.add_substs(substs);
255+
ty::PredicateKind::ConstEvaluatable(uv) => {
256+
self.add_unevaluated_const(uv);
251257
}
252258
ty::PredicateKind::ConstEquate(expected, found) => {
253259
self.add_const(expected);
@@ -304,7 +310,7 @@ impl FlagComputation {
304310
}
305311
}
306312

307-
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) {
313+
fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
308314
self.add_substs(ct.substs);
309315
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
310316
}

compiler/rustc_middle/src/ty/fold.rs

+16
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,10 @@ pub trait TypeVisitor<'tcx>: Sized {
350350
c.super_visit_with(self)
351351
}
352352

353+
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
354+
uv.super_visit_with(self)
355+
}
356+
353357
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
354358
p.super_visit_with(self)
355359
}
@@ -1242,6 +1246,18 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
12421246
}
12431247
}
12441248

1249+
#[inline]
1250+
#[instrument(level = "trace")]
1251+
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
1252+
let flags = FlagComputation::for_unevaluated_const(uv);
1253+
trace!(r.flags=?flags);
1254+
if flags.intersects(self.flags) {
1255+
ControlFlow::Break(FoundFlags)
1256+
} else {
1257+
ControlFlow::CONTINUE
1258+
}
1259+
}
1260+
12451261
#[inline]
12461262
#[instrument(level = "trace")]
12471263
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {

compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ pub enum PredicateKind<'tcx> {
598598
Coerce(CoercePredicate<'tcx>),
599599

600600
/// Constant initializer must evaluate successfully.
601-
ConstEvaluatable(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
601+
ConstEvaluatable(ty::Unevaluated<'tcx, ()>),
602602

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

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -2539,8 +2539,8 @@ define_print_and_forward_display! {
25392539
print_value_path(closure_def_id, &[]),
25402540
write("` implements the trait `{}`", kind))
25412541
}
2542-
ty::PredicateKind::ConstEvaluatable(def, substs) => {
2543-
p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
2542+
ty::PredicateKind::ConstEvaluatable(uv) => {
2543+
p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
25442544
}
25452545
ty::PredicateKind::ConstEquate(c1, c2) => {
25462546
p!("the constant `", print(c1), "` equals `", print(c2), "`")

compiler/rustc_middle/src/ty/relate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
587587
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
588588
if tcx.features().generic_const_exprs =>
589589
{
590-
tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs)))
590+
tcx.try_unify_abstract_consts((au.shrink(), bu.shrink()))
591591
}
592592

593593
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`

compiler/rustc_middle/src/ty/structural_impls.rs

+48-12
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
184184
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
185185
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
186186
}
187-
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
188-
write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
187+
ty::PredicateKind::ConstEvaluatable(uv) => {
188+
write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
189189
}
190190
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
191191
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
@@ -445,8 +445,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
445445
ty::PredicateKind::ObjectSafe(trait_def_id) => {
446446
Some(ty::PredicateKind::ObjectSafe(trait_def_id))
447447
}
448-
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
449-
tcx.lift(substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs))
448+
ty::PredicateKind::ConstEvaluatable(uv) => {
449+
tcx.lift(uv).map(|uv| ty::PredicateKind::ConstEvaluatable(uv))
450450
}
451451
ty::PredicateKind::ConstEquate(c1, c2) => {
452452
tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
@@ -1185,13 +1185,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
11851185
Ok(match self {
11861186
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?),
11871187
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?),
1188-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
1189-
ty::ConstKind::Unevaluated(ty::Unevaluated {
1190-
def,
1191-
substs: substs.try_fold_with(folder)?,
1192-
promoted,
1193-
})
1194-
}
1188+
ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.try_fold_with(folder)?),
11951189
ty::ConstKind::Value(_)
11961190
| ty::ConstKind::Bound(..)
11971191
| ty::ConstKind::Placeholder(..)
@@ -1203,7 +1197,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
12031197
match *self {
12041198
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
12051199
ty::ConstKind::Param(p) => p.visit_with(visitor),
1206-
ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor),
1200+
ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
12071201
ty::ConstKind::Value(_)
12081202
| ty::ConstKind::Bound(..)
12091203
| ty::ConstKind::Placeholder(_)
@@ -1224,3 +1218,45 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
12241218
ControlFlow::CONTINUE
12251219
}
12261220
}
1221+
1222+
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
1223+
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
1224+
self,
1225+
folder: &mut F,
1226+
) -> Result<Self, F::Error> {
1227+
Ok(ty::Unevaluated {
1228+
def: self.def,
1229+
substs: self.substs.try_fold_with(folder)?,
1230+
promoted: self.promoted,
1231+
})
1232+
}
1233+
1234+
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1235+
visitor.visit_unevaluated_const(*self)
1236+
}
1237+
1238+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1239+
self.substs.visit_with(visitor)
1240+
}
1241+
}
1242+
1243+
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
1244+
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
1245+
self,
1246+
folder: &mut F,
1247+
) -> Result<Self, F::Error> {
1248+
Ok(ty::Unevaluated {
1249+
def: self.def,
1250+
substs: self.substs.try_fold_with(folder)?,
1251+
promoted: self.promoted,
1252+
})
1253+
}
1254+
1255+
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1256+
visitor.visit_unevaluated_const(self.expand())
1257+
}
1258+
1259+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1260+
self.substs.visit_with(visitor)
1261+
}
1262+
}

compiler/rustc_mir_build/src/thir/cx/expr.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -716,11 +716,10 @@ impl<'tcx> Cx<'tcx> {
716716
// and not the beginning of discriminants (which is always `0`)
717717
let substs = InternalSubsts::identity_for_item(self.tcx(), did);
718718
let lhs = ty::Const {
719-
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
720-
def: ty::WithOptConstParam::unknown(did),
719+
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
720+
ty::WithOptConstParam::unknown(did),
721721
substs,
722-
promoted: None,
723-
}),
722+
)),
724723
ty: var_ty,
725724
};
726725
let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs)));
@@ -912,11 +911,10 @@ impl<'tcx> Cx<'tcx> {
912911
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
913912
ExprKind::Literal {
914913
literal: self.tcx.mk_const(ty::Const {
915-
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
916-
def: ty::WithOptConstParam::unknown(def_id),
914+
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
915+
ty::WithOptConstParam::unknown(def_id),
917916
substs,
918-
promoted: None,
919-
}),
917+
)),
920918
ty: self.typeck_results().node_type(expr.hir_id),
921919
}),
922920
user_ty,

compiler/rustc_privacy/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,11 @@ where
135135
ty.visit_with(self)
136136
}
137137
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
138-
ty::PredicateKind::ConstEvaluatable(defs, substs)
138+
ty::PredicateKind::ConstEvaluatable(uv)
139139
if self.def_id_visitor.tcx().features().generic_const_exprs =>
140140
{
141141
let tcx = self.def_id_visitor.tcx();
142-
if let Ok(Some(ct)) = AbstractConst::new(tcx, defs, substs) {
142+
if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
143143
self.visit_abstract_const_expr(tcx, ct)?;
144144
}
145145
ControlFlow::CONTINUE

compiler/rustc_query_impl/src/keys.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -245,18 +245,13 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
245245
}
246246
}
247247

248-
impl<'tcx> Key
249-
for (
250-
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
251-
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
252-
)
253-
{
248+
impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
254249
#[inline(always)]
255250
fn query_crate_is_local(&self) -> bool {
256-
(self.0).0.did.krate == LOCAL_CRATE
251+
(self.0).def.did.krate == LOCAL_CRATE
257252
}
258253
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
259-
(self.0).0.did.default_span(tcx)
254+
(self.0).def.did.default_span(tcx)
260255
}
261256
}
262257

0 commit comments

Comments
 (0)