-
Notifications
You must be signed in to change notification settings - Fork 28
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
test_unbound_args: add a functionality to ignore specific methods #316
base: master
Are you sure you want to change the base?
test_unbound_args: add a functionality to ignore specific methods #316
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #316 +/- ##
==========================================
- Coverage 74.90% 74.86% -0.04%
==========================================
Files 11 11
Lines 761 764 +3
==========================================
+ Hits 570 572 +2
- Misses 191 192 +1 ☔ View full report in Codecov by Sentry. |
The ability to ignore specific methods when testing for unbound arguments would be helpful. |
New `tups_to_mat` function results in unbound type parameters because of `Vararg`, trying to fix. See [Aqua.jl #316](JuliaTesting/Aqua.jl#316) and [#86](JuliaTesting/Aqua.jl#86).
New `tups_to_mat` function results in unbound type parameters because of `Vararg`, trying to fix. See [Aqua.jl #316](JuliaTesting/Aqua.jl#316) and [#86](JuliaTesting/Aqua.jl#86).
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.
Thanks for working on this. Adding exceptions is indeed something that each of the test functions should have. Some detailed comments below
src/unbound_args.jl
Outdated
unbounds = detect_unbound_args_recursively(m) | ||
for i in ignore | ||
# i[2:end] is empty if length(i) == 1 | ||
ignore_signature = Tuple{typeof(i[1]),i[2: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.
This approach unfortunately does not work for callable objects.
Please make sure that this also works for cases like
struct S{U}
s::U
end
(::S{U})(::NTuple{N,T}) where {N,T,U} = (N,T,U)
(::S{U})(::Tuple{}) where {U} = (0,Any,U)
and include such an example in the tests
All done! |
src/unbound_args.jl
Outdated
callable, args = i[1], i[2:end] # i[2:end] is empty if length(i) == 1 | ||
|
||
# the type of the function is the function itself if it is a callable object | ||
callable_t = callable isa Function ? typeof(callable) : callable |
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.
Hmm, I thinks this still isn't quite what we want here.
For custom structs, say struct S end
, there are both function signatures containing S
and Type{S}
(which isn't even quite typeof(S)
), since the former is for callable objects and the latter for constructors.
Furthermore, there are subtypes of Function
, that are not a singleton type of function xxx
, e.g. Base.ComposedFunction
.
Maybe you have an idea that makes all of these cases work. If not, I think we just need the user to specify the exact signature, i.e. foo(x::Int, y::Float64)
as (typeof(foo), Int, Float64)
.
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.
Ah, I understand now. Thank you very much for your patience. After some research, I can't find any way to be 100% sure that we are dealing with a "simple" method.
But specifying the exact signature requires some knowledge from the user. To help the user, I think adding what method.sig returns in the error message can be a good idea. For example from this:
Unbound type parameters detected:
[1] f(x) where T @ Main.Foo ~/projets/forks/Aqua/Aqua.jl/a.jl:15
[2] (::Main.Foo.S{U})(::NTuple{N, T}) where {N, T, U} @ Main.Foo ~/projets/forks/Aqua/Aqua.jl/a.jl:8
[3] Main.Foo.S(::NTuple{N, T}) where {N, T} @ Main.Foo ~/projets/forks/Aqua/Aqua.jl/a.jl:11
to this:
Unbound type parameters detected:
[1] f(x) where T @ Main.Foo ~/projets/forks/Aqua/Aqua.jl/a.jl:15
signature: Tuple{typeof(Main.Foo.f), Any} where T
[2] (::Main.Foo.S{U})(::NTuple{N, T}) where {N, T, U} @ Main.Foo ~/projets/forks/Aqua/Aqua.jl/a.jl:8
signature: Tuple{Main.Foo.S{U}, NTuple{N, T}} where {N, T, U}
[3] Main.Foo.S(::NTuple{N, T}) where {N, T} @ Main.Foo ~/projets/forks/Aqua/Aqua.jl/a.jl:11
signature: Tuple{Type{Main.Foo.S}, NTuple{N, T}} where {N, T}
What do you think about that?
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 am not a fan of requiring 3x of vertical space. Instead, I think we could make a function public that returns the list of methods, so that a user can query this for the signature themselves. But I would put that to a follow-up PR.
For this PR, it would be great if you could do the small adaptions needed for this, and adapt the docstring as well.
…est_unbounds_args
With this PR, it is now possible to ignore some methods, given their signature. For example, taking the false positive in #86:
It is possible to disable the false positive with:
This specific example has been added in the unit tests.
To improve flexibility, the possibility to call directlyAqua.test_unbound_args(unbounds_args)
whereunbounds_args
is a collection of methods (probably got withTest.detect_unbound_args
) is also added.