about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
Diffstat (limited to 'tvix')
-rw-r--r--tvix/eval/docs/builtins.md2
-rw-r--r--tvix/eval/src/builtins/mod.rs42
-rw-r--r--tvix/eval/src/value/string.rs6
3 files changed, 43 insertions, 7 deletions
diff --git a/tvix/eval/docs/builtins.md b/tvix/eval/docs/builtins.md
index 26bbd1b2d344..4e09e0f9e600 100644
--- a/tvix/eval/docs/builtins.md
+++ b/tvix/eval/docs/builtins.md
@@ -120,7 +120,7 @@ The `impl` column indicates implementation status in tvix:
 | true                          | true   |       |       |         |
 | tryEval                       | false  |       |       |         |
 | typeOf                        | false  |       |       |         |
-| unsafeDiscardOutputDependency | false  |       |       | context |
+| unsafeDiscardOutputDependency | false  |       |       |         |
 | unsafeDiscardStringContext    | false  |       |       |         |
 | unsafeGetAttrPos              | false  |       |       | todo    |
 | valueSize                     | false  |       |       | todo    |
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index e1e296ba633e..048c8867a717 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -1575,12 +1575,42 @@ mod placeholder_builtins {
         co: GenCo,
         s: Value,
     ) -> Result<Value, ErrorKind> {
-        generators::emit_warning_kind(
-            &co,
-            WarningKind::NotImplemented("builtins.unsafeDiscardOutputDependency"),
-        )
-        .await;
-        Ok(s)
+        let span = generators::request_span(&co).await;
+        let mut v = s
+            .coerce_to_string(
+                co,
+                // It's weak because
+                // lists, integers, floats and null are not
+                // accepted as parameters.
+                CoercionKind {
+                    strong: false,
+                    import_paths: true,
+                },
+                span,
+            )
+            .await?
+            .to_contextful_str()?;
+
+        // If there's any context, we will swap any ... by a path one.
+        if let Some(ctx) = v.context_mut() {
+            let new_context: tvix_eval::NixContext = ctx
+                .iter()
+                .map(|elem| match elem {
+                    // FUTUREWORK(performance): ideally, we should either:
+                    // (a) do interior mutation of the existing context.
+                    // (b) let the structural sharing make those clones cheap.
+                    crate::NixContextElement::Derivation(drv_path) => {
+                        crate::NixContextElement::Plain(drv_path.to_string())
+                    }
+                    elem => elem.clone(),
+                })
+                .collect::<HashSet<_>>()
+                .into();
+
+            *ctx = new_context;
+        }
+
+        Ok(Value::from(v))
     }
 
     #[builtin("addErrorContext")]
diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string.rs
index 6ce0d190c0a0..dd027895fd1c 100644
--- a/tvix/eval/src/value/string.rs
+++ b/tvix/eval/src/value/string.rs
@@ -48,6 +48,12 @@ impl From<NixContextElement> for NixContext {
     }
 }
 
+impl From<HashSet<NixContextElement>> for NixContext {
+    fn from(value: HashSet<NixContextElement>) -> Self {
+        Self(value)
+    }
+}
+
 impl NixContext {
     /// Creates an empty context that can be populated
     /// and passed to form a contextful [NixString], albeit