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

fix another case where we might return free TypeVar #48228

Merged
merged 8 commits into from
Apr 13, 2023
Merged

Conversation

vtjnash
Copy link
Sponsor Member

@vtjnash vtjnash commented Jan 11, 2023

Still one error caused here (this intersection is not satisfiable except by Union{})

julia> T=Tuple{Type{Q}, Q, Ref{Q}} where Q<:Ref;

julia> S=Tuple{Type{S}, Union{Ref{S}, Ref{R}}, R} where R where S;

julia> typeintersect(S,T)
Tuple{Type{Q}, Q, R} where {Q<:(Ref), R<:Ref{Q}}
                         
julia> typeintersect(T,S)
StackOverflowError

Original PR text:


We had an environment here that looked like while computing the upper bound for J{S} where S:

where S=T
where T
where I{T}
where J{S} where S

Then we started handling those, and filling in the values:

First replacing S with T, which creates a res of J{T}

where T
where I{T}
where J{S} where S

Then we handled T, which is also going to set wrap=0, so our result for J{T} will not be made into J{T} where T.

where I{T} (wrap 0)
where J{S} where S

Here we then had finished handling all the dependencies for J{S} where S, which resulted in an upper bound assignment of J{T}

where I{T}
where J{T}

Next, we handle I{T}, though it is now unused, so while we will make I{T} where T (via innervars) here for it, this goes unuesd.

And finally, we had our resulting clause:

where J{T}

But it is missing the where T, since I (from lhs) was discarded.

Thus we need to add that back now, when handling some innervars, if we see our term got duplicated to a higher part of the bounds before reaching this handling for its placement movement.

@N5N3
Copy link
Member

N5N3 commented Feb 16, 2023

Adding too many inner-vars might not be a good idea.
As inner-var is not in stenv and would be ignored during subtyping.
But the "wrapping" change seems reasonable. We'd better assign the inner-var with the outmost in-env-var rather than wrap it many times.
Some of the current PkgEval error should be fixed with that.

@N5N3 N5N3 added the types and dispatch Types, subtyping and method dispatch label Feb 16, 2023
@vtjnash vtjnash marked this pull request as ready for review March 16, 2023 18:55
@vtjnash vtjnash added the needs pkgeval Tests for all registered packages should be run with this change label Mar 16, 2023
@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Mar 16, 2023

Upon review, I think we should attempt to go ahead with this now. It turns out the intersection in the tests that stackoverflows, would have instead become incorrect if it was simplified:

julia> T = Tuple{Type{Q}, Q, Ref{Q}} where Q<:Ref;

julia> S = Tuple{Type{S}, Ref{S}, R} where R where S;

julia> typeintersect(S,T)
Union{}

julia> typeintersect(T,S)
Union{}

julia> I = Tuple{Type{Ref}, Ref{Ref}, Ref{Ref}}; I<:T, I<:S
(true, true)

In particular, I believe I = Tuple{Type{Ref}, Ref{Ref}, Ref{Ref}} may be the one-true-intersect for these types. So I think that, on net, this PR seems to likely be an improvement.

@N5N3
Copy link
Member

N5N3 commented Mar 17, 2023

@nanosoldier runtests()

@N5N3
Copy link
Member

N5N3 commented Mar 17, 2023

In particular, I believe I = Tuple{Type{Ref}, Ref{Ref}, Ref{Ref}}

I think there have been some discussion for this pattern.
As you pointed out in #38245 (comment), perhaps we should return Tuple{Type{T}, Ref{T}, Ref{T}} where {T<:Ref} in this case.

@nanosoldier
Copy link
Collaborator

Your package evaluation job has completed - possible new issues were detected.
A full report can be found here.

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Mar 18, 2023

I see that did quite poorly

@vtjnash vtjnash removed the needs pkgeval Tests for all registered packages should be run with this change label Mar 20, 2023
@vtjnash vtjnash marked this pull request as draft March 20, 2023 17:47
@vtjnash

This comment was marked as resolved.

@nanosoldier
Copy link
Collaborator

Your package evaluation job has completed - possible new issues were detected.
A full report can be found here.

@N5N3
Copy link
Member

N5N3 commented Mar 28, 2023

Looks like most of the problem get fixed.

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Mar 28, 2023

Yes, looks like we are down to 2 new internal failures, and 3 fixed subtyping results (causing ambiguity tests to fail)

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Apr 5, 2023

I think we are starting to converge here towards something usable. It looks like one of N5N3's tests successfully demonstrated why the innervars update was needed (which I had previously commented out, in the absence of a test case for it). The failing package test inference looks something like:

(gdb) p jl_(a)
Tuple{typeof(Phylo.API._getnode), T, N} where T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL}) where N where NL where RT

(gdb) p (void*) jl_call2((void*) jl_get_global(jl_base_module, (void*)jl_symbol("show")), (void*) jl_get_global(jl_core_module, (void*)jl_symbol("stdout")), types)
Tuple{typeof(Phylo.API._getnode), Union{Union{LinkTree{RT3, NL, N, B} where {RT2<:Union{RT, RT1}, N<:Union{LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}, LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}}, B<:Union{LinkBranch{RT, NL}, LinkBranch{RT2, NL}, LinkBranch{RT1, NL}}, RT3<:Union{RT, RT2, RT1}}, LinkTree{var"#s63", NL, N, B} where {var"#s63"<:Union{RT, RT1}, N<:Union{LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s63", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s63", NL}}, LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}}, B<:Union{LinkBranch{RT, NL}, LinkBranch{var"#s63", NL}, LinkBranch{RT1, NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}, Union{LinkTree{RT2, NL, N, B} where {RT2<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{RT2, NL}}}, LinkTree{var"#s63", NL, N, B} where {var"#s63"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s63", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s63", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s63", NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}, Union{LinkTree{var"#s65", NL, N, B} where {var"#s65"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s65", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s65", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s65", NL}}}, LinkTree{var"#s63", NL, N, B} where {var"#s63"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s63", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s63", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s63", NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}} where NL<:Missing, Missing}

caused by inference of
branchroute(Phylo.LinkTree{Phylo.OneRoot, String, Phylo.LinkNode{Phylo.OneRoot, String, Base.Dict{String, Any}, Phylo.LinkBranch{Phylo.OneRoot, String, Base.Dict{String, Any}, Float64}}, Phylo.LinkBranch{Phylo.OneRoot, String, Base.Dict{String, Any}, Float64}, Base.Dict{String, Any}}, String, String)
from branchroute(T, N, N) where {RT, N, T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL} where N<:Phylo.AbstractNode{RT, NL} where NL)}

where we eventually get stuck (recurse infinitely) on something like the intersection of these values:

RT<:Union{Phylo.Rooted, RT<:Phylo.Rooted}
Union{Phylo.Rooted, RT}

(Aside: it also makes me feel very uncomfortable that inference is producing that mess in the first place also. This might end up being worked around by #49167, or something like that PR.)

src/subtype.c Outdated
// the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are
// iterating 2 trees at once), so once we set `wrap`, there might remain other branches
// of the type walk that now may have incomplete bounds: finish those now too
jl_varbinding_t *btemp = e->vars;
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we still need to make sure there no duplicated innervar in the env (just like the jl_varbinding_t *wrap = NULL; trick above)?

And the TODO seems get resolved?

Copy link
Member

Choose a reason for hiding this comment

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

And perhaps we'd better not wrap res if we update the innervars?

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

From my original analysis, I didn't expect that would be possible. There are only 2 sides to the type tree, so either wrapping to the left or wrapping to the right should be needed, but not more than that. With an attempt of asserting for this case, I don't think it is hit either, but the code rearrangement probably makes sense anyways to be more straightforward. I believe a variable would have to switch sides multiple times by combinations to get tricky here, and it doesn't seem like that happens in existing code.

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Apr 5, 2023

Further call stack analysis, which can be simply by plugging this into Core.Compiler.return_type. This package is quite designed to be quite uninferable apparently, so Cthulhu has absolutely no idea what is going on with inference, sometimes even annotating calls with multiple conflicting remarks and contains some messy Unions almost immediately from the user.

hasinbound(Type{SimpleTraits.Not{Phylo.API.MatchNodeType{T, NL}}}, T, NL) where {NL, T<:(Phylo.AbstractTree{Phylo.OneTree, var"#s63", NL, N, B} where B<:Phylo.AbstractBranch{var"#s63", NL} where N<:Phylo.AbstractNode{var"#s63", NL} where var"#s63"<:Phylo.Rooted)}
hasinbound(T, NL) where {NL, T<:(Phylo.AbstractTree{Phylo.OneTree, var"#s65", NL, N, B} where B<:Phylo.AbstractBranch{var"#s65", NL} where N<:Phylo.AbstractNode{var"#s65", NL} where var"#s65"<:Phylo.Rooted)}
_treehistory(Type{Phylo.API.PreferBranchObjects{T}}, T, N1) where {N1, NL, N, B, T<:(Phylo.AbstractTree{Phylo.OneTree, var"#s63", NL, N, B} where var"#s63"<:Phylo.Rooted)}
_treehistory(T, N1) where {N1, NL, N, B, T<:(Phylo.AbstractTree{Phylo.OneTree, var"#s65", NL, N, B} where var"#s65"<:Phylo.Rooted)}
branchroute(Type{Phylo.API.MatchNodeType{T, N}}, T, N, N) where {RT, N, T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL} where N<:Phylo.AbstractNode{RT, NL} where NL)}
branchroute(T, N, N) where {RT, N, T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL} where N<:Phylo.AbstractNode{RT, NL} where NL)}
branchroute(Type{SimpleTraits.Not{Phylo.API.MatchNodeType{T, N}}}, T, N, N) where {RT, N, T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL} where N<:Phylo.AbstractNode{RT, NL} where NL)}
branchroute(T, N, N) where {RT, N, T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL} where N<:Phylo.AbstractNode{RT, NL} where NL)}

specialized as

Tuple{typeof(hasinbound), Type{SimpleTraits.Not{Phylo.API.MatchNodeType{T, NL}}}, Union{Union{LinkTree{RT3, NL, N, B} where {RT2<:Union{RT, RT1}, N<:Union{LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}, LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}}, B<:Union{LinkBranch{RT, NL}, LinkBranch{RT2, NL}, LinkBranch{RT1, NL}}, RT3<:Union{RT, RT2, RT1}}, LinkTree{var"#s63", NL, N, B} where {var"#s63"<:Union{RT, RT1}, N<:Union{LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s63", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s63", NL}}, LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}}, B<:Union{LinkBranch{RT, NL}, LinkBranch{var"#s63", NL}, LinkBranch{RT1, NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}, Union{LinkTree{RT2, NL, N, B} where {RT2<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{RT2, NL}}}, LinkTree{var"#s63", NL, N, B} where {var"#s63"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s63", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s63", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s63", NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}, Union{LinkTree{var"#s65", NL, N, B} where {var"#s65"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s65", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s65", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s65", NL}}}, LinkTree{var"#s63", NL, N, B} where {var"#s63"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s63", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s63", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s63", NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}}, NL} where {NL<:Missing, T<:(AbstractTree{OneTree, var"#s63", NL, N, B} where {var"#s63"<:Phylo.Rooted, N<:Phylo.AbstractNode{var"#s63", NL}, B<:Phylo.AbstractBranch{var"#s63", NL}})}

Tuple{typeof(hasinbound), T, NL} where {NL<:Missing, T<:Union{LinkTree{RT3, NL, N, B} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted, RT2<:Union{RT, RT1}, N<:Union{LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}, LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}}, B<:Union{LinkBranch{RT, NL}, LinkBranch{RT2, NL}, LinkBranch{RT1, NL}}, RT3<:Union{RT, RT2, RT1}}, Union{LinkTree{RT2, NL, N, B} where {RT2<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{RT2, NL}}}, LinkTree{var"#s65", NL, N, B} where {var"#s65"<:Union{Phylo.Rooted, RT1, RT}, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}, LinkNode{var"#s65", NL, Data, B} where {Data, B<:Phylo.AbstractBranch{var"#s65", NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}, LinkBranch{var"#s65", NL}}}} where {RT<:Phylo.Rooted, RT1<:Phylo.Rooted}}}


Tuple{typeof(Phylo._treehistory), Type{Phylo.API.PreferBranchObjects{T}}, T, Missing} where {NL, RT<:Phylo.Rooted, RT1<:Union{Phylo.Rooted, RT}, RT, RT2<:Union{Phylo.Rooted, RT}, RT, N<:Union{LinkNode{RT2, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT2, NL}}, LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}}, B<:Union{LinkBranch{RT2, NL}, LinkBranch{RT1, NL}, LinkBranch{RT, NL}}, T<:Union{LinkTree{RT1, NL, N, B} where RT1<:Union{RT2, RT}, LinkTree{RT, NL, N, B}}}


Tuple{typeof(Phylo._treehistory), T, Missing} where {NL, RT<:Phylo.Rooted, RT1<:Phylo.Rooted, N<:Union{LinkNode{RT1, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT1, NL}}, LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}}, B<:Union{LinkBranch{RT1, NL}, LinkBranch{RT, NL}}, T<:Union{LinkTree{RT1, NL, N, B}, LinkTree{RT, NL, N, B}}}


Tuple{typeof(branchroute), Type{Phylo.API.MatchNodeType{T, N}}, Union{LinkTree{RT, NL, N, B} where {NL, N<:(LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}), B<:(LinkBranch{RT, NL})}, LinkTree{RT, NL, N, B} where {NL, N<:(LinkNode{RT, NL, Data, B} where {Data, B<:Phylo.AbstractBranch{RT, NL}}), B<:(LinkBranch{RT, NL})}}, Missing, Missing} where {RT, N, T<:(AbstractTree{OneTree, RT, NL, N, B} where {NL, N<:Phylo.AbstractNode{RT, NL}, B<:Phylo.AbstractBranch{RT, NL}})}

Tuple{typeof(branchroute), LinkTree, Missing, Missing}

Tuple{typeof(branchroute), Type{SimpleTraits.Not{Phylo.API.MatchNodeType{RootedTree, String}}}, RootedTree, String, String}

Tuple{typeof(branchroute), RootedTree, String, String}

@vtjnash vtjnash force-pushed the jn/47476more3 branch 2 times, most recently from 68f1c50 to 67e2297 Compare April 7, 2023 20:11
@vtjnash vtjnash marked this pull request as ready for review April 7, 2023 20:11
@vtjnash

This comment was marked as resolved.

@nanosoldier
Copy link
Collaborator

Your package evaluation job has completed - possible new issues were detected.
A full report can be found here.

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Apr 9, 2023

@N5N3 Phylo is a deterministic crash caused by omit_bad_union. In particular, the bound of one of the vars is being set to NULL here:

2833            if (jl_has_typevar(btemp->ub, vb->var)) {
2834                if (vb->ub == (jl_value_t*)btemp->var) {
2835 >>>                btemp->ub = omit_bad_union(btemp->ub, vb->var); <<<
2836                    if (btemp->ub == NULL) {
2837                        JL_GC_POP();
2838                        return jl_bottom_type;
2839                    }
2840                }

But I don't think the code expects these to ever be NULL, so a later call to omit_bad_union then segfaults. Did you intend this state to be valid, or should we reset those to something legal (bottom) immediately:

diff --git a/src/subtype.c b/src/subtype.c
index 7373db4e01..38b07db8d6 100644
--- a/src/subtype.c
+++ b/src/subtype.c
@@ -2834,6 +2834,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
             if (vb->ub == (jl_value_t*)btemp->var) {
                 btemp->ub = omit_bad_union(btemp->ub, vb->var);
                 if (btemp->ub == NULL) {
+                    btemp->ub = jl_bottom_type;
                     JL_GC_POP();
                     return jl_bottom_type;
                 }
@@ -2998,7 +2999,7 @@ static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv
             vb->ub = omit_bad_union(vb->ub, u->var);
             JL_GC_POP();
             if (vb->ub == NULL)
-                res = jl_bottom_type;
+                res = vb->ub = jl_bottom_type;
         }
     }
     if (res != jl_bottom_type)

The types under comparison are deceptively simple looking

(rr) p jl_(a)
Tuple{typeof(Phylo.API._getnode), T, NL} where T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL} where N<:Phylo.AbstractNode{RT, NL}) where NL where RT
$1 = void
(rr) p jl_(b)
Tuple{typeof(Phylo.API._getnode), T, N} where T<:(Phylo.AbstractTree{Phylo.OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL}) where N where NL where RT

Though their intersection is far from simple, with that patch (I suspect these are not real):

julia> typeintersect(T,S)
Tuple{typeof(Phylo.API._getnode), Union{T, T1}, NL} where {RT, NL, N<:Phylo.AbstractNode{RT, NL}, T<:(AbstractTree{OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL}), N<:Phylo.AbstractNode{RT, Union{}}, T1<:(AbstractTree{OneTree, RT, Union{}, N, B} where B<:Phylo.AbstractBranch{RT, Union{}})}

julia> typeintersect(S,T)
Tuple{typeof(Phylo.API._getnode), Union{T, T1}, Union{Phylo.AbstractNode{RT, NL}, N}} where {RT, NL, N<:Phylo.AbstractNode{RT, NL}, T<:(AbstractTree{OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL}), N1<:Phylo.AbstractNode{RT, NL}, T1<:(AbstractTree{OneTree, RT, NL, N1, B} where B<:Phylo.AbstractBranch{RT, NL})}

I see the constraints that N <: Phylo.AbstractNode{RT, NL} but also N <: NL <: N, which seem like they should be failing, but not crashing.

@N5N3
Copy link
Member

N5N3 commented Apr 10, 2023

I thought setting res = Union{} is enough to avoid future accessing. But apparently, we get fooled here.
301f57d changes some test, e.g.

julia> typeintersect(Tuple{Type{T}, T, Ref{T}} where T,
                         Tuple{Type{S}, Ref{S}, S} where S)
Tuple{Type{Union{}}, Union{}, Union{}}

But I think there's no need to change the test as #49111 would "fix" it.

Edit1: The bad result before switch_union_tuple is

Union{Tuple{T, NL} where {NL, N<:Phylo.AbstractNode{RT, NL}, T<:(AbstractTree{OneTree, RT, NL, N, B} where B<:Phylo.AbstractBranch{RT, NL})}, Tuple{T, Union{}} where {N<:Phylo.AbstractNode{RT, Union{}}, T<:(AbstractTree{OneTree, RT, Union{}, N, B} where B<:Phylo.AbstractBranch{RT, Union{}})}} where RT

and ans.b would be Union{} after #49111, so I think there would be no invariant Union{}

We had an environment here that looked like while computing the upper bound for J{S} where S:

where S=T
where T
where I{T}
where J{S} where S

Then we started handling those, and filling in the values:

First replacing S with T, which creates a `res` of `J{T}`

where T
where I{T}
where J{S} where S

Then we handled T, which is also going to set `wrap=0`, so our result
for `J{T}` will not be made into `J{T} where T`.

where I{T} (wrap 0)
where J{S} where S

Here we then had finished handling all the dependencies for J{S} where
S, which resulted in an upper bound assignment of J{T}

where I{T}
where J{T}

Next, we handle I{T}, though it is now unused, so while we will make `I{T}
where T` (via innervars) here for it, this goes unuesd.

And finally, we had our resulting clause:

where J{T}

But it is missing the `where T`, since `I` (from lhs) was discarded.

Thus we need to add that back now, when handling some innervars, if we
see our term got duplicated to a higher part of the bounds before
reaching this handling for its placement movement.
N5N3 and others added 6 commits April 10, 2023 10:35
Should also fix some stackoverflow in PkgEval
Had an issue where (S<:T<:S with innervar N) would add the (where N) to
each S instead of the whole expression, resulting to creation of
(Val{. where N}) instead of (Val{.} where N) later.
I think this might be NFC, since I don't think this can simultaneously
affect the left and right envs, but it looks better this way.
Correct test for some other improvement also now on master.
@vtjnash vtjnash added the merge me PR is reviewed. Merge when all tests are passing label Apr 10, 2023
@vtjnash vtjnash merged commit c931884 into master Apr 13, 2023
@vtjnash vtjnash deleted the jn/47476more3 branch April 13, 2023 16:56
@giordano giordano removed the merge me PR is reviewed. Merge when all tests are passing label Apr 19, 2023
github-merge-queue bot pushed a commit that referenced this pull request Jul 16, 2023
On master, we only record direct `innervars` (`T` -> `S<:Val{T}`).
And chained `innervars` might be ignored (`T` -> `S<:Val{V<:T}`.

Before #48228, those chained
`innervars` would have been wrapped into an `UnionAll`, thus we just
need to check outer vars' lb/ub.

Test added.
~Note: this only fix
#50456 (comment),
the other MWE still get stackoverflow.~
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants