Missing implicit type conversions

Few implicit type conversions are sorely missing from Solidity.

e.g.

Example #1:

bytes32 b = bytes32(1);

This fails to compile with error Explicit type conversion not allowed from "int_const 1" to "bytes32".
The “int_const” is internal type, and the compile can’t do the implicit conversion from it to “bytes32”, forcing the user to use bytes32(uint(1)) syntax.

Example #2:

uint[2] memory arr =  [1,2]

Stragely, the above line is rejected with error:
Type uint8[2] memory is not implicitly convertible to expected type uint256[2] memory

Here the compiler took the “int_const” type, and already casted it to the narrowest possible type, which is in this case uint8[]
The user is forced to use the following format:

uint[2] memory arr =  [uint(1),2]

in order to get compiled.

Example #3:

uint[] memory arr = [uint(1),2];

(note that we already applied mitigation #2 above for the uint8=>uint conversion)

The error in this case is: Type uint256[2] memory is not implicitly convertible to expected type uint256[] memory
You can’t initialize a dynamic array from a static array. That is true. The point is that there is no way to initialize a dynamic array, except using the cumbersome multiline code. the user is forced to do:

uint[] memory arr = new uint[](2); 
arr[0] = 1;
arr[1] = 2;

That’s true.

The compiler dev team’s assumption was probably that one would never really need to initialize a dynamic array with a known number of values (otherwise, why declare it dynamic to begin with?).

Unfortunately, the common use-case here is that sometimes, despite knowing the exact number of values in a given array, one nevertheless needs to pass the array to a function which doesn’t know that number (i.e., a function which takes a dynamic array as input).

BTW and FYI, the same syntax-problem (of not being able to initialize the values in a dynamic array upon declaration) also exists in other strongly-typed languages such as C and C++, so it’s not unique to Solidity in that sense, and I would therefore tend to speculate that the compiler dev team is not likely to support such syntax.

The actual annoyance here is that while in C and C++, static and dynamic arrays become identical when passed to other functions (as both of them decay to a pointer), this is not the case in Solidity, as these two array types actually have two different structures in memory; so you cannot use a static array when the target function takes a dynamic array as input, which means that you are left with this “cumbersome initialization” as your only option.

2 Likes

At least in C++, you have a generic type system strong enough that you can make an implicit conversion between such types (dynamic and static arrays, or even lists, of some member types)

Like I said, in C/C++, both decay to a memory pointer once you pass them to another function.
But again - just like Solidity, these languages do not support initializing the contents of a dynamic array upon declaration, so the same “inconvenience” applies in both cases.

In native languages, the length of a dynamic array is generally hidden from the user (i.e., from the developer). The practical solution is typically to store it right before the start of the array in memory, but it is generally a decision made by whoever implements the compiler, and there is no standard which dictates how it should be done.

The advantage here is that you can treat static arrays and dynamic arrays in the same way, and pass both of them to any function which takes a memory pointer as input.

The disadvantage is that in order to keep track of the length of an array, you must pass that length along with the array itself to every function which relies on that length.

In Solidity, it’s the exact opposite - the advantage and the disadvantage “switch sides”.