Issues
function with return type array accepts certain forms of structs to be returned
Description
Environment
Details
Assignee
UnassignedUnassignedReporter
Kai KoenigKai KoenigPriority
MinorNew Issue warning screen
Before you create a new Issue, please post to the mailing list first https://dev.lucee.org
Once the issue has been verified, one of the Lucee team will ask you to file an issue
Affects versions
Details
Details
Assignee
Reporter
Priority
New Issue warning screen
Before you create a new Issue, please post to the mailing list first https://dev.lucee.org
Once the issue has been verified, one of the Lucee team will ask you to file an issue
Affects versions
Activity
Kai Koenig21 August 2021 at 01:37
After discussion with @Brad Wood retracted the ticket.
Kai Koenig21 August 2021 at 01:36
Closing
Kai Koenig4 August 2021 at 06:11Edited
I’ll leave it open to see if others chime in, but if there’s agreement this is indented behaviour, then happy for this to be closed.
Kai Koenig4 August 2021 at 06:10
@Brad Wood Your string/number analogy to this sadly makes sense.
If this is expected/intended behaviour, that’s cool with me then - it sure was unexpected, yup.
I went and had a look at passing structs are array-typed arguments into a function and the same applies. At least it’s consistent: https://trycf.com/gist/cc78caade3e430a473a00cd3edf88f0a/lucee5?theme=monokai
Brad Wood4 August 2021 at 05:00
Type validation in CFML for arguments and function returns types has never been “what is it?”, but rather “what could it be?”. For this reason, you can pass a java.lang.String as a numeric argument. It may not be a number, but it can become one if necessary.
In both of your examples above, Lucee will happily convert both of those structs into arrays if you ask it (because they either have no keys or only numeric keys). Therefore, both of them can become an array.
foo={}
bar={1:'brad',2:'kai'}
writeDump( foo )
writeDump( bar )
writeDump( arrayLen( foo ) )
writeDump( arrayFirst( bar ) )
Unexpected? Possibly. By design? Most likely, yes. At least in Lucee. Adobe doesn’t try as hard to cast things to arrays, but I’m not sure it’s a bug that Lucee is trying harder here even though it is an incompat.
https://trycf.com/gist/7bac4e61528745fb9cf53e3fb8e88658/lucee5?theme=monokai
It seems that a function with havuing a returntype of array also happily returns a structure (provided the structure is created in a certain way - which might depend on numeric vs. string keys). That seems wrong.
<cfscript> array function getMeAnArrayFalse1() { var a = {} dump(a) return a; } array function getMeAnArrayFalse2() { var a = StructNew() a["4"] = 6 dump(a) return a; } array function getMeAnArrayFalse3() { var a = {"sfd":4} dump(a) return a; } writedump(getMeAnArrayFalse1) writedump(getMeAnArrayFalse1()) writedump(getMeAnArrayFalse2) writedump(getMeAnArrayFalse2()) writedump(getMeAnArrayFalse3) writedump(getMeAnArrayFalse3()) </cfscript>
Observed: the code above errors correctly for getMeAnArrayFalse3() but versions 1 and 2 of this function work fine incorrectly.
Expectation: all of them fail due to wrong return type.
Note: UDF type checking is enabled in Lucee admin.
I've been able to repo this both on Lucee 5.3.8, latest snapshot, as well as on Trycf.com running on Lucee 5, 4.5 and Railo 4.2.
ACF in all versions back to 2016 on TryCF.com works as expected.
Here's a TMCF gist: https://trycf.com/gist/bd81e1fc51260657e9213d9648e6903d/lucee5?theme=monokai
On further investgation it seems the criteria of a declared struct from inside the function to “pass” as an array on return is numeric struct keys.
Something like:
var a = {"56":4}
will be accepted as an array in a return statement, butvar a = {"sfd":4}
not. In fact, it only successfully pretends to be an array if all keys are numerics or numerics-in-string. As soon as a struct has a single non-numeric or non-numeric-in-string key, it behaves correctly.