Skip to content
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

Add optional argument to @inferred that relaxes the case of Nothing and Missing #27516

Conversation

haampie
Copy link
Contributor

@haampie haampie commented Jun 9, 2018

Brought up in #27511, where I want to test inference of an iterate call, yet @inferred is not applicable because the return type is Union{Nothing, T} by design.

The fix is to have @weakly_inferred, which does the same as @inferred, but relaxes the cases of nothing and missing:

> using Test
> v = [1, missing]
> @inferred v[1]
ERROR: return type Int64 does not match inferred return type Union{Missing, Int64}
> @weakly_inferred v[1]
1
> @weakly_inferred v[2]
missing
> @weakly_inferred rand([1, "str", nothing]) # note: might pass when `nothing` is returned!
ERROR: return type Int64 does not weakly match inferred return type Any
> using Test
> @inferred iterate(1:10)
ERROR: return type Tuple{Int64,Int64} does not match inferred return type Union{Nothing, Tuple{Int64,Int64}}
> @weakly_inferred iterate(1:10)
(1, 1)

If there's a better name for the macro, I'll be happy to change it.


Edit: final contribution in this PR is to add an optional type as argument to @inferred which is "white listed":

@inferred [Type] call()

@haampie haampie changed the title [RFC] Add @inferred-like test macro that passes for functions returning nothing or missing [RFC] Add @inferred-like test macro that relaxes the case of Nothing and Missing Jun 9, 2018
@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from a1fdab0 to a3294e6 Compare June 10, 2018 07:55
@nalimilan
Copy link
Member

Thanks! I agree it's useful, but would a syntax like @inferred Union{T,Missing} f(x) work instead?

@haampie
Copy link
Contributor Author

haampie commented Jun 10, 2018

Yeah, I think extending @inferred is better. What about @inferred f(x) T where the test passes if return_type <: T || return_type == typesubtract(inferred_type, T)?

@inferred iterate(...) Nothing
@inferred getdata(...) Missing
@inferred anything(...) Union{Nothing,Missing}

@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from a3294e6 to 1263dd4 Compare June 10, 2018 13:56
@StefanKarpinski
Copy link
Sponsor Member

Putting the type argument first seems more legible and intuitive to me.

@martinholters
Copy link
Member

If you need to explicitly give the expected return type, what's the advantage compared to a type assertion?

@haampie
Copy link
Contributor Author

haampie commented Jun 10, 2018

If you need to explicitly give the expected return type, what's the advantage compared to a type assertion?

You don't know what the inferred type minus the expected / allowed return type is. For example:

function iterate(it, state)
   some_condition && return nothing
   new_value = ...
   new_state = ...
   new_value, new_state
end

I know iterate(it, state) gets inferred to Union{Nothing, T} for some T I am not sure about, so I want to test whether a concrete value y = iterate(it, state) has type T (when it is not nothing).

With the old behaviour of @inferred you could test it by splitting the iterate function like this:

function produce_new_state_and_value(it, state)
  new_value = ...
  new_state = ...
  new_value, new_state
end

function iterate(it, state)
  some_condition && return nothing
  produce_new_state_and_value(it, state)
end

@inferred produce_new_state_and_value(someiterator, somestate)

but often these functions are just 3 lines long, and it wouldn't make sense to define a new function just to test inference. With this PR, you would just run

@inferred Nothing iterate(someiterator, somestate)

I think this test is very useful now that Union{Nothing, T} and Union{Missing, T} are not really considered type instabilities anymore.

@@ -21,7 +21,7 @@ export @test, @test_throws, @test_broken, @test_skip,

export @testset
# Legacy approximate testing functions, yet to be included
export @inferred
export @inferred, @weakly_inferred
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed since you're no longer defining it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@martinholters
Copy link
Member

Right, sorry, I had misinterpreted the proposal here. Carry on.

@haampie
Copy link
Contributor Author

haampie commented Jun 14, 2018

Is this ready to be merged? Then I could use it in #27511 :)

@ararslan
Copy link
Member

Yeah, looks good to me. Though perhaps we should rerun CI since it's been a couple days?

@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from 047b715 to dec2417 Compare June 14, 2018 20:08
@haampie
Copy link
Contributor Author

haampie commented Jun 15, 2018

Circleci is killed during the build, and Travis probably the same? Other look good.

@ararslan
Copy link
Member

The CI failures are doctest failures.

@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from dec2417 to 3379a94 Compare June 21, 2018 21:55
@haampie
Copy link
Contributor Author

haampie commented Jun 22, 2018

Fixed the doctest issue, things look good. Not sure why circleci is failing.

@haampie haampie mentioned this pull request Jun 24, 2018
@haampie haampie force-pushed the feature-test-inference-with-small-unions branch 3 times, most recently from e36a2e4 to 2264cdb Compare October 5, 2018 10:37
@haampie haampie changed the title [RFC] Add @inferred-like test macro that relaxes the case of Nothing and Missing Add optional argument to @inferred that relaxes the case of Nothing and Missing Oct 5, 2018
@nalimilan
Copy link
Member

Too bad this wasn't merged. Could you rebase it?

@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from 2264cdb to 01d8124 Compare December 21, 2018 21:10
@haampie
Copy link
Contributor Author

haampie commented Dec 21, 2018

Sure

@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from 01d8124 to fa19651 Compare December 21, 2018 21:12
@haampie haampie force-pushed the feature-test-inference-with-small-unions branch from fa19651 to a50a8ca Compare December 21, 2018 21:17
@haampie
Copy link
Contributor Author

haampie commented Dec 22, 2018

Error has to do with the maximum PR?

Error in testset Profile:
Test Failed at C:\projects\julia\julia-\share\julia\stdlib\v1.2\Profile\test\runtests.jl:34
  Expression: !(isempty(str))
Error in testset Profile:
Test Failed at C:\projects\julia\julia-\share\julia\stdlib\v1.2\Profile\test\runtests.jl:41
  Expression: !(isempty(String(take!(iobuf))))
Error in testset Profile:
Error During Test at C:\projects\julia\julia-\share\julia\test\testdefs.jl:20
  Got exception outside of a @test
  LoadError: ArgumentError: reducing over an empty collection is not allowed
  Stacktrace:
   [1] _empty_reduce_error() at .\reduce.jl:216
   [2] reduce_empty(::Function, ::Type) at .\reduce.jl:226
   [3] mapreduce_empty(::typeof(identity), ::Function, ::Type) at .\reduce.jl:251
   [4] _mapreduce at .\reduce.jl:305 [inlined]
   [5] _mapreduce_dim at .\reducedim.jl:308 [inlined]
   [6] #mapreduce#549 at .\reducedim.jl:304 [inlined]
   [7] mapreduce at .\reducedim.jl:304 [inlined]
   [8] _maximum at .\reducedim.jl:653 [inlined]
   [9] _maximum at .\reducedim.jl:652 [inlined]
   [10] #maximum#555 at .\reducedim.jl:648 [inlined]
   [11] maximum at .\reducedim.jl:648 [inlined]
   [12] print_flat(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Array{Base.StackTraces.StackFrame,1}, ::Array{Int32,1}, ::Int32, ::Profile.ProfileFormat) at C:\projects\julia\usr\share\julia\stdlib\v1.2\Profile\src\Profile.jl:398
   [13] flat(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Array{UInt64,1}, ::Dict{UInt64,Array{Base.StackTraces.StackFrame,1}}, ::Int32, ::Profile.ProfileFormat) at C:\projects\julia\usr\share\julia\stdlib\v1.2\Profile\src\Profile.jl:368
   [14] print(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Array{UInt32,1}, ::Dict{UInt64,Array{Base.StackTraces.StackFrame,1}}, ::Profile.ProfileFormat, ::Symbol) at C:\projects\julia\usr\share\julia\stdlib\v1.2\Profile\src\Profile.jl:149
   [15] (::getfield(Profile, Symbol("#kw##print")))(::NamedTuple{(:format, :sortedby),Tuple{Symbol,Symbol}}, ::typeof(Profile.print), ::Base.GenericIOBuffer{Array{UInt8,1}}) at C:\projects\julia\usr\share\julia\stdlib\v1.2\Profile\src\Profile.jl:134
   [16] top-level scope at C:\projects\julia\julia-\share\julia\stdlib\v1.2\Profile\test\runtests.jl:43

@nalimilan
Copy link
Member

Looks like problem with stack traces (probably not related)... :-/

@haampie haampie closed this Dec 23, 2018
@haampie haampie reopened this Dec 23, 2018
@haampie
Copy link
Contributor Author

haampie commented Dec 23, 2018

Tests are green now @nalimilan

@andreasnoack andreasnoack merged commit f713a4b into JuliaLang:master Jan 2, 2019
@KristofferC KristofferC added the needs news A NEWS entry is required for this change label Jan 2, 2019
@KristofferC
Copy link
Sponsor Member

Would be good with a news entry so people can more easily discover this :)

awadell1 added a commit to awadell1/Interpolations.jl that referenced this pull request Jan 21, 2021
Julia 1.0's cumsum doesn't work for iterators -> Collect first

@inferred didn't support Allowed types until v1.2
- Added in JuliaLang/julia#27516
- Add VERSION check and only run type stability checks if >= v1.2

.≈ does seem to be defined in v1.0 (Weird)
- Use separate Eq Checks if 1D or 2D (Don't need to map at all if 1D)
- Replace broadcasting with map -> Seems to work
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs news A NEWS entry is required for this change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants