-
Notifications
You must be signed in to change notification settings - Fork 212
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
Support where
clause and type equality constraint.
#4986
Conversation
where
clause.where
clause and type equality constraint.
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.
Overall this looks really good.
As discussed elsewhere, one big category of work that keeps this from being truly feature-complete is that we don't yet have a step to canonicalize the constraints on a generic declaration, which will both be important to producing consistent mangled names, and also required to detect whether or not two generic function signatures are equivalent (and should be considered redefinitions/redeclarations), or not (in which case they should be treated as distinct overloads).
// If this decl is defined in a where clause, store the source location of the where token. | ||
SourceLoc whereTokenLoc = SourceLoc(); | ||
|
||
bool isEqualityConstraint = false; |
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.
It really feels like the kind of constraint should be captured as distinct subclasses of GenericTypeConstraintDecl
. In the simplest case we'd just have TypeConformanceConstraintDecl
and TypeEqualityConstraintDecl
.
A more refined version of things (down the line) might be to have a distinct hierarchy to represent relations on types (e.g., TypeConformanceRelation
, TypeEqualityRelation
, SubtypeRelation
, etc.), and then have a GenericConstraintDecl
simply store the relation (or other proposition) it requires to be true.
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 thought about having separate subclasses for GenericTypeConstraintDecl but that will lead a much bigger change.
Having a single GenericTypeConstraintDecl with a getType() that returns the relation type seems easier to do.
inline bool isTypeEqualityWitness(Val* witness) | ||
{ |
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.
If we have the model proposed above where we use a distinct hierarchy for type relations, then those relations (and other propositions) would be the type of values that satisfy them. In that case, the isTypeEqualityWitness(w)
query would amount to as<TypeEqualityRelation>(w->getType())
. That change would enable this query to also return the type-equality relationship that w
is witnessing, which clients of this query probably want to know.
|
||
// A placeholder witness for the fact that two types are equal. | ||
INST(TypeEqualityWitness, TypeEqualityWitness, 2, HOISTABLE) | ||
|
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 we get around to being more formal with our type system, we may find that we need more nuance here and a type equality witness isn't just a no-op "placeholder."
It really comes down to whether we are talking about identical types, or just equivalent types. If it is possible in our system to have two types T
and U
where each is a subtype of the other, but they are not identical, then those types are equivalent, and a witness to their equivalence would basically amount to a pair of witnesses: one for each of the subtype relations involved. Those subtype witnesses would in turn but usable for converting a value of type T
into one of type U
, and vice versa, which might not otherwise be possible for the IR codegen to synthesize.
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.
Because inheritance isn't really a thing right now in the language, such case won't arise. When we have general support of inheritance, then equivalence vs equality becomes relevant and we will need more formality about it.
Closes #4890.
This PR adds syntax for
where
clause and extended the generic syntax so that it can work more nicely with codebases that wish to share with C++.Generics can now be defined as:
Which is the same as
struct Vector<T, let N:int>
orstruct Vector<T, int N>
.Generic constraints can now be defined as trailing
where
clauses:In addition, this PR brings support for type equality constraints: