Skip to content

Commit cd88bb3

Browse files
committed
Improve pretty printing of valtrees for references
1 parent 94e9374 commit cd88bb3

File tree

9 files changed

+144
-102
lines changed

9 files changed

+144
-102
lines changed

compiler/rustc_const_eval/src/const_eval/mod.rs

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_middle::mir;
55
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
66
use rustc_middle::ty::{self, TyCtxt};
77
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
8-
use rustc_target::abi::VariantIdx;
98

109
use crate::interpret::{
1110
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
@@ -91,83 +90,6 @@ pub(crate) fn eval_to_valtree<'tcx>(
9190
}
9291
}
9392

94-
/// Tries to destructure constants of type Array or Adt into the constants
95-
/// of its fields.
96-
pub(crate) fn try_destructure_const<'tcx>(
97-
tcx: TyCtxt<'tcx>,
98-
const_: ty::Const<'tcx>,
99-
) -> Option<ty::DestructuredConst<'tcx>> {
100-
if let ty::ConstKind::Value(valtree) = const_.kind() {
101-
let branches = match valtree {
102-
ty::ValTree::Branch(b) => b,
103-
_ => return None,
104-
};
105-
106-
let (fields, variant) = match const_.ty().kind() {
107-
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
108-
// construct the consts for the elements of the array/slice
109-
let field_consts = branches
110-
.iter()
111-
.map(|b| {
112-
tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })
113-
})
114-
.collect::<Vec<_>>();
115-
debug!(?field_consts);
116-
117-
(field_consts, None)
118-
}
119-
ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
120-
ty::Adt(def, substs) => {
121-
let variant_idx = if def.is_enum() {
122-
VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().ok()?)
123-
} else {
124-
VariantIdx::from_u32(0)
125-
};
126-
let fields = &def.variant(variant_idx).fields;
127-
let mut field_consts = Vec::with_capacity(fields.len());
128-
129-
// Note: First element inValTree corresponds to variant of enum
130-
let mut valtree_idx = if def.is_enum() { 1 } else { 0 };
131-
for field in fields {
132-
let field_ty = field.ty(tcx, substs);
133-
let field_valtree = branches[valtree_idx]; // first element of branches is variant
134-
let field_const = tcx.mk_const(ty::ConstS {
135-
kind: ty::ConstKind::Value(field_valtree),
136-
ty: field_ty,
137-
});
138-
field_consts.push(field_const);
139-
valtree_idx += 1;
140-
}
141-
debug!(?field_consts);
142-
143-
(field_consts, Some(variant_idx))
144-
}
145-
ty::Tuple(elem_tys) => {
146-
let fields = elem_tys
147-
.iter()
148-
.enumerate()
149-
.map(|(i, elem_ty)| {
150-
let elem_valtree = branches[i];
151-
tcx.mk_const(ty::ConstS {
152-
kind: ty::ConstKind::Value(elem_valtree),
153-
ty: elem_ty,
154-
})
155-
})
156-
.collect::<Vec<_>>();
157-
158-
(fields, None)
159-
}
160-
_ => bug!("cannot destructure constant {:?}", const_),
161-
};
162-
163-
let fields = tcx.arena.alloc_from_iter(fields.into_iter());
164-
165-
Some(ty::DestructuredConst { variant, fields })
166-
} else {
167-
None
168-
}
169-
}
170-
17193
#[instrument(skip(tcx), level = "debug")]
17294
pub(crate) fn try_destructure_mir_constant<'tcx>(
17395
tcx: TyCtxt<'tcx>,

compiler/rustc_const_eval/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ pub fn provide(providers: &mut Providers) {
4242
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
4343
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
4444
providers.const_caller_location = const_eval::const_caller_location;
45-
providers.try_destructure_const = |tcx, val| const_eval::try_destructure_const(tcx, val);
4645
providers.eval_to_valtree = |tcx, param_env_and_value| {
4746
let (param_env, raw) = param_env_and_value.into_parts();
4847
const_eval::eval_to_valtree(tcx, param_env, raw)

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,8 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
205205
}
206206

207207
impl<'tcx> TyCtxt<'tcx> {
208-
/// Destructure a type-level constant ADT or array into its variant index and its field values.
209-
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
210-
pub fn destructure_const(self, const_: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
211-
self.try_destructure_const(const_).unwrap()
212-
}
213-
214208
/// Destructure a mir constant ADT or array into its variant index and its field values.
215-
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
209+
/// Panics if the destructuring fails, use `try_destructure_mir_constant` for fallible version.
216210
pub fn destructure_mir_constant(
217211
self,
218212
param_env: ty::ParamEnv<'tcx>,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -978,11 +978,8 @@ rustc_queries! {
978978
desc { "converting type-level constant value to mir constant value"}
979979
}
980980

981-
/// Destructure a constant ADT or array into its variant index and its
982-
/// field values or return `None` if constant is invalid.
983-
///
984-
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
985-
query try_destructure_const(key: ty::Const<'tcx>) -> Option<ty::DestructuredConst<'tcx>> {
981+
/// Destructure a type-level constant ADT or array into its variant index and its field values.
982+
query destructure_const(key: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
986983
desc { "destructuring type level constant"}
987984
}
988985

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

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,11 @@ pub trait PrettyPrinter<'tcx>:
14471447
p!(write("{:?}", String::from_utf8_lossy(bytes)));
14481448
return Ok(self);
14491449
}
1450-
_ => {}
1450+
_ => {
1451+
p!("&");
1452+
p!(pretty_print_const_valtree(valtree, *inner_ty, print_ty));
1453+
return Ok(self);
1454+
}
14511455
},
14521456
(ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
14531457
let bytes = valtree.try_to_raw_bytes(self.tcx(), *t).unwrap_or_else(|| {
@@ -1459,16 +1463,8 @@ pub trait PrettyPrinter<'tcx>:
14591463
}
14601464
// Aggregates, printed as array/tuple/struct/variant construction syntax.
14611465
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
1462-
let Some(contents) = self.tcx().try_destructure_const(
1463-
ty::Const::from_value(self.tcx(), valtree, ty)
1464-
) else {
1465-
// Fall back to debug pretty printing for invalid constants.
1466-
p!(write("{:?}", valtree));
1467-
if print_ty {
1468-
p!(": ", print(ty));
1469-
}
1470-
return Ok(self);
1471-
};
1466+
let contents =
1467+
self.tcx().destructure_const(ty::Const::from_value(self.tcx(), valtree, ty));
14721468
let fields = contents.fields.iter().copied();
14731469
match *ty.kind() {
14741470
ty::Array(..) => {

compiler/rustc_ty_utils/src/consts.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use rustc_middle::ty::{self, TyCtxt};
2+
use rustc_target::abi::VariantIdx;
3+
4+
/// Tries to destructure constants of type Array or Adt into the constants
5+
/// of its fields.
6+
pub(crate) fn destructure_const<'tcx>(
7+
tcx: TyCtxt<'tcx>,
8+
const_: ty::Const<'tcx>,
9+
) -> ty::DestructuredConst<'tcx> {
10+
if let ty::ConstKind::Value(valtree) = const_.kind() {
11+
let branches = match valtree {
12+
ty::ValTree::Branch(b) => b,
13+
_ => bug!("cannot destructure constant {:?}", const_),
14+
};
15+
16+
let (fields, variant) = match const_.ty().kind() {
17+
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
18+
// construct the consts for the elements of the array/slice
19+
let field_consts = branches
20+
.iter()
21+
.map(|b| {
22+
tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })
23+
})
24+
.collect::<Vec<_>>();
25+
debug!(?field_consts);
26+
27+
(field_consts, None)
28+
}
29+
ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
30+
ty::Adt(def, substs) => {
31+
let variant_idx = if def.is_enum() {
32+
VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().unwrap())
33+
} else {
34+
VariantIdx::from_u32(0)
35+
};
36+
let fields = &def.variant(variant_idx).fields;
37+
let mut field_consts = Vec::with_capacity(fields.len());
38+
39+
// Note: First element inValTree corresponds to variant of enum
40+
let mut valtree_idx = if def.is_enum() { 1 } else { 0 };
41+
for field in fields {
42+
let field_ty = field.ty(tcx, substs);
43+
let field_valtree = branches[valtree_idx]; // first element of branches is variant
44+
let field_const = tcx.mk_const(ty::ConstS {
45+
kind: ty::ConstKind::Value(field_valtree),
46+
ty: field_ty,
47+
});
48+
field_consts.push(field_const);
49+
valtree_idx += 1;
50+
}
51+
debug!(?field_consts);
52+
53+
(field_consts, Some(variant_idx))
54+
}
55+
ty::Tuple(elem_tys) => {
56+
let fields = elem_tys
57+
.iter()
58+
.enumerate()
59+
.map(|(i, elem_ty)| {
60+
let elem_valtree = branches[i];
61+
tcx.mk_const(ty::ConstS {
62+
kind: ty::ConstKind::Value(elem_valtree),
63+
ty: elem_ty,
64+
})
65+
})
66+
.collect::<Vec<_>>();
67+
68+
(fields, None)
69+
}
70+
_ => bug!("cannot destructure constant {:?}", const_),
71+
};
72+
73+
let fields = tcx.arena.alloc_from_iter(fields.into_iter());
74+
75+
ty::DestructuredConst { variant, fields }
76+
} else {
77+
bug!("cannot destructure constant {:?}", const_)
78+
}
79+
}
80+
81+
pub fn provide(providers: &mut ty::query::Providers) {
82+
*providers =
83+
ty::query::Providers { destructure_const, ..*providers };
84+
}

compiler/rustc_ty_utils/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_middle::ty::query::Providers;
1818

1919
mod assoc;
2020
mod common_traits;
21+
pub mod consts;
2122
pub mod instance;
2223
mod needs_drop;
2324
pub mod representability;
@@ -26,6 +27,7 @@ mod ty;
2627
pub fn provide(providers: &mut Providers) {
2728
assoc::provide(providers);
2829
common_traits::provide(providers);
30+
consts::provide(providers);
2931
needs_drop::provide(providers);
3032
ty::provide(providers);
3133
instance::provide(providers);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![feature(adt_const_params)]
2+
#![allow(incomplete_features)]
3+
4+
#[derive(Debug, PartialEq, Eq)]
5+
struct Foo {
6+
value: i32,
7+
nested: &'static Bar<i32>,
8+
}
9+
10+
#[derive(Debug, PartialEq, Eq)]
11+
struct Bar<T>(T);
12+
13+
struct Test<const F: Foo>;
14+
15+
fn main() {
16+
let x: Test<{
17+
Foo {
18+
value: 3,
19+
nested: &Bar(4),
20+
}
21+
}> = Test;
22+
let y: Test<{
23+
Foo {
24+
value: 3,
25+
nested: &Bar(5),
26+
}
27+
}> = x; //~ ERROR mismatched types
28+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-66451.rs:27:10
3+
|
4+
LL | let y: Test<{
5+
| ____________-
6+
LL | | Foo {
7+
LL | | value: 3,
8+
LL | | nested: &Bar(5),
9+
LL | | }
10+
LL | | }> = x;
11+
| | - ^ expected `Foo { value: 3_i32, nested: &Bar::<i32>(5_i32) }`, found `Foo { value: 3_i32, nested: &Bar::<i32>(4_i32) }`
12+
| |______|
13+
| expected due to this
14+
|
15+
= note: expected struct `Test<Foo { value: 3_i32, nested: &Bar::<i32>(5_i32) }>`
16+
found struct `Test<Foo { value: 3_i32, nested: &Bar::<i32>(4_i32) }>`
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)