about summary refs log tree commit diff
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2022-10-20T22·52+0200
committerclbot <clbot@tvl.fyi>2022-10-21T00·11+0000
commit64bb501de1d52ce004d530d1fc15392537ee2beb (patch)
tree40ffd435406f3235cbb323e98cfcd2ad8d02084a
parent5753fc14f5a24b2c4d5f4c76ed22d28a1be67c2a (diff)
fix(tvix): distinguish search- and relative path resolution errors r/5172
Failures to resolve a nix search path lookup in angle brackets can be
caught using tryEval (if it reaches the runtime). Resolving relative
paths (either to the current directory or the current user's home) can
never be caught, even if they happen inside a thunk at runtime (which is
currently the case for home-relative paths).

Change-Id: I7f73221df66d82a381dd4063358906257826995a
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7025
Autosubmit: sterni <sternenseemann@systemli.org>
Reviewed-by: Adam Joseph <adam@westernsemico.com>
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
-rw-r--r--tvix/eval/src/compiler/mod.rs4
-rw-r--r--tvix/eval/src/errors.rs20
-rw-r--r--tvix/eval/src/nix_search_path.rs4
-rw-r--r--tvix/eval/src/vm.rs2
4 files changed, 19 insertions, 11 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 819a37ec71eb..619445f2ce85 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -115,7 +115,7 @@ impl<'observer> Compiler<'observer> {
             Some(dir) if cfg!(target_arch = "wasm32") || dir.is_absolute() => Ok(dir),
             _ => {
                 let current_dir = std::env::current_dir().map_err(|e| Error {
-                    kind: ErrorKind::PathResolution(format!(
+                    kind: ErrorKind::RelativePathResolution(format!(
                         "could not determine current directory: {}",
                         e
                     )),
@@ -290,7 +290,7 @@ impl Compiler<'_> {
             if raw_path.len() == 2 {
                 return self.emit_error(
                     node,
-                    ErrorKind::PathResolution("Empty <> path not allowed".into()),
+                    ErrorKind::NixPathResolution("Empty <> path not allowed".into()),
                 );
             }
             let path = &raw_path[1..(raw_path.len() - 1)];
diff --git a/tvix/eval/src/errors.rs b/tvix/eval/src/errors.rs
index a3fe3876093c..5437db7bcbb6 100644
--- a/tvix/eval/src/errors.rs
+++ b/tvix/eval/src/errors.rs
@@ -50,8 +50,11 @@ pub enum ErrorKind {
         rhs: &'static str,
     },
 
-    /// Resolving a user-supplied path literal failed in some way.
-    PathResolution(String),
+    /// Resolving a user-supplied angle brackets path literal failed in some way.
+    NixPathResolution(String),
+
+    /// Resolving a user-supplied relative or home-relative path literal failed in some way.
+    RelativePathResolution(String),
 
     /// Dynamic keys are not allowed in some scopes.
     DynamicKeyInScope(&'static str),
@@ -178,7 +181,7 @@ impl ErrorKind {
     /// Returns `true` if this error can be caught by `builtins.tryEval`
     pub fn is_catchable(&self) -> bool {
         match self {
-            Self::Throw(_) | Self::AssertionFailed | Self::PathResolution(_) => true,
+            Self::Throw(_) | Self::AssertionFailed | Self::NixPathResolution(_) => true,
             Self::ThunkForce(err) => err.kind.is_catchable(),
             _ => false,
         }
@@ -238,7 +241,9 @@ impl Display for Error {
                 write!(f, "can not compare a {} with a {}", lhs, rhs)
             }
 
-            ErrorKind::PathResolution(err) => write!(f, "could not resolve path: {}", err),
+            ErrorKind::NixPathResolution(err) | ErrorKind::RelativePathResolution(err) => {
+                write!(f, "could not resolve path: {}", err)
+            }
 
             ErrorKind::DynamicKeyInScope(scope) => {
                 write!(f, "dynamically evaluated keys are not allowed in {}", scope)
@@ -619,7 +624,9 @@ impl Error {
         let label = match &self.kind {
             ErrorKind::DuplicateAttrsKey { .. } => "in this attribute set",
             ErrorKind::InvalidAttributeName(_) => "in this attribute set",
-            ErrorKind::PathResolution(_) => "in this path literal",
+            ErrorKind::NixPathResolution(_) | ErrorKind::RelativePathResolution(_) => {
+                "in this path literal"
+            }
             ErrorKind::UnexpectedArgument { .. } => "in this function call",
 
             // The spans for some errors don't have any more descriptive stuff
@@ -668,7 +675,7 @@ impl Error {
             ErrorKind::AttributeNotFound { .. } => "E005",
             ErrorKind::TypeError { .. } => "E006",
             ErrorKind::Incomparable { .. } => "E007",
-            ErrorKind::PathResolution(_) => "E008",
+            ErrorKind::NixPathResolution(_) => "E008",
             ErrorKind::DynamicKeyInScope(_) => "E009",
             ErrorKind::UnknownStaticVariable => "E010",
             ErrorKind::UnknownDynamicVariable(_) => "E011",
@@ -691,6 +698,7 @@ impl Error {
             ErrorKind::IO { .. } => "E029",
             ErrorKind::FromJsonError { .. } => "E030",
             ErrorKind::UnexpectedArgument { .. } => "E031",
+            ErrorKind::RelativePathResolution(_) => "E032",
 
             // Placeholder error while Tvix is under construction.
             ErrorKind::NotImplemented(_) => "E999",
diff --git a/tvix/eval/src/nix_search_path.rs b/tvix/eval/src/nix_search_path.rs
index b19c5c1dd5cf..8295aaa0ef91 100644
--- a/tvix/eval/src/nix_search_path.rs
+++ b/tvix/eval/src/nix_search_path.rs
@@ -103,7 +103,7 @@ impl NixSearchPath {
                 return Ok(p);
             }
         }
-        Err(ErrorKind::PathResolution(format!(
+        Err(ErrorKind::NixPathResolution(format!(
             "path '{}' was not found in the Nix search path",
             path.display()
         )))
@@ -178,7 +178,7 @@ mod tests {
             let nix_search_path = NixSearchPath::from_str("./.").unwrap();
             let err = nix_search_path.resolve("nope").unwrap_err();
             assert!(
-                matches!(err, ErrorKind::PathResolution(..)),
+                matches!(err, ErrorKind::NixPathResolution(..)),
                 "err = {err:?}"
             );
         }
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index ff39cf129572..1128031b41bc 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -555,7 +555,7 @@ impl<'o> VM<'o> {
                 Value::UnresolvedPath(path) => {
                     match dirs::home_dir() {
                         None => {
-                            return Err(self.error(ErrorKind::PathResolution(
+                            return Err(self.error(ErrorKind::RelativePathResolution(
                                 "failed to determine home directory".into(),
                             )));
                         }