-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
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.