diff options
Diffstat (limited to 'tvix/eval/src/vm')
-rw-r--r-- | tvix/eval/src/vm/generators.rs | 17 | ||||
-rw-r--r-- | tvix/eval/src/vm/mod.rs | 63 |
2 files changed, 68 insertions, 12 deletions
diff --git a/tvix/eval/src/vm/generators.rs b/tvix/eval/src/vm/generators.rs index 6563a82790a6..9686e6542f13 100644 --- a/tvix/eval/src/vm/generators.rs +++ b/tvix/eval/src/vm/generators.rs @@ -144,10 +144,19 @@ impl Display for VMRequest { } VMRequest::StackPush(v) => write!(f, "stack_push({})", v.type_of()), VMRequest::StackPop => write!(f, "stack_pop"), - VMRequest::StringCoerce(v, kind) => match kind { - CoercionKind::Weak => write!(f, "weak_string_coerce({})", v.type_of()), - CoercionKind::Strong => write!(f, "strong_string_coerce({})", v.type_of()), - }, + VMRequest::StringCoerce( + v, + CoercionKind { + strong, + import_paths, + }, + ) => write!( + f, + "{}_{}importing_string_coerce({})", + if *strong { "strong" } else { "weak" }, + if *import_paths { "" } else { "non_" }, + v.type_of() + ), VMRequest::Call(v) => write!(f, "call({})", v), VMRequest::EnterLambda { lambda, .. } => { write!(f, "enter_lambda({:p})", *lambda) diff --git a/tvix/eval/src/vm/mod.rs b/tvix/eval/src/vm/mod.rs index 902121ebc727..0ac5024d6b11 100644 --- a/tvix/eval/src/vm/mod.rs +++ b/tvix/eval/src/vm/mod.rs @@ -780,7 +780,14 @@ impl<'o> VM<'o> { self.push_call_frame(span, frame); self.enqueue_generator("coerce_to_string", gen_span.clone(), |co| { - value.coerce_to_string(co, CoercionKind::Weak, gen_span) + value.coerce_to_string( + co, + CoercionKind { + strong: false, + import_paths: true, + }, + gen_span, + ) }); return Ok(false); @@ -1206,7 +1213,23 @@ async fn add_values(co: GenCo, a: Value, b: Value) -> Result<Value, ErrorKind> { let result = match (a, b) { (Value::Path(p), v) => { let mut path = p.to_string_lossy().into_owned(); - match generators::request_string_coerce(&co, v, CoercionKind::Weak).await { + match generators::request_string_coerce( + &co, + v, + CoercionKind { + strong: false, + + // Concatenating a Path with something else results in a + // Path, so we don't need to import any paths (paths + // imported by Nix always exist as a string, unless + // converted by the user). In C++ Nix they even may not + // contain any string context, the resulting error of such a + // case can not be replicated by us. + import_paths: false, + }, + ) + .await + { Ok(vs) => { path.push_str(vs.as_str()); crate::value::canon_path(PathBuf::from(path)).into() @@ -1215,14 +1238,38 @@ async fn add_values(co: GenCo, a: Value, b: Value) -> Result<Value, ErrorKind> { } } (Value::String(s1), Value::String(s2)) => Value::String(s1.concat(&s2)), - (Value::String(s1), v) => generators::request_string_coerce(&co, v, CoercionKind::Weak) - .await - .map(|s2| Value::String(s1.concat(&s2))) - .into(), + (Value::String(s1), v) => generators::request_string_coerce( + &co, + v, + CoercionKind { + strong: false, + // Behaves the same as string interpolation + import_paths: true, + }, + ) + .await + .map(|s2| Value::String(s1.concat(&s2))) + .into(), (a @ Value::Integer(_), b) | (a @ Value::Float(_), b) => arithmetic_op!(&a, &b, +)?, (a, b) => { - let r1 = generators::request_string_coerce(&co, a, CoercionKind::Weak).await; - let r2 = generators::request_string_coerce(&co, b, CoercionKind::Weak).await; + let r1 = generators::request_string_coerce( + &co, + a, + CoercionKind { + strong: false, + import_paths: false, + }, + ) + .await; + let r2 = generators::request_string_coerce( + &co, + b, + CoercionKind { + strong: false, + import_paths: false, + }, + ) + .await; match (r1, r2) { (Ok(s1), Ok(s2)) => Value::String(s1.concat(&s2)), (Err(c), _) => return Ok(Value::Catchable(c)), |