Struct A{} v.s. A()

Hi,

The following code (playground)

struct A ();

impl A {
    fn get(&self) -> [f64; 1] { [0.] }
}

fn main() {
    for _ in A().get() {}
}

compiles fine but the slight modification (playground)

struct A {}

impl A {
    fn get(&self) -> [f64; 1] { [0.] }
}

fn main() {
    for _ in A{}.get() {}
}

doesn't (I have to write (A{}.get()) for it to work). I'm a bit surprised by this discrepancy. Is it simply a limitation of the parser or is there a more fundamental reason? (Of course, I could make get a pure function but, in my real case, it comes from A implementing some trait...)

Have a nice WE,
Christophe

It can also be recognized as

for _ in A{

}
.get()
//    ^error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
{

}

So to disambiguate, (A{}).get() like (A{}.get()), which is called grouped expression or parenthesized expression, would be a choice too.

1 Like

Of course! Should stop working so late! :face_with_spiral_eyes: Thanks.

Conditional blocks (for ... in _, while _, if _) all seem to have this "Expression except struct expression" grammar, probably because of ambiguity the following block.

For the empty A {}, you could make your own const A but... probably I'd say just #[derive(Default)] and call A::default() instead.

Now let's look at why the tuple struct works...


With the first, struct A() also creates a constructor function (or function-like [1]), fn A() -> A, and you're [2] calling that function. It chains together like you're use to functions doing.

So this also doesn't work (only the type is aliased, not the constructor):

struct T();
type U = T;

fn main() {
    for _ in U().get() {}
}

But this also does:

fn main() {
    for _ in (U {}).get() {}
}

Unit structs similarly create a const (or const-like) value.


  1. I'm not thinking of any differences from a typical function item off the top of my head, but there may be some ↩︎

  2. notionally at least ↩︎

3 Likes

Is there a typo here? Changing to for _ in T().get() {} seems to compile just fine.

No typo, it's a demonstration via type alias that the tuple type constructor is not $type (...), it's a function item [1].


  1. or so ↩︎

2 Likes

Ah yep, I see what you mean. Another example would be using const U: fn() -> T = T.

2 Likes