Short answer: You need to use angle brackets: <[usize; 2]>::foo()
.
Long answer:
If you'll look in the reference, you'll see the syntax:
CallExpression :
Expression (
CallParams? )
Inside Expression, you have PathExpression. There are two kinds of PathExpression s: PathInExpression and QualifiedPathInExpression. PathInExpression is a simple path of the form a::b::c::<generics>::d::<generics>
etc.. This is what you use when you type e.g. String::new()
or String::from("abc")
.
QualifiedPathInExpression, on the other hand, has the form QualifiedPathType (::
PathExprSegment)+, or in simple words, QualifiedPathType followed by one or more instances of two colons then PathExprSegement. PathExprSegment is defined as a name (identifier) optionally followed by two colons and generics: i.e., foo
or foo::<a, b, c>
.
And what is QualifiedPathType ? It is defined as <
Type (as
TypePath)? >
, or a type enclosed in angle brackets, optionally followed by as
and a TypePath, which is very similar to PathExpression with some differences.
Type is any Rust type syntax: a path (e.g. a::b<generics>
or a::b::<generics>
, trait objects (dyn Trait
), impl Trait
, tuples ((T1, T2, T3, ...)
), arrays ([T; N]
), slices ([T]
), references (&T
or &mut T
, potentially with a lifetime), and more.
All of this means that when you call a method, unless the method type is a simple path - that is, has the form a::b::c
, potentially with generics, you must enclose the type in angle brackets - <Type>::method()
. That includes arrays, slices, references, tuples, function pointers (fn(Args) -> Ret
), and more. [usize; 2]::foo()
is not a valid Rust syntax, only <[usize; 2]>::foo()
is.
Of course, there is another reason to use this form: UFCS (Universal Function Call Syntax). When you want to specify the trait (usually for disambiguition), you must use the form <Type as Trait>::method()
(this is the "(as
TypePath)?" we saw).