Skip to content

Commit dbacfbc

Browse files
committed
Add a new normalization query just for mir constants
1 parent c7c39ce commit dbacfbc

File tree

19 files changed

+128
-34
lines changed

19 files changed

+128
-34
lines changed

compiler/rustc_infer/src/infer/resolve.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
22
use super::{FixupError, FixupResult, InferCtxt, Span};
3+
use rustc_middle::mir;
34
use rustc_middle::ty::fold::{TypeFolder, TypeVisitor};
45
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
56

@@ -46,6 +47,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
4647
ct.super_fold_with(self)
4748
}
4849
}
50+
51+
fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
52+
constant.super_fold_with(self)
53+
}
4954
}
5055

5156
/// The opportunistic region resolver opportunistically resolves regions

compiler/rustc_middle/src/mir/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,8 @@ pub struct Constant<'tcx> {
24102410
pub literal: ConstantKind<'tcx>,
24112411
}
24122412

2413-
#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
2413+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
2414+
#[derive(Lift)]
24142415
pub enum ConstantKind<'tcx> {
24152416
/// This constant came from the type system
24162417
Ty(&'tcx ty::Const<'tcx>),
@@ -2709,7 +2710,13 @@ impl<'tcx> Display for Constant<'tcx> {
27092710
ty::FnDef(..) => {}
27102711
_ => write!(fmt, "const ")?,
27112712
}
2712-
match self.literal {
2713+
Display::fmt(&self.literal, fmt)
2714+
}
2715+
}
2716+
2717+
impl<'tcx> Display for ConstantKind<'tcx> {
2718+
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2719+
match *self {
27132720
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
27142721
ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
27152722
}

compiler/rustc_middle/src/mir/type_foldable.rs

+4
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
348348
}
349349

350350
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
351+
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
352+
folder.fold_mir_const(self)
353+
}
354+
351355
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
352356
match self {
353357
ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),

compiler/rustc_middle/src/query/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,13 @@ rustc_queries! {
14821482
desc { "normalizing `{}`", goal.value }
14831483
}
14841484

1485+
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
1486+
query normalize_mir_const_after_erasing_regions(
1487+
goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
1488+
) -> mir::ConstantKind<'tcx> {
1489+
desc { "normalizing `{}`", goal.value }
1490+
}
1491+
14851492
query implied_outlives_bounds(
14861493
goal: CanonicalTyGoal<'tcx>
14871494
) -> Result<

compiler/rustc_middle/src/ty/erase_regions.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::mir;
12
use crate::ty::fold::{TypeFoldable, TypeFolder};
23
use crate::ty::{self, Ty, TyCtxt, TypeFlags};
34

@@ -65,4 +66,8 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
6566
_ => self.tcx.lifetimes.re_erased,
6667
}
6768
}
69+
70+
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
71+
c.super_fold_with(self)
72+
}
6873
}

compiler/rustc_middle/src/ty/fold.rs

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
//!
3131
//! These methods return true to indicate that the visitor has found what it is
3232
//! looking for, and does not need to visit anything else.
33+
use crate::mir;
3334
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
3435
use rustc_hir as hir;
3536
use rustc_hir::def_id::DefId;
@@ -179,6 +180,10 @@ pub trait TypeFolder<'tcx>: Sized {
179180
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
180181
c.super_fold_with(self)
181182
}
183+
184+
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
185+
bug!("most type folders should not be folding MIR datastructures: {:?}", c)
186+
}
182187
}
183188

184189
pub trait TypeVisitor<'tcx>: Sized {

compiler/rustc_middle/src/ty/normalize_erasing_regions.rs

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//! `normalize_generic_arg_after_erasing_regions` query for each type
88
//! or constant found within. (This underlying query is what is cached.)
99
10+
use crate::mir;
1011
use crate::ty::fold::{TypeFoldable, TypeFolder};
1112
use crate::ty::subst::{Subst, SubstsRef};
1213
use crate::ty::{self, Ty, TyCtxt};
@@ -101,4 +102,9 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
101102
let arg = self.param_env.and(c.into());
102103
self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const()
103104
}
105+
106+
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
107+
let arg = self.param_env.and(c);
108+
self.tcx.normalize_mir_const_after_erasing_regions(arg)
109+
}
104110
}

compiler/rustc_middle/src/ty/subst.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Type substitutions.
22

3+
use crate::mir;
34
use crate::ty::codec::{TyDecoder, TyEncoder};
45
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
56
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
@@ -503,6 +504,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
503504
c.super_fold_with(self)
504505
}
505506
}
507+
508+
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
509+
c.super_fold_with(self)
510+
}
506511
}
507512

508513
impl<'a, 'tcx> SubstFolder<'a, 'tcx> {

compiler/rustc_mir/src/monomorphize/collector.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
184184
use rustc_hir::itemlikevisit::ItemLikeVisitor;
185185
use rustc_hir::lang_items::LangItem;
186186
use rustc_index::bit_set::GrowableBitSet;
187-
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
188187
use rustc_middle::mir::interpret::{AllocId, ConstValue};
189188
use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
190189
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
@@ -193,6 +192,7 @@ use rustc_middle::mir::{self, Local, Location};
193192
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
194193
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
195194
use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable};
195+
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
196196
use rustc_session::config::EntryFnType;
197197
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
198198
use smallvec::SmallVec;
@@ -638,6 +638,35 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
638638
self.super_rvalue(rvalue, location);
639639
}
640640

641+
/// This does not walk the constant, as it has been handled entirely here and trying
642+
/// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
643+
/// work, as some constants cannot be represented in the type system.
644+
fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
645+
let literal = self.monomorphize(constant.literal);
646+
let val = match literal {
647+
mir::ConstantKind::Val(val, _) => val,
648+
mir::ConstantKind::Ty(ct) => match ct.val {
649+
ty::ConstKind::Value(val) => val,
650+
ty::ConstKind::Unevaluated(ct) => {
651+
let param_env = ty::ParamEnv::reveal_all();
652+
match self.tcx.const_eval_resolve(param_env, ct, None) {
653+
// The `monomorphize` call should have evaluated that constant already.
654+
Ok(val) => val,
655+
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => return,
656+
Err(ErrorHandled::TooGeneric) => span_bug!(
657+
self.body.source_info(location).span,
658+
"collection encountered polymorphic constant: {:?}",
659+
literal
660+
),
661+
}
662+
}
663+
_ => return,
664+
},
665+
};
666+
collect_const_value(self.tcx, val, self.output);
667+
self.visit_ty(literal.ty(), TyContext::Location(location));
668+
}
669+
641670
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
642671
debug!("visiting const {:?} @ {:?}", *constant, location);
643672

compiler/rustc_mir/src/util/pretty.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,11 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
452452
match literal {
453453
ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
454454
ConstantKind::Val(val, ty) => {
455-
self.push(&format!("+ literal: {:?}, {}", val, ty))
455+
// To keep the diffs small, we render this almost like we render ty::Const
456+
self.push(&format!(
457+
"+ literal: Const {{ ty: {}, val: Value({:?}) }}",
458+
ty, val
459+
))
456460
}
457461
}
458462
}

compiler/rustc_query_impl/src/keys.rs

+9
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,15 @@ impl<'tcx> Key for GenericArg<'tcx> {
255255
}
256256
}
257257

258+
impl<'tcx> Key for mir::ConstantKind<'tcx> {
259+
fn query_crate(&self) -> CrateNum {
260+
LOCAL_CRATE
261+
}
262+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
263+
DUMMY_SP
264+
}
265+
}
266+
258267
impl<'tcx> Key for &'tcx ty::Const<'tcx> {
259268
fn query_crate(&self) -> CrateNum {
260269
LOCAL_CRATE

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
1010
use rustc_data_structures::sso::SsoHashMap;
1111
use rustc_data_structures::stack::ensure_sufficient_stack;
1212
use rustc_infer::traits::Normalized;
13+
use rustc_middle::mir;
1314
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
1415
use rustc_middle::ty::subst::Subst;
1516
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -214,4 +215,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
214215
let constant = constant.super_fold_with(self);
215216
constant.eval(self.infcx.tcx, self.param_env)
216217
}
218+
219+
fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
220+
constant.super_fold_with(self)
221+
}
217222
}

compiler/rustc_traits/src/normalize_erasing_regions.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
use rustc_infer::infer::TyCtxtInferExt;
22
use rustc_middle::traits::query::NoSolution;
33
use rustc_middle::ty::query::Providers;
4-
use rustc_middle::ty::subst::GenericArg;
54
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable};
65
use rustc_trait_selection::traits::query::normalize::AtExt;
76
use rustc_trait_selection::traits::{Normalized, ObligationCause};
87
use std::sync::atomic::Ordering;
98

109
crate fn provide(p: &mut Providers) {
11-
*p = Providers { normalize_generic_arg_after_erasing_regions, ..*p };
10+
*p = Providers {
11+
normalize_generic_arg_after_erasing_regions: |tcx, goal| {
12+
debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal);
13+
14+
tcx.sess
15+
.perf_stats
16+
.normalize_generic_arg_after_erasing_regions
17+
.fetch_add(1, Ordering::Relaxed);
18+
normalize_after_erasing_regions(tcx, goal)
19+
},
20+
normalize_mir_const_after_erasing_regions: |tcx, goal| {
21+
normalize_after_erasing_regions(tcx, goal)
22+
},
23+
..*p
24+
};
1225
}
1326

14-
fn normalize_generic_arg_after_erasing_regions<'tcx>(
27+
#[instrument(level = "debug", skip(tcx))]
28+
fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
1529
tcx: TyCtxt<'tcx>,
16-
goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>,
17-
) -> GenericArg<'tcx> {
18-
debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal);
19-
30+
goal: ParamEnvAnd<'tcx, T>,
31+
) -> T {
2032
let ParamEnvAnd { param_env, value } = goal;
21-
tcx.sess.perf_stats.normalize_generic_arg_after_erasing_regions.fetch_add(1, Ordering::Relaxed);
2233
tcx.infer_ctxt().enter(|infcx| {
2334
let cause = ObligationCause::dummy();
2435
match infcx.at(&cause, param_env).normalize(value) {

src/test/ui/associated-consts/defaults-cyclic-fail.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// build-fail
2-
//~^ ERROR cycle detected when normalizing `<() as Tr>::A`
2+
//~^ ERROR cycle detected when normalizing
33

44
// Cyclic assoc. const defaults don't error unless *used*
55
trait Tr {

src/test/ui/consts/const-eval/conditional_array_execution.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
1010

1111
fn main() {
1212
println!("{}", FOO);
13-
//~^ ERROR
13+
//~^ ERROR evaluation of constant value failed
1414
//~| WARN erroneous constant used [const_err]
1515
//~| WARN this was previously accepted by the compiler but is being phased out
1616
}

src/test/ui/consts/const-eval/const-eval-query-stack.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
//~ERROR constructed but no error reported
2-
// compile-flags: -Ztreat-err-as-bug=2
1+
// compile-flags: -Ztreat-err-as-bug=1
32
// build-fail
43
// failure-status: 101
54
// rustc-env:RUST_BACKTRACE=1
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
warning: any use of this value will cause an error
2-
--> $DIR/const-eval-query-stack.rs:20:16
2+
--> $DIR/const-eval-query-stack.rs:19:16
33
|
44
LL | const X: i32 = 1 / 0;
55
| ---------------^^^^^-
66
| |
77
| attempt to divide `1_i32` by zero
88
|
99
note: the lint level is defined here
10-
--> $DIR/const-eval-query-stack.rs:19:8
10+
--> $DIR/const-eval-query-stack.rs:18:8
1111
|
1212
LL | #[warn(const_err)]
1313
| ^^^^^^^^^
1414
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1515
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
1616

1717
error[E0080]: evaluation of constant value failed
18-
--> $DIR/const-eval-query-stack.rs:24:28
18+
--> $DIR/const-eval-query-stack.rs:23:28
1919
|
2020
LL | let x: &'static i32 = &X;
2121
| ^ referenced constant has errors
22+
2223
query stack during panic:
23-
#0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
24-
#1 [optimized_mir] optimizing MIR for `main`
25-
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
24+
#0 [eval_to_allocation_raw] const-evaluating + checking `main::promoted[1]`
25+
#1 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
26+
#2 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
27+
#3 [normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
28+
#4 [optimized_mir] optimizing MIR for `main`
29+
#5 [collect_and_partition_mono_items] collect_and_partition_mono_items
2630
end of query stack

src/test/ui/consts/const-eval/issue-44578.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ impl Foo for u16 {
2525

2626
fn main() {
2727
println!("{}", <Bar<u16, u8> as Foo>::AMT);
28-
//~^ ERROR evaluation of constant value failed [E0080]
28+
//~^ ERROR evaluation of constant value failed
2929
}

src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr

-11
This file was deleted.

0 commit comments

Comments
 (0)