-
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
Allow overriding types for other modules in prelude #193
Conversation
With this change, we're also not using the remote spec syntax which is not supported in OTP anymore.
Codecov Report
@@ Coverage Diff @@
## master #193 +/- ##
==========================================
- Coverage 84.68% 84.31% -0.38%
==========================================
Files 13 13
Lines 2253 2263 +10
==========================================
Hits 1908 1908
- Misses 345 355 +10
Continue to review full report at Codecov.
|
This is the follow-up to #191, as suggested by @gomoripeti in #187 (comment). I used the syntax |
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.
great job 👍
src/gradualizer_db.erl
Outdated
FormsByModule), | ||
%% Mark the just overridden modules as not yet loaded, to make sure they | ||
%% are loaded on demand | ||
State1#state{loaded = Loaded#{gradualizer_prelude => 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.
hah, nice
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.
Having thought about this a little more, I'm not a huge fan of the file format here. Each spec cannot be understood in isolation. In order to understand what module a spec belongs to we have to work our way backwards in the file until we get to an override_module
directive. This makes the file format stateful in a way that I think is unnecessary.
@Zalastax had a suggestion in #187 to rewrite the specs as atoms so erlang:apply
would become 'erlang:apply'
. I think that's clearer and more preferable. Each spec can be understood in isolation that way.
That's a good point @josefs. The -type 'lists:deep_list'(A) :: [A | deep_list(A)].
-spec 'lists:flatten'(deep_list(A)) -> [A]. Here, because of the -type 'lists:deep_list'(A) :: [A | 'lists:deep_list'(A)].
-spec 'lists:flatten'('lists:deep_list'(A)) -> [A]. ...but then we'd obviously have to handle this syntax in a lot more places. The beauty of the An alternative would be to have one file per module we want to override, e.g. |
I like the idea of having one file per overridden module. We've already talked about splitting up this module anyway so that seems like a really nice solution actually! |
One more thing we could consider when defining the format of the override file is that in the future users could also define their own override files (eg for 3rd party libs). In that case I think its more convenient to allow a single file to override let's say 3 specs each from 3 different libs. Similar to a single dialyzer.ignore file. In that example it would be a bit less convenient to create 3 files for 3 modules each with only 1 function. But I also agree the prelude file grew too large so it makes sense to split it up and support multiple override files. |
@gomoripeti yes, if we allow users to override libraries in the future it'd be somewhat less convenient to have one file per overridden module. Are you arguing that this inconvenience is a killer and that we should allow multiple overridden modules per file? |
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.
Making a feature easy to explain is a high priority for me so I want us to go for split files. Users won't complain over having to split their overrides and split files is more intuitive.
We can allow users so specify their own prelude directories, $ gradualizer --prelude-dir ~/my/prelude -pa xyz -- files_to_check` Such dir can have the same structure, i.e. one file per module to override stuff for (e.g. lists.erl). Many small files? Who cares? It's a simple interface. Maybe we should consider a different suffix than |
Having a separate file suffix sounds like a good idea. I don't have a strong opinion on the actual name |
962b848
to
5afd85a
Compare
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.
00a455e
to
5e7e592
Compare
great work @zuiderkwast Im not sure if this is the case but if |
I don't trust the recompilation process anyway so I always delete the |
Right.... In a Makefile (let's say erlang.mk) it would be so easy to just add a dependency, like
I guess it needs to be addressed whenever someone adds or changes a prelude spec the next time. Otherwise users won't see any effect. Personally, I don't want to have hard dependencies on rebar, so I prefer a parse transform, but as long as rebar is used to build, a hook for at least invalidating the prelude would be good. (IMO gradualizer should be compatible with rebar as a plugin, etc. but preferably it should also be possible to build and use it with e.g. Mix or GNU Make or even Erlang
Wow, it really is a ridiculous build system then. IMO you can't expect people to |
I'm just going to add that I've lost a lot of time because the recompilation checker in rebar doesn't do the right thing. And I still have an issue when using dialyzer which I cannot seem to fix no matter how many files I delete. At this point I'm considering setting my laptop on fire to see if that helps. |
With this change, we're also not using the remote spec syntax
which is not supported in OTP anymore.