fix(tvix/eval): ensure callable is forced when using call_with
When passing multiple arguments, every intermediate callable needs to be forced as this is expected by the VM's call_value function. Also adds a debug assertion for this which makes it easier to spot exactly what went wrong. Change-Id: I3aa519cb6cdaab713bd18282bef901c4cd77c535 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7312 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
		
							parent
							
								
									e1e8285ecf
								
							
						
					
					
						commit
						994bf03b74
					
				
					 2 changed files with 9 additions and 1 deletions
				
			
		| 
						 | 
					@ -133,6 +133,10 @@ impl Thunk {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn is_evaluated(&self) -> bool {
 | 
				
			||||||
 | 
					        matches!(*self.0.borrow(), ThunkRepr::Evaluated(_))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns a reference to the inner evaluated value of a thunk.
 | 
					    /// Returns a reference to the inner evaluated value of a thunk.
 | 
				
			||||||
    /// It is an error to call this on a thunk that has not been
 | 
					    /// It is an error to call this on a thunk that has not been
 | 
				
			||||||
    /// forced, or is not otherwise known to be fully evaluated.
 | 
					    /// forced, or is not otherwise known to be fully evaluated.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,7 +230,10 @@ impl<'o> VM<'o> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Value::Builtin(b) => self.call_builtin(b.clone()),
 | 
					            Value::Builtin(b) => self.call_builtin(b.clone()),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Value::Thunk(t) => self.call_value(&t.value()),
 | 
					            Value::Thunk(t) => {
 | 
				
			||||||
 | 
					                debug_assert!(t.is_evaluated(), "call_value called with unevaluated thunk");
 | 
				
			||||||
 | 
					                self.call_value(&t.value())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Attribute sets with a __functor attribute are callable.
 | 
					            // Attribute sets with a __functor attribute are callable.
 | 
				
			||||||
            Value::Attrs(ref attrs) => match attrs.select("__functor") {
 | 
					            Value::Attrs(ref attrs) => match attrs.select("__functor") {
 | 
				
			||||||
| 
						 | 
					@ -277,6 +280,7 @@ impl<'o> VM<'o> {
 | 
				
			||||||
        let mut res = self.pop();
 | 
					        let mut res = self.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for _ in 0..(num_args - 1) {
 | 
					        for _ in 0..(num_args - 1) {
 | 
				
			||||||
 | 
					            res.force(self).map_err(|e| self.error(e))?;
 | 
				
			||||||
            self.call_value(&res)?;
 | 
					            self.call_value(&res)?;
 | 
				
			||||||
            res = self.pop();
 | 
					            res = self.pop();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue