Skip to content

Commit 93a73da

Browse files
committed
add new Reveal for const eval during selection
1 parent 72c7b70 commit 93a73da

File tree

16 files changed

+155
-33
lines changed

16 files changed

+155
-33
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, impl Module>) {
5959
err
6060
);
6161
}
62+
ErrorHandled::Silent => {
63+
span_bug!(
64+
constant.span,
65+
"codgen encountered silent error",
66+
);
67+
}
6268
}
6369
}
6470
}

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
194194
// errored or at least linted
195195
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {}
196196
ErrorHandled::TooGeneric => {
197-
span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err)
197+
span_bug!(const_.span, "codegen encountered polymorphic constant: {:?}", err)
198+
}
199+
ErrorHandled::Silent => {
200+
span_bug!(const_.span, "silent error during codegen")
198201
}
199202
}
200203
}

compiler/rustc_codegen_ssa/src/mir/operand.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
446446
ErrorHandled::TooGeneric => {
447447
bug!("codegen encountered polymorphic constant")
448448
}
449+
ErrorHandled::Silent => {
450+
bug!("silent error encountered codegen for {:?}", operand)
451+
}
449452
}
450453
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
451454
// the above error (or silence it under some conditions) will not cause UB.

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub enum ErrorHandled {
1818
Reported(ErrorReported),
1919
/// Already emitted a lint for this evaluation.
2020
Linted,
21+
/// Encountered an error without emitting anything. Only returned
22+
/// with `Reveal::Selection`.
23+
Silent,
2124
/// Don't emit an error, the evaluation failed because the MIR was generic
2225
/// and the substs didn't fully monomorphize it.
2326
TooGeneric,
@@ -72,7 +75,7 @@ fn print_backtrace(backtrace: &Backtrace) {
7275
impl From<ErrorHandled> for InterpErrorInfo<'_> {
7376
fn from(err: ErrorHandled) -> Self {
7477
match err {
75-
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {
78+
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted | ErrorHandled::Silent => {
7679
err_inval!(ReferencedConstant)
7780
}
7881
ErrorHandled::TooGeneric => err_inval!(TooGeneric),

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner
3838
/// more or less conservative.
3939
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
4040
pub enum Reveal {
41+
// Similar to `Reveal::UserFacing`, except that we also do not emit errors
42+
// when failing const evaluation.
43+
//
44+
// Used by `feature(const_evaluatable_checked)` to allow for `ConstEvaluatable`
45+
// predicates to not hold without emitting an error.
46+
Selection,
4147
/// At type-checking time, we refuse to project any associated
4248
/// type that is marked `default`. Non-`default` ("final") types
4349
/// are always projected. This is necessary in general for

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<'tcx> ConstKind<'tcx> {
129129
// (which may be identity substs, see above),
130130
// can leak through `val` into the const we return.
131131
Ok(val) => Some(Ok(val)),
132-
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
132+
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted | ErrorHandled::Silent) => None,
133133
Err(ErrorHandled::Reported(e)) => Some(Err(e)),
134134
}
135135
} else {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,17 +1768,19 @@ pub struct ParamEnv<'tcx> {
17681768
}
17691769

17701770
unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
1771-
const BITS: usize = 1;
1771+
const BITS: usize = 2;
17721772
fn into_usize(self) -> usize {
17731773
match self {
1774-
traits::Reveal::UserFacing => 0,
1775-
traits::Reveal::All => 1,
1774+
traits::Reveal::Selection => 0,
1775+
traits::Reveal::UserFacing => 1,
1776+
traits::Reveal::All => 2,
17761777
}
17771778
}
17781779
unsafe fn from_usize(ptr: usize) -> Self {
17791780
match ptr {
1780-
0 => traits::Reveal::UserFacing,
1781-
1 => traits::Reveal::All,
1781+
0 => traits::Reveal::Selection,
1782+
1 => traits::Reveal::UserFacing,
1783+
2 => traits::Reveal::All,
17821784
_ => std::hint::unreachable_unchecked(),
17831785
}
17841786
}
@@ -1849,6 +1851,11 @@ impl<'tcx> ParamEnv<'tcx> {
18491851
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) }
18501852
}
18511853

1854+
pub fn with_reveal_selection(mut self) -> Self {
1855+
self.packed.set_tag(Reveal::Selection);
1856+
self
1857+
}
1858+
18521859
pub fn with_user_facing(mut self) -> Self {
18531860
self.packed.set_tag(Reveal::UserFacing);
18541861
self
@@ -1890,7 +1897,7 @@ impl<'tcx> ParamEnv<'tcx> {
18901897
/// although the surrounding function is never reachable.
18911898
pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
18921899
match self.reveal() {
1893-
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
1900+
Reveal::Selection | Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
18941901

18951902
Reveal::All => {
18961903
if value.is_global() {
@@ -2561,6 +2568,7 @@ impl<'tcx> AdtDef {
25612568
"enum discriminant evaluation failed"
25622569
}
25632570
ErrorHandled::TooGeneric => "enum discriminant depends on generics",
2571+
ErrorHandled::Silent => return None,
25642572
};
25652573
tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg);
25662574
None

compiler/rustc_mir/src/const_eval/eval_queries.rs

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_hir::def::DefKind;
1111
use rustc_middle::mir;
1212
use rustc_middle::mir::interpret::ErrorHandled;
1313
use rustc_middle::traits::Reveal;
14+
use rustc_middle::ty::layout::LayoutError;
1415
use rustc_middle::ty::print::with_no_trimmed_paths;
1516
use rustc_middle::ty::{self, subst::Subst, TyCtxt};
1617
use rustc_span::source_map::Span;
@@ -209,14 +210,28 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
209210
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
210211
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
211212
// see comment in const_eval_raw_provider for what we're doing here
212-
if key.param_env.reveal() == Reveal::All {
213-
let mut key = key;
214-
key.param_env = key.param_env.with_user_facing();
215-
match tcx.eval_to_const_value_raw(key) {
216-
// try again with reveal all as requested
217-
Err(ErrorHandled::TooGeneric) => {}
218-
// deduplicate calls
219-
other => return other,
213+
match key.param_env.reveal() {
214+
Reveal::Selection => {}
215+
Reveal::UserFacing => {
216+
let mut key = key;
217+
key.param_env = key.param_env.with_reveal_selection();
218+
match tcx.eval_to_const_value_raw(key) {
219+
// try again with reveal all as requested
220+
Err(ErrorHandled::Silent) => {}
221+
// deduplicate calls
222+
other => return other,
223+
}
224+
}
225+
Reveal::All => {
226+
let mut key = key;
227+
key.param_env = key.param_env.with_user_facing();
228+
match tcx.eval_to_const_value_raw(key) {
229+
// try again with reveal all as requested
230+
Err(ErrorHandled::Silent) => bug!("unexpected error for {:?}", key),
231+
Err(ErrorHandled::TooGeneric) => {}
232+
// deduplicate calls
233+
other => return other,
234+
}
220235
}
221236
}
222237

@@ -248,18 +263,29 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
248263
// computed. For a large percentage of constants that will already have succeeded. Only
249264
// associated constants of generic functions will fail due to not enough monomorphization
250265
// information being available.
251-
252-
// In case we fail in the `UserFacing` variant, we just do the real computation.
253-
if key.param_env.reveal() == Reveal::All {
254-
let mut key = key;
255-
key.param_env = key.param_env.with_user_facing();
256-
match tcx.eval_to_allocation_raw(key) {
257-
// try again with reveal all as requested
258-
Err(ErrorHandled::TooGeneric) => {}
259-
// deduplicate calls
260-
other => return other,
266+
match key.param_env.reveal() {
267+
Reveal::Selection => {}
268+
Reveal::UserFacing => {
269+
let mut key = key;
270+
key.param_env = key.param_env.with_reveal_selection();
271+
match tcx.eval_to_allocation_raw(key) {
272+
Err(ErrorHandled::Silent) => {}
273+
// deduplicate calls
274+
other => return other,
275+
}
276+
}
277+
Reveal::All => {
278+
let mut key = key;
279+
key.param_env = key.param_env.with_user_facing();
280+
match tcx.eval_to_allocation_raw(key) {
281+
Err(ErrorHandled::Silent) => bug!("unexpected error for {:?}", key),
282+
Err(ErrorHandled::TooGeneric) => {}
283+
// deduplicate calls
284+
other => return other,
285+
}
261286
}
262287
}
288+
263289
if cfg!(debug_assertions) {
264290
// Make sure we format the instance even if we do not print it.
265291
// This serves as a regression test against an ICE on printing.
@@ -304,6 +330,15 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
304330
let res = ecx.load_mir(cid.instance.def, cid.promoted);
305331
match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
306332
Err(error) => {
333+
if key.param_env.reveal() == Reveal::Selection {
334+
match error.kind {
335+
err_inval!(Layout(LayoutError::Unknown(_)))
336+
| err_inval!(TooGeneric)
337+
| err_inval!(AlreadyReported(_)) => {}
338+
_ => return Err(ErrorHandled::Silent),
339+
}
340+
}
341+
307342
let err = ConstEvalErr::new(&ecx, error, None);
308343
// errors in statics are always emitted as fatal errors
309344
if is_static {

compiler/rustc_mir/src/monomorphize/collector.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
655655
"collection encountered polymorphic constant: {}",
656656
substituted_constant
657657
),
658+
Err(ErrorHandled::Silent) => span_bug!(
659+
self.body.source_info(location).span,
660+
"silent error emitted during collection",
661+
),
658662
}
659663
}
660664
_ => {}

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
147147
// and hopefully soon change this to an error.
148148
//
149149
// See #74595 for more details about this.
150-
let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span));
150+
let concrete =
151+
infcx.const_eval_resolve(param_env.with_reveal_selection(), def, substs, None, Some(span));
151152

152153
if concrete.is_ok() && substs.has_param_types_or_consts() {
153154
match infcx.tcx.def_kind(def.did) {

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
739739
let violations = self.tcx.object_safety_violations(did);
740740
report_object_safety_error(self.tcx, span, did, violations)
741741
}
742+
ConstEvalFailure(ErrorHandled::Silent) => {
743+
tcx.sess.struct_span_err(span, "failed to evaluate the given constant")
744+
}
742745
ConstEvalFailure(ErrorHandled::TooGeneric) => {
743746
bug!("too generic should have been handled in `is_const_evaluatable`");
744747
}

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
589589
"ConstEquate: const_eval_resolve returned an unexpected error"
590590
)
591591
}
592+
(Err(ErrorHandled::Silent), _) | (_, Err(ErrorHandled::Silent)) => {
593+
ProcessResult::Error(CodeSelectionError(ConstEvalFailure(
594+
ErrorHandled::Silent,
595+
)))
596+
}
592597
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
593598
ProcessResult::Unchanged
594599
}

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
341341
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
342342
// Only normalize `impl Trait` after type-checking, usually in codegen.
343343
match self.param_env.reveal() {
344-
Reveal::UserFacing => ty,
344+
Reveal::Selection | Reveal::UserFacing => ty,
345345

346346
Reveal::All => {
347347
let recursion_limit = self.tcx().sess.recursion_limit();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
112112
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
113113
// Only normalize `impl Trait` after type-checking, usually in codegen.
114114
match self.param_env.reveal() {
115-
Reveal::UserFacing => ty,
115+
Reveal::Selection | Reveal::UserFacing => ty,
116116

117117
Reveal::All => {
118118
let recursion_limit = self.tcx().sess.recursion_limit();

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
562562
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
563563
self.infcx
564564
.const_eval_resolve(
565-
obligation.param_env,
565+
obligation.param_env.with_reveal_selection(),
566566
def,
567567
substs,
568568
promoted,
@@ -585,8 +585,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
585585
Err(_) => Ok(EvaluatedToErr),
586586
}
587587
}
588-
(Err(ErrorHandled::Reported(ErrorReported)), _)
589-
| (_, Err(ErrorHandled::Reported(ErrorReported))) => Ok(EvaluatedToErr),
588+
(Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Silent), _)
589+
| (_, Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Silent)) => {
590+
Ok(EvaluatedToErr)
591+
}
590592
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
591593
span_bug!(
592594
obligation.cause.span(self.tcx()),
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// run-pass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
struct Array<const N: usize>;
6+
7+
trait Matrix {
8+
fn do_it(&self) -> usize;
9+
}
10+
11+
impl Matrix for Array<0> {
12+
fn do_it(&self) -> usize {
13+
0
14+
}
15+
}
16+
17+
impl Matrix for Array<1> {
18+
fn do_it(&self) -> usize {
19+
1
20+
}
21+
}
22+
23+
impl Matrix for Array<2> {
24+
fn do_it(&self) -> usize {
25+
2
26+
}
27+
}
28+
29+
impl<const N: usize> Matrix for Array<N>
30+
where
31+
[u8; N - 3]: Sized,
32+
{
33+
fn do_it(&self) -> usize {
34+
N + 1
35+
}
36+
}
37+
38+
fn main() {
39+
assert_eq!(Array::<0>.do_it(), 0);
40+
assert_eq!(Array::<1>.do_it(), 1);
41+
assert_eq!(Array::<2>.do_it(), 2);
42+
assert_eq!(Array::<3>.do_it(), 4);
43+
}

0 commit comments

Comments
 (0)