-
Notifications
You must be signed in to change notification settings - Fork 12
Add SP032 - Unique Generic Interface Parameters. #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you didn’t mean for this file to be part of the PR.
| ``` | ||
| It will be difficult for the compiler to find out who to blame for the duplication. | ||
|
|
||
| The free form extension feature was originally implemented as a workaround to absence of default interface method implementations. Now that Slang is now supporting default interface methods with [SP #030](030-interface-method-default-impl.md), this main use of free-form generic extensions now has a better substitute and should be deprecated instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was initially hopeful that this proposal may allow my specific use case:
public extension<U : IHashable, T : IArray<U>> T: IHashable
{
public uint64_t hash()
{
uint64_t h = 0;
for (int i = 0; i < this.getCount(); ++i)
h = hashCombine(h, this[i].hash());
return h;
}
}But reading this, it seems that this kind of usage would instead be fully deprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if you can just rely on ordinary function overload for this specific case:
public static uint64_t hash(int x) {...}
public static uint64_t hash(float x) {...}
public static uint64_t hash<T:IHashable>(T x) {...}
public static uint64_t hash<U:IHashable, T:IArray<U>>(T x) {...}
tangent-vector
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably the best approach to solving this particular problem that we can incorporate into the language any time soon.
Reading through this proposal, though, I also get the sinking feeling that maybe we have backed ourselves into a bit of a semantic corner with the way we think about conformances. The discussion here makes it clear that we've coupled ourselves strongly to the idea that in any given context a type has a finite and enumerable set of conformances, and that there will never be multiple distinct conformances of a given type to the same interface (the only thing being introduced here is that the "same"-ness check there ignores the arguments for any unique parameters).
In truth, though, the type system and also the IR for the most part don't care about uniqueness, enumerability, or even that there are finitely many conformances for a given type. A conformance is just a witness table, and a conformance introduced via a generic extension is just a generic that returns a witness table. There is no theoretical reason why a single generic extension cannot be instantiated more than once to synthesize conformances for a concrete type; that's a limitation borne from our implementation choices.
Still, this proposal is a practical path forward that works with our current implementation approach, and does not appear to road-block any more flexible (but expensive) solutions in the future.
|
|
||
| If we try to use an instance of `MyType` in a context that relies on the generic extension, the compiler cannot uniquely determine whether to apply `extension<int>` or `extension<float>`. The current behavior is to pick the first encountered specialization, which can lead to surprises. | ||
|
|
||
| However, there are many legitimate and important use cases for this kind of extension, particularly with interfaces that are conceptually unique per type, such as `IBuffer<T>`, `IArray<T>`, or `IGrid<int DIM>`. In these cases, a user knows that a type will never implement, for instance, both `IBuffer<int>` and `IBuffer<float>`. The current warning discourages these valid patterns and forces users into more verbose or duplicative code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you say that a user knows that a type will never conform to more than one specialization of the interface, I think there is some subtle ambiguity there about who the user is, and the meaning of what is being said depends on the difference.
If we are talking about the user who introduced the interface, then it might be better to say that they (reasonably) expect that a type will never conform to more than one specialization of their interface, but the problem at the heart of this proposal is that the user declaring the interface currently cannot truly know or enforce what they expect.
If we are talking about the user who defines a type that will implement such an interface, it is more reasonable to say that the user likely knows when their type will never implement more than one specialization of such an interface.
| ``` | ||
|
|
||
| The `unique` keyword introduces a new semantic rule: | ||
| **A type cannot have multiple conformances to an interface with a `unique` parameter that differ only by the argument to that `unique` parameter.** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems like the right way to define the constraint.
Until I read your text here, I was mistakenly thinking that the right semantics would be something like: if a type has two distinct conformances to different specializations of a generic interface with a unique parameter, both of those specializations must have equivalent generic arguments for that parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These rules would probably need to be revisited if/when we support user-defined generics with covariant or contravariant parameters.
No description provided.