Skip to content

Commit 371c77b

Browse files
committed
make unevaluated const substs optional
1 parent 4e8e894 commit 371c77b

File tree

25 files changed

+122
-80
lines changed

25 files changed

+122
-80
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,13 @@ pub(crate) fn codegen_constant<'tcx>(
116116
let const_ = fx.monomorphize(constant.literal);
117117
let const_val = match const_.val {
118118
ConstKind::Value(const_val) => const_val,
119-
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) if fx.tcx.is_static(def.did) => {
120-
assert!(substs.is_empty());
121-
assert!(promoted.is_none());
119+
ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => {
120+
assert!(uv.substs(fx.tcx).is_empty());
121+
assert!(uv.promoted.is_none());
122122

123123
return codegen_static_ref(
124124
fx,
125-
def.did,
125+
uv.def.did,
126126
fx.layout_of(fx.monomorphize(&constant.literal.ty)),
127127
)
128128
.to_cvalue(fx);

compiler/rustc_infer/src/infer/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1498,16 +1498,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14981498
pub fn const_eval_resolve(
14991499
&self,
15001500
param_env: ty::ParamEnv<'tcx>,
1501-
ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>,
1501+
unevaluated: ty::Unevaluated<'tcx>,
15021502
span: Option<Span>,
15031503
) -> EvalToConstValueResult<'tcx> {
15041504
let mut original_values = OriginalQueryValues::default();
1505-
let canonical = self.canonicalize_query((param_env, substs), &mut original_values);
1505+
let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values);
15061506

1507-
let (param_env, substs) = canonical.value;
1507+
let (param_env, unevaluated) = canonical.value;
15081508
// The return value is the evaluated value which doesn't contain any reference to inference
15091509
// variables, thus we don't need to substitute back the original values.
1510-
self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span)
1510+
self.tcx.const_eval_resolve(param_env, unevaluated, span)
15111511
}
15121512

15131513
/// If `typ` is a type variable of some kind, resolve it one level

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> {
3838
ct: ty::Unevaluated<'tcx>,
3939
span: Option<Span>,
4040
) -> EvalToConstValueResult<'tcx> {
41-
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
41+
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs(self)) {
4242
Ok(Some(instance)) => {
4343
let cid = GlobalId { instance, promoted: ct.promoted };
4444
self.const_eval_global_id(param_env, cid, span)

compiler/rustc_middle/src/query/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ rustc_queries! {
9393
desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) }
9494
}
9595

96+
query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
97+
desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) }
98+
}
99+
96100
/// Records the type of every item.
97101
query type_of(key: DefId) -> Ty<'tcx> {
98102
desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }

compiler/rustc_middle/src/ty/consts.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::mir::interpret::ConstValue;
22
use crate::mir::interpret::{LitToConstInput, Scalar};
3-
use crate::ty::subst::InternalSubsts;
43
use crate::ty::{self, Ty, TyCtxt};
54
use crate::ty::{ParamEnv, ParamEnvAnd};
65
use rustc_errors::ErrorReported;
@@ -98,7 +97,7 @@ impl<'tcx> Const<'tcx> {
9897
}
9998
_ => ty::ConstKind::Unevaluated(ty::Unevaluated {
10099
def: def.to_global(),
101-
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
100+
non_default_substs: None,
102101
promoted: None,
103102
}),
104103
};

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

+23-11
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ use rustc_target::abi::Size;
1414
#[derive(Hash, HashStable)]
1515
pub struct Unevaluated<'tcx> {
1616
pub def: ty::WithOptConstParam<DefId>,
17-
pub substs: SubstsRef<'tcx>,
17+
pub non_default_substs: Option<SubstsRef<'tcx>>,
1818
pub promoted: Option<Promoted>,
1919
}
2020

21+
impl<'tcx> Unevaluated<'tcx> {
22+
pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> {
23+
self.non_default_substs.unwrap_or_else(|| tcx.default_anon_const_substs(self.def.did))
24+
}
25+
}
26+
2127
/// Represents a constant in Rust.
2228
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
2329
#[derive(Hash, HashStable)]
@@ -102,7 +108,7 @@ impl<'tcx> ConstKind<'tcx> {
102108
tcx: TyCtxt<'tcx>,
103109
param_env: ParamEnv<'tcx>,
104110
) -> Option<Result<ConstValue<'tcx>, ErrorReported>> {
105-
if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self {
111+
if let ConstKind::Unevaluated(unevaluated) = self {
106112
use crate::mir::interpret::ErrorHandled;
107113

108114
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
@@ -111,29 +117,35 @@ impl<'tcx> ConstKind<'tcx> {
111117
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
112118
// so that we don't try to invoke this query with
113119
// any region variables.
114-
let param_env_and_substs = tcx
120+
let param_env_and = tcx
115121
.erase_regions(param_env)
116122
.with_reveal_all_normalized(tcx)
117-
.and(tcx.erase_regions(substs));
123+
.and(tcx.erase_regions(unevaluated));
118124

119125
// HACK(eddyb) when the query key would contain inference variables,
120126
// attempt using identity substs and `ParamEnv` instead, that will succeed
121127
// when the expression doesn't depend on any parameters.
122128
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
123129
// we can call `infcx.const_eval_resolve` which handles inference variables.
124-
let param_env_and_substs = if param_env_and_substs.needs_infer() {
125-
tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
130+
let param_env_and = if param_env_and.needs_infer() {
131+
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
132+
def: unevaluated.def,
133+
non_default_substs: Some(InternalSubsts::identity_for_item(
134+
tcx,
135+
unevaluated.def.did,
136+
)),
137+
promoted: unevaluated.promoted,
138+
})
126139
} else {
127-
param_env_and_substs
140+
param_env_and
128141
};
129142

130143
// FIXME(eddyb) maybe the `const_eval_*` methods should take
131-
// `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
132-
let (param_env, substs) = param_env_and_substs.into_parts();
144+
// `ty::ParamEnvAnd` instead of having them separate.
145+
let (param_env, unevaluated) = param_env_and.into_parts();
133146
// try to resolve e.g. associated constants to their definition on an impl, and then
134147
// evaluate the const.
135-
match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None)
136-
{
148+
match tcx.const_eval_resolve(param_env, unevaluated, None) {
137149
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
138150
// and we use the original type, so nothing from `substs`
139151
// (which may be identity substs, see above),

compiler/rustc_middle/src/ty/flags.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ impl FlagComputation {
295295
}
296296

297297
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
298-
self.add_substs(ct.substs);
298+
// TODO
299+
self.add_substs(ct.non_default_substs.unwrap());
299300
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
300301
}
301302

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,9 @@ pub trait PrettyPrinter<'tcx>:
915915
}
916916

917917
match ct.val {
918-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
918+
ty::ConstKind::Unevaluated(ty::Unevaluated { def, non_default_substs, promoted }) => {
919+
// TODO
920+
let substs = non_default_substs.unwrap();
919921
if let Some(promoted) = promoted {
920922
p!(print_value_path(def.did, substs));
921923
p!(write("::{:?}", promoted));

compiler/rustc_middle/src/ty/relate.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
590590
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
591591
if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() =>
592592
{
593-
if tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) {
593+
if tcx.try_unify_abstract_consts(((au.def, au.substs(tcx)), (bu.def, bu.substs(tcx)))) {
594594
Ok(a.val)
595595
} else {
596596
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
@@ -603,11 +603,14 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
603603
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
604604
if au.def == bu.def && au.promoted == bu.promoted =>
605605
{
606-
let substs =
607-
relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?;
606+
let substs = relation.relate_with_variance(
607+
ty::Variance::Invariant,
608+
au.substs(tcx),
609+
bu.substs(tcx),
610+
)?;
608611
Ok(ty::ConstKind::Unevaluated(ty::Unevaluated {
609612
def: au.def,
610-
substs,
613+
non_default_substs: Some(substs),
611614
promoted: au.promoted,
612615
}))
613616
}

compiler/rustc_middle/src/ty/structural_impls.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -1031,13 +1031,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
10311031
match self {
10321032
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
10331033
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
1034-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
1035-
ty::ConstKind::Unevaluated(ty::Unevaluated {
1036-
def,
1037-
substs: substs.fold_with(folder),
1038-
promoted,
1039-
})
1040-
}
1034+
ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
10411035
ty::ConstKind::Value(_)
10421036
| ty::ConstKind::Bound(..)
10431037
| ty::ConstKind::Placeholder(..)
@@ -1049,7 +1043,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
10491043
match *self {
10501044
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
10511045
ty::ConstKind::Param(p) => p.visit_with(visitor),
1052-
ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor),
1046+
ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
10531047
ty::ConstKind::Value(_)
10541048
| ty::ConstKind::Bound(..)
10551049
| ty::ConstKind::Placeholder(_)
@@ -1067,3 +1061,17 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
10671061
ControlFlow::CONTINUE
10681062
}
10691063
}
1064+
1065+
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
1066+
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
1067+
ty::Unevaluated {
1068+
def: self.def,
1069+
non_default_substs: Some(self.substs(folder.tcx()).fold_with(folder)),
1070+
promoted: self.promoted,
1071+
}
1072+
}
1073+
1074+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1075+
self.substs(visitor.tcx_for_anon_const_substs()).visit_with(visitor)
1076+
}
1077+
}

compiler/rustc_middle/src/ty/walk.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
196196
| ty::ConstKind::Error(_) => {}
197197

198198
ty::ConstKind::Unevaluated(ct) => {
199-
stack.extend(ct.substs.iter().rev());
199+
// TODO
200+
stack.extend(ct.non_default_substs.unwrap().iter().rev());
200201
}
201202
}
202203
}

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
314314
}
315315
} else {
316316
let tcx = self.tcx();
317-
if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) =
318-
constant.literal.val
319-
{
320-
if let Some(promoted) = promoted {
317+
if let ty::ConstKind::Unevaluated(uv) = constant.literal.val {
318+
if let Some(promoted) = uv.promoted {
321319
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
322320
promoted: &Body<'tcx>,
323321
ty,
@@ -352,8 +350,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
352350
ConstraintCategory::Boring,
353351
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
354352
constant.literal.ty,
355-
def.did,
356-
UserSubsts { substs, user_self_ty: None },
353+
uv.def.did,
354+
UserSubsts { substs: uv.substs(tcx), user_self_ty: None },
357355
)),
358356
) {
359357
span_mirbug!(

compiler/rustc_mir/src/interpret/operand.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
566566
let val_val = match val.val {
567567
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
568568
ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
569-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
570-
let instance = self.resolve(def, substs)?;
571-
return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into());
569+
ty::ConstKind::Unevaluated(uv) => {
570+
let instance = self.resolve(uv.def, uv.substs(*self.tcx))?;
571+
return Ok(self
572+
.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?
573+
.into());
572574
}
573575
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
574576
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val)

compiler/rustc_mir/src/monomorphize/polymorphize.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -302,21 +302,24 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
302302
self.unused_parameters.clear(param.index);
303303
ControlFlow::CONTINUE
304304
}
305-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
305+
ty::ConstKind::Unevaluated(ty::Unevaluated { def, non_default_substs: _, promoted: Some(p)})
306306
// Avoid considering `T` unused when constants are of the form:
307307
// `<Self as Foo<T>>::foo::promoted[p]`
308308
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
309309
{
310310
// If there is a promoted, don't look at the substs - since it will always contain
311311
// the generic parameters, instead, traverse the promoted MIR.
312+
//
313+
// FIXME(lcnr): This seems incorrect if we get the promoted by inlining.
314+
// We have to consider its substs in that case.
312315
let promoted = self.tcx.promoted_mir(def.did);
313316
self.visit_body(&promoted[p]);
314317
ControlFlow::CONTINUE
315318
}
316-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None })
317-
if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
319+
ty::ConstKind::Unevaluated(uv)
320+
if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst =>
318321
{
319-
self.visit_child_body(def.did, substs);
322+
self.visit_child_body(uv.def.did, uv.substs(self.tcx));
320323
ControlFlow::CONTINUE
321324
}
322325
_ => c.super_visit_with(self),

compiler/rustc_mir/src/transform/check_consts/qualifs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ where
246246
};
247247

248248
// Check the qualifs of the value of `const` items.
249-
if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) =
249+
if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, non_default_substs: _, promoted }) =
250250
constant.literal.val
251251
{
252252
assert!(promoted.is_none());

compiler/rustc_mir/src/transform/promote_consts.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -1002,13 +1002,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
10021002
ty,
10031003
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
10041004
def,
1005-
substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
1006-
if let ty::GenericParamDefKind::Lifetime = param.kind {
1007-
tcx.lifetimes.re_erased.into()
1008-
} else {
1009-
tcx.mk_param_from_def(param)
1010-
}
1011-
}),
1005+
non_default_substs: Some(InternalSubsts::for_item(
1006+
tcx,
1007+
def.did,
1008+
|param, _| {
1009+
if let ty::GenericParamDefKind::Lifetime = param.kind {
1010+
tcx.lifetimes.re_erased.into()
1011+
} else {
1012+
tcx.mk_param_from_def(param)
1013+
}
1014+
},
1015+
)),
10121016
promoted: Some(promoted_id),
10131017
}),
10141018
}),

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
694694
let lhs = mk_const(self.tcx().mk_const(ty::Const {
695695
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
696696
def: ty::WithOptConstParam::unknown(did),
697-
substs,
697+
non_default_substs: Some(substs),
698698
promoted: None,
699699
}),
700700
ty: var_ty,
@@ -892,7 +892,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
892892
literal: self.tcx.mk_const(ty::Const {
893893
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
894894
def: ty::WithOptConstParam::unknown(def_id),
895-
substs,
895+
non_default_substs: Some(substs),
896896
promoted: None,
897897
}),
898898
ty: self.typeck_results().node_type(expr.hir_id),

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
165165
// See #74595 for more details about this.
166166
let concrete = infcx.const_eval_resolve(
167167
param_env,
168-
ty::Unevaluated { def, substs, promoted: None },
168+
ty::Unevaluated { def, non_default_substs: Some(substs), promoted: None },
169169
Some(span),
170170
);
171171

@@ -243,9 +243,7 @@ impl AbstractConst<'tcx> {
243243
ct: &ty::Const<'tcx>,
244244
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
245245
match ct.val {
246-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => {
247-
AbstractConst::new(tcx, def, substs)
248-
}
246+
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.def, uv.substs(tcx)),
249247
ty::ConstKind::Error(_) => Err(ErrorReported),
250248
_ => Ok(None),
251249
}

0 commit comments

Comments
 (0)