Hello,
Version: [email protected]
Story: I upgraded assemblyscript package to the last version and the code stops compiling. It does however with version 0.9.4
Summary: I went deeper and managed to find that extending an array returns a lot of errors on the compilation.
Code
export class MyArray extends Array<u8> { }
Compilation Log
ERROR AS202: Type 'i32' cannot be changed to type 'u8'.
store<T>(base + (<usize>lastIndex << alignof<T>()), changetype<T>(0));
~~~~~~~~~~~~~~~~
in ~lib/array.ts(370,57)
ERROR AS102: User-defined: "Cannot call flat() on Array<T> where T is not an Array."
ERROR("Cannot call flat() on Array<T> where T is not an Array.");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(499,7)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
size += child == 0 ? 0 : load<i32>(child, offsetof<T>("length_"));
~
in ~lib/array.ts(509,58)
ERROR AS220: Expression must be a compile-time constant.
size += child == 0 ? 0 : load<i32>(child, offsetof<T>("length_"));
~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(509,49)
ERROR TS2329: Index signature is missing in type 'u8'.
var byteLength = <usize>size << usize(alignof<valueof<T>>());
~
in ~lib/array.ts(513,59)
ERROR TS2558: Expected 1 type arguments, but got 0.
var byteLength = <usize>size << usize(alignof<valueof<T>>());
~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(513,43)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
var result = __alloc(offsetof<T>(), idof<T>());
~
in ~lib/array.ts(517,35)
ERROR AS203: Operation 'idof' cannot be applied to type 'u8'.
var result = __alloc(offsetof<T>(), idof<T>());
~
in ~lib/array.ts(517,46)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
store<i32>(result, size, offsetof<T>("length_"));
~
in ~lib/array.ts(518,39)
ERROR AS220: Expression must be a compile-time constant.
store<i32>(result, size, offsetof<T>("length_"));
~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(518,30)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
store<i32>(result, byteLength, offsetof<T>("byteLength"));
~
in ~lib/array.ts(521,45)
ERROR AS220: Expression must be a compile-time constant.
store<i32>(result, byteLength, offsetof<T>("byteLength"));
~~~~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(521,36)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
store<usize>(result, dataStart, offsetof<T>("dataStart"));
~
in ~lib/array.ts(522,46)
ERROR AS220: Expression must be a compile-time constant.
store<usize>(result, dataStart, offsetof<T>("dataStart"));
~~~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(522,37)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
store<usize>(result, __retain(dataStart), offsetof<T>("buffer"));
~
in ~lib/array.ts(523,56)
ERROR AS220: Expression must be a compile-time constant.
store<usize>(result, __retain(dataStart), offsetof<T>("buffer"));
~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(523,47)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
let childDataLength = load<i32>(child, offsetof<T>("byteLength"));
~
in ~lib/array.ts(534,55)
ERROR AS220: Expression must be a compile-time constant.
let childDataLength = load<i32>(child, offsetof<T>("byteLength"));
~~~~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(534,46)
ERROR AS203: Operation 'offsetof' cannot be applied to type 'u8'.
load<usize>(child, offsetof<T>("dataStart")),
~
in ~lib/array.ts(537,37)
ERROR AS220: Expression must be a compile-time constant.
load<usize>(child, offsetof<T>("dataStart")),
~~~~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(537,28)
ERROR TS2329: Index signature is missing in type 'u8'.
if (isManaged<valueof<T>>()) {
~
in ~lib/array.ts(546,27)
ERROR TS2558: Expected 1 type arguments, but got 0.
if (isManaged<valueof<T>>()) {
~~~~~~~~~~
in ~lib/array.ts(546,19)
ERROR TS2329: Index signature is missing in type 'u8'.
__retain(load<usize>(dataStart + (<usize>i << usize(alignof<valueof<T>>()))));
~
in ~lib/array.ts(548,77)
ERROR TS2558: Expected 1 type arguments, but got 0.
__retain(load<usize>(dataStart + (<usize>i << usize(alignof<valueof<T>>()))));
~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(548,61)
ERROR AS202: Type 'usize' cannot be changed to type 'u8'.
return changetype<T>(result);
~~~~~~~~~~~~~~~~~~~~~
in ~lib/array.ts(552,12)
WARNING AS232: Exported generic function or class has no concrete instances.
map<U>(fn: (value: T, index: i32, array: Array<T>) => U): Array<U> {
~~~
in ~lib/array.ts(312,3)
WARNING AS232: Exported generic function or class has no concrete instances.
reduce<U>(
~~~~~~
in ~lib/array.ts(337,3)
WARNING AS232: Exported generic function or class has no concrete instances.
reduceRight<U>(
~~~~~~~~~~~
in ~lib/array.ts(348,3)
Did you update as-pect to 0.4.x?
UPDATE Reproduced here
Quick workaround:
export class MyArray extends Uint8Array {
}
If it's possible
Or don't export MyArray. Currently problem relate to methods which return generic parameter T or accept extra parameter U like map<U> and reduce<U> / reduceRight<U>. So since U unresolved this cause to problems. Previous version (0.9.4) was simply unsound to such of edge cases
Thank you so much for your help. Just to be on the same page -> Is it some kind of bug? If so, could we expect to be fixed in one of the next releases?
If, however, this is the expected behavior, that means there is no way to extend Array, right?
You could extend Array
So this absolutely valid as you can see:
https://webassembly.studio/?f=j7a6mfqz1x
But not:
export function boo<T>(): void {} // `T` unresolved during export to JavaScript or other host
or
export class Foo<T> {} // `T` unresolved during export to JavaScript or other host
or
export class Boo extends Foo<u8> {
flat<U>(): u8 { return 0 } // `U` unresolved during export to JavaScript or other host
}
All that cases will print warnings
The reason why this is failing is that Array<u8> is exported (by means of exporting a subclass), so the compiler attempts to compile all of its methods, which it can't do for Array<u8>#flat because it is designed to emit a compile-time error when T is not an array. As such, this is not so much about the generic export but more about the compiler attempting to compile that specific method.
Given that this is failing in an unexpected way, I suggest changing this line to a throw instead and adding its error message here, so it becomes a runtime error (currently abort) instead of a compile time error, in turn fixing this issue as long as Array<u8>#flat is never called.
@dcodeIO It's just half of problem. I tried just overload CustomArray#flat and errors relate to flat is gone but we still have similar problems for Array#map<U> and Array#reduce<U> / Array#reduceRight<U>
However I'll try make PR which expose such changes. Will see what happens
@dcodeIO So #1353 fix only one case when:
export class MyArray extends Array<i32> {}
But we still have issues for this case (when type is u8 instead i32):
export class MyArray extends Array<u8> {}
Output:
ERROR AS202: Type 'i32' cannot be changed to type 'u8'.
store<T>(base + (<usize>lastIndex << alignof<T>()), changetype<T>(0));
in ~lib/array.ts(370,57)
Maybe something like
if (isReference<T>()) {
store<usize>(base + (<usize>lastIndex << alignof<T>()), 0);
} else {
store<T>(base + (<usize>lastIndex << alignof<T>()), 0);
}
Currently I just switched to store<T>(base + (<usize>lastIndex << alignof<T>()), <T>0)
But does this work on export class MyArray extends Array<string> {}?
You're right.
Should be fixed in next minor release
@MaxGraey and @dcodeIO, Thank you guys for your support!