Improve error handle-ability with Lua require - #14937
Conversation
`require` uses pcall to catch errors and display them to the user. This is usually okay, but it also hides errors if Lua tries to load a nonexistent module, which the Lua config might actually want to detect and handle on its own (e.g. by loading a different module, or disabling functionality). Ref hyprwm#14534
|
Hello and thank you for making a PR to Hyprland! Please check the PR Guidelines and make sure your PR follows them. If your code can be tested, please always add tests. See more here. beep boop, I'm just a bot. A real human will review your PR soon. |
|
Just to clarify some behavior here:
|
|
I'll try to remember to test this in a few hours with more notes, I've had several issues with safeLuaRequire, all of which are fixed by bypassing safeLuaRequire... |
|
Yep this fixed my own optional requires with pcall and also all issues with a few 3rd party modules that apparently use pcall(require), like lua-posix. |
|
Yeah, this will still have nonstandard behavior in a few cases that might matter (i.e. ones where an existing but broken module is The alternative is to have some kind of additional input from the user β like a new |
|
I'd be happy enough if vanilla require was just renamed to __require so it's still available if needed. |
|
I mean, I could add that to this PR very easily. But also, it'd only work for contexts where you can modify the Lua yourself, which doesn't include third-party modules like you mentioned above... |
|
Unless the first line in your config is |
require throw a detectable error for nonexistent modulesrequire
If `safeLuaRequire()`'s error-catching behavior isn't wanted, this allows the user to call the original version directly, as `__require`. Or, they could bring it back as the default by doing e.g. `require = __require`, which might be desired to avoid breaking third-party modules that want to catch errors during module load.
154a5e2 to
9d152e5
Compare
β¦4937) * config/lua: make `require` throw an actual error for nonexistent modules `require` uses pcall to catch errors and display them to the user. This is usually okay, but it also hides errors if Lua tries to load a nonexistent module, which the Lua config might actually want to detect and handle on its own (e.g. by loading a different module, or disabling functionality). Ref hyprwm#14534 * config/lua: make vanilla `require` available as `__require` If `safeLuaRequire()`'s error-catching behavior isn't wanted, this allows the user to call the original version directly, as `__require`. Or, they could bring it back as the default by doing e.g. `require = __require`, which might be desired to avoid breaking third-party modules that want to catch errors during module load.
Normally,
requireuses Lua's pcall facility to catch any errors, increasing reliability if the user splits their config into modules. Any errors from within those modules are sent to the config manager for eventual display in the config-errors bar.However, this use of pcall also catches the error case where the user tries to require a nonexistent module. This forcibly displays a message to the user, while also making it impossible to catch or detect such errors from within Lua itself (i.e.
pcall(require, "nonexistent")always indicates success).This PR makes
requirethrow a proper error if module resolution fails, while still hiding (and adding to the config-errors list) any other errors that occur from inside therequired module.Would love feedback on a few details I'm not sure about:
require'd module) just via string comparison, which feels kind of wrong. However, I don't think Lua gives us enough information to do this any other way β even the C return value fromlua_pcall()is identical between the "nonexistent module" and "erroring module" cases (it'sLUA_ERRRUN, specifically).requires produce somewhat strange-looking error messages. I thiiiink this is probably okay, since it should still be clear where the error came from, but maybe we want to clean this up somehow?Fixes #14534
Edit: This PR also makes Lua's original
requireavailable as__require, in case advanced users want to bypass Hyprland's error catching completely.