Order dependence of calls to isa through Cassette

I’m having a bit of a weird problem with Cassette when trying to overdub isa , as the result appears to change based on the sequence of calls despite no explicit state being shared between the calls. The example

using Cassette
Cassette.@context Ctx

typ = Tuple{P} where P <: Int
a = Cassette.overdub(Ctx(), isa, typ, DataType)
b = Cassette.overdub(Ctx(), isa, typ.body, DataType)
println("false: $a true: $b")

produces false: false true: false despite the expected result being false: false true: true. If a is replaced by a constant, then b is correct (is true); if we invoke isa with Cassette.fallback it works, and if we replace the definition of Cassette.call with one that calls jl_isa directly then it works. For example, adding

function Cassette.call(ctx::Cassette.Context{Cassette.nametype(Ctx),M,Nothing,P,B,H} where H<:Union{Cassette.DisableHooks, Nothing} where B<:Union{Nothing, IdDict{Module,Dict{Symbol,Cassette.BindingMeta}}} where P<:Cassette.AbstractPass where M, ::typeof(isa), a, b::Type) 
	return ccall(:jl_isa, Cint, (Any, Any), a, b) == 1
end

in between the definition of Ctx and the calls to overdub fixes the problem.

I suspect that the proximal cause of the issue is something to do with the unbound type variable in typ.body causing the second invocation to call the older (yet still type-specialized) version of isa, as when you attempt to identify the specialization that is called specifically reflection yells at you because it is a non-leaf-type. However, I haven’t been able to reproduce this in other generated methods, so am at something of a loose end as to where to look next.

I’ve narrowed this down to a bug in generated functions, see here https://github.com/JuliaLang/julia/issues/36931