Summary
I run into a very odd situation that was easily overlooked as the verse compiler didn’t yield any errors not even warnings about a key-type mismatch. This caused the code to compile without any issues but always produce a runtime network error that leads to a full disconnection from the UEFN session.
Please select what you are reporting on:
Verse
What Type of Bug are you experiencing?
Verse
Steps to Reproduce
key_enum := enum { A }
Test(): void = {
var Map: [tuple(string, key_enum)]int = map {}
# WARNING: This container lookup is unlikely to succeed. (Did you mean to use a different key?) (2017)
Map[42] or 1
# Nothing, the compiler is perfectly happy with this key-type mismatch.
Map["string"] or 2
}
Expected Result
Key-type mismatches should be compiler errors, it should not be relaxed to warnings!
Map[42]
aka warning (2017) should be an error
Map["string"]
should be an error
Observed Result
Mismatches like Map[42]
are only warnings, which can be ignored and will likely also cause network errors at runtime.
Map["string"]
mismatch is more critical as it’s completely silent and potentially very hard to spot in the code base. It caused network errors at runtime every time the read operation was performed.
Platform(s)
UEFN (v36.20)
The way I personally trapped myself with this was a type update due to a refactor. The type went from [string]value
to [tuple(string, some_enum_type)]value
. All compiler errors were fixed except that the compiler didn’t highlight the key-type mismatch for some read operations, which were still using the string
key. I consider this compiler behavior in a strongly typed language as bad and it should be addressed as it’s too easy to run into, but is not trivial to find and fix. Furthermore I’m very much surprised that other key-type mismatches are warnings instead of errors.
What should happen here is that it warns you that the map lookups aren’t going to succeed, and the Map[42]
and Map["string"]
calls fail at runtime.
A runtime network error that leads to a disconnect of the UEFN session indicates that something is crashing the server. I couldn’t reproduce that with the code from your post in a fresh project.
If you can reproduce the network error, can you post your UEFN and/or Fortnite client log files here, or DM them to me?
Why is it a warning? In my opinion the compiler should reject the key-type mismatch and prevent it from compiling.
I’ll check after the update tomorrow if I can still reproduce it in an isolated or my current project.
maps takes comparable as keys, any keys that can be compared for equality should work. If no element exists on the map with that same key value, will fail. That’s the normal behavior
You providing a value that is not of same type its expected to fail, since they’re not the same. The LSP is smart enough to say “this will never succeed because the values are not the same type” when acidentally using a mismatching type to help you during development, but the types/values are still valid and comparable, it will just always fail (ItemA = ItemB)
during the map query (the same as other languages that return null when not found matching element for some key). It does not crash the verse execution as a runtime error because is a simple comparable check and query on the map that fails to find it
This is similar as other user on the forum who suggested to make a warning for if (MyInt = 1.0)
because it did not give warns/messages but always falied, because int 1
is not the same as float 1.0
. Mismatching types can still be compared if both are comparable, they will just never succeed…
My expectation is [key]value where key: comparable
not [comparable]value
. The second has no real use case unless you can explicitly intermix the type. In case of the former, the key-type mismatch has to be explicitly rejected by the compiler.
This has no real use case as far as I can tell, so I don’t see why it should be supported.
In Swift this would be Dictionary<AnyHashable, Value>
, but only when the key type is explicitly fixed as AnyHashable
, otherwise a concrete key-type cannot be changed, not at compile time not at runtime.
If you have Dictionary<Int, Value>
the compiler does not allow using string as key values, it will naturally result in a compile time error in a strongly typed language.
The verse docs do not state that maps operate on comparable
existential, it only says that the key types have to be comparable. That‘s a very fine detail that does not imply [comparable]value
.
1 Like
map access is [comparable]value
map definition/allocation is [key]value where key:comparable, value:any
same as
variable definition/allocation = MyVar:t where t:type
variable comparison = MyVar:comparable
it fails comparison because are not the same and comparable
that provides that check, but does not allow allocation since the type is strict
The map query is an access+comparison and not allocating any value to it for checking type safety. That’s why allocating is an error and accessing just fails. Now, using a non-comparable value as key for access will give an error since it can’t be compared
The same with the if example, setting any var must match type, but comparing equality just needs both to be comparable, even if they would always fail. (And if you use any non comparable type, will also prevent from comparing in if statements)
(The warning also shows when you don’t provide any key at all during query on a map, since the query will also fail when nothing to be compared)
I agree that mismatching types may have no use case currently (unless considering some subclass and inheritance, idk…), and I also agree that if that’s not something related to future plans, it makes sense to be more strict and actually giving compile errors to the user instead of just warnings to improve development workflow
1 Like
FORT-942645 changed to ‘Needs More Info’. We’re missing information that would help us determine the source of the issue.
This kind of static analysis needs to produce a warning instead of an error so that if we make improvements to the compiler that result in more precise type inference, that doesn’t lead to compile errors in code that previously compiled without errors.
I tried to reproduce the network failure in an isolated project and I couldn’t make it fail any longer. Either it was an issue in the past version or something else in my main project triggered it back when I reported it. However the issue was caused by the read operation with a mismatched type back when I was hitting the network errors.
Right now only the set
operation will cause a compile time key-type mismatch error, but the read operation with a string as an input is totally silent, not ever a warning is diagnosed (v36.30).