-
Notifications
You must be signed in to change notification settings - Fork 3k
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
dialyzer: add global variable binding (ERIERL-935) #7582
dialyzer: add global variable binding (ERIERL-935) #7582
Conversation
CT Test ResultsNo tests were run for this PR. This is either because the build failed, or the PR is based on a branch without GH actions tests configured. Results for commit d47e840 To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts
// Erlang/OTP Github Action Bot |
This is really nice little quality of live improvement. It would be great to have a note on https://www.erlang.org/doc/reference_manual/typespec.html saying this is possible since OTP xx. |
ada798a
to
2c5f4ed
Compare
46c9143
to
778fc0b
Compare
I have added some fixes so that (globally) bound type annotations cannot receive different types, which was something that we never took care of. Example: -spec id(X) -> X when
X :: string(),
X :: integer(). # notice that this was allowed This PR throws a linter error if such declaration of duplicate names with different types appear. This means that the following is an error, even if their internal structure represent the same thing: -spec id(X :: string()) -> X :: [char()]. The main reason for not detecting this type equivalence is that, if one really is going to duplicate the name, then it should be explicit that the types assigned to the same type annotation are identical. |
0890347
to
af74d58
Compare
9df2223
to
983c18b
Compare
983c18b
to
1718914
Compare
Make typed argument names and type variables global in their declaration. Before this PR, the following example would make the linter to complain about singleton variable used: ```erlang -foo(X :: integer()) -> X. foo(X) -> X. ``` So the linter would complain with the following message: ``` type variable 'X' is only used once (is unbound) ``` With this pull request, an argument name given to a type becomes bound globally and usable anywhere in the type specification. bound type annotations cannot receive different types, which was something that we never took care of. Example: ``` -spec id(X) -> X when X :: string(), X :: integer(). # notice that this was allowed ``` This PR throws a linter error if such declaration of duplicate names with different types appear. That said, in cases where there are multiple type annotations with different types, the PR simply performs type equality of the types (such as nominal typing), and does not try to infer their structure (structural typing). This means that the following is an error, even if their internal structure represent the same thing: ``` -spec id(X :: string()) -> X :: [char()]. ``` The main reason for not detecting this type equivalence is that, if one really is going to duplicate the name, then it should be explicit that the types assigned to the same type annotation are identical.
1718914
to
d47e840
Compare
We agreed that annotated variables can only be defined once. That is, the PR needs to be updated to reflect that the following is a linter error: -spec id(X :: string()) -> X :: string(). Annotated variables can only be defined once. |
with this commit, the linter rejects annotated variables that have the same type: ```erlang -spec id(X :: term()) -> X :: term(). ``` the example above will be rejected.
53ad5c4
to
5d09cb9
Compare
Wrong naming scheme, superseeded by #7717 |
Make typed argument names and type variables global in their declaration.
Before this PR, the following example would make the linter to complain about singleton variable used:
So the linter would complain with the following message:
With this pull request, an argument name given to a type becomes bound globally and usable anywhere in the type specification.