- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.7k
Inference for splatting numbers (and more) #27434
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
Conversation
| Same error across the board: This is interesting, because a) it somehow managed to build locally and b) even if inference gives a wrong result, bad things may happen, but invalid LLVM IR should not be among them AFAICT. | 
| Ok, a) resolved:  diff --git a/base/number.jl b/base/number.jl
index 89cec5169e..514747bed3 100644
--- a/base/number.jl
+++ b/base/number.jl
@@ -233,7 +233,8 @@ julia> widemul(Float32(3.), 4.)
 """
 widemul(x::Number, y::Number) = widen(x)*widen(y)
 
-iterate(x::Number, done = false) = done ? nothing : (x, true)
+iterate(x::Number) = (x, true)
+iterate(x::Number, ::Any) = nothing
 isempty(x::Number) = false
 in(x::Number, y::Number) = x == y
 is enough to make  | 
| Can anyone give me a clue how I can figure out what method is being compiled when that error is thrown? | 
| valtype = Any | ||
| break | ||
| end | ||
| if nounion.parameters[1] <: valtype && nounion.parameters[2] <: statetype | 
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.
Copy this conditional above? (or at least the nounion.parameters[2] <: statetype part of it). If the new statetype is narrower, this must have been an infinite iterator (or throws an error).
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.
True. However, for an infinite iterator, we get a slightly wider type then, e.g. Tuple{Char,Vararg{Char,N} where N} instead of Body::Tuple{Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Vararg{Char,N} where N} for splatting Iterators.repeated('a'). Probably doesn't matter. Or is your suggestion to return Any[Bottom} (instead of breaking out of the loop) then? While theoretically correct (or did I get something wrong?), that looks rather aggressive.
        
          
                base/number.jl
              
                Outdated
          
        
      | widemul(x::Number, y::Number) = widen(x)*widen(y) | ||
|  | ||
| iterate(x::Number, done = false) = done ? nothing : (x, true) | ||
| iterate(x::Number) = (x, 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.
Should never matter (after inference, inlining, or SROA), but constructing (x, nothing) would require 1 byte less space. Maybe use that instead?
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.
Yes. I've actually changed that locally to see whether it makes a difference with the failure in make julia-debug (which it doesn't), and realized that it might be better anyway.
|  | ||
| # simulate iteration protocol on container type up to fixpoint | ||
| function abstract_iteration(@nospecialize(itertype), vtypes::VarTable, sv::InferenceState) | ||
| tm = _topmod(sv) | 
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.
As implemented right now, this actually always uses Base, not _topmod(sv) to find iterate. We should probably redefine this as if isdefined(Main, :Base) || !isdefined(Main.Base, :iterate) || !isconst(Main.Base, :iterate) to be pedantic and precise about correctness here
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, will adjust then.
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.
Um, are you sure? If I look at e.g. Core.Compiler.append_any(1), it seems to be calling Core.Compiler.iterate. And that's what we want to reflect, no?
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 don’t think there’s any callers of Core.Compiler.append_any. The implementation of _apply right now always uses Base
| Ok, I've incorporated the comments locally (including returning Bottom for infinite iterators), but I'm struggling with the invalid LLVM IR when doing  with this debug info (excerpt): How do I figure out for which types this was specialized exactly? | 
a69650f    to
    df14e50      
    Compare
  
    | Ok, with #27609 in, this now seems to pass CI (Circle 64bit was killed (OOM?), Travis on OSX was hit by #26725). I've also addressed Jameson's remarks, so unless @nanosoldier  | 
| Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan | 
Exploit the fact that the (minimum) number of elements obtained from iteration can be derived from the types in certain cases and hence, a more exact type can be inferred for splatting them.
Letting the presence of a second argument alone decide whether iteration is done lets `abstract_iteration` determine that splatting a `Number` yields exactly one `Number`.
df14e50    to
    e086018      
    Compare
  
    | As I let this go a bit stale, @nanosoldier  | 
| Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan | 
| The logical next step would be eliding the call to  julia/base/compiler/ssair/inlining.jl Lines 793 to 794 in 2e168b5 
 iteratecalls injulia/base/compiler/ssair/inlining.jl Line 556 in 2e168b5 
 But I'm relatively clueless how to thread the information gathered during inference through to the inlining pass. If @Keno or @vtjnash can give me a hint, I might try to give it a shot. | 
Fixes #22291, closes #22292 (from where I've taken the tests).
But even more: