New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No implicit type conversions #360
Comments
Rhai integers default to Try: let _: () = engine.call_fn(&mut scope, &ast, "function", (42i64,))?; |
So I can only use |
There are no types in Rhai, so you can use any type. It doesn't matter at all to the engine. By default, all Rust integer types are supported in Rhai. Your problem is trying to mix them (for example, comparing a You can use if age0.to_int() == 42 { Or you can directly compare types of // here assume 'age_target' is another 'u32' variable
if age0 == age_target { |
You're right, it doesn't make it clear. I'll add a section into the Book about no implicit type conversions for integers. EDIT: Warning section added - https://rhai.rs/book/language/numbers.html |
You can use But if you want to use I'd suggest you simply use This is better than many scripting languages where you don't even have the choice of integers - many of them only have one |
That sounds like a really bad design decision when combined with the fact that rhai is dynamically typed. So this is likely the real issue I have:
Edit: I don't want to sound rude, but this was a really painful experience so far. |
Well, it is probably more a design choice. Option 1: Allow only specific types. So you'll get an error if you try to put in a function with Option 2: Allow all types. Anything works. There are no restrictions. But that also means that the user can put anything in, and it is probably easy to mess up data types. Rhai takes Option 2. |
A bit more on Option 1: in order to restrict types, the user no longer has the freedom to work directly with For example: let foo = SomeType::new();
let d = Dynamic::try_from(foo)?; // is `SomeType` an allowed type? How should `Dynamic` know? Should this fail?
let mut scope = Scope::new();
scope.push("x", 42_u8); // is `u8` allowed? How should `Scope` know?
// The only alternative is this:
engine.allow::<u8>();
engine.set_scope_value(&mut scope, "x", 42_u8)?; |
You're probably right... I have been struggling for quite a while whether to build in automatic type conversions for integer values... Even had a prototype a long time ago. However, it opens up to yet another set of problems, especially when Rhai doesn't have typed literals. It is easy to have an expression and lose track of the actual number type; then things start failing somewhere down the road. So far, the only reasonable route is to always use |
I agree on that Option 1 isn't a good choice for a scripting language. But I don't think these are the only options and Option 2 can be further divided. I image implementing compare just like the other operands (if I understand them correctly), so that there will be an error for I feel like rhai picks concepts from other language and ends up with bad collection while there are good variants/compromises near by. In my experience having strict types is a very good thing and other languages struggle so hard without, same goes for implicit conversions. But then rhai does dynamic typing like Python which will break during execution (or produce unexpected behavior) and doesn't allow enforcing types. While I see why a scripting language wants this, there is still the mentioned problem with compares. Without that dynamic typing is okay-ish. I think a great compromise would be a TypeScript like approach:
Then compares would work if any operand is I see how this could be huge implementation cost. So maybe the stricter compare function and other integer literals are the more practical way to go. |
The comparison operators default to let x = "hello";
if x == 42 {
print("It is The Answer!");
} else {
print("Well... " + x);
} Without the default, if type_of(x) == "i64" && x == 42 { But maybe the solution is to turn off defaults when comparing between different integer types? |
I see, for these cases it's a sensible default.
That sounds like a low hanging fruit we want to grab. An alternative could be an additional compare operator like I'm also thinking about a linting mode where warnings are emitted if the types differ, but that could be a bit noisy. |
Something like a |
Documentation updated: https://rhai.rs/book/language/numbers.html#warning--no-implicit-type-conversions |
I thought more of something like an engine option for that. But letting scripts define strict mode also sounds nice as it won't affect everything. |
It can easily be an engine option together with a script option to turn it on. |
The new versions will now disallow by default:
Only defaults will be comparing between two different types. |
Yeah, both sounds nice.
Maybe I'm reading this wrong, but are all comparisons disabled by default then? Or only ones for "unknown" types? |
Yes, It is more of a refinement. For example, for
|
That sounds fine. Should prevent a lot of silent coding errors without the burden of type checking everywhere. |
Closing this for now as the new refinement will come to the next version. |
Not sure how to describe the problem further than "function arguments are broken" as I can reduce the problem with just a simple compare and no optimizations enabled.
Minimal Reproducer:
Output:
The text was updated successfully, but these errors were encountered: