-
Notifications
You must be signed in to change notification settings - Fork 35
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
Normalize annotated types #228
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.
Good finding! I have a suggestion for simplification. Not sure it works (but I assume it does).
src/typechecker.erl
Outdated
normalize({ann_type, _, _} = Type, TEnv) -> | ||
Types = flatten_type(Type, TEnv), | ||
case merge_union_types(Types, TEnv) of | ||
[] -> type(none); | ||
[T] -> T; | ||
Ts -> type(union, Ts) | ||
end; |
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.
Why not simply this:
normalize({ann_type, _Ann, Type}, TEnv) ->
normalize(Type, TEnv);
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 doesn't work. The absform for an annotated type is {ann_type, _, List}
, where that third parameter is a list of things. And then normalize
does nothing on a list, it is expecting a tagged tuple, for all other possibilities (like the list), it passes them to the do-nothing clause at the bottom.
And parsing this list is precisely what flatten_type
does, so no need to reimplement it 🤷♂
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.
OK, I had a closer look now. The list is a fixed list of arguments, which is typical for these AST nodes. For ann_type
it's always 2 arguments, namely the variable name and the type. E.g. the A :: atom()
(where 55 is a line number) is represented as:
{ann_type,55,[{var,55,'A'},{type,55,atom,[]}]}
Using flatten_list and then taking the union of the returned types actually give us the type [Edit] Sorry, I missed the merge_union_types.A | atom()
instead of the expected atom()
.
My revised suggestion then:
normalize({ann_type, _Ann, [_Var, Type]}, TEnv) ->
normalize(Type, TEnv);
And I suggest adding a line for this in the existing test case for the normalize function. [Edit] Not really needed since there are other tests covering this.
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.
@zuiderkwast hey there, I'm doing as you suggested, and I haven't seen any infinite loop as described in #178, but on the other hand I'm having a hard time to follow all the discussion about annotated types like in #180 as well.
What are your thoughts about this?
I think it's the right thing to remove these in normalize, but see also #178. If we instead want to treat these as type variables with a subtype constraint, we should instead replace But that is not very likely, given that we actually replace the type variables defined using |
Codecov Report
@@ Coverage Diff @@
## master #228 +/- ##
=========================================
+ Coverage 83.82% 85.1% +1.28%
=========================================
Files 14 16 +2
Lines 2380 2498 +118
=========================================
+ Hits 1995 2126 +131
+ Misses 385 372 -13
Continue to review full report at Codecov.
|
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 good to me. I don't want to merge it however, as long as @josefs opposes it.
ann_type
was not normalised correctly.Solves #224, and perhaps some more stuff.