Description
Skript/Server Version
[21:49:43 INFO]: [Skript] Skript's aliases can be found here: https://github.com/SkriptLang/skript-aliases
[21:49:43 INFO]: [Skript] Skript's documentation can be found here: https://skriptlang.github.io/Skript
[21:49:43 INFO]: [Skript] Skript's tutorials can be found here: https://docs.skriptlang.org/tutorials
[21:49:43 INFO]: [Skript] Server Version: git-Paper-350 (MC: 1.18.2)
[21:49:43 INFO]: [Skript] Skript Version: 2.6.3
[21:49:43 INFO]: [Skript] Installed Skript Addons: None
[21:49:43 INFO]: [Skript] Installed dependencies: None
Bug Description
This issue has probably been present in Skript for a long time, but it didn't become apparent until PR #4260 (part of Skript 2.6.2+), which removed a 7 years old chunk of code added by Mirreski, based on another 9 years old code by Njol.
That code had the (side?) effect of catching some common literals and returning them with their proper type (instead of becoming UnparsedLiterals later on). With it removed, these literals can now become UnparsedLiterals (with Object return type). This leads to some issues later on, in LiteralLists.
When a LiteralList is formed with UnparsedLiterals, the return type of the list will be Object. Even if the list's UnparsedLiterals are converted (LiteralUtils.defendExpression(Expression)
), the return type remains unchanged - still Object.
An expression like loop-value
will use that Object return type. If loop-value
is used in a syntax taking in a specific type (like itemtype
), the expression will be wrapped in a ConvertedExpression to convert the value to the required type. But here, another problem appears. There are no Object -> X
converters, so Skript will try to improvise and return a wrong converter or not return anything at all.
With the wrong converter, the expression will fail to return. On the other hand, if no converter is found, an error will be issued at parse time saying the expression is not of the required type.
To sum it up: SkriptParser makes UnparsedLiteral which becomes part of LiteralList which keeps Object return type. Some expressions then use that return type. Those expression get wrapped in a ConvertedExpression which might use the wrong converter which will result in 💥 (ok, maybe not that dramatic)
(Keep in mind that #4260 did not cause the whole of this, it only made the problem obvious by making it apply to some common types. The issue can be reproduced on other types even without that PR.)
Expected Behavior
The expression should return the correct value (i.e. the converter must not fail).
There are a few different ways this could've gone differently to reach proper behaviour:
- UnparsedLiterals shouldn't be created if there are no conflicts
- The LiteralList should have changed its type; because all syntaxes taking in
%object(s)%
(and therefore allowing UnparsedLiterals) should already defend their expressions, this is a viable fix - Converters should account for this issue
- There might be a limited number of expressions with this problem (I only know of
loop-value
), so it could be fixed from there - Other ways I didn't think of
Steps to Reproduce
on load:
loop 1, 2 and 3:
broadcast loop-value + 1
The above code prints:
1
1
1
This is because, as described above, 1, 2 and 3
will form a LiteralList of UnparsedLiterals. The loop-value
expression will use an Object return type, so it needs to be converted to Number. There isn't any Object -> Number
converter, so Skript uses something else. (It looks like it uses Integer -> Long
(because that's the first 'acceptable' converter it could find) and it fails because the looped value is a Long, not an Integer.)
Types like Boolean that have no registered converters will simply throw an error. (Because Boolean was not actually covered in the code removed by that PR, this issue also happens on older versions.)
This can also be reproduced with other literals (except Strings - they get handled beforehand).
Errors or Screenshots
No response
Other
A workaround is using the default value expression on the bad expression. For the above code, one can do loop-value ? {_}
to fix it. This is because converting default values works slightly different.
Agreement
- I have read the guidelines above and affirm I am following them with this report.