Skip to content

Commit 8d67f57

Browse files
committed
Auto merge of #71049 - eddyb:const-err, r=oli-obk
Add `ConstKind::Error` and convert `ErrorHandled::Reported` to it. By replicating the `ty::Error` approach to encoding "an error has occurred", all of the mechanisms that skip redundant/downstream errors are engaged and help out (see the reduction in test output). This PR also adds `ErrorHandled::Linted` for the lint case because using `ErrorHandled::Reported` *without* having emitted an error that is *guaranteed* to stop compilation, is incorrect now. r? @oli-obk cc @rust-lang/wg-const-eval @varkor @yodaldevoid
2 parents b2c1a60 + 77f38dc commit 8d67f57

Some content is hidden

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

57 files changed

+193
-408
lines changed

src/librustc_codegen_ssa/mir/operand.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::glue;
66
use crate::traits::*;
77
use crate::MemFlags;
88

9+
use rustc_errors::ErrorReported;
910
use rustc_middle::mir;
1011
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
1112
use rustc_middle::ty::layout::TyAndLayout;
@@ -447,8 +448,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
447448
self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|err| {
448449
match err {
449450
// errored or at least linted
450-
ErrorHandled::Reported => {}
451-
ErrorHandled::TooGeneric => bug!("codgen encountered polymorphic constant"),
451+
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {}
452+
ErrorHandled::TooGeneric => {
453+
bug!("codegen encountered polymorphic constant")
454+
}
452455
}
453456
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
454457
// the above error (or silence it under some conditions) will not cause UB.

src/librustc_infer/infer/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,8 @@ pub fn unexpected_hidden_region_diagnostic(
304304
// down this path which gives a decent human readable
305305
// explanation.
306306
//
307-
// (*) if not, the `tainted_by_errors` flag would be set to
308-
// true in any case, so we wouldn't be here at all.
307+
// (*) if not, the `tainted_by_errors` field would be set to
308+
// `Some(ErrorReported)` in any case, so we wouldn't be here at all.
309309
note_and_explain_free_region(
310310
tcx,
311311
&mut err,

src/librustc_infer/infer/freshen.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
251251
bug!("unexpected const {:?}", ct)
252252
}
253253

254-
ty::ConstKind::Param(_) | ty::ConstKind::Value(_) | ty::ConstKind::Unevaluated(..) => {}
254+
ty::ConstKind::Param(_)
255+
| ty::ConstKind::Value(_)
256+
| ty::ConstKind::Unevaluated(..)
257+
| ty::ConstKind::Error => {}
255258
}
256259

257260
ct.super_fold_with(self)

src/librustc_infer/infer/resolve.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
227227
match c.val {
228228
ty::ConstKind::Infer(InferConst::Var(vid)) => {
229229
self.err = Some(FixupError::UnresolvedConst(vid));
230-
return self.tcx().consts.err;
230+
return self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: c.ty });
231231
}
232232
ty::ConstKind::Infer(InferConst::Fresh(_)) => {
233233
bug!("Unexpected const in full const resolver: {:?}", c);

src/librustc_middle/mir/interpret/error.rs

+25-32
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::ty::{self, layout, Ty};
88

99
use backtrace::Backtrace;
1010
use rustc_data_structures::sync::Lock;
11-
use rustc_errors::{struct_span_err, DiagnosticBuilder};
11+
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
1212
use rustc_hir as hir;
1313
use rustc_hir::definitions::DefPathData;
1414
use rustc_macros::HashStable;
@@ -19,25 +19,16 @@ use std::{any::Any, fmt, mem};
1919

2020
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
2121
pub enum ErrorHandled {
22-
/// Already reported a lint or an error for this evaluation.
23-
Reported,
22+
/// Already reported an error for this evaluation, and the compilation is
23+
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
24+
Reported(ErrorReported),
25+
/// Already emitted a lint for this evaluation.
26+
Linted,
2427
/// Don't emit an error, the evaluation failed because the MIR was generic
2528
/// and the substs didn't fully monomorphize it.
2629
TooGeneric,
2730
}
2831

29-
impl ErrorHandled {
30-
pub fn assert_reported(self) {
31-
match self {
32-
ErrorHandled::Reported => {}
33-
ErrorHandled::TooGeneric => bug!(
34-
"MIR interpretation failed without reporting an error \
35-
even though it was fully monomorphized"
36-
),
37-
}
38-
}
39-
}
40-
4132
CloneTypeFoldableImpls! {
4233
ErrorHandled,
4334
}
@@ -84,15 +75,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
8475
tcx: TyCtxtAt<'tcx>,
8576
message: &str,
8677
emit: impl FnOnce(DiagnosticBuilder<'_>),
87-
) -> Result<(), ErrorHandled> {
78+
) -> ErrorHandled {
8879
self.struct_generic(tcx, message, emit, None)
8980
}
9081

9182
pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled {
92-
match self.struct_error(tcx, message, |mut e| e.emit()) {
93-
Ok(_) => ErrorHandled::Reported,
94-
Err(x) => x,
95-
}
83+
self.struct_error(tcx, message, |mut e| e.emit())
9684
}
9785

9886
pub fn report_as_lint(
@@ -102,7 +90,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
10290
lint_root: hir::HirId,
10391
span: Option<Span>,
10492
) -> ErrorHandled {
105-
match self.struct_generic(
93+
self.struct_generic(
10694
tcx,
10795
message,
10896
|mut lint: DiagnosticBuilder<'_>| {
@@ -122,10 +110,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
122110
lint.emit();
123111
},
124112
Some(lint_root),
125-
) {
126-
Ok(_) => ErrorHandled::Reported,
127-
Err(err) => err,
128-
}
113+
)
129114
}
130115

131116
/// Create a diagnostic for this const eval error.
@@ -143,12 +128,14 @@ impl<'tcx> ConstEvalErr<'tcx> {
143128
message: &str,
144129
emit: impl FnOnce(DiagnosticBuilder<'_>),
145130
lint_root: Option<hir::HirId>,
146-
) -> Result<(), ErrorHandled> {
131+
) -> ErrorHandled {
147132
let must_error = match self.error {
148133
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
149-
return Err(ErrorHandled::TooGeneric);
134+
return ErrorHandled::TooGeneric;
135+
}
136+
err_inval!(TypeckError(error_reported)) => {
137+
return ErrorHandled::Reported(error_reported);
150138
}
151-
err_inval!(TypeckError) => return Err(ErrorHandled::Reported),
152139
// We must *always* hard error on these, even if the caller wants just a lint.
153140
err_inval!(Layout(LayoutError::SizeOverflow(_))) => true,
154141
_ => false,
@@ -183,6 +170,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
183170
// caller thinks anyway.
184171
// See <https://github.com/rust-lang/rust/pull/63152>.
185172
finish(struct_error(tcx, &err_msg), None);
173+
ErrorHandled::Reported(ErrorReported)
186174
} else {
187175
// Regular case.
188176
if let Some(lint_root) = lint_root {
@@ -200,12 +188,13 @@ impl<'tcx> ConstEvalErr<'tcx> {
200188
tcx.span,
201189
|lint| finish(lint.build(message), Some(err_msg)),
202190
);
191+
ErrorHandled::Linted
203192
} else {
204193
// Report as hard error.
205194
finish(struct_error(tcx, message), Some(err_msg));
195+
ErrorHandled::Reported(ErrorReported)
206196
}
207197
}
208-
Ok(())
209198
}
210199
}
211200

@@ -246,7 +235,9 @@ fn print_backtrace(backtrace: &mut Backtrace) {
246235
impl From<ErrorHandled> for InterpErrorInfo<'_> {
247236
fn from(err: ErrorHandled) -> Self {
248237
match err {
249-
ErrorHandled::Reported => err_inval!(ReferencedConstant),
238+
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {
239+
err_inval!(ReferencedConstant)
240+
}
250241
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
251242
}
252243
.into()
@@ -288,7 +279,7 @@ pub enum InvalidProgramInfo<'tcx> {
288279
/// which already produced an error.
289280
ReferencedConstant,
290281
/// Abort in case type errors are reached.
291-
TypeckError,
282+
TypeckError(ErrorReported),
292283
/// An error occurred during layout computation.
293284
Layout(layout::LayoutError<'tcx>),
294285
/// An invalid transmute happened.
@@ -301,7 +292,9 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
301292
match self {
302293
TooGeneric => write!(f, "encountered overly generic constant"),
303294
ReferencedConstant => write!(f, "referenced constant has errors"),
304-
TypeckError => write!(f, "encountered constants with type errors, stopping evaluation"),
295+
TypeckError(ErrorReported) => {
296+
write!(f, "encountered constants with type errors, stopping evaluation")
297+
}
305298
Layout(ref err) => write!(f, "{}", err),
306299
TransmuteSizeDiff(from_ty, to_ty) => write!(
307300
f,

src/librustc_middle/ty/context.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub struct CommonLifetimes<'tcx> {
182182
}
183183

184184
pub struct CommonConsts<'tcx> {
185-
pub err: &'tcx Const<'tcx>,
185+
pub unit: &'tcx Const<'tcx>,
186186
}
187187

188188
pub struct LocalTableInContext<'a, V> {
@@ -410,8 +410,8 @@ pub struct TypeckTables<'tcx> {
410410
pub used_trait_imports: Lrc<DefIdSet>,
411411

412412
/// If any errors occurred while type-checking this body,
413-
/// this field will be set to `true`.
414-
pub tainted_by_errors: bool,
413+
/// this field will be set to `Some(ErrorReported)`.
414+
pub tainted_by_errors: Option<ErrorReported>,
415415

416416
/// All the opaque types that are restricted to concrete types
417417
/// by this function.
@@ -447,7 +447,7 @@ impl<'tcx> TypeckTables<'tcx> {
447447
fru_field_types: Default::default(),
448448
coercion_casts: Default::default(),
449449
used_trait_imports: Lrc::new(Default::default()),
450-
tainted_by_errors: false,
450+
tainted_by_errors: None,
451451
concrete_opaque_types: Default::default(),
452452
upvar_list: Default::default(),
453453
generator_interior_types: Default::default(),
@@ -858,9 +858,9 @@ impl<'tcx> CommonConsts<'tcx> {
858858
let mk_const = |c| interners.const_.intern(c, |c| Interned(interners.arena.alloc(c))).0;
859859

860860
CommonConsts {
861-
err: mk_const(ty::Const {
861+
unit: mk_const(ty::Const {
862862
val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())),
863-
ty: types.err,
863+
ty: types.unit,
864864
}),
865865
}
866866
}

src/librustc_middle/ty/flags.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,7 @@ impl FlagComputation {
7070
| &ty::Str
7171
| &ty::Foreign(..) => {}
7272

73-
// You might think that we could just return Error for
74-
// any type containing Error as a component, and get
75-
// rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
76-
// the exception of function types that return bot).
77-
// But doing so caused sporadic memory corruption, and
78-
// neither I (tjc) nor nmatsakis could figure out why,
79-
// so we're doing it this way.
80-
&ty::Error => self.add_flags(TypeFlags::HAS_TY_ERR),
73+
&ty::Error => self.add_flags(TypeFlags::HAS_ERROR),
8174

8275
&ty::Param(_) => {
8376
self.add_flags(TypeFlags::HAS_TY_PARAM);
@@ -239,6 +232,7 @@ impl FlagComputation {
239232
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
240233
}
241234
ty::ConstKind::Value(_) => {}
235+
ty::ConstKind::Error => self.add_flags(TypeFlags::HAS_ERROR),
242236
}
243237
}
244238

src/librustc_middle/ty/fold.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
8282
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
8383
}
8484
fn references_error(&self) -> bool {
85-
self.has_type_flags(TypeFlags::HAS_TY_ERR)
85+
self.has_type_flags(TypeFlags::HAS_ERROR)
8686
}
8787
fn has_param_types_or_consts(&self) -> bool {
8888
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)

src/librustc_middle/ty/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_data_structures::fx::FxIndexMap;
2727
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
2828
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2929
use rustc_data_structures::sync::{self, par_iter, ParallelIterator};
30+
use rustc_errors::ErrorReported;
3031
use rustc_hir as hir;
3132
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
3233
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
@@ -567,8 +568,8 @@ bitflags! {
567568
| TypeFlags::HAS_TY_OPAQUE.bits
568569
| TypeFlags::HAS_CT_PROJECTION.bits;
569570

570-
/// Is an error type reachable?
571-
const HAS_TY_ERR = 1 << 13;
571+
/// Is an error type/const reachable?
572+
const HAS_ERROR = 1 << 13;
572573

573574
/// Does this have any region that "appears free" in the type?
574575
/// Basically anything but [ReLateBound] and [ReErased].
@@ -2388,7 +2389,7 @@ impl<'tcx> AdtDef {
23882389
None
23892390
}
23902391
}
2391-
Err(ErrorHandled::Reported) => {
2392+
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {
23922393
if !expr_did.is_local() {
23932394
span_bug!(
23942395
tcx.def_span(expr_did),

src/librustc_middle/ty/print/pretty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,7 @@ pub trait PrettyPrinter<'tcx>:
938938
self.pretty_print_bound_var(debruijn, bound_var)?
939939
}
940940
ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
941+
ty::ConstKind::Error => p!(write("[const error]")),
941942
};
942943
Ok(self)
943944
}

src/librustc_middle/ty/relate.rs

+12
Original file line numberDiff line numberDiff line change
@@ -510,12 +510,21 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
510510
let tcx = relation.tcx();
511511

512512
let eagerly_eval = |x: &'tcx ty::Const<'tcx>| {
513+
// FIXME(eddyb) this doesn't account for lifetime inference variables
514+
// being erased by `eval`, *nor* for the polymorphic aspect of `eval`.
515+
// That is, we could always use `eval` and it will just return the
516+
// old value back if it doesn't succeed.
513517
if !x.val.needs_infer() {
514518
return x.eval(tcx, relation.param_env()).val;
515519
}
516520
x.val
517521
};
518522

523+
// FIXME(eddyb) doesn't look like everything below checks that `a.ty == b.ty`.
524+
// We could probably always assert it early, as `const` generic parameters
525+
// are not allowed to depend on other generic parameters, i.e. are concrete.
526+
// (although there could be normalization differences)
527+
519528
// Currently, the values that can be unified are primitive types,
520529
// and those that derive both `PartialEq` and `Eq`, corresponding
521530
// to structural-match types.
@@ -524,6 +533,9 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
524533
// The caller should handle these cases!
525534
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
526535
}
536+
537+
(ty::ConstKind::Error, _) | (_, ty::ConstKind::Error) => Ok(ty::ConstKind::Error),
538+
527539
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
528540
return Ok(a);
529541
}

src/librustc_middle/ty/structural_impls.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -1022,9 +1022,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
10221022
ty::ConstKind::Unevaluated(did, substs, promoted) => {
10231023
ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted)
10241024
}
1025-
ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => {
1026-
*self
1027-
}
1025+
ty::ConstKind::Value(_)
1026+
| ty::ConstKind::Bound(..)
1027+
| ty::ConstKind::Placeholder(..)
1028+
| ty::ConstKind::Error => *self,
10281029
}
10291030
}
10301031

@@ -1033,9 +1034,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
10331034
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
10341035
ty::ConstKind::Param(p) => p.visit_with(visitor),
10351036
ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor),
1036-
ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
1037-
false
1038-
}
1037+
ty::ConstKind::Value(_)
1038+
| ty::ConstKind::Bound(..)
1039+
| ty::ConstKind::Placeholder(_)
1040+
| ty::ConstKind::Error => false,
10391041
}
10401042
}
10411043
}

0 commit comments

Comments
 (0)