diff options
author | Vincent Ambo <mail@tazj.in> | 2023-03-12T21·30+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2023-03-17T19·31+0000 |
commit | 3fa6b13c1e8cbd7a007365dbac0ffc30d03d8472 (patch) | |
tree | 5aa4b1692bc71730408dae780b172b777e4bf815 /tvix/eval/src/value/thunk.rs | |
parent | 5095e4f2696ef85ee7c6ae0515eb8d1586459f8c (diff) |
feat(tvix/eval): track span of first force in a thunk blackhole r/6025
This is step 1 towards being able to use all 4 spans that we know when dealing with infinite recursion. It tracks the span at which the force of a thunk was first requested when constructing a blackhole, so that we can highlight the spans of the first and second forces. These are actually the least relevant spans, but the easiest to put in place, more coming soon. Change-Id: I4c7e82f6211b98756439d4148a4191457cc46807 Reviewed-on: https://cl.tvl.fyi/c/depot/+/8269 Autosubmit: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
Diffstat (limited to 'tvix/eval/src/value/thunk.rs')
-rw-r--r-- | tvix/eval/src/value/thunk.rs | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/tvix/eval/src/value/thunk.rs b/tvix/eval/src/value/thunk.rs index f2959ba15c74..0290e73ebb7d 100644 --- a/tvix/eval/src/value/thunk.rs +++ b/tvix/eval/src/value/thunk.rs @@ -65,7 +65,7 @@ enum ThunkRepr { /// Thunk currently under-evaluation; encountering a blackhole /// value means that infinite recursion has occured. - Blackhole, + Blackhole { forced_at: LightSpan }, /// Fully evaluated thunk. Evaluated(Value), @@ -75,7 +75,7 @@ impl ThunkRepr { fn debug_repr(&self) -> String { match self { ThunkRepr::Evaluated(v) => format!("thunk(val|{})", v), - ThunkRepr::Blackhole => "thunk(blackhole)".to_string(), + ThunkRepr::Blackhole { .. } => "thunk(blackhole)".to_string(), ThunkRepr::Native(_) => "thunk(native)".to_string(), ThunkRepr::Suspended { lambda, .. } => format!("thunk({:p})", *lambda), } @@ -114,7 +114,7 @@ impl Thunk { } // TODO(amjoseph): de-asyncify this - pub async fn force(self, co: GenCo) -> Result<Value, ErrorKind> { + pub async fn force(self, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> { // If the current thunk is already fully evaluated, return its evaluated // value. The VM will continue running the code that landed us here. if self.is_forced() { @@ -124,12 +124,14 @@ impl Thunk { // Begin evaluation of this thunk by marking it as a blackhole, meaning // that any other forcing frame encountering this thunk before its // evaluation is completed detected an evaluation cycle. - let inner = self.0.replace(ThunkRepr::Blackhole); + let inner = self.0.replace(ThunkRepr::Blackhole { forced_at: span }); match inner { // If there was already a blackhole in the thunk, this is an // evaluation cycle. - ThunkRepr::Blackhole => Err(ErrorKind::InfiniteRecursion), + ThunkRepr::Blackhole { forced_at } => Err(ErrorKind::InfiniteRecursion { + first_force: forced_at.span(), + }), // If there is a native function stored in the thunk, evaluate it // and replace this thunk's representation with the result. @@ -206,7 +208,7 @@ impl Thunk { pub fn value(&self) -> Ref<Value> { Ref::map(self.0.borrow(), |thunk| match thunk { ThunkRepr::Evaluated(value) => value, - ThunkRepr::Blackhole => panic!("Thunk::value called on a black-holed thunk"), + ThunkRepr::Blackhole { .. } => panic!("Thunk::value called on a black-holed thunk"), ThunkRepr::Suspended { .. } | ThunkRepr::Native(_) => { panic!("Thunk::value called on a suspended thunk") } |