lang: change const array to const roarray
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index e86124a..8b84472 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -561,10 +561,10 @@
 	"io_writer.position() u64",
 	"io_writer.since(mark: u64) slice u8",
 
-	"io_writer.copy_from_slice!(s: slice u8) u64",
+	"io_writer.copy_from_slice!(s: roslice u8) u64",
 	"io_writer.limited_copy_u32_from_history!(up_to: u32, distance: u32) u32",
 	"io_writer.limited_copy_u32_from_reader!(up_to: u32, r: io_reader) u32",
-	"io_writer.limited_copy_u32_from_slice!(up_to: u32, s: slice u8) u32",
+	"io_writer.limited_copy_u32_from_slice!(up_to: u32, s: roslice u8) u32",
 
 	// TODO: this should have explicit pre-conditions:
 	//  - up_to <= this.length()
@@ -630,14 +630,14 @@
 
 	"pixel_swizzler.prepare!(" +
 		"dst_pixfmt: pixel_format, dst_palette: slice u8," +
-		"src_pixfmt: pixel_format, src_palette: slice u8, blend: pixel_blend) status",
+		"src_pixfmt: pixel_format, src_palette: roslice u8, blend: pixel_blend) status",
 
 	"pixel_swizzler.limited_swizzle_u32_interleaved_from_reader!(" +
 		"up_to_num_pixels: u32, dst: slice u8, dst_palette: slice u8, src: io_reader) u64",
 	"pixel_swizzler.swizzle_interleaved_from_reader!(" +
 		"dst: slice u8, dst_palette: slice u8, src: io_reader) u64",
 	"pixel_swizzler.swizzle_interleaved_from_slice!(" +
-		"dst: slice u8, dst_palette: slice u8, src: slice u8) u64",
+		"dst: slice u8, dst_palette: slice u8, src: roslice u8) u64",
 	"pixel_swizzler.swizzle_interleaved_transparent_black!(" +
 		"dst: slice u8, dst_palette: slice u8, num_pixels: u64) u64",
 
@@ -688,8 +688,8 @@
 	"arm_neon_utility.make_u32x4_repeat(a: u32) arm_neon_u32x4",
 	"arm_neon_utility.make_u64x2_repeat(a: u64) arm_neon_u64x2",
 
-	"arm_neon_utility.make_u8x8_slice64(a: slice base.u8) arm_neon_u8x8",
-	"arm_neon_utility.make_u8x16_slice128(a: slice base.u8) arm_neon_u8x16",
+	"arm_neon_utility.make_u8x8_slice64(a: roslice base.u8) arm_neon_u8x8",
+	"arm_neon_utility.make_u8x16_slice128(a: roslice base.u8) arm_neon_u8x16",
 
 	// ---- arm_neon_uAxB.as_uCxD
 
@@ -732,7 +732,7 @@
 	"x86_sse42_utility.make_m128i_single_u32(a: u32) x86_m128i",
 	"x86_sse42_utility.make_m128i_single_u64(a: u64) x86_m128i",
 
-	"x86_sse42_utility.make_m128i_slice128(a: slice base.u8) x86_m128i",
+	"x86_sse42_utility.make_m128i_slice128(a: roslice base.u8) x86_m128i",
 
 	"x86_sse42_utility.make_m128i_zeroes() x86_m128i",
 
@@ -832,7 +832,7 @@
 	"x86_avx2_utility.make_m256i_repeat_u32(a: u32) x86_m256i",
 	"x86_avx2_utility.make_m256i_repeat_u64(a: u64) x86_m256i",
 
-	"x86_avx2_utility.make_m256i_slice256(a: slice base.u8) x86_m256i",
+	"x86_avx2_utility.make_m256i_slice256(a: roslice base.u8) x86_m256i",
 
 	"x86_avx2_utility.make_m256i_zeroes() x86_m256i",
 
diff --git a/lang/check/check.go b/lang/check/check.go
index a4c2b5f..c327efb 100644
--- a/lang/check/check.go
+++ b/lang/check/check.go
@@ -375,14 +375,14 @@
 
 	nLists := 0
 	for elemTyp := typ; ; {
-		if elemTyp.IsEitherArrayType() {
+		if dec := elemTyp.Decorator(); dec == t.IDRoarray {
 			if nLists == a.MaxTypeExprDepth {
 				return fmt.Errorf("check: type expression recursion depth too large")
 			}
 			nLists++
 			elemTyp = elemTyp.Inner()
 			continue
-		} else if elemTyp.Decorator() != 0 {
+		} else if dec != 0 {
 			return fmt.Errorf("check: invalid const type %q for %s", n.XType().Str(c.tm), qid.Str(c.tm))
 		}
 		break
diff --git a/std/bzip2/decode_bzip2.wuffs b/std/bzip2/decode_bzip2.wuffs
index e766ba1..9df73fd 100644
--- a/std/bzip2/decode_bzip2.wuffs
+++ b/std/bzip2/decode_bzip2.wuffs
@@ -26,7 +26,7 @@
 
 pub const DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE : base.u64 = 0
 
-pri const CLAMP_TO_5 : array[8] base.u8[..= 5] = [0, 1, 2, 3, 4, 5, 5, 5]
+pri const CLAMP_TO_5 : roarray[8] base.u8[..= 5] = [0, 1, 2, 3, 4, 5, 5, 5]
 
 pub struct decoder? implements base.io_transformer(
         bits   : base.u32,
@@ -755,7 +755,7 @@
 // The table below was created by script/print-crc32-magic-numbers.go with the
 // -reverse flag set.
 
-pri const REV_CRC32_TABLE : array[256] base.u32 = [
+pri const REV_CRC32_TABLE : roarray[256] base.u32 = [
         0x0000_0000, 0x04C1_1DB7, 0x0982_3B6E, 0x0D43_26D9, 0x1304_76DC, 0x17C5_6B6B, 0x1A86_4DB2, 0x1E47_5005,
         0x2608_EDB8, 0x22C9_F00F, 0x2F8A_D6D6, 0x2B4B_CB61, 0x350C_9B64, 0x31CD_86D3, 0x3C8E_A00A, 0x384F_BDBD,
         0x4C11_DB70, 0x48D0_C6C7, 0x4593_E01E, 0x4152_FDA9, 0x5F15_ADAC, 0x5BD4_B01B, 0x5697_96C2, 0x5256_8B75,
diff --git a/std/cbor/decode_cbor.wuffs b/std/cbor/decode_cbor.wuffs
index 3abccb8..ef6adb4 100644
--- a/std/cbor/decode_cbor.wuffs
+++ b/std/cbor/decode_cbor.wuffs
@@ -76,14 +76,14 @@
 
 // --------
 
-pri const LITERALS : array[4] base.u32[..= 0x1FF_FFFF] = [
+pri const LITERALS : roarray[4] base.u32[..= 0x1FF_FFFF] = [
         (base.TOKEN__VBC__LITERAL << 21) | base.TOKEN__VBD__LITERAL__FALSE,
         (base.TOKEN__VBC__LITERAL << 21) | base.TOKEN__VBD__LITERAL__TRUE,
         (base.TOKEN__VBC__LITERAL << 21) | base.TOKEN__VBD__LITERAL__NULL,
         (base.TOKEN__VBC__LITERAL << 21) | base.TOKEN__VBD__LITERAL__UNDEFINED,
 ]
 
-pri const TOKEN_LENGTHS : array[32] base.u8[..= 9] = [
+pri const TOKEN_LENGTHS : roarray[32] base.u8[..= 9] = [
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
diff --git a/std/crc32/common_crc32.wuffs b/std/crc32/common_crc32.wuffs
index 769b8dc..d4c6bb7 100644
--- a/std/crc32/common_crc32.wuffs
+++ b/std/crc32/common_crc32.wuffs
@@ -74,7 +74,7 @@
 
 // The table below was created by script/print-crc32-magic-numbers.go.
 
-pri const IEEE_TABLE : array[16] array[256] base.u32 = [[
+pri const IEEE_TABLE : roarray[16] roarray[256] base.u32 = [[
         0x0000_0000, 0x7707_3096, 0xEE0E_612C, 0x9909_51BA, 0x076D_C419, 0x706A_F48F, 0xE963_A535, 0x9E64_95A3,
         0x0EDB_8832, 0x79DC_B8A4, 0xE0D5_E91E, 0x97D2_D988, 0x09B6_4C2B, 0x7EB1_7CBD, 0xE7B8_2D07, 0x90BF_1D91,
         0x1DB7_1064, 0x6AB0_20F2, 0xF3B9_7148, 0x84BE_41DE, 0x1ADA_D47D, 0x6DDD_E4EB, 0xF4D4_B551, 0x83D3_85C7,
diff --git a/std/crc32/common_up_x86_sse42.wuffs b/std/crc32/common_up_x86_sse42.wuffs
index 7dce000..8fd3dcc 100644
--- a/std/crc32/common_up_x86_sse42.wuffs
+++ b/std/crc32/common_up_x86_sse42.wuffs
@@ -140,22 +140,22 @@
 //
 // The k6' constant from the Gopal paper is unused.
 
-pri const IEEE_X86_SSE42_K1K2 : array[16] base.u8 = [
+pri const IEEE_X86_SSE42_K1K2 : roarray[16] base.u8 = [
         0xD4, 0x2B, 0x44, 0x54, 0x01, 0x00, 0x00, 0x00,  // k1' = 0x1_5444_2BD4
         0x96, 0x15, 0xE4, 0xC6, 0x01, 0x00, 0x00, 0x00,  // k2' = 0x1_C6E4_1596
 ]
 
-pri const IEEE_X86_SSE42_K3K4 : array[16] base.u8 = [
+pri const IEEE_X86_SSE42_K3K4 : roarray[16] base.u8 = [
         0xD0, 0x97, 0x19, 0x75, 0x01, 0x00, 0x00, 0x00,  // k3' = 0x1_7519_97D0
         0x9E, 0x00, 0xAA, 0xCC, 0x00, 0x00, 0x00, 0x00,  // k4' = 0x0_CCAA_009E
 ]
 
-pri const IEEE_X86_SSE42_K5ZZ : array[16] base.u8 = [
+pri const IEEE_X86_SSE42_K5ZZ : roarray[16] base.u8 = [
         0x24, 0x61, 0xCD, 0x63, 0x01, 0x00, 0x00, 0x00,  // k5' = 0x1_63CD_6124
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Unused
 ]
 
-pri const IEEE_X86_SSE42_PXMU : array[16] base.u8 = [
+pri const IEEE_X86_SSE42_PXMU : roarray[16] base.u8 = [
         0x41, 0x06, 0x71, 0xDB, 0x01, 0x00, 0x00, 0x00,  // Px' = 0x1_DB71_0641
         0x41, 0x16, 0x01, 0xF7, 0x01, 0x00, 0x00, 0x00,  // μ'  = 0x1_F701_1641
 ]
diff --git a/std/deflate/common_consts.wuffs b/std/deflate/common_consts.wuffs
index dc0e1e8..e6e81a0 100644
--- a/std/deflate/common_consts.wuffs
+++ b/std/deflate/common_consts.wuffs
@@ -13,12 +13,12 @@
 // limitations under the License.
 
 // CODE_ORDER is defined in the RFC section 3.2.7.
-pri const CODE_ORDER : array[19] base.u8[..= 18] = [
+pri const CODE_ORDER : roarray[19] base.u8[..= 18] = [
         16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
 ]
 
 // REVERSE8 reverses the bits in a byte.
-pri const REVERSE8 : array[256] base.u8 = [
+pri const REVERSE8 : roarray[256] base.u8 = [
         0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,  // 0x00 - 0x07
         0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,  // 0x08 - 0x0F
         0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,  // 0x10 - 0x17
diff --git a/std/deflate/decode_deflate.wuffs b/std/deflate/decode_deflate.wuffs
index e97560f..0db616a 100644
--- a/std/deflate/decode_deflate.wuffs
+++ b/std/deflate/decode_deflate.wuffs
@@ -44,14 +44,14 @@
 //
 // Some trailing elements are 0x08000000. Bit 27 indicates an invalid value.
 
-pri const LCODE_MAGIC_NUMBERS : array[32] base.u32 = [
+pri const LCODE_MAGIC_NUMBERS : roarray[32] base.u32 = [
         0x4000_0000, 0x4000_0100, 0x4000_0200, 0x4000_0300, 0x4000_0400, 0x4000_0500, 0x4000_0600, 0x4000_0700,
         0x4000_0810, 0x4000_0A10, 0x4000_0C10, 0x4000_0E10, 0x4000_1020, 0x4000_1420, 0x4000_1820, 0x4000_1C20,
         0x4000_2030, 0x4000_2830, 0x4000_3030, 0x4000_3830, 0x4000_4040, 0x4000_5040, 0x4000_6040, 0x4000_7040,
         0x4000_8050, 0x4000_A050, 0x4000_C050, 0x4000_E050, 0x4000_FF00, 0x0800_0000, 0x0800_0000, 0x0800_0000,
 ]
 
-pri const DCODE_MAGIC_NUMBERS : array[32] base.u32 = [
+pri const DCODE_MAGIC_NUMBERS : roarray[32] base.u32 = [
         0x4000_0000, 0x4000_0100, 0x4000_0200, 0x4000_0300, 0x4000_0410, 0x4000_0610, 0x4000_0820, 0x4000_0C20,
         0x4000_1030, 0x4000_1830, 0x4000_2040, 0x4000_3040, 0x4000_4050, 0x4000_6050, 0x4000_8060, 0x4000_C060,
         0x4001_0070, 0x4001_8070, 0x4002_0080, 0x4003_0080, 0x4004_0090, 0x4006_0090, 0x4008_00A0, 0x400C_00A0,
diff --git a/std/gif/common_consts.wuffs b/std/gif/common_consts.wuffs
index e940023..8e3af00 100644
--- a/std/gif/common_consts.wuffs
+++ b/std/gif/common_consts.wuffs
@@ -39,26 +39,26 @@
 // accessed after all interlace stages are complete. Being the maximum base.u32
 // value means that, after all interlace stages are complete, dst_y will be set
 // to that maximum value (and therefore outside the frame rect).
-pri const INTERLACE_START : array[5] base.u32 = [0xFFFF_FFFF, 1, 2, 4, 0]
-pri const INTERLACE_DELTA : array[5] base.u8 = [1, 2, 4, 8, 8]
-pri const INTERLACE_COUNT : array[5] base.u8 = [0, 1, 2, 4, 8]
+pri const INTERLACE_START : roarray[5] base.u32 = [0xFFFF_FFFF, 1, 2, 4, 0]
+pri const INTERLACE_DELTA : roarray[5] base.u8 = [1, 2, 4, 8, 8]
+pri const INTERLACE_COUNT : roarray[5] base.u8 = [0, 1, 2, 4, 8]
 
 // ANIMEXTS1DOT0 is "ANIMEXTS1.0" as bytes.
-pri const ANIMEXTS1DOT0 : array[11] base.u8 = [
+pri const ANIMEXTS1DOT0 : roarray[11] base.u8 = [
         0x41, 0x4E, 0x49, 0x4D, 0x45, 0x58, 0x54, 0x53, 0x31, 0x2E, 0x30,
 ]
 
 // NETSCAPE2DOT0 is "NETSCAPE2.0" as bytes.
-pri const NETSCAPE2DOT0 : array[11] base.u8 = [
+pri const NETSCAPE2DOT0 : roarray[11] base.u8 = [
         0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30,
 ]
 
 // ICCRGBG1012 Is "ICCRGBG1012" as bytes.
-pri const ICCRGBG1012 : array[11] base.u8 = [
+pri const ICCRGBG1012 : roarray[11] base.u8 = [
         0x49, 0x43, 0x43, 0x52, 0x47, 0x42, 0x47, 0x31, 0x30, 0x31, 0x32,
 ]
 
 // XMPDATAXMP IS "XMP DataXMP" as bytes.
-pri const XMPDATAXMP : array[11] base.u8 = [
+pri const XMPDATAXMP : roarray[11] base.u8 = [
         0x58, 0x4D, 0x50, 0x20, 0x44, 0x61, 0x74, 0x61, 0x58, 0x4D, 0x50,
 ]
diff --git a/std/json/common_consts.wuffs b/std/json/common_consts.wuffs
index 110bc15..3b9c315 100644
--- a/std/json/common_consts.wuffs
+++ b/std/json/common_consts.wuffs
@@ -84,7 +84,7 @@
 //
 // If the element is zero then "\i" is invalid, or it is a special case, the
 // start of "\x12", "\u1234" or "\U12345678".
-pri const LUT_BACKSLASHES : array[256] base.u8 = [
+pri const LUT_BACKSLASHES : roarray[256] base.u8 = [
         // 0     1     2     3     4     5     6     7
         // 8     9     A     B     C     D     E     F
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x00 ..= 0x07.
@@ -129,7 +129,7 @@
 // LUT_QUIRKY_BACKSLASHES_QUIRKS is discussed in the LUT_BACKSLASHES comment.
 // The first element (index 0) is not used, but 8 is a round power of 2, so
 // enforcing index-in-bounds is a simple "&7" operation.
-pri const LUT_QUIRKY_BACKSLASHES_QUIRKS : array[8] base.u8[..= 0x0A] = [
+pri const LUT_QUIRKY_BACKSLASHES_QUIRKS : roarray[8] base.u8[..= 0x0A] = [
         0,
         // Uncommenting the following lines requires being able to define consts in
         // terms of other consts, which could be non-trivial to specify and
@@ -146,7 +146,7 @@
 // LUT_QUIRKY_BACKSLASHES_CHARS is discussed in the LUT_BACKSLASHES comment.
 // The first element (index 0) is not used, but 8 is a round power of 2, so
 // enforcing index-in-bounds is a simple "&7" operation.
-pri const LUT_QUIRKY_BACKSLASHES_CHARS : array[8] base.u8 = [
+pri const LUT_QUIRKY_BACKSLASHES_CHARS : roarray[8] base.u8 = [
         0x00, 0x07, 0x1B, 0x0A, 0x3F, 0x27, 0x0B, 0x00,
 ]
 
@@ -169,7 +169,7 @@
 //    UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
 //                  %xF4 %x80-8F 2( UTF8-tail )
 //    UTF8-tail   = %x80-BF
-pri const LUT_CHARS : array[256] base.u8 = [
+pri const LUT_CHARS : roarray[256] base.u8 = [
         // 0     1     2     3     4     5     6     7
         // 8     9     A     B     C     D     E     F
         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  // 0x00 ..= 0x07. C0 control codes.
@@ -269,7 +269,7 @@
 //
 // The bitmasks are used by the "expect" variable: what the next character
 // class can be. See EXPECT_ETC above.
-pri const LUT_CLASSES : array[256] base.u8[..= 0x0F] = [
+pri const LUT_CLASSES : roarray[256] base.u8[..= 0x0F] = [
         // 0     1     2     3     4     5     6     7
         // 8     9     A     B     C     D     E     F
         0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x00 ..= 0x07.
@@ -311,7 +311,7 @@
         // 8     9     A     B     C     D     E     F
 ]
 
-pri const LUT_DECIMAL_DIGITS : array[256] base.u8 = [
+pri const LUT_DECIMAL_DIGITS : roarray[256] base.u8 = [
         // 0     1     2     3     4     5     6     7
         // 8     9     A     B     C     D     E     F
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x00 ..= 0x07.
@@ -353,7 +353,7 @@
         // 8     9     A     B     C     D     E     F
 ]
 
-pri const LUT_HEXADECIMAL_DIGITS : array[256] base.u8 = [
+pri const LUT_HEXADECIMAL_DIGITS : roarray[256] base.u8 = [
         // 0     1     2     3     4     5     6     7
         // 8     9     A     B     C     D     E     F
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x00 ..= 0x07.
diff --git a/std/png/common_consts.wuffs b/std/png/common_consts.wuffs
index c4ef220..23d2807 100644
--- a/std/png/common_consts.wuffs
+++ b/std/png/common_consts.wuffs
@@ -57,7 +57,7 @@
 //  3: log2(y_stride)
 //  4: y_stride - y_offset - 1
 //  5: y_offset
-pri const INTERLACING : array[8] array[6] base.u8[..= 7] = [
+pri const INTERLACING : roarray[8] roarray[6] base.u8[..= 7] = [
         [0, 0, 0, 0, 0, 0],  // non-interlaced; xy_stride=1, xy_offset=0
         [3, 7, 0, 3, 7, 0],  // interlace_pass == 1
         [3, 3, 4, 3, 7, 0],  // interlace_pass == 2
@@ -70,7 +70,7 @@
 
 // LOW_BIT_DEPTH_MULTIPLIERS holds multipliers that convert D-bit values into
 // 8-bit values, for depth D.
-pri const LOW_BIT_DEPTH_MULTIPLIERS : array[8] base.u8 = [
+pri const LOW_BIT_DEPTH_MULTIPLIERS : roarray[8] base.u8 = [
         0,
         0b1111_1111,  // depth == 1
         0b0101_0101,  // depth == 2
@@ -83,7 +83,7 @@
 
 // LOW_BIT_DEPTH_NUM_PACKS holds the number of smaller-than-1-byte units that
 // are packed into each byte.
-pri const LOW_BIT_DEPTH_NUM_PACKS : array[8] base.u8 = [
+pri const LOW_BIT_DEPTH_NUM_PACKS : roarray[8] base.u8 = [
         0,
         8,  // depth == 1
         4,  // depth == 2
@@ -95,7 +95,7 @@
 ]
 
 // NUM_CHANNELS holds the number of channels for each valid color type.
-pri const NUM_CHANNELS : array[8] base.u8[..= 4] = [
+pri const NUM_CHANNELS : roarray[8] base.u8[..= 4] = [
         1,  // color_type == 0: Y
         0,
         3,  // color_type == 2: RGB
@@ -108,7 +108,7 @@
 
 // LATIN_1 converts from printable Latin-1 (ISO/IEC 8859-1) to UTF-8 (encoded
 // as little-endian u16). It was created by script/print-png-latin-1.go.
-pri const LATIN_1 : array[256] base.u16 = [
+pri const LATIN_1 : roarray[256] base.u16 = [
         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,