Skip to content

Commit b1f427c

Browse files
committed
Auto merge of #53821 - oli-obk:sanity_query, r=<try>
Report const eval error inside the query r? @RalfJung fixes #53561
2 parents 20dc0c5 + a1cfc95 commit b1f427c

File tree

152 files changed

+1150
-1309
lines changed

Some content is hidden

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

152 files changed

+1150
-1309
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ define_dep_nodes!( <'tcx>
527527
[] UsedTraitImports(DefId),
528528
[] HasTypeckTables(DefId),
529529
[] ConstEval { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
530+
[] ConstEvalRaw { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
530531
[] CheckMatch(DefId),
531532
[] SymbolName(DefId),
532533
[] InstanceSymbolName { instance: Instance<'tcx> },

src/librustc/hir/map/blocks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub struct FnLikeNode<'a> { node: Node<'a> }
4343

4444
/// MaybeFnLike wraps a method that indicates if an object
4545
/// corresponds to some FnLikeNode.
46-
pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
46+
trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
4747

4848
impl MaybeFnLike for ast::Item {
4949
fn is_fn_like(&self) -> bool {

src/librustc/ich/impls_ty.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,9 @@ impl_stable_hash_for!(struct ty::Const<'tcx> {
478478
val
479479
});
480480

481-
impl_stable_hash_for!(struct ::mir::interpret::ConstEvalErr<'tcx> {
482-
span,
483-
stacktrace,
484-
error
481+
impl_stable_hash_for!(enum mir::interpret::ErrorHandled {
482+
Reported,
483+
TooGeneric
485484
});
486485

487486
impl_stable_hash_for!(struct ::mir::interpret::FrameInfo {
@@ -498,8 +497,6 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
498497
predicates
499498
});
500499

501-
impl_stable_hash_for!(struct ::mir::interpret::EvalError<'tcx> { kind });
502-
503500
impl<'a, 'gcx, O: HashStable<StableHashingContext<'a>>> HashStable<StableHashingContext<'a>>
504501
for ::mir::interpret::EvalErrorKind<'gcx, O> {
505502
fn hash_stable<W: StableHasherResult>(&self,
@@ -538,14 +535,14 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
538535
UnimplementedTraitSelection |
539536
TypeckError |
540537
TooGeneric |
541-
CheckMatchError |
542538
DerefFunctionPointer |
543539
ExecuteMemory |
544540
OverflowNeg |
545541
RemainderByZero |
546542
DivisionByZero |
547543
GeneratorResumedAfterReturn |
548544
GeneratorResumedAfterPanic |
545+
ReferencedConstant |
549546
InfiniteLoop => {}
550547
ReadUndefBytes(offset) => offset.hash_stable(hcx, hasher),
551548
InvalidDiscriminant(val) => val.hash_stable(hcx, hasher),
@@ -555,7 +552,6 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
555552
line.hash_stable(hcx, hasher);
556553
col.hash_stable(hcx, hasher);
557554
},
558-
ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
559555
MachineError(ref err) => err.hash_stable(hcx, hasher),
560556
FunctionAbiMismatch(a, b) => {
561557
a.hash_stable(hcx, hasher);

src/librustc/mir/interpret/error.rs

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ use std::{fmt, env};
1212

1313
use mir;
1414
use ty::{Ty, layout};
15-
use ty::layout::{Size, Align};
16-
use rustc_data_structures::sync::Lrc;
15+
use ty::layout::{Size, Align, LayoutError};
1716
use rustc_target::spec::abi::Abi;
1817

1918
use super::{
@@ -30,7 +29,26 @@ use syntax_pos::Span;
3029
use syntax::ast;
3130
use syntax::symbol::Symbol;
3231

33-
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>;
32+
#[derive(Debug, Clone, PartialEq, Eq)]
33+
pub enum ErrorHandled {
34+
/// Already reported a lint or an error for this evaluation
35+
Reported,
36+
/// Don't emit an error, the evaluation failed because the MIR was generic
37+
/// and the substs didn't fully monomorphize it.
38+
TooGeneric,
39+
}
40+
41+
impl ErrorHandled {
42+
pub fn assert_reported(self) {
43+
match self {
44+
ErrorHandled::Reported => {},
45+
ErrorHandled::TooGeneric => bug!("MIR interpretation failed without reporting an error \
46+
even though it was fully monomorphized"),
47+
}
48+
}
49+
}
50+
51+
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
3452

3553
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
3654
pub struct ConstEvalErr<'tcx> {
@@ -50,33 +68,41 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
5068
pub fn struct_error(&self,
5169
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
5270
message: &str)
53-
-> Option<DiagnosticBuilder<'tcx>>
71+
-> Result<DiagnosticBuilder<'tcx>, ErrorHandled>
5472
{
5573
self.struct_generic(tcx, message, None)
5674
}
5775

5876
pub fn report_as_error(&self,
5977
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
6078
message: &str
61-
) {
79+
) -> ErrorHandled {
6280
let err = self.struct_error(tcx, message);
63-
if let Some(mut err) = err {
64-
err.emit();
81+
match err {
82+
Ok(mut err) => {
83+
err.emit();
84+
ErrorHandled::Reported
85+
},
86+
Err(err) => err,
6587
}
6688
}
6789

6890
pub fn report_as_lint(&self,
6991
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
7092
message: &str,
7193
lint_root: ast::NodeId,
72-
) {
94+
) -> ErrorHandled {
7395
let lint = self.struct_generic(
7496
tcx,
7597
message,
7698
Some(lint_root),
7799
);
78-
if let Some(mut lint) = lint {
79-
lint.emit();
100+
match lint {
101+
Ok(mut lint) => {
102+
lint.emit();
103+
ErrorHandled::Reported
104+
},
105+
Err(err) => err,
80106
}
81107
}
82108

@@ -85,15 +111,12 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
85111
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
86112
message: &str,
87113
lint_root: Option<ast::NodeId>,
88-
) -> Option<DiagnosticBuilder<'tcx>> {
114+
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
89115
match self.error.kind {
90-
::mir::interpret::EvalErrorKind::TypeckError |
91-
::mir::interpret::EvalErrorKind::TooGeneric |
92-
::mir::interpret::EvalErrorKind::CheckMatchError |
93-
::mir::interpret::EvalErrorKind::Layout(_) => return None,
94-
::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
95-
inner.struct_generic(tcx, "referenced constant has errors", lint_root)?.emit();
96-
},
116+
EvalErrorKind::Layout(LayoutError::Unknown(_)) |
117+
EvalErrorKind::TooGeneric => return Err(ErrorHandled::TooGeneric),
118+
EvalErrorKind::Layout(LayoutError::SizeOverflow(_)) |
119+
EvalErrorKind::TypeckError => return Err(ErrorHandled::Reported),
97120
_ => {},
98121
}
99122
trace!("reporting const eval failure at {:?}", self.span);
@@ -117,7 +140,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
117140
for FrameInfo { span, location, .. } in &self.stacktrace {
118141
err.span_label(*span, format!("inside call to `{}`", location));
119142
}
120-
Some(err)
143+
Ok(err)
121144
}
122145
}
123146

@@ -278,10 +301,9 @@ pub enum EvalErrorKind<'tcx, O> {
278301
TypeckError,
279302
/// Resolution can fail if we are in a too generic context
280303
TooGeneric,
281-
CheckMatchError,
282304
/// Cannot compute this constant because it depends on another one
283305
/// which already produced an error
284-
ReferencedConstant(Lrc<ConstEvalErr<'tcx>>),
306+
ReferencedConstant,
285307
GeneratorResumedAfterReturn,
286308
GeneratorResumedAfterPanic,
287309
InfiniteLoop,
@@ -405,9 +427,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
405427
"encountered constants with type errors, stopping evaluation",
406428
TooGeneric =>
407429
"encountered overly generic constant",
408-
CheckMatchError =>
409-
"match checking failed",
410-
ReferencedConstant(_) =>
430+
ReferencedConstant =>
411431
"referenced constant has errors",
412432
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
413433
Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",

src/librustc/mir/interpret/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod value;
2020

2121
pub use self::error::{
2222
EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
23-
FrameInfo, ConstEvalResult,
23+
FrameInfo, ConstEvalResult, ErrorHandled,
2424
};
2525

2626
pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
@@ -156,31 +156,31 @@ impl<'tcx> Pointer {
156156
Pointer { alloc_id, offset }
157157
}
158158

159-
pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
159+
pub fn wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
160160
Pointer::new(
161161
self.alloc_id,
162162
Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
163163
)
164164
}
165165

166-
pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Self, bool) {
166+
pub fn overflowing_signed_offset(self, i: i128, cx: impl HasDataLayout) -> (Self, bool) {
167167
let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
168168
(Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
169169
}
170170

171-
pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
171+
pub fn signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
172172
Ok(Pointer::new(
173173
self.alloc_id,
174174
Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
175175
))
176176
}
177177

178-
pub fn overflowing_offset<C: HasDataLayout>(self, i: Size, cx: C) -> (Self, bool) {
178+
pub fn overflowing_offset(self, i: Size, cx: impl HasDataLayout) -> (Self, bool) {
179179
let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
180180
(Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
181181
}
182182

183-
pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
183+
pub fn offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
184184
Ok(Pointer::new(
185185
self.alloc_id,
186186
Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),

src/librustc/traits/error_reporting.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -840,15 +840,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
840840
violations)
841841
}
842842

843-
ConstEvalFailure(ref err) => {
844-
match err.struct_error(
845-
self.tcx.at(span),
846-
"could not evaluate constant expression",
847-
) {
848-
Some(err) => err,
849-
None => return,
850-
}
851-
}
843+
// already reported in the query
844+
ConstEvalFailure => return,
852845

853846
Overflow => {
854847
bug!("overflow should be handled before the `report_selection_error` path");

src/librustc/traits/fulfill.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Obligati
1616
use rustc_data_structures::obligation_forest::{ObligationProcessor, ProcessResult};
1717
use std::marker::PhantomData;
1818
use hir::def_id::DefId;
19-
use mir::interpret::ConstEvalErr;
20-
use mir::interpret::EvalErrorKind;
2119

2220
use super::CodeAmbiguity;
2321
use super::CodeProjectionError;
@@ -495,17 +493,11 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
495493
match self.selcx.tcx().at(obligation.cause.span)
496494
.const_eval(param_env.and(cid)) {
497495
Ok(_) => ProcessResult::Changed(vec![]),
498-
Err(err) => ProcessResult::Error(
499-
CodeSelectionError(ConstEvalFailure(err)))
496+
Err(_) => ProcessResult::Error(
497+
CodeSelectionError(ConstEvalFailure))
500498
}
501499
} else {
502-
ProcessResult::Error(
503-
CodeSelectionError(ConstEvalFailure(ConstEvalErr {
504-
span: obligation.cause.span,
505-
error: EvalErrorKind::TooGeneric.into(),
506-
stacktrace: vec![],
507-
}.into()))
508-
)
500+
ProcessResult::Error(CodeSelectionError(ConstEvalFailure))
509501
}
510502
},
511503
None => {

src/librustc/traits/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use hir;
2222
use hir::def_id::DefId;
2323
use infer::outlives::env::OutlivesEnvironment;
2424
use middle::region;
25-
use mir::interpret::ConstEvalErr;
2625
use ty::subst::Substs;
2726
use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
2827
use ty::error::{ExpectedFound, TypeError};
@@ -383,7 +382,7 @@ pub enum SelectionError<'tcx> {
383382
ty::PolyTraitRef<'tcx>,
384383
ty::error::TypeError<'tcx>),
385384
TraitNotObjectSafe(DefId),
386-
ConstEvalFailure(Lrc<ConstEvalErr<'tcx>>),
385+
ConstEvalFailure,
387386
Overflow,
388387
}
389388

src/librustc/traits/structural_impls.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
172172
})
173173
}
174174
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
175-
super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
176-
err.into(),
177-
)),
175+
super::ConstEvalFailure => Some(super::ConstEvalFailure),
178176
super::Overflow => bug!(), // FIXME: ape ConstEvalFailure?
179177
}
180178
}

src/librustc/ty/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
2727
use middle::privacy::AccessLevels;
2828
use middle::resolve_lifetime::ObjectLifetimeDefault;
2929
use mir::Mir;
30-
use mir::interpret::GlobalId;
30+
use mir::interpret::{GlobalId, ErrorHandled};
3131
use mir::GeneratorLayout;
3232
use session::CrateDisambiguator;
3333
use traits::{self, Reveal};
@@ -2172,18 +2172,18 @@ impl<'a, 'gcx, 'tcx> AdtDef {
21722172
None
21732173
}
21742174
}
2175-
Err(err) => {
2176-
err.report_as_error(
2177-
tcx.at(tcx.def_span(expr_did)),
2178-
"could not evaluate enum discriminant",
2179-
);
2175+
Err(ErrorHandled::Reported) => {
21802176
if !expr_did.is_local() {
21812177
span_bug!(tcx.def_span(expr_did),
21822178
"variant discriminant evaluation succeeded \
21832179
in its crate but failed locally");
21842180
}
21852181
None
21862182
}
2183+
Err(ErrorHandled::TooGeneric) => span_bug!(
2184+
tcx.def_span(expr_did),
2185+
"enum discriminant depends on generic arguments",
2186+
),
21872187
}
21882188
}
21892189

src/librustc/ty/query/config.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,27 @@ impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> {
275275
}
276276

277277
impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
278+
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String {
279+
format!(
280+
"const-evaluating + checking `{}`",
281+
tcx.item_path_str(key.value.instance.def.def_id()),
282+
)
283+
}
284+
285+
#[inline]
286+
fn cache_on_disk(_key: Self::Key) -> bool {
287+
true
288+
}
289+
290+
#[inline]
291+
fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
292+
id: SerializedDepNodeIndex)
293+
-> Option<Self::Value> {
294+
tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
295+
}
296+
}
297+
298+
impl<'tcx> QueryDescription<'tcx> for queries::const_eval_raw<'tcx> {
278299
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String {
279300
format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id()))
280301
}

0 commit comments

Comments
 (0)