fix: preserve string context in + operator

This commit is contained in:
2026-02-13 19:44:37 +08:00
parent 3aee3c67b9
commit df4edaf5bb
3 changed files with 49 additions and 8 deletions

View File

@@ -1,15 +1,15 @@
[no-exit-message]
@repl:
RUST_LOG=none,nix_js=debug cargo run --bin repl
RUST_LOG=none cargo run --bin repl
[no-exit-message]
@eval expr:
RUST_LOG=none,nix_js=debug cargo run --bin eval -- '{{expr}}'
RUST_LOG=none cargo run --bin eval -- '{{expr}}'
[no-exit-message]
@replr:
RUST_LOG=info cargo run --bin repl --release
RUST_LOG=none cargo run --bin repl --release
[no-exit-message]
@evalr expr:
RUST_LOG=silent cargo run --bin eval --release -- '{{expr}}'
RUST_LOG=none cargo run --bin eval --release -- '{{expr}}'

View File

@@ -7,7 +7,7 @@ import type { NixValue, NixList, NixAttrs, NixString, NixPath } from "./types";
import { isNixPath } from "./types";
import { force } from "./thunk";
import { forceNumeric, forceList, forceAttrs, coerceNumeric } from "./type-assert";
import { getStringValue, getStringContext, mergeContexts, mkStringWithContext } from "./string-context";
import { type NixStringContext, getStringValue, getStringContext, mergeContexts, mkStringWithContext } from "./string-context";
import { coerceToString, StringCoercionMode } from "./builtins/conversion";
import { mkPath } from "./path";
import { typeOf, isNixString } from "./builtins/type-check";
@@ -146,9 +146,14 @@ export const op = {
// Auto-coerce to string if possible
if (canCoerceToString(a) && canCoerceToString(b)) {
const strA = coerceToString(a, StringCoercionMode.Interpolation, false);
const strB = coerceToString(b, StringCoercionMode.Interpolation, false);
return strA + strB;
const context: NixStringContext = new Set();
const strA = coerceToString(a, StringCoercionMode.Interpolation, false, context);
const strB = coerceToString(b, StringCoercionMode.Interpolation, false, context);
const result = strA + strB;
if (context.size === 0) {
return result;
}
return mkStringWithContext(result, context);
}
// Numeric addition

View File

@@ -3,6 +3,42 @@ mod utils;
use nix_js::value::Value;
use utils::{eval_deep, eval_deep_result};
#[test]
fn add_operator_preserves_derivation_context() {
let result = eval_deep(
r#"
let
dep = derivation { name = "dep"; builder = "/bin/sh"; system = "x86_64-linux"; outputs = ["out" "dev"]; };
getOutput = output: pkg: pkg.${output} or pkg.out or pkg;
user = derivation {
name = "user";
builder = "/bin/sh";
system = "x86_64-linux";
libPath = (getOutput "lib" dep) + "/lib";
devPath = dep.dev + "/include";
};
in user.drvPath
"#,
);
let nix_result = eval_deep(
r#"
let
dep = derivation { name = "dep"; builder = "/bin/sh"; system = "x86_64-linux"; outputs = ["out" "dev"]; };
user = derivation {
name = "user";
builder = "/bin/sh";
system = "x86_64-linux";
libPath = "${dep.out}/lib";
devPath = "${dep.dev}/include";
};
in user.drvPath
"#,
);
assert_eq!(result, nix_result);
}
#[test]
fn derivation_minimal() {
let result = eval_deep(