What type is [u16]?

In tiff crate, to encode tags and their values, there's this trait tiff::encoder::TiffValue. In foreign type implementations, there's a list of [T] types. But what are they? These aren't sized arrays, nor vectors.

I create tiff encoder, then I access the DirectoryEncoder, that encodes tags, then I try writing a tag with write_tag method:

let te = TiffEncoder::something...
let directory = te.image_directory()?;
let geokey: Vec<u16> = vec![1, 1, 0, 7, 1024, 0, 1, 1, 1025, 0, 1, 1, 1026, 34737, 25, 0, 2049, 34737, 7, 25, 2054, 0, 1, 9102, 3072, 0, 1, 3857, 3076, 0, 1, 9001];
directory.write_tag(Tag::GeoKeyDirectoryTag, &geokey);
                                             ^^^^^^^

The error is that my geokey does not implement TiffValue trait. I tried both vector, Vec<i16>, and array, in this case it's [u16; 32]. I also tried passing each of these by reference. Nothing works.

So, what is [u16] type?

these are called slice types, they don't have known size at compile time:

1 Like

Oh, didn't know there's a seprate notation for this. I thought slices are &[T]. I changed the parameter to &geokey[..], and it worked, thanks!

Those are slice references, but which are colloquially also just called slices which may lead to confusion. slice references are fat pointers, whose size (not length though) is known at compile-time.

The slice notation is often used in trait implementations when you implement a trait whose methods takes a reference to self so that &self becomes &[T] as I did here:

1 Like

Interesting pit-fall to notice. In an interface typed &[u16] the compiler would automatically convert the reference to vector or array you passed so the argument actually has slice type. See ops::Deref for Vec (note Target = [T] mentioning the type you're wondering about) and coerce the reference for arrays which does a similar thing.

But since the method has the generic signature with parameter type T: TiffValue, neither coercion nor auto-deref can be tried since type deduction happens first and that fixes the type to T= &Vec<u16> or T = &[u16; N], a reference itself. There is an impl for references but it is recursively defined based on the pointee's type and that's where the unfulfilled requirements Vec<u16>: TiffValue and [u16; 32]: TiffValue originate. But the error message makes this context of having removed the indirection and alternatives hard to grasp in the context of this trait.

Anyways, since the original error could be much more helpful in pointing you towards the right direction, I've tried to fix this upstream. Would be great if you could let me know if this would have been helpful: Add diagnostic helps for TiffValue proxy implementations by 197g · Pull Request #321 · image-rs/image-tiff · GitHub

2 Likes

I think this would have made something click in my head, and try a slice, sure. Great to hear!