-
Notifications
You must be signed in to change notification settings - Fork 24
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
Implement method parsing and type checking (closes #9) #22
Conversation
Methods of polymorphic classes are now typed correctly. Record field names now use `Var`s instead of plain strings to track locations. Field order in outputs are shuffled and seem unstable. Potentially due to the use of `Map` instead of `SortedMap` in ConstraintSolver.
Also included field names in the `children` of `Sel`s, which was made possible by changing field names to `Var`s in the last commit.
Broken due to polarity of `TypeRef`s in `ConstraintSolver.extrude`. Deduplicated `Typer.MethodDef` with `MethodDef`.
Fixed more polymorphism issues, which requires implementing bounds on rigidified variables.
Minor improvements
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 amazing, thanks!
However, I've outlined several places where the code seems unclear or needs some documentation/refactoring. Let's make sure to fix these before the merge.
val decls = newMthDecls(tn.name) | ||
val defs = newMthDefs(tn.name) | ||
val rigidSubsMap = ctx.getTargsMaps(td.nme.name, "").getOrElse(Map.empty).collect { | ||
case s -> (tv: TypeVariable) => tv -> freshenAbove(ctx.lvl, tv, 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.
How can it be okay to filter out only the cases where the mapped value is a TypeVariable
? That's very fishy. Couldn't it be a ProxyType
at some point (maybe not now, but if the code base changes in the future)? Or an application Id[X]
of the type Id[T] = T
type? If we're indeed only interested in type variables here, this should be expressed in the type, to make sure we're not messing up, and for documentation.
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.
targsMaps
store the mapping from type parameters to the dummy TypeVariable
s, and to the rigidified TraitTag
a when typing methods. It was originally just a map to TypeVariable
s before I realized the class type parameters should be rigidified when typing methods.
I couldn't come up with a way to express this invariant in the type. I tried to use TypeVariable \/ TraitTag
, but it would require a use of asInstanceOf
, as freshenAbove
returns a SimpleType
even when called directly with a TypeVariable
. For now I have added 3 die
statements before I can come up with a better solution.
I think your worry about the other cases came from nested TypeRef
s or ProxyType
s in the body. They are in fact not handled by this map, but by the subsMap
a few lines below. The TypeVariable
s we are collecting are the dummy type arguments created when typing the body of the TypeDef
. The actually applied type arguments are on the rhs of subsMap
. I believe it is handling nested AppliedType
s properly, as they would be typed as TypeRef
s by targsAppOf
(formerly targsMapOf
. I am running out of names...).
However, as I was writing tests to test this out, I discovered that nested type arguments are not typed correctly, even in the mlscript
branch:
class Foo[A]: { value: A }
class Bar[A]: Foo[Foo[A]]
//│ Defined class Foo
The TypeDef
of Bar
is not registered to the context, even though no error are emitted. I believe this is due to checkRegular
returning 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.
Okay, thanks for the explanation. Now I understand what you are doing, although I don't really agree with how it's done. See my other comment #22 (comment) for an idea to make the whole thing more functional, relying on computing the relevant information once, at the right place. We'd simply pass that relevant info along with each type definition being processed (instead of storing it in the context through the weird targsMaps
mutable map), so that we can later perform subsumption checking after typing methods. Does that make sense to you?
Cache results of `allBaseClasses` in the `Ctx`. Renamed type provenance for type definitions. Added comments for documentation and `die` statesments to express invariants... Changed the use of empty strings in `Ctx.targsMaps` to options for clarity.
I think we can merge this, after you've addressed #22 (comment) and #22 (comment). Not sure why the CI is failing, though. |
The CI was failing because of my parallel bug fix in 199e937 |
Oh and also the selection-typing part should be improved as we discussed: https://github.com/hkust-taco/mlscript/pull/22/files#diff-09ce6a8849c3c07173c504d6966f025cfa3338fa80afedecb4e77c6c013d50d3R660 |
Fix method override checking Prohibit inheritence from type aliases
Addressed in bc397a9 |
Okay thanks, that's really good work! The |
Implemented:
this
identifier with shadowing semantics in method definitionsIssues:
ConstraintSolver.extrude
does not handle the polarity of type variables inTypeRef
sDiffTests
outputs the defined method type for methods declaration if the same method is both declared and defined in the class