Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 30ff1ef

Browse files
committed
support const_evaluatable_checked across crate boundaries
1 parent 82ebbd7 commit 30ff1ef

File tree

14 files changed

+157
-2
lines changed

14 files changed

+157
-2
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
562562
}
563563
}
564564

565+
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
566+
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
567+
ty::codec::RefDecodable::decode(d)
568+
}
569+
}
570+
565571
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
566572
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
567573
ty::codec::RefDecodable::decode(d)
@@ -1191,6 +1197,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
11911197
.decode((self, tcx))
11921198
}
11931199

1200+
fn get_mir_abstract_const(
1201+
&self,
1202+
tcx: TyCtxt<'tcx>,
1203+
id: DefIndex,
1204+
) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
1205+
self.root
1206+
.tables
1207+
.mir_abstract_consts
1208+
.get(self, id)
1209+
.filter(|_| !self.is_proc_macro(id))
1210+
.map_or(None, |v| Some(v.decode((self, tcx))))
1211+
}
1212+
11941213
fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> {
11951214
self.root
11961215
.tables

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
112112
}
113113
optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
114114
promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
115+
mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
115116
unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
116117
mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
117118
fn_sig => { cdata.fn_sig(def_id.index, tcx) }

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,12 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
321321
}
322322
}
323323

324+
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
325+
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
326+
(**self).encode(s)
327+
}
328+
}
329+
324330
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
325331
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
326332
(**self).encode(s)
@@ -1109,6 +1115,11 @@ impl EncodeContext<'a, 'tcx> {
11091115
if !unused.is_empty() {
11101116
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
11111117
}
1118+
1119+
let abstract_const = self.tcx.mir_abstract_const(def_id);
1120+
if let Some(abstract_const) = abstract_const {
1121+
record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
1122+
}
11121123
}
11131124
}
11141125

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ define_tables! {
284284
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
285285
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
286286
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
287+
mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
287288
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
288289
// `def_keys` and `def_path_hashes` represent a lazy version of a
289290
// `DefPathTable`. This allows us to avoid deserializing an entire

compiler/rustc_middle/src/mir/abstract_const.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ rustc_index::newtype_index! {
1111
}
1212

1313
/// A node of an `AbstractConst`.
14-
#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable)]
14+
#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
1515
pub enum Node<'tcx> {
1616
Leaf(&'tcx ty::Const<'tcx>),
1717
Binop(mir::BinOp, NodeId, NodeId),

compiler/rustc_middle/src/ty/codec.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,26 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>,
357357
}
358358
}
359359

360+
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] {
361+
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
362+
Ok(decoder.tcx().arena.alloc_from_iter(
363+
(0..decoder.read_usize()?)
364+
.map(|_| Decodable::decode(decoder))
365+
.collect::<Result<Vec<_>, _>>()?,
366+
))
367+
}
368+
}
369+
370+
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] {
371+
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
372+
Ok(decoder.tcx().arena.alloc_from_iter(
373+
(0..decoder.read_usize()?)
374+
.map(|_| Decodable::decode(decoder))
375+
.collect::<Result<Vec<_>, _>>()?,
376+
))
377+
}
378+
}
379+
360380
impl_decodable_via_ref! {
361381
&'tcx ty::TypeckResults<'tcx>,
362382
&'tcx ty::List<Ty<'tcx>>,

compiler/rustc_middle/src/ty/query/on_disk_cache.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
760760
}
761761
}
762762

763+
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
764+
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
765+
RefDecodable::decode(d)
766+
}
767+
}
768+
763769
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
764770
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
765771
RefDecodable::decode(d)

compiler/rustc_privacy/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ where
9797
ty.visit_with(self)
9898
}
9999
ty::PredicateAtom::RegionOutlives(..) => false,
100+
ty::PredicateAtom::ConstEvaluatable(..)
101+
if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
102+
{
103+
// FIXME(const_evaluatable_checked): If the constant used here depends on a
104+
// private function we may have to do something here...
105+
//
106+
// For now, let's just pretend that everything is fine.
107+
false
108+
}
100109
_ => bug!("unexpected predicate: {:?}", predicate),
101110
}
102111
}

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
142142
return None;
143143
}
144144

145+
// We don't have to look at concrete constants, as we
146+
// can just evaluate them.
147+
if !body.is_polymorphic {
148+
return None;
149+
}
150+
145151
Some(AbstractConstBuilder {
146152
tcx,
147153
body,
@@ -304,6 +310,15 @@ pub(super) fn mir_abstract_const<'tcx>(
304310
def: ty::WithOptConstParam<LocalDefId>,
305311
) -> Option<&'tcx [Node<'tcx>]> {
306312
if tcx.features().const_evaluatable_checked {
313+
match tcx.def_kind(def.did) {
314+
// FIXME(const_evaluatable_checked): We currently only do this for anonymous constants,
315+
// meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
316+
// we want to look into them or treat them as opaque projections.
317+
//
318+
// Right now we do neither of that and simply always fail to unify them.
319+
DefKind::AnonConst => (),
320+
_ => return None,
321+
}
307322
let body = tcx.mir_const(def).borrow();
308323
AbstractConstBuilder::new(tcx, &body)?.build()
309324
} else {

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
553553
type_implements_trait,
554554
subst_and_check_impossible_predicates,
555555
mir_abstract_const: |tcx, def_id| {
556-
let def_id = def_id.as_local()?; // We do not store failed AbstractConst's.
556+
let def_id = def_id.expect_local();
557557
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
558558
tcx.mir_abstract_const_of_const_arg(def)
559559
} else {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(const_generics, const_evaluatable_checked)]
2+
#![allow(incomplete_features)]
3+
4+
pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
5+
where
6+
[u8; std::mem::size_of::<T>() - 1]: Sized,
7+
{
8+
[0; std::mem::size_of::<T>() - 1]
9+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// aux-build:const_evaluatable_lib.rs
2+
// run-pass
3+
#![feature(const_generics, const_evaluatable_checked)]
4+
#![allow(incomplete_features)]
5+
extern crate const_evaluatable_lib;
6+
7+
fn user<T>() where [u8; std::mem::size_of::<T>() - 1]: Sized {
8+
assert_eq!(const_evaluatable_lib::test1::<T>(), [0; std::mem::size_of::<T>() - 1]);
9+
}
10+
11+
fn main() {
12+
assert_eq!(const_evaluatable_lib::test1::<u32>(), [0; 3]);
13+
user::<u32>();
14+
user::<u64>();
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// aux-build:const_evaluatable_lib.rs
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
extern crate const_evaluatable_lib;
5+
6+
fn user<T>() {
7+
let _ = const_evaluatable_lib::test1::<T>();
8+
//~^ ERROR constant expression depends
9+
//~| ERROR constant expression depends
10+
//~| ERROR constant expression depends
11+
}
12+
13+
fn main() {}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error: constant expression depends on a generic parameter
2+
--> $DIR/cross_crate_predicate.rs:7:13
3+
|
4+
LL | let _ = const_evaluatable_lib::test1::<T>();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
8+
|
9+
LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
10+
| ----- required by this bound in `test1`
11+
|
12+
= note: this may fail depending on what value the parameter takes
13+
14+
error: constant expression depends on a generic parameter
15+
--> $DIR/cross_crate_predicate.rs:7:13
16+
|
17+
LL | let _ = const_evaluatable_lib::test1::<T>();
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
|
20+
::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
21+
|
22+
LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
23+
| ----- required by this bound in `test1::{{constant}}#1`
24+
|
25+
= note: this may fail depending on what value the parameter takes
26+
27+
error: constant expression depends on a generic parameter
28+
--> $DIR/cross_crate_predicate.rs:7:13
29+
|
30+
LL | let _ = const_evaluatable_lib::test1::<T>();
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
|
33+
= note: this may fail depending on what value the parameter takes
34+
35+
error: aborting due to 3 previous errors
36+

0 commit comments

Comments
 (0)