# How can I get this to infer types?

I’m having problems getting my code to infer a return type correctly. Here’s a MWE:

``````using Test
struct TwoTo{N} end
@inline t(g::Base.Generator{<:TwoTo{N}, F}) where {N,F} = ntuple(i->g.f(i+1), Val{N-1}())
f(r) = t(t(i for i in r) for j in r)
Test.@inferred f(TwoTo{3}())
# ERROR: return type Tuple{Tuple{Int64,Int64},Tuple{Int64,Int64}} does not match inferred return type Tuple{Tuple{Any,Any},Tuple{Any,Any}}
``````

If I change the definition of `t` to:

``````@inline t(g::Base.Generator{<:TwoTo{N}, F}) where {N,F} = ntuple(g.f, Val{N-1}())
``````

then type inference works (but the output is different, of course.)

I can’t figure out any way to wrap `g.f` in a function in a way that does not destroy type inference. Any help would be appreciated!

I think I’ve figured this out. If I change the code slightly:

``````using Test
struct TwoTo{N} end
@inline t(g::Base.Generator{<:TwoTo{N}, F}) where {N,F} = ntuple(i->g.f(i+1), Val{N-1}())
@inline u(g::Base.Generator{<:TwoTo{N}, F}) where {N,F} = ntuple(i->g.f(i+1), Val{N-1}())
f2(r) = t(u(i for i in r) for j in r)
Test.@inferred f2(TwoTo{3}())
``````

then it works. (Note that `u` is an exact copy of `t`, only with a different name.)
Apparently, type inference gives up when `t` calls itself recursively even though the function argument is different. I can see how this can be a reasonable heuristic. Now I just need to figure out a good way to get around it!

2 Likes
{"ft_lang_label":"__label__en","ft_lang_prob":0.61165696,"math_prob":0.89969933,"size":726,"snap":"2020-10-2020-16","text_gpt3_token_len":235,"char_repetition_ratio":0.11495845,"word_repetition_ratio":0.039215688,"special_character_ratio":0.30853996,"punctuation_ratio":0.17777778,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.99763936,"pos_list":[0,1,2],"im_url_duplicate_count":[null,null,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-02-22T01:16:42Z\",\"WARC-Record-ID\":\"<urn:uuid:4b74db64-6549-45fb-9546-81ff4e46c1bb>\",\"Content-Length\":\"13513\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:e2c95a65-5136-4726-a814-0920d6080776>\",\"WARC-Concurrent-To\":\"<urn:uuid:0556800b-f2bd-43fd-9e77-1057b4232d92>\",\"WARC-IP-Address\":\"72.52.80.20\",\"WARC-Target-URI\":\"https://discourse.julialang.org/t/how-can-i-get-this-to-infer-types/33617\",\"WARC-Payload-Digest\":\"sha1:7VRLB47I54QMVK43HLHHF5BZ6RDOUQUA\",\"WARC-Block-Digest\":\"sha1:W6MKO7DKZFVSMWX4UCZD5PDYKXWEF2ZP\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-10/CC-MAIN-2020-10_segments_1581875145621.28_warc_CC-MAIN-20200221233354-20200222023354-00397.warc.gz\"}"}