Recently there seems to be some confusion about what values functions should return when they encounter an error.
Historically, the following has been the general policy; (1):
Somewhere along the way we realised functions that ordinarily return booleans (isPedDead, hasObjectPermissionTo, etc) should not return meaningful values (false) when errors are encountered, so we started doing something else for new functions; (2):
nil.false.Some new functions / pull requests have started to do something else; (3):
nil on failure, no matter the return type.Things to pin down:
Okay, so my current POV is that (3) is a good way to go. I think it's nice because it's consistent for every function.
Nevertheless, I have been asking for PRs to stick to (2) since that's what is currently done.
I am unsure as to whether existing functions should change. I imagine a lot of existing code does if result == false instead of if not result.
What do you think about this one?
https://github.com/multitheftauto/mtasa-blue/blob/a547e4bad58a7475f4323ba0d12a92d866a59de5/Server/mods/deathmatch/logic/luadefs/CLuaACLDefs.cpp#L890-L891 ...
https://github.com/multitheftauto/mtasa-blue/blob/a547e4bad58a7475f4323ba0d12a92d866a59de5/Server/mods/deathmatch/logic/luadefs/CLuaACLDefs.cpp#L963-L966
I prefer to return nil on failure, no matter the return type (3).
I am not sure if changing existing functions, to return nil, would break scripts.
hasObjectPermissionTo is a getter that returns boolean values, so fits into (2).
It's not actually a getter, because by definition, it doesn't simply return a private member variable of the player/resource/..., which gets passed to the function. It has to lookup the permission in the ACL for the object and then returns a boolean.
(2) isn't restricted to getters in that traditional sense, it is more about false having a special meaning.
So because false has a special meaning in hasObjectPermissionTo, (i.e. "no, this object doesn't have permission"), it fits into (2).
I've edited this issue to reflect this.
In fact, hasObjectPermissionTo was ahead of its time, doing (2) before we noticed we needed to do (2).
I'd prefer another option: Hard error on usage mistakes. hasObjectPermissionTo(false) is obviously wrong and needs to be fixed at the call site. Relying on results from that call is also fairly pointless and regularly causes trouble in other parts of a script, for example by adding results to a table, which then incorrectly contains false instead of strings. This would also be more consistent with built-in Lua functions.
For new functions this could be applied easily. Applying this to old functions is a bit tricky since it could break badly written scripts and we'd be willing to break backwards compat (yet another reason for 1.6 ;)) with (wrong) code like setElementPosition(vehicle, "potato") setElementHealth(vehicle, 1000), which would currently throw a warning, but still set the health to 1000. With a hard error, setElementHealth would not be executed.
I would be in support of just erroring. Are there any other situations where we might want to use warnings, or would this eradicate the use of warnings completely? (Ignoring existing functions.)
We could also add a "strict" mode, which could, if enabled, throw an error for already existing functions.
Okay, so let's hard error on usage mistakes, as per https://github.com/multitheftauto/mtasa-blue/issues/821#issuecomment-464497531.
Let's also do something like a strict mode (https://github.com/multitheftauto/mtasa-blue/issues/821#issuecomment-464854801)... how do we want to implement this?
Potential ways would be:
<strict>true</strict>We could add server-wide, per-resource and per-script. Everyone would be happy.
Haha that's a joke right?
Yes, only server-wide and per-resource is enough.
It's been 3 months, has there been any progress with this? It's blocking a few pull request and doesn't seem like it's going to change soon
@sbx320 has been working on this — am I fine to assign this to you?
To clarify the functionality mentioned here is blocking pull requests:
Okay, so let's hard error on usage mistakes, as per #821 (comment).
"Strict mode" can be discussed and added later as a separate issue/feature.
I think what @sbx320 suggested is enough. Throwing hard error on usage mistake is good. The strict mode looks nice, but it might break scripts, and I can only imagine boomers using it.
Current state: Stuff works, I've gotten stuck on some performance isuse, but that is resolved now. Only missing part now is to handle errors properly (right now the errors are handled, but the messages are empty). Plus a whole bunch of testing obviously.
Okay, so let's hard error on usage mistakes, as per #821 (comment).
Let's also do something like a strict mode (#821 (comment))... how do we want to implement this?
Potential ways would be:
- per-resource meta
<strict>true</strict>- server-wide
- some others
I am going to close this issue now. See quote for final decision.
Before sbx320's pull request is done, the following code should be fine:
if (argStream.HasErrors())
{
return luaL_error(luaVM, argStream.GetFullErrorMessage());
}
(Docs: http://pgl.yoyo.org/luai/i/luaL_error)
Sounds good!
What about gathering stats to measure the impact of causing hard errors. i.e. Servers and clients upload info about usage mistakes
I can't find any downside to gathering more anonymized information with consent of the server owners in order to make a better decision :+1:
Most helpful comment
We could also add a "strict" mode, which could, if enabled, throw an error for already existing functions.