Repository: gleam-lang/gleam (Rust)

Issue:
Javascript InvalidVersionFormat on Windows
When running gleam build on windows 11 with 1.12.0-rc3, with default code from gleam new
with this added to gleam.toml
```yaml
target = "javascript"

[javascript]
typescript_declarations = true

runtime = "node"
```

Logs with trace
```
DEBUG download_deps: locking_directory path="E:\\dev\\temp\\gl_ts\\build\\packages\\gleam.lock"
TRACE download_deps: reading_file path="E:\\dev\\temp\\gl_ts\\gleam.toml"
error: Fatal compiler bug!

This is a bug in the Gleam compiler, sorry!

Please report this crash to https://github.com/gleam-lang/gleam/issues/new
and include this error message with your report.

Panic: D:\a\gleam\gleam\compiler-core\src\requirement.rs:125
        expected string: InvalidVersionFormat { input: "javascript", error: "encountered unexpected token: \"javascript\"" }
Gleam version: 1.12.0-rc3
Operating system: windows
```


Discussion:
Can you share your entire config please 🙏 
IMO, this is not bug. I'm able to reproduce your case:
```sh
test localhost@10.54.65.52 @main
A $ GLEAM_LOG=trace gleam1.12 build
DEBUG download_deps: locking_directory path="/data/data/com.termux/files/home/test/build/packages/gleam.lock"
TRACE download_deps: reading_file path="/data/data/com.termux/files/home/test/gleam.toml"
error: Fatal compiler bug!

This is a bug in the Gleam compiler, sorry!

Please report this crash to https://github.com/gleam-lang/gleam/issues/new
and include this error message with your report.

Panic: /project/compiler-core/src/requirement.rs:125
        expected string: InvalidVersionFormat { input: "javascript", error: "encountered unexpected token: \"javascript\"" }
Gleam version: 1.12.0-rc2
Operating system: linux

If you can also share your code and say what file you were editing or any
steps to reproduce the crash that would be a great help.

You may also want to try again with the `GLEAM_LOG=trace` environment
variable set.

test localhost@10.54.65.52 @main
A $ ^cat gleam.toml
name = "test_app"
version = "1.0.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "", repo = "" }
# links = [{ title = "Website", href = "" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.

[dependencies]
gleam_stdlib = ">= 0.44.0 and < 2.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"

target = "javascript"

[javascript]
typescript_declarations = false

runtime = "node"
```
But if I edit code so `target` is before any block, it works correctly (I get another issue due to Hex's cert):
```sh
gleam1.12 build
  Resolving versions
error: Dependency resolution failed

An error occured while chosing the version of gleam_stdlib: error sending
request for url (https://repo.hex.pm/packages/gleam_stdlib)

test localhost@10.54.65.52 @main
A $ nvim
test localhost@10.54.65.52 @main
A $ ^cat gleam.toml
name = "test_app"
version = "1.0.0"
target = "javascript"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "", repo = "" }
# links = [{ title = "Website", href = "" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.

[dependencies]
gleam_stdlib = ">= 0.44.0 and < 2.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"

[javascript]
typescript_declarations = false

runtime = "node"
```
So, when first variant is applied, target field is parsed as one of `dev-dependencies`s entries.
If `target` is in the wrong place, then there will be an error, yes. However, this should not cause the compiler to panic. Rather, a proper error message should be reported
For instance, panic message points to this fragment:
https://github.com/gleam-lang/gleam/blob/7eeac6de4d27edf28448c3072a93158a97b7c904/compiler-core/src/requirement.rs#L121-L126
This type probably constructs here:
https://github.com/gleam-lang/gleam/blob/7eeac6de4d27edf28448c3072a93158a97b7c904/compiler-core/src/requirement.rs#L33-L40
Gears is right, the config is invalid, but the build tool shouldn't crash because of user error. We'll fix this.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe22e167143..f725bf83d63 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -138,3 +138,7 @@
   expression as safe to remove, instead of just highlighting the double
   negation.
   ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
+
+- Fixed a bug where the compiler would crash if there was an invalid version
+  requirement in a project's `gleam.toml`.
+  ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
diff --git a/compiler-core/src/requirement.rs b/compiler-core/src/requirement.rs
index 036ae08b682..02e7c75a40c 100644
--- a/compiler-core/src/requirement.rs
+++ b/compiler-core/src/requirement.rs
@@ -122,7 +122,10 @@ impl<'de> Visitor<'de> for RequirementVisitor {
     where
         E: de::Error,
     {
-        Ok(FromStr::from_str(value).expect("expected string"))
+        match value.parse::<Requirement>() {
+            Ok(value) => Ok(value),
+            Err(error) => Err(de::Error::custom(error)),
+        }
     }
 
     fn visit_map<M>(self, visitor: M) -> Result<Self::Value, M::Error>
@@ -165,4 +168,15 @@ mod tests {
             Requirement::git("https://github.com/gleam-lang/otp.git", "4d34935")
         );
     }
+
+    #[test]
+    fn read_wrong_version() {
+        let toml = r#"
+            short = ">= 2.0 and < 3.0.0"
+        "#;
+
+        let error =
+            toml::from_str::<HashMap<String, Requirement>>(toml).expect_err("invalid version");
+        insta::assert_snapshot!(error.to_string());
+    }
 }


Test patch:
diff --git a/compiler-core/src/snapshots/gleam_core__requirement__tests__read_wrong_version.snap b/compiler-core/src/snapshots/gleam_core__requirement__tests__read_wrong_version.snap
new file mode 100644
index 00000000000..9f71c70f618
--- /dev/null
+++ b/compiler-core/src/snapshots/gleam_core__requirement__tests__read_wrong_version.snap
@@ -0,0 +1,5 @@
+---
+source: compiler-core/src/requirement.rs
+expression: error.to_string()
+---
+>= 2.0 and < 3.0.0 is not a valid version. missing patch version: 2.0 for key `short` at line 2 column 21