feat(tvix/eval): report all known spans on infinite recursion
This reports the span 1. of the code within a thunk, 2. of the place where the thunk was instantiated, 3. of the place where the thunk was first forced, 4. of the place where the thunk was forced again, when yielding an infinite recursion error, which hopefully makes it easier to debug them. The spans are tracked in the ThunkRepr::Blackhole variant when putting a thunk under evaluation. Note that we currently have some loss of span precision in the VM loop when switching between frame types, so spans 3/4 are currently a bit wonky. Working on it. Change-Id: Icbd2a9df903d00e8c2545b3fc46dcd2a9e3e3e55 Reviewed-on: https://cl.tvl.fyi/c/depot/+/8270 Reviewed-by: flokli <flokli@flokli.de> Tested-by: BuildkiteCI Autosubmit: tazjin <tazjin@tvl.su>
This commit is contained in:
parent
3fa6b13c1e
commit
8c13f18d11
3 changed files with 80 additions and 16 deletions
|
|
@ -79,6 +79,8 @@ pub enum ErrorKind {
|
|||
/// Infinite recursion encountered while forcing thunks.
|
||||
InfiniteRecursion {
|
||||
first_force: Span,
|
||||
suspended_at: Option<Span>,
|
||||
content_span: Option<Span>,
|
||||
},
|
||||
|
||||
ParseErrors(Vec<rnix::parser::ParseError>),
|
||||
|
|
@ -871,19 +873,42 @@ impl Error {
|
|||
]
|
||||
}
|
||||
|
||||
ErrorKind::InfiniteRecursion { first_force } => {
|
||||
vec![
|
||||
SpanLabel {
|
||||
label: Some("first requested here".into()),
|
||||
span: *first_force,
|
||||
ErrorKind::InfiniteRecursion {
|
||||
first_force,
|
||||
suspended_at,
|
||||
content_span,
|
||||
} => {
|
||||
let mut spans = vec![];
|
||||
|
||||
if let Some(content_span) = content_span {
|
||||
spans.push(SpanLabel {
|
||||
label: Some("this lazily-evaluated code".into()),
|
||||
span: *content_span,
|
||||
style: SpanStyle::Secondary,
|
||||
},
|
||||
SpanLabel {
|
||||
label: Some("requested again here".into()),
|
||||
span: self.span,
|
||||
style: SpanStyle::Primary,
|
||||
},
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
if let Some(suspended_at) = suspended_at {
|
||||
spans.push(SpanLabel {
|
||||
label: Some("which was instantiated here".into()),
|
||||
span: *suspended_at,
|
||||
style: SpanStyle::Secondary,
|
||||
})
|
||||
}
|
||||
|
||||
spans.push(SpanLabel {
|
||||
label: Some("was first requested to be evaluated here".into()),
|
||||
span: *first_force,
|
||||
style: SpanStyle::Secondary,
|
||||
});
|
||||
|
||||
spans.push(SpanLabel {
|
||||
label: Some("but then requested again here during its own evaluation".into()),
|
||||
span: self.span,
|
||||
style: SpanStyle::Primary,
|
||||
});
|
||||
|
||||
spans
|
||||
}
|
||||
|
||||
// All other errors pretty much have the same shape.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue