fix(tvix/eval): make sure to deref thunk in type predicate builtins
Previously we only matched the outer constructor after forcing which would mean that we would always return `false` if the inspected value was a thunk, regardless what value would be present inside. Change-Id: I361ea6e855e23ef8e5b59098a50b9cd59253803f Reviewed-on: https://cl.tvl.fyi/c/depot/+/6692 Reviewed-by: tazjin <tazjin@tvl.su> Autosubmit: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									fe3c4720a6
								
							
						
					
					
						commit
						e04ccc9354
					
				
					 3 changed files with 63 additions and 18 deletions
				
			
		|  | @ -154,35 +154,45 @@ fn pure_builtins() -> Vec<Builtin> { | |||
|             Some(x) => Ok(x.clone()), | ||||
|             None => Err(ErrorKind::IndexOutOfBounds { index: 0 }), | ||||
|         }), | ||||
|         Builtin::new("isAttrs", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::Attrs(_)))) | ||||
|         // For `is*` predicates we force manually, as Value::force also unwraps any Thunks
 | ||||
|         Builtin::new("isAttrs", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::Attrs(_)))) | ||||
|         }), | ||||
|         Builtin::new("isBool", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::Bool(_)))) | ||||
|         Builtin::new("isBool", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::Bool(_)))) | ||||
|         }), | ||||
|         Builtin::new("isFloat", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::Float(_)))) | ||||
|         Builtin::new("isFloat", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::Float(_)))) | ||||
|         }), | ||||
|         Builtin::new("isFunction", &[true], |args, _| { | ||||
|         Builtin::new("isFunction", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!( | ||||
|                 args[0], | ||||
|                 *value, | ||||
|                 Value::Closure(_) | Value::Builtin(_) | ||||
|             ))) | ||||
|         }), | ||||
|         Builtin::new("isInt", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::Integer(_)))) | ||||
|         Builtin::new("isInt", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::Integer(_)))) | ||||
|         }), | ||||
|         Builtin::new("isList", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::List(_)))) | ||||
|         Builtin::new("isList", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::List(_)))) | ||||
|         }), | ||||
|         Builtin::new("isNull", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::Null))) | ||||
|         Builtin::new("isNull", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::Null))) | ||||
|         }), | ||||
|         Builtin::new("isPath", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::Path(_)))) | ||||
|         Builtin::new("isPath", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::Path(_)))) | ||||
|         }), | ||||
|         Builtin::new("isString", &[true], |args, _| { | ||||
|             Ok(Value::Bool(matches!(args[0], Value::String(_)))) | ||||
|         Builtin::new("isString", &[false], |args, vm| { | ||||
|             let value = args[0].force(vm)?; | ||||
|             Ok(Value::Bool(matches!(*value, Value::String(_)))) | ||||
|         }), | ||||
|         Builtin::new("mul", &[true, true], |mut args, _| { | ||||
|             let b = args.pop().unwrap(); | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| [ true true false true true false true true false true true false true true false true true false true true false true true false true true true false ] | ||||
|  | @ -0,0 +1,34 @@ | |||
| let | ||||
|   # apply is thunked, so we can create a thunked value using the identity function | ||||
|   thunk = x: x; | ||||
| in | ||||
| [ | ||||
|   (builtins.isAttrs { bar = throw "baz"; }) | ||||
|   (builtins.isAttrs (thunk { foo = 13; })) | ||||
|   (builtins.isAttrs (thunk 123)) | ||||
|   (builtins.isBool true) | ||||
|   (builtins.isBool (thunk false)) | ||||
|   (builtins.isBool (thunk "lol")) | ||||
|   (builtins.isFloat 1.2) | ||||
|   (builtins.isFloat (thunk (1 * 1.0))) | ||||
|   (builtins.isFloat 1) | ||||
|   (builtins.isFunction thunk) | ||||
|   (builtins.isFunction (thunk thunk)) | ||||
|   (builtins.isFunction {}) | ||||
|   (builtins.isInt 1) | ||||
|   (builtins.isInt (thunk 42)) | ||||
|   (builtins.isInt 1.0) | ||||
|   (builtins.isList [ (throw "oh no") (abort "it's over") ]) | ||||
|   (builtins.isList (thunk [ 21 21 ])) | ||||
|   (builtins.isList (thunk {})) | ||||
|   (builtins.isNull null) | ||||
|   (builtins.isNull (thunk null)) | ||||
|   (builtins.isNull 42) | ||||
|   (builtins.isPath ./relative) | ||||
|   (builtins.isPath (thunk /absolute)) | ||||
|   (builtins.isPath "/not/a/path") | ||||
|   (builtins.isString "simple") | ||||
|   (builtins.isString "${{ outPath = "coerced"; }}") | ||||
|   (builtins.isString "hello ${"interpolation"}") | ||||
|   (builtins.isString true) | ||||
| ] | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue