Syntax for fully qualified calls to slice methods


#1

How do you use Universal Function Call Syntax with slices?
[]::<i32>::len(&[1]) and similar variants all give a syntax error.


As a (very silly) use case, let’s say that I have defined a trait like this:

trait MyLen {
    fn len(&self) -> usize;
}

impl<T> MyLen for T {
    fn len(&self) -> usize { 0 }
}

And then want to know the actual length of a slice I have. Using [1,2,3].len() will just use my custom len method and always return 0. Both [i32]::len and []::len are syntax errors, with the message:

error: no rules expected the token `::`

#2

Static methods expect a type to call from rather than a value.

The type of an array is [T; n], where n is the length of the array. The type of a slice is &[T], without the length.

So you should be able to call something like [i32; 3]::len() or <&[i32]>::len().

If you’re not sure why arrays are typed the way they are, and are curious, Rust by Example has a nice little summary about it. The docs also go into plenty of detail.


#3
assert_eq!(3, <[i32]>::len(&[1, 2, 3]);

#4

Heh, well there you go. So what exactly is [T]?

EDIT: Turns out it’s just a slice, but without the lifetime. So [T] is a type, just like &'a [T] is a type, but the former can’t be used as a function parameter because we don’t know how big it is.


#5

That’s where the Sized trait comes in, and things must be marked ?Sized to let dereferenced slices like this be allowed, roughly promising never to try to use that type by value.


#6

Aha, so you use angle brackets around the square brackets in this case. Thank you!

Are there any other cases where angle brackets are used like this? Or is it just a special case to differentiate between the type of a slice and a slice literal?

Also, where is this syntax documented?


#7

Neither of those works. The first gives a syntax error, the second will still call MyLen::len. See this playground for an example of this and a couple of other variants.


As a side note, was surprised that in the vector example, the native method is called, while in the slice case, my custom method is called:

vec!(1 , 2 , 3).len()      // == 3
[1,2,3].len()              // == 0

Until I realized that the issue can be resolved like this:

(&[1,2,3] as &[_]).len    // == 3

#8

Yeh I forgot to include the angle brackets when copying over. Coding on phones is hard :wink:

The Vec example is because Vec itself defines a method len, so it’s taking precedence over your trait method. See this gist