Skip to content

Commit 1bc1691

Browse files
committed
make unevaluated const substs optional
1 parent 3372f27 commit 1bc1691

File tree

47 files changed

+232
-185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+232
-185
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ pub(crate) fn codegen_constant<'tcx>(
129129
};
130130
let const_val = match const_.val {
131131
ConstKind::Value(const_val) => const_val,
132-
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
133-
if fx.tcx.is_static(def.did) =>
132+
ConstKind::Unevaluated(uv)
133+
if fx.tcx.is_static(uv.def.did) =>
134134
{
135-
assert!(substs.is_empty());
136-
assert!(promoted.is_none());
135+
assert!(uv.substs(fx.tcx).is_empty());
136+
assert!(uv.promoted.is_none());
137137

138-
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
138+
return codegen_static_ref(fx, uv.def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
139139
}
140140
ConstKind::Unevaluated(unevaluated) => {
141141
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {

compiler/rustc_infer/src/infer/combine.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -737,10 +737,9 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
737737
}
738738
}
739739
}
740-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
741-
if self.tcx().lazy_normalization() =>
742-
{
743-
assert_eq!(promoted, None);
740+
ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
741+
assert_eq!(uv.promoted, None);
742+
let substs = uv.substs(self.tcx());
744743
let substs = self.relate_with_variance(
745744
ty::Variance::Invariant,
746745
ty::VarianceDiagInfo::default(),
@@ -749,7 +748,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
749748
)?;
750749
Ok(self.tcx().mk_const(ty::Const {
751750
ty: c.ty,
752-
val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
751+
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
753752
}))
754753
}
755754
_ => relate::super_relate_consts(self, c, c),
@@ -971,10 +970,9 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
971970
}
972971
}
973972
}
974-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
975-
if self.tcx().lazy_normalization() =>
976-
{
977-
assert_eq!(promoted, None);
973+
ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
974+
assert_eq!(uv.promoted, None);
975+
let substs = uv.substs(self.tcx());
978976
let substs = self.relate_with_variance(
979977
ty::Variance::Invariant,
980978
ty::VarianceDiagInfo::default(),
@@ -983,7 +981,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
983981
)?;
984982
Ok(self.tcx().mk_const(ty::Const {
985983
ty: c.ty,
986-
val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
984+
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
987985
}))
988986
}
989987
_ => relate::super_relate_consts(self, c, c),

compiler/rustc_infer/src/infer/error_reporting/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,8 +1517,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15171517
}
15181518

15191519
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
1520-
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
1521-
self.tcx
1520+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1521+
Some(self.tcx)
15221522
}
15231523

15241524
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
473473
struct TraitObjectVisitor(Vec<DefId>);
474474

475475
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
476-
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
477-
bug!("tcx_for_anon_const_substs called for TraitObjectVisitor");
476+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
477+
// The default anon const substs cannot include
478+
// trait objects, so we don't have to bother looking.
479+
None
478480
}
479481

480482
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,16 +1487,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14871487
pub fn const_eval_resolve(
14881488
&self,
14891489
param_env: ty::ParamEnv<'tcx>,
1490-
ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>,
1490+
unevaluated: ty::Unevaluated<'tcx>,
14911491
span: Option<Span>,
14921492
) -> EvalToConstValueResult<'tcx> {
14931493
let mut original_values = OriginalQueryValues::default();
1494-
let canonical = self.canonicalize_query((param_env, substs), &mut original_values);
1494+
let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values);
14951495

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

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

compiler/rustc_infer/src/infer/nll_relate/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,8 +765,8 @@ struct ScopeInstantiator<'me, 'tcx> {
765765
}
766766

767767
impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
768-
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
769-
self.tcx
768+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
769+
Some(self.tcx)
770770
}
771771

772772
fn visit_binder<T: TypeFoldable<'tcx>>(

compiler/rustc_infer/src/infer/resolve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
127127
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
128128
type BreakTy = (Ty<'tcx>, Option<Span>);
129129

130-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
131-
self.infcx.tcx
130+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
131+
Some(self.infcx.tcx)
132132
}
133133

134134
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

compiler/rustc_lint/src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,8 +1160,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
11601160

11611161
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
11621162
type BreakTy = Ty<'tcx>;
1163-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
1164-
self.cx.tcx
1163+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1164+
Some(self.cx.tcx)
11651165
}
11661166

11671167
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

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

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ rustc_queries! {
114114
desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) }
115115
}
116116

117+
query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
118+
desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) }
119+
}
120+
117121
/// Records the type of every item.
118122
query type_of(key: DefId) -> Ty<'tcx> {
119123
desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 1 addition & 2 deletions
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;
@@ -100,7 +99,7 @@ impl<'tcx> Const<'tcx> {
10099
}
101100
_ => ty::ConstKind::Unevaluated(ty::Unevaluated {
102101
def: def.to_global(),
103-
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
102+
substs_: None,
104103
promoted: None,
105104
}),
106105
};

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

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,23 @@ use super::ScalarInt;
1616
#[derive(Hash, HashStable)]
1717
pub struct Unevaluated<'tcx> {
1818
pub def: ty::WithOptConstParam<DefId>,
19-
pub substs: SubstsRef<'tcx>,
19+
pub substs_: Option<SubstsRef<'tcx>>,
2020
pub promoted: Option<Promoted>,
2121
}
2222

23+
impl<'tcx> Unevaluated<'tcx> {
24+
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> {
25+
Unevaluated { def, substs_: Some(substs), promoted: None }
26+
}
27+
28+
pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> {
29+
self.substs_.unwrap_or_else(|| {
30+
debug_assert_eq!(self.promoted, None);
31+
tcx.default_anon_const_substs(self.def.did)
32+
})
33+
}
34+
}
35+
2336
/// Represents a constant in Rust.
2437
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
2538
#[derive(Hash, HashStable)]
@@ -109,7 +122,7 @@ impl<'tcx> ConstKind<'tcx> {
109122
tcx: TyCtxt<'tcx>,
110123
param_env: ParamEnv<'tcx>,
111124
) -> Option<Result<ConstValue<'tcx>, ErrorReported>> {
112-
if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self {
125+
if let ConstKind::Unevaluated(unevaluated) = self {
113126
use crate::mir::interpret::ErrorHandled;
114127

115128
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
@@ -118,29 +131,32 @@ impl<'tcx> ConstKind<'tcx> {
118131
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
119132
// so that we don't try to invoke this query with
120133
// any region variables.
121-
let param_env_and_substs = tcx
134+
let param_env_and = tcx
122135
.erase_regions(param_env)
123136
.with_reveal_all_normalized(tcx)
124-
.and(tcx.erase_regions(substs));
137+
.and(tcx.erase_regions(unevaluated));
125138

126139
// HACK(eddyb) when the query key would contain inference variables,
127140
// attempt using identity substs and `ParamEnv` instead, that will succeed
128141
// when the expression doesn't depend on any parameters.
129142
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
130143
// 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))
144+
let param_env_and = if param_env_and.needs_infer() {
145+
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
146+
def: unevaluated.def,
147+
substs_: Some(InternalSubsts::identity_for_item(tcx, unevaluated.def.did)),
148+
promoted: unevaluated.promoted,
149+
})
133150
} else {
134-
param_env_and_substs
151+
param_env_and
135152
};
136153

137154
// 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();
155+
// `ty::ParamEnvAnd` instead of having them separate.
156+
let (param_env, unevaluated) = param_env_and.into_parts();
140157
// try to resolve e.g. associated constants to their definition on an impl, and then
141158
// evaluate the const.
142-
match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None)
143-
{
159+
match tcx.const_eval_resolve(param_env, unevaluated, None) {
144160
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
145161
// and we use the original type, so nothing from `substs`
146162
// (which may be identity substs, see above),

compiler/rustc_middle/src/ty/flags.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ impl FlagComputation {
301301
}
302302

303303
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
304-
self.add_substs(ct.substs);
304+
// TODO
305+
self.add_substs(ct.substs_.unwrap());
305306
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
306307
}
307308

compiler/rustc_middle/src/ty/fold.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,11 @@ pub trait TypeVisitor<'tcx>: Sized {
192192
/// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
193193
/// are not yet supplied.
194194
///
195-
/// Visitors which do not look into these substs may leave this unimplemented, so be
196-
/// careful when calling this method elsewhere.
197-
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx>;
195+
/// Visitors which do not look into these substs may return `None` here, in which case
196+
/// `super_visit_with` completely skips the default substs. Incorrectly returning
197+
/// `None` can very quickly lead to ICE or other critical bugs, so be careful and
198+
/// try to return an actual `tcx` if at all possible.
199+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>>;
198200

199201
fn visit_binder<T: TypeFoldable<'tcx>>(
200202
&mut self,
@@ -336,8 +338,8 @@ impl<'tcx> TyCtxt<'tcx> {
336338
{
337339
type BreakTy = ();
338340

339-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
340-
self.tcx
341+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
342+
Some(self.tcx)
341343
}
342344

343345
fn visit_binder<T: TypeFoldable<'tcx>>(
@@ -788,8 +790,9 @@ impl<'tcx> ValidateBoundVars<'tcx> {
788790
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
789791
type BreakTy = ();
790792

791-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
792-
bug!("default anon const substs can't contain bound vars");
793+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
794+
// Anonymous constants do not contain bound vars in their substs by default.
795+
None
793796
}
794797

795798
fn visit_binder<T: TypeFoldable<'tcx>>(
@@ -1006,8 +1009,9 @@ struct HasEscapingVarsVisitor {
10061009
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
10071010
type BreakTy = FoundEscapingVars;
10081011

1009-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
1010-
bug!("tcx_for_anon_const_substs called for HasEscpaingVarsVisitor");
1012+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1013+
// Anonymous constants do not contain bound vars in their substs by default.
1014+
None
10111015
}
10121016

10131017
fn visit_binder<T: TypeFoldable<'tcx>>(
@@ -1080,8 +1084,13 @@ struct HasTypeFlagsVisitor {
10801084

10811085
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
10821086
type BreakTy = FoundFlags;
1083-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
1084-
bug!("tcx_for_anon_const_substs called for HasTypeFlagsVisitor");
1087+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1088+
// TypeFlagsVisitor must not look into the default anon const substs
1089+
// as that would cause cycle errors, but we do care about them for
1090+
// some flags.
1091+
//
1092+
// We therefore have to be very careful here.
1093+
None
10851094
}
10861095

10871096
#[inline]
@@ -1164,8 +1173,8 @@ impl LateBoundRegionsCollector<'tcx> {
11641173
}
11651174

11661175
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> {
1167-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
1168-
self.tcx
1176+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1177+
Some(self.tcx)
11691178
}
11701179

11711180
fn visit_binder<T: TypeFoldable<'tcx>>(

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -927,20 +927,21 @@ pub trait PrettyPrinter<'tcx>:
927927
}
928928

929929
match ct.val {
930-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
931-
if let Some(promoted) = promoted {
932-
p!(print_value_path(def.did, substs));
930+
ty::ConstKind::Unevaluated(uv) => {
931+
if let Some(promoted) = uv.promoted {
932+
let substs = uv.substs_.unwrap();
933+
p!(print_value_path(uv.def.did, substs));
933934
p!(write("::{:?}", promoted));
934935
} else {
935-
match self.tcx().def_kind(def.did) {
936+
let tcx = self.tcx();
937+
match tcx.def_kind(uv.def.did) {
936938
DefKind::Static | DefKind::Const | DefKind::AssocConst => {
937-
p!(print_value_path(def.did, substs))
939+
p!(print_value_path(uv.def.did, uv.substs(tcx)))
938940
}
939941
_ => {
940-
if def.is_local() {
941-
let span = self.tcx().def_span(def.did);
942-
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
943-
{
942+
if uv.def.is_local() {
943+
let span = tcx.def_span(uv.def.did);
944+
if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) {
944945
p!(write("{}", snip))
945946
} else {
946947
print_underscore!()
@@ -1957,8 +1958,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
19571958
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
19581959
type BreakTy = ();
19591960

1960-
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
1961-
self.tcx
1961+
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1962+
Some(self.tcx)
19621963
}
19631964

19641965
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {

0 commit comments

Comments
 (0)