Skip to content

Why do we use .Self instead of the binding name? #6026

@danakj

Description

@danakj

We use .Self to refer to the name of the binding from a facet type for the binding. This leaves us open to ambiguity: some .Self can refer to something else if you nest enough. But if you only nest a little bit, the .Self look like they refer to something else but they don't. This ended up surprising @zygoloid and @danakj in open discussion. In this example, the first two .Self refer to T, while the third does not, and could be said to refer to T.A, or to be ambiguous and an error.

T:! I(.Self) where .A = (I(.Self) where .A = I(.Self))

You can write a facet type in any place that accepts a type.

let Constant:! type = I(.Self) where .A = .Self;
Class as I(.Self) where .A = .Self;
fn F(B:! I(.Self) where .A = .Self);

.Self only makes sense in the binding case, which is also the only case where you have a name for the value which the facet type applies to. If we used the name instead, this would become immediately clear why you can't factor the facet type from the binding out into a comptime variable like Constant above:

fn F(B:! I(B) where .A = B);

As it is, it's weird that you can't factor out the facet type.

Notably, all three examples also have an implicit .Self reference hidden in the .A, but these .Self are an implementation detail for how we construct references to associated constants, and they are not pointed to the B in the same way.

For the explicit .Self, they are the same type as the B ultimately:

T:! I(.Self) where .A = .Self
U:! I(T) where .A = T

The T and U are interchangeable and inter-convertible, if not actually the same type (and we think they should be the same type).

So as different as .Self and B are during construction of the binding, they are really the same type, and using the same name would not be misleading. The things visible through B would change over the course of construction of the facet type, but the same is true for .Self now, as rewrite constraints can see constraints to the left of them.

Named constraints

Named constraints also have a .Self but it is the same as Self. So it's already possible to use the real name (Self in this case) in a named constraint, and .Self is redundant there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    leads questionA question for the leads team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions